diff --git a/crates/erg_common/config.rs b/crates/erg_common/config.rs index 7abf0a93..dfa9d71c 100644 --- a/crates/erg_common/config.rs +++ b/crates/erg_common/config.rs @@ -350,6 +350,19 @@ impl Input { } } + pub fn try_read(&mut self) -> std::io::Result { + match &mut self.kind { + InputKind::File(filename) => { + let file = File::open(filename)?; + read_file(file) + } + InputKind::Pipe(s) | InputKind::Str(s) => Ok(s.clone()), + InputKind::REPL => Ok(GLOBAL_STDIN.read()), + InputKind::DummyREPL(dummy) => Ok(dummy.read_line()), + InputKind::Dummy => panic!("cannot read from a dummy file"), + } + } + pub fn read_non_dummy(&self) -> String { match &self.kind { InputKind::File(filename) => { diff --git a/crates/erg_compiler/context/register.rs b/crates/erg_compiler/context/register.rs index 45462dfd..64f266eb 100644 --- a/crates/erg_compiler/context/register.rs +++ b/crates/erg_compiler/context/register.rs @@ -51,7 +51,7 @@ use super::instantiate::TyVarCache; use super::instantiate_spec::ParamKind; pub fn valid_mod_name(name: &str) -> bool { - !name.is_empty() && name.trim() == name + !name.is_empty() && !name.starts_with('/') && name.trim() == name } /// format: @@ -1762,24 +1762,28 @@ impl Context { } } - fn import_erg_mod(&self, __name__: &Str, loc: &impl Locational) -> CompileResult { + fn import_err(&self, __name__: &Str, loc: &impl Locational) -> TyCheckErrors { let mod_cache = self.mod_cache(); let py_mod_cache = self.py_mod_cache(); + TyCheckErrors::from(TyCheckError::import_error( + self.cfg.input.clone(), + line!() as usize, + format!("module {__name__} not found"), + loc.loc(), + self.caused_by(), + self.similar_builtin_erg_mod_name(__name__) + .or_else(|| mod_cache.get_similar_name(__name__)), + self.similar_builtin_py_mod_name(__name__) + .or_else(|| py_mod_cache.get_similar_name(__name__)), + )) + } + + fn import_erg_mod(&self, __name__: &Str, loc: &impl Locational) -> CompileResult { + let mod_cache = self.mod_cache(); 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, - format!("module {__name__} not found"), - loc.loc(), - self.caused_by(), - self.similar_builtin_erg_mod_name(__name__) - .or_else(|| mod_cache.get_similar_name(__name__)), - self.similar_builtin_py_mod_name(__name__) - .or_else(|| py_mod_cache.get_similar_name(__name__)), - )); - return Err(err); + return Err(self.import_err(__name__, loc)); } }; if let Some(referrer) = self.cfg.input.path() { @@ -1790,7 +1794,10 @@ impl Context { return Ok(path); } let mut cfg = self.cfg.inherit(path.clone()); - let src = cfg.input.read(); + let src = cfg + .input + .try_read() + .map_err(|_| self.import_err(__name__, loc))?; let mut builder = HIRBuilder::new_with_cache(cfg, __name__, self.shared.as_ref().unwrap().clone()); match builder.build(src, "exec") { @@ -1942,7 +1949,10 @@ impl Context { return Ok(path); } let mut cfg = self.cfg.inherit(path.clone()); - let src = cfg.input.read(); + let src = cfg + .input + .try_read() + .map_err(|_| self.import_err(__name__, loc))?; let mut builder = HIRBuilder::new_with_cache( cfg, self.mod_name(&path), diff --git a/crates/erg_compiler/declare.rs b/crates/erg_compiler/declare.rs index b95f0bd7..09e5221d 100644 --- a/crates/erg_compiler/declare.rs +++ b/crates/erg_compiler/declare.rs @@ -40,7 +40,7 @@ impl ASTLowerer { } else { None }; - let chunk = self.declare_chunk(body.block.remove(0))?; + let chunk = self.declare_chunk(body.block.remove(0), true)?; let py_name = if let hir::Expr::TypeAsc(tasc) = &chunk { enum_unwrap!(tasc.expr.as_ref(), hir::Expr::Accessor) .local_name() @@ -645,12 +645,13 @@ impl ASTLowerer { } } - fn declare_chunk(&mut self, expr: ast::Expr) -> LowerResult { + fn declare_chunk(&mut self, expr: ast::Expr, allow_acc: bool) -> LowerResult { log!(info "entered {}", fn_name!()); match expr { ast::Expr::Literal(lit) if lit.is_doc_comment() => { Ok(hir::Expr::Lit(self.lower_literal(lit)?)) } + ast::Expr::Accessor(acc) if allow_acc => Ok(hir::Expr::Accessor(self.lower_acc(acc)?)), ast::Expr::Def(def) => Ok(hir::Expr::Def(self.declare_def(def)?)), ast::Expr::TypeAscription(tasc) => Ok(hir::Expr::TypeAsc(self.declare_ident(tasc)?)), ast::Expr::Call(call) @@ -674,7 +675,7 @@ impl ASTLowerer { let mut module = hir::Module::with_capacity(ast.module.len()); let _ = self.module.context.preregister(ast.module.block()); for chunk in ast.module.into_iter() { - match self.declare_chunk(chunk) { + match self.declare_chunk(chunk, false) { Ok(chunk) => { module.push(chunk); } diff --git a/crates/erg_compiler/lower.rs b/crates/erg_compiler/lower.rs index 8c00357b..8cde11f0 100644 --- a/crates/erg_compiler/lower.rs +++ b/crates/erg_compiler/lower.rs @@ -591,7 +591,7 @@ impl ASTLowerer { )) } - fn lower_acc(&mut self, acc: ast::Accessor) -> LowerResult { + pub(crate) fn lower_acc(&mut self, acc: ast::Accessor) -> LowerResult { log!(info "entered {}({acc})", fn_name!()); match acc { ast::Accessor::Ident(ident) => {