Fix pyimport bug

This commit is contained in:
Shunsuke Shibayama 2022-10-13 00:23:14 +09:00
parent a2aa38ac25
commit fe339a7dc7
7 changed files with 36 additions and 6 deletions

View file

@ -5,6 +5,19 @@ use std::process::Command;
use crate::serialize::get_magic_num_from_bytes; use crate::serialize::get_magic_num_from_bytes;
pub const BUILTIN_PYTHON_MODS: [&str; 10] = [
"glob",
"importlib",
"io",
"math",
"re",
"random",
"socket",
"sys",
"time",
"urllib",
];
pub fn which_python() -> String { pub fn which_python() -> String {
let (cmd, python) = if cfg!(windows) { let (cmd, python) = if cfg!(windows) {
("where", "python") ("where", "python")

View file

@ -1660,7 +1660,11 @@ impl Context {
let path = let path =
option_enum_unwrap!(params.remove(0), TyParam::Value:(ValueObj::Str:(_)))?; option_enum_unwrap!(params.remove(0), TyParam::Value:(ValueObj::Str:(_)))?;
let path = Path::new(&path[..]); let path = Path::new(&path[..]);
let path = self.cfg.input.resolve(path).ok()?; let path = if let Ok(path) = self.cfg.input.resolve(path) {
path
} else {
PathBuf::from(format!("<builtins>.{}", path.display()))
};
self.mod_cache self.mod_cache
.as_ref() .as_ref()
.and_then(|cache| cache.ref_ctx(&path)) .and_then(|cache| cache.ref_ctx(&path))

View file

@ -4,6 +4,7 @@ use std::path::PathBuf;
use crate::ty::free::HasLevel; use crate::ty::free::HasLevel;
use erg_common::config::{ErgConfig, Input}; use erg_common::config::{ErgConfig, Input};
use erg_common::levenshtein::get_similar_name; use erg_common::levenshtein::get_similar_name;
use erg_common::python_util::BUILTIN_PYTHON_MODS;
use erg_common::set::Set; use erg_common::set::Set;
use erg_common::traits::{Locational, Stream}; use erg_common::traits::{Locational, Stream};
use erg_common::vis::Visibility; use erg_common::vis::Visibility;
@ -1011,11 +1012,7 @@ impl Context {
} }
fn similar_builtin_py_mod_name(&self, name: &Str) -> Option<Str> { fn similar_builtin_py_mod_name(&self, name: &Str) -> Option<Str> {
get_similar_name( get_similar_name(BUILTIN_PYTHON_MODS.into_iter(), name).map(Str::rc)
["importlib", "io", "math", "random", "socket", "sys", "time"].into_iter(),
name,
)
.map(Str::rc)
} }
fn import_user_py_mod(&self, mod_name: &Literal) -> CompileResult<PathBuf> { fn import_user_py_mod(&self, mod_name: &Literal) -> CompileResult<PathBuf> {

View file

@ -2,6 +2,7 @@ use std::mem;
use std::path::{Path, PathBuf}; use std::path::{Path, PathBuf};
use erg_common::config::{ErgConfig, Input}; use erg_common::config::{ErgConfig, Input};
use erg_common::python_util::BUILTIN_PYTHON_MODS;
use erg_common::traits::{Locational, Stream}; use erg_common::traits::{Locational, Stream};
use erg_common::Str; use erg_common::Str;
use erg_common::{enum_unwrap, log}; use erg_common::{enum_unwrap, log};
@ -238,6 +239,10 @@ impl<'a> Linker<'a> {
let args = &mut enum_unwrap!(expr, Expr::Call).args; let args = &mut enum_unwrap!(expr, Expr::Call).args;
let mod_name_lit = enum_unwrap!(args.remove_left_or_key("Path").unwrap(), Expr::Lit); let mod_name_lit = enum_unwrap!(args.remove_left_or_key("Path").unwrap(), Expr::Lit);
let mod_name_str = enum_unwrap!(mod_name_lit.value.clone(), ValueObj::Str); let mod_name_str = enum_unwrap!(mod_name_lit.value.clone(), ValueObj::Str);
if BUILTIN_PYTHON_MODS.contains(&&mod_name_str[..]) {
args.push_pos(PosArg::new(Expr::Lit(mod_name_lit)));
return;
}
let mod_name_str = if let Some(stripped) = mod_name_str.strip_prefix("./") { let mod_name_str = if let Some(stripped) = mod_name_str.strip_prefix("./") {
stripped stripped
} else { } else {

View file

@ -1760,6 +1760,7 @@ impl Type {
pub fn is_nonelike(&self) -> bool { pub fn is_nonelike(&self) -> bool {
match self { match self {
Self::Never | Self::Failure => true,
Self::FreeVar(fv) if fv.is_linked() => fv.crack().is_nonelike(), Self::FreeVar(fv) if fv.is_linked() => fv.crack().is_nonelike(),
Self::NoneType => true, Self::NoneType => true,
Self::Poly { name, params, .. } if &name[..] == "Option" || &name[..] == "Option!" => { Self::Poly { name, params, .. } if &name[..] == "Option" || &name[..] == "Option!" => {

5
examples/pyimport.er Normal file
View file

@ -0,0 +1,5 @@
math = pyimport "math"
sys = pyimport "sys"
print! math.pi
sys.exit 111

View file

@ -66,6 +66,11 @@ fn exec_prelude() -> Result<(), ()> {
expect_success("compiler/erg_compiler/std/prelude.er") expect_success("compiler/erg_compiler/std/prelude.er")
} }
#[test]
fn exec_pyimport() -> Result<(), ()> {
expect_end_with("examples/pyimport.er", 111)
}
#[test] #[test]
fn exec_quantified() -> Result<(), ()> { fn exec_quantified() -> Result<(), ()> {
expect_success("examples/quantified.er") expect_success("examples/quantified.er")