From a395938413e1446b6629feaa15883c7caf9f5364 Mon Sep 17 00:00:00 2001 From: Shunsuke Shibayama Date: Fri, 9 Dec 2022 11:48:13 +0900 Subject: [PATCH] Fix an Erg standard library loading bug --- compiler/erg_common/str.rs | 4 +- compiler/erg_compiler/context/inquire.rs | 46 +++++++++++++++++------ compiler/erg_compiler/context/mod.rs | 6 +++ compiler/erg_compiler/context/register.rs | 25 +++++------- compiler/erg_compiler/lib/std/semver.er | 4 +- compiler/erg_compiler/link.rs | 3 +- compiler/erg_compiler/lower.rs | 27 ++++++------- 7 files changed, 68 insertions(+), 47 deletions(-) diff --git a/compiler/erg_common/str.rs b/compiler/erg_common/str.rs index 04a2bc94..681fa5f8 100644 --- a/compiler/erg_common/str.rs +++ b/compiler/erg_common/str.rs @@ -64,8 +64,8 @@ impl From for String { impl<'a> From for Cow<'a, str> { fn from(s: Str) -> Self { match s { - Str::Static(s) => Cow::Owned(s.to_owned()), - _ => unreachable!(), + Str::Static(s) => Cow::Borrowed(s), + Str::Rc(s) => Cow::Owned(s.to_string()), } } } diff --git a/compiler/erg_compiler/context/inquire.rs b/compiler/erg_compiler/context/inquire.rs index e1d3f4d5..dd26b4ea 100644 --- a/compiler/erg_compiler/context/inquire.rs +++ b/compiler/erg_compiler/context/inquire.rs @@ -2,8 +2,8 @@ use std::option::Option; // conflicting to Type::Option use std::path::{Path, PathBuf}; -use erg_common::config::Input; -use erg_common::env::erg_pystd_path; +use erg_common::config::{ErgConfig, Input}; +use erg_common::env::{erg_pystd_path, erg_std_path}; use erg_common::error::{ErrorCore, ErrorKind, Location, SubMessage}; use erg_common::levenshtein::get_similar_name; use erg_common::set::Set; @@ -1736,7 +1736,7 @@ impl Context { } let type_name = namespaces.pop().unwrap(); // Response let path = Path::new(namespaces.remove(0)); - let mut path = self.resolve_path(path); + let mut path = Self::resolve_path(&self.cfg, path)?; for p in namespaces.into_iter() { path = self.push_path(path, Path::new(p)); } @@ -1766,7 +1766,7 @@ impl Context { } let type_name = namespaces.pop().unwrap(); // Response let path = Path::new(namespaces.remove(0)); - let mut path = self.resolve_path(path); + let mut path = Self::resolve_path(&self.cfg, path)?; for p in namespaces.into_iter() { path = self.push_path(path, Path::new(p)); } @@ -1925,23 +1925,45 @@ impl Context { } } - // TODO: erg std - pub(crate) fn resolve_path(&self, path: &Path) -> PathBuf { - if let Ok(path) = self.cfg.input.local_resolve(path) { - path + pub(crate) fn resolve_path(cfg: &ErgConfig, path: &Path) -> Option { + Self::resolve_real_path(cfg, path).or_else(|| Self::resolve_d_path(cfg, path)) + } + + pub(crate) fn resolve_real_path(cfg: &ErgConfig, path: &Path) -> Option { + if let Ok(path) = cfg.input.local_resolve(path) { + Some(path) + } else if let Ok(path) = erg_std_path() + .join(format!("{}.er", path.display())) + .canonicalize() + { + Some(path) + } else if let Ok(path) = erg_std_path() + .join(format!("{}", path.display())) + .join("__init__.er") + .canonicalize() + { + Some(path) + } else { + None + } + } + + pub(crate) fn resolve_d_path(cfg: &ErgConfig, path: &Path) -> Option { + if let Ok(path) = cfg.input.local_resolve(path) { + Some(path) } else if let Ok(path) = erg_pystd_path() .join(format!("{}.d.er", path.display())) .canonicalize() { - path + Some(path) } else if let Ok(path) = erg_pystd_path() .join(format!("{}.d", path.display())) .join("__init__.d.er") .canonicalize() { - path + Some(path) } else { - PathBuf::from(format!(".{}", path.display())) + None } } @@ -1968,7 +1990,7 @@ impl Context { if t.is_module() { let path = option_enum_unwrap!(t.typarams().remove(0), TyParam::Value:(ValueObj::Str:(_)))?; - let path = self.resolve_path(Path::new(&path[..])); + let path = Self::resolve_path(&self.cfg, Path::new(&path[..]))?; self.mod_cache .as_ref() .and_then(|cache| cache.ref_ctx(&path)) diff --git a/compiler/erg_compiler/context/mod.rs b/compiler/erg_compiler/context/mod.rs index d5c98941..3efc0788 100644 --- a/compiler/erg_compiler/context/mod.rs +++ b/compiler/erg_compiler/context/mod.rs @@ -1008,6 +1008,12 @@ impl Context { self.params.retain(|(_, v)| v.t != Failure); } + pub(crate) fn clear_all_vars(&mut self) { + self.locals.clear(); + self.decls.clear(); + self.params.retain(|(_, v)| v.t != Failure); + } + pub fn pop(&mut self) -> Context { if let Some(parent) = self.outer.as_mut() { let parent = mem::take(parent); diff --git a/compiler/erg_compiler/context/register.rs b/compiler/erg_compiler/context/register.rs index 494b5fa7..ee21ec04 100644 --- a/compiler/erg_compiler/context/register.rs +++ b/compiler/erg_compiler/context/register.rs @@ -1168,22 +1168,18 @@ impl Context { let __name__ = enum_unwrap!(mod_name.value.clone(), ValueObj::Str); let mod_cache = self.mod_cache.as_ref().unwrap(); let py_mod_cache = self.py_mod_cache.as_ref().unwrap(); - let path = match self.cfg.input.local_resolve(Path::new(&__name__[..])) { - Ok(path) => path, - Err(err) => { + let path = match Self::resolve_real_path(&self.cfg, Path::new(&__name__[..])) { + Some(path) => path, + None => { let err = TyCheckErrors::from(TyCheckError::import_error( self.cfg.input.clone(), line!() as usize, - err.to_string(), + format!("module {__name__} not found"), mod_name.loc(), self.caused_by(), self.mod_cache.as_ref().unwrap().get_similar_name(&__name__), - self.similar_builtin_py_mod_name(&__name__).or_else(|| { - self.py_mod_cache - .as_ref() - .unwrap() - .get_similar_name(&__name__) - }), + self.similar_builtin_py_mod_name(&__name__) + .or_else(|| py_mod_cache.get_similar_name(&__name__)), )); return Err(err); } @@ -1250,9 +1246,8 @@ impl Context { let __name__ = enum_unwrap!(mod_name.value.clone(), ValueObj::Str); let mod_cache = self.mod_cache.as_ref().unwrap(); let py_mod_cache = self.py_mod_cache.as_ref().unwrap(); - let path = self.resolve_path(Path::new(&__name__[..])); - let path = match path.canonicalize() { - Ok(path) => { + let path = match Self::resolve_d_path(&self.cfg, Path::new(&__name__[..])) { + Some(path) => { if self.is_pystd_main_module(path.as_path()) && !BUILTIN_PYTHON_MODS.contains(&&__name__[..]) { @@ -1267,11 +1262,11 @@ impl Context { } path } - Err(err) => { + None => { let err = TyCheckError::import_error( self.cfg.input.clone(), line!() as usize, - err.to_string(), + format!("module {__name__} not found"), mod_name.loc(), self.caused_by(), self.mod_cache.as_ref().unwrap().get_similar_name(&__name__), diff --git a/compiler/erg_compiler/lib/std/semver.er b/compiler/erg_compiler/lib/std/semver.er index 700da5bf..1720e676 100644 --- a/compiler/erg_compiler/lib/std/semver.er +++ b/compiler/erg_compiler/lib/std/semver.er @@ -8,14 +8,14 @@ .Version. new major, minor, patch, pre := None = .Version::__new__ { .major = major; .minor = minor; .patch = patch; .pre = pre } - #[ +#[ greater self, other: .Version = match [self.major > other.major, self.major >= other.major, self.minor > other.minor, self.minor >= other.minor, self.patch > other.patch]: [True, _, _, _, _] -> True [_, True, True, _, _] -> True [_, True, _, True, True] -> True _ -> False - ]# +]# .Version|.Version <: Eq|. __eq__ self, other: .Version = self.major == other.major and self.minor == other.minor and self.patch == other.patch and self.pre == other.pre diff --git a/compiler/erg_compiler/link.rs b/compiler/erg_compiler/link.rs index b87b0f01..fae37ead 100644 --- a/compiler/erg_compiler/link.rs +++ b/compiler/erg_compiler/link.rs @@ -10,6 +10,7 @@ use erg_common::{enum_unwrap, log}; use erg_parser::ast::{DefId, OperationKind}; use erg_parser::token::{Token, TokenKind, DOT, EQUAL}; +use crate::context::Context; use crate::ty::typaram::TyParam; use crate::ty::value::ValueObj; use crate::ty::HasType; @@ -297,7 +298,7 @@ impl<'a> Linker<'a> { let path = enum_unwrap!(expr.ref_t().typarams().remove(0), TyParam::Value:(ValueObj::Str:(_))); let path = Path::new(&path[..]); - let path = self.cfg.input.local_resolve(path).unwrap(); + let path = Context::resolve_real_path(self.cfg, path).unwrap(); // In the case of REPL, entries cannot be used up let hir = if self.cfg.input.is_repl() { self.mod_cache diff --git a/compiler/erg_compiler/lower.rs b/compiler/erg_compiler/lower.rs index 9f051920..c1338433 100644 --- a/compiler/erg_compiler/lower.rs +++ b/compiler/erg_compiler/lower.rs @@ -2051,6 +2051,15 @@ impl ASTLowerer { HIR::new(ast.name, module) } + fn return_incomplete_artifact(&mut self, hir: HIR) -> IncompleteArtifact { + self.ctx.clear_all_vars(); + IncompleteArtifact::new( + Some(hir), + LowerErrors::from(self.errs.take_all()), + LowerWarnings::from(self.warns.take_all()), + ) + } + pub fn lower(&mut self, ast: AST, mode: &str) -> Result { log!(info "the AST lowering process has started."); log!(info "the type-checking process has started."); @@ -2070,11 +2079,7 @@ impl ASTLowerer { )); } else { log!(err "the declaring process has failed."); - return Err(IncompleteArtifact::new( - Some(hir), - LowerErrors::from(self.errs.take_all()), - LowerWarnings::from(self.warns.take_all()), - )); + return Err(self.return_incomplete_artifact(hir)); } } let mut module = hir::Module::with_capacity(ast.module.len()); @@ -2105,11 +2110,7 @@ impl ASTLowerer { Err((hir, errs)) => { self.errs.extend(errs); log!(err "the resolving process has failed. errs: {}", self.errs.len()); - return Err(IncompleteArtifact::new( - Some(hir), - LowerErrors::from(self.errs.take_all()), - LowerWarnings::from(self.warns.take_all()), - )); + return Err(self.return_incomplete_artifact(hir)); } }; // TODO: recursive check @@ -2126,11 +2127,7 @@ impl ASTLowerer { )) } else { log!(err "the AST lowering process has failed. errs: {}", self.errs.len()); - Err(IncompleteArtifact::new( - Some(hir), - LowerErrors::from(self.errs.take_all()), - LowerWarnings::from(self.warns.take_all()), - )) + Err(self.return_incomplete_artifact(hir)) } } }