diff --git a/compiler/erg_compiler/codegen.rs b/compiler/erg_compiler/codegen.rs index 54211383..770c0ef3 100644 --- a/compiler/erg_compiler/codegen.rs +++ b/compiler/erg_compiler/codegen.rs @@ -1619,7 +1619,10 @@ impl CodeGenerator { Expr::Compound(chunks) => { self.emit_frameless_block(chunks, vec![]); } - // Dict, Decl + Expr::TypeAsc(tasc) => { + self.emit_expr(*tasc.expr); + } + // Dict, other => { self.errs.push(CompileError::feature_error( self.cfg.input.clone(), diff --git a/compiler/erg_compiler/context/instantiate.rs b/compiler/erg_compiler/context/instantiate.rs index 20145775..09c1d9dd 100644 --- a/compiler/erg_compiler/context/instantiate.rs +++ b/compiler/erg_compiler/context/instantiate.rs @@ -529,8 +529,8 @@ impl Context { Ok(decl_t.typ().clone()) } else { let typ = mono(self.mod_name(), Str::rc(other)); - if self.get_nominal_type_ctx(&typ).is_some() { - Ok(typ) + if let Some((defined_t, _)) = self.get_nominal_type_ctx(&typ) { + Ok(defined_t.clone()) } else { Err(TyCheckError::no_var_error( line!() as usize, diff --git a/compiler/erg_compiler/context/register.rs b/compiler/erg_compiler/context/register.rs index 4beee1f9..909c01d4 100644 --- a/compiler/erg_compiler/context/register.rs +++ b/compiler/erg_compiler/context/register.rs @@ -839,6 +839,7 @@ impl Context { let py_mod_cache = self.py_mod_cache.as_ref().unwrap(); #[allow(clippy::match_single_binding)] match &__name__[..] { + // TODO: erg builtin modules _ => self.import_user_erg_mod( current_input, var_name, @@ -957,13 +958,62 @@ impl Context { fn import_user_py_mod( &self, - _current_input: Input, - _var_name: &VarName, + current_input: Input, + var_name: &VarName, lit: &Literal, ) -> TyCheckResult<()> { let __name__ = enum_unwrap!(lit.value.clone(), ValueObj::Str); - let _mod_cache = self.mod_cache.as_ref().unwrap(); - todo!() + let py_mod_cache = self.py_mod_cache.as_ref().unwrap(); + if let Some((_, entry)) = py_mod_cache.get_by_name(&__name__) { + py_mod_cache.register_alias(var_name.clone(), entry); + return Ok(()); + } + let mut dir = if let Input::File(mut path) = current_input { + path.pop(); + path + } else { + PathBuf::new() + }; + dir.push(format!("{__name__}.er")); + // TODO: returns an error + let path = match dir.canonicalize() { + Ok(path) => path, + Err(err) => { + return Err(TyCheckError::import_error( + line!() as usize, + err.to_string(), + lit.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__) + }), + )); + } + }; + let cfg = ErgConfig { + input: Input::File(path), + ..ErgConfig::default() + }; + let src = cfg.input.read(); + let mut builder = HIRBuilder::new_with_cache( + cfg, + var_name.inspect(), + py_mod_cache.clone(), + py_mod_cache.clone(), + ); + match builder.build(src, "declare") { + Ok(hir) => { + py_mod_cache.register(var_name.clone(), Some(hir), builder.pop_ctx()); + } + Err(errs) => { + errs.fmt_all_stderr(); + } + } + Ok(()) } pub(crate) fn _push_subtype_bound(&mut self, sub: Type, sup: Type) { diff --git a/compiler/erg_compiler/effectcheck.rs b/compiler/erg_compiler/effectcheck.rs index 1984044b..c7893655 100644 --- a/compiler/erg_compiler/effectcheck.rs +++ b/compiler/erg_compiler/effectcheck.rs @@ -137,6 +137,9 @@ impl SideEffectChecker { self.path_stack.pop(); self.block_stack.pop(); } + Expr::TypeAsc(tasc) => { + self.check_expr(&tasc.expr); + } other => todo!("{other}"), } } @@ -292,6 +295,9 @@ impl SideEffectChecker { self.path_stack.pop(); self.block_stack.pop(); } + Expr::TypeAsc(type_asc) => { + self.check_expr(&type_asc.expr); + } _ => {} } } @@ -306,6 +312,7 @@ impl SideEffectChecker { // !procedural: !x.y Expr::Accessor(Accessor::Attr(attr)) => attr.ident.is_procedural(), Expr::Accessor(_) => todo!(), + Expr::TypeAsc(tasc) => self.is_procedural(&tasc.expr), _ => false, } } diff --git a/compiler/erg_compiler/hir.rs b/compiler/erg_compiler/hir.rs index c065f2de..59cde0bc 100644 --- a/compiler/erg_compiler/hir.rs +++ b/compiler/erg_compiler/hir.rs @@ -1579,6 +1579,10 @@ impl Expr { _ => None, } } + + pub fn is_type_asc(&self) -> bool { + matches!(self, Expr::TypeAsc(_)) + } } /// Toplevel grammar unit diff --git a/compiler/erg_compiler/lower.rs b/compiler/erg_compiler/lower.rs index f7e9be88..5635e362 100644 --- a/compiler/erg_compiler/lower.rs +++ b/compiler/erg_compiler/lower.rs @@ -146,8 +146,12 @@ impl ASTLowerer { }) } + /// OK: exec `i: Int` + /// OK: exec `i: Int = 1` + /// NG: exec `1 + 2` + /// OK: exec `None` fn use_check(&self, expr: &hir::Expr, mode: &str) -> LowerResult<()> { - if mode != "eval" && !expr.ref_t().is_nonelike() { + if mode != "eval" && !expr.ref_t().is_nonelike() && !expr.is_type_asc() { Err(LowerError::syntax_error( 0, expr.loc(), diff --git a/compiler/erg_compiler/ownercheck.rs b/compiler/erg_compiler/ownercheck.rs index 774e85d7..6e516a32 100644 --- a/compiler/erg_compiler/ownercheck.rs +++ b/compiler/erg_compiler/ownercheck.rs @@ -187,6 +187,9 @@ impl OwnershipChecker { self.check_block(&lambda.body); self.path_stack.pop(); } + Expr::TypeAsc(asc) => { + self.check_expr(&asc.expr, ownership, chunk); + } _ => {} } }