Fix an Erg standard library loading bug

This commit is contained in:
Shunsuke Shibayama 2022-12-09 11:48:13 +09:00
parent a460b431a3
commit a395938413
7 changed files with 68 additions and 47 deletions

View file

@ -64,8 +64,8 @@ impl From<Str> for String {
impl<'a> From<Str> for Cow<'a, str> { impl<'a> From<Str> for Cow<'a, str> {
fn from(s: Str) -> Self { fn from(s: Str) -> Self {
match s { match s {
Str::Static(s) => Cow::Owned(s.to_owned()), Str::Static(s) => Cow::Borrowed(s),
_ => unreachable!(), Str::Rc(s) => Cow::Owned(s.to_string()),
} }
} }
} }

View file

@ -2,8 +2,8 @@
use std::option::Option; // conflicting to Type::Option use std::option::Option; // conflicting to Type::Option
use std::path::{Path, PathBuf}; use std::path::{Path, PathBuf};
use erg_common::config::Input; use erg_common::config::{ErgConfig, Input};
use erg_common::env::erg_pystd_path; use erg_common::env::{erg_pystd_path, erg_std_path};
use erg_common::error::{ErrorCore, ErrorKind, Location, SubMessage}; use erg_common::error::{ErrorCore, ErrorKind, Location, SubMessage};
use erg_common::levenshtein::get_similar_name; use erg_common::levenshtein::get_similar_name;
use erg_common::set::Set; use erg_common::set::Set;
@ -1736,7 +1736,7 @@ impl Context {
} }
let type_name = namespaces.pop().unwrap(); // Response let type_name = namespaces.pop().unwrap(); // Response
let path = Path::new(namespaces.remove(0)); 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() { for p in namespaces.into_iter() {
path = self.push_path(path, Path::new(p)); path = self.push_path(path, Path::new(p));
} }
@ -1766,7 +1766,7 @@ impl Context {
} }
let type_name = namespaces.pop().unwrap(); // Response let type_name = namespaces.pop().unwrap(); // Response
let path = Path::new(namespaces.remove(0)); 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() { for p in namespaces.into_iter() {
path = self.push_path(path, Path::new(p)); path = self.push_path(path, Path::new(p));
} }
@ -1925,23 +1925,45 @@ impl Context {
} }
} }
// TODO: erg std pub(crate) fn resolve_path(cfg: &ErgConfig, path: &Path) -> Option<PathBuf> {
pub(crate) fn resolve_path(&self, path: &Path) -> PathBuf { Self::resolve_real_path(cfg, path).or_else(|| Self::resolve_d_path(cfg, path))
if let Ok(path) = self.cfg.input.local_resolve(path) { }
path
pub(crate) fn resolve_real_path(cfg: &ErgConfig, path: &Path) -> Option<PathBuf> {
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<PathBuf> {
if let Ok(path) = cfg.input.local_resolve(path) {
Some(path)
} else if let Ok(path) = erg_pystd_path() } else if let Ok(path) = erg_pystd_path()
.join(format!("{}.d.er", path.display())) .join(format!("{}.d.er", path.display()))
.canonicalize() .canonicalize()
{ {
path Some(path)
} else if let Ok(path) = erg_pystd_path() } else if let Ok(path) = erg_pystd_path()
.join(format!("{}.d", path.display())) .join(format!("{}.d", path.display()))
.join("__init__.d.er") .join("__init__.d.er")
.canonicalize() .canonicalize()
{ {
path Some(path)
} else { } else {
PathBuf::from(format!("<builtins>.{}", path.display())) None
} }
} }
@ -1968,7 +1990,7 @@ impl Context {
if t.is_module() { if t.is_module() {
let path = let path =
option_enum_unwrap!(t.typarams().remove(0), TyParam::Value:(ValueObj::Str:(_)))?; 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 self.mod_cache
.as_ref() .as_ref()
.and_then(|cache| cache.ref_ctx(&path)) .and_then(|cache| cache.ref_ctx(&path))

View file

@ -1008,6 +1008,12 @@ impl Context {
self.params.retain(|(_, v)| v.t != Failure); 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 { pub fn pop(&mut self) -> Context {
if let Some(parent) = self.outer.as_mut() { if let Some(parent) = self.outer.as_mut() {
let parent = mem::take(parent); let parent = mem::take(parent);

View file

@ -1168,22 +1168,18 @@ impl Context {
let __name__ = enum_unwrap!(mod_name.value.clone(), ValueObj::Str); let __name__ = enum_unwrap!(mod_name.value.clone(), ValueObj::Str);
let mod_cache = self.mod_cache.as_ref().unwrap(); let mod_cache = self.mod_cache.as_ref().unwrap();
let py_mod_cache = self.py_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__[..])) { let path = match Self::resolve_real_path(&self.cfg, Path::new(&__name__[..])) {
Ok(path) => path, Some(path) => path,
Err(err) => { None => {
let err = TyCheckErrors::from(TyCheckError::import_error( let err = TyCheckErrors::from(TyCheckError::import_error(
self.cfg.input.clone(), self.cfg.input.clone(),
line!() as usize, line!() as usize,
err.to_string(), format!("module {__name__} not found"),
mod_name.loc(), mod_name.loc(),
self.caused_by(), self.caused_by(),
self.mod_cache.as_ref().unwrap().get_similar_name(&__name__), self.mod_cache.as_ref().unwrap().get_similar_name(&__name__),
self.similar_builtin_py_mod_name(&__name__).or_else(|| { self.similar_builtin_py_mod_name(&__name__)
self.py_mod_cache .or_else(|| py_mod_cache.get_similar_name(&__name__)),
.as_ref()
.unwrap()
.get_similar_name(&__name__)
}),
)); ));
return Err(err); return Err(err);
} }
@ -1250,9 +1246,8 @@ impl Context {
let __name__ = enum_unwrap!(mod_name.value.clone(), ValueObj::Str); let __name__ = enum_unwrap!(mod_name.value.clone(), ValueObj::Str);
let mod_cache = self.mod_cache.as_ref().unwrap(); let mod_cache = self.mod_cache.as_ref().unwrap();
let py_mod_cache = self.py_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 Self::resolve_d_path(&self.cfg, Path::new(&__name__[..])) {
let path = match path.canonicalize() { Some(path) => {
Ok(path) => {
if self.is_pystd_main_module(path.as_path()) if self.is_pystd_main_module(path.as_path())
&& !BUILTIN_PYTHON_MODS.contains(&&__name__[..]) && !BUILTIN_PYTHON_MODS.contains(&&__name__[..])
{ {
@ -1267,11 +1262,11 @@ impl Context {
} }
path path
} }
Err(err) => { None => {
let err = TyCheckError::import_error( let err = TyCheckError::import_error(
self.cfg.input.clone(), self.cfg.input.clone(),
line!() as usize, line!() as usize,
err.to_string(), format!("module {__name__} not found"),
mod_name.loc(), mod_name.loc(),
self.caused_by(), self.caused_by(),
self.mod_cache.as_ref().unwrap().get_similar_name(&__name__), self.mod_cache.as_ref().unwrap().get_similar_name(&__name__),

View file

@ -8,14 +8,14 @@
.Version. .Version.
new major, minor, patch, pre := None = new major, minor, patch, pre := None =
.Version::__new__ { .major = major; .minor = minor; .patch = patch; .pre = pre } .Version::__new__ { .major = major; .minor = minor; .patch = patch; .pre = pre }
#[ #[
greater self, other: .Version = 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]: 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, _, _] -> True
[_, True, _, True, True] -> True [_, True, _, True, True] -> True
_ -> False _ -> False
]# ]#
.Version|.Version <: Eq|. .Version|.Version <: Eq|.
__eq__ self, other: .Version = __eq__ self, other: .Version =
self.major == other.major and self.minor == other.minor and self.patch == other.patch and self.pre == other.pre self.major == other.major and self.minor == other.minor and self.patch == other.patch and self.pre == other.pre

View file

@ -10,6 +10,7 @@ use erg_common::{enum_unwrap, log};
use erg_parser::ast::{DefId, OperationKind}; use erg_parser::ast::{DefId, OperationKind};
use erg_parser::token::{Token, TokenKind, DOT, EQUAL}; use erg_parser::token::{Token, TokenKind, DOT, EQUAL};
use crate::context::Context;
use crate::ty::typaram::TyParam; use crate::ty::typaram::TyParam;
use crate::ty::value::ValueObj; use crate::ty::value::ValueObj;
use crate::ty::HasType; use crate::ty::HasType;
@ -297,7 +298,7 @@ impl<'a> Linker<'a> {
let path = let path =
enum_unwrap!(expr.ref_t().typarams().remove(0), TyParam::Value:(ValueObj::Str:(_))); enum_unwrap!(expr.ref_t().typarams().remove(0), TyParam::Value:(ValueObj::Str:(_)));
let path = Path::new(&path[..]); 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 // In the case of REPL, entries cannot be used up
let hir = if self.cfg.input.is_repl() { let hir = if self.cfg.input.is_repl() {
self.mod_cache self.mod_cache

View file

@ -2051,6 +2051,15 @@ impl ASTLowerer {
HIR::new(ast.name, module) 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<CompleteArtifact, IncompleteArtifact> { pub fn lower(&mut self, ast: AST, mode: &str) -> Result<CompleteArtifact, IncompleteArtifact> {
log!(info "the AST lowering process has started."); log!(info "the AST lowering process has started.");
log!(info "the type-checking process has started."); log!(info "the type-checking process has started.");
@ -2070,11 +2079,7 @@ impl ASTLowerer {
)); ));
} else { } else {
log!(err "the declaring process has failed."); log!(err "the declaring process has failed.");
return Err(IncompleteArtifact::new( return Err(self.return_incomplete_artifact(hir));
Some(hir),
LowerErrors::from(self.errs.take_all()),
LowerWarnings::from(self.warns.take_all()),
));
} }
} }
let mut module = hir::Module::with_capacity(ast.module.len()); let mut module = hir::Module::with_capacity(ast.module.len());
@ -2105,11 +2110,7 @@ impl ASTLowerer {
Err((hir, errs)) => { Err((hir, errs)) => {
self.errs.extend(errs); self.errs.extend(errs);
log!(err "the resolving process has failed. errs: {}", self.errs.len()); log!(err "the resolving process has failed. errs: {}", self.errs.len());
return Err(IncompleteArtifact::new( return Err(self.return_incomplete_artifact(hir));
Some(hir),
LowerErrors::from(self.errs.take_all()),
LowerWarnings::from(self.warns.take_all()),
));
} }
}; };
// TODO: recursive check // TODO: recursive check
@ -2126,11 +2127,7 @@ impl ASTLowerer {
)) ))
} else { } else {
log!(err "the AST lowering process has failed. errs: {}", self.errs.len()); log!(err "the AST lowering process has failed. errs: {}", self.errs.len());
Err(IncompleteArtifact::new( Err(self.return_incomplete_artifact(hir))
Some(hir),
LowerErrors::from(self.errs.take_all()),
LowerWarnings::from(self.warns.take_all()),
))
} }
} }
} }