diff --git a/compiler/erg_compiler/builder.rs b/compiler/erg_compiler/builder.rs index 632bc593..bc9f5946 100644 --- a/compiler/erg_compiler/builder.rs +++ b/compiler/erg_compiler/builder.rs @@ -1,4 +1,4 @@ -use erg_common::config::{ErgConfig, Input}; +use erg_common::config::ErgConfig; use erg_common::traits::{Runnable, Stream}; use erg_parser::ast::VarName; @@ -31,25 +31,9 @@ impl HIRBuilder { } } - pub fn build_and_cache(&mut self, var_name: VarName) -> Result<(), CompileErrors> { + pub fn build_and_cache(&mut self, var_name: VarName, mode: &str) -> Result<(), CompileErrors> { let mut ast_builder = ASTBuilder::new(self.checker.cfg().copy()); let ast = ast_builder.build()?; - let ast = Reorderer::new() - .reorder(ast) - .map_err(|errs| self.convert(errs))?; - let (hir, ctx) = self - .checker - .check(ast, "exec") - .map_err(|errs| self.convert(errs))?; - self.mod_cache.register(var_name, Some(hir), ctx); - Ok(()) - } - - pub fn build_and_cache_main(&mut self, src: String, mode: &str) -> Result<(), CompileErrors> { - let mut cfg = self.checker.cfg().copy(); - cfg.input = Input::Str(src); - let mut ast_builder = ASTBuilder::new(cfg); - let ast = ast_builder.build()?; let ast = Reorderer::new() .reorder(ast) .map_err(|errs| self.convert(errs))?; @@ -57,8 +41,7 @@ impl HIRBuilder { .checker .check(ast, mode) .map_err(|errs| self.convert(errs))?; - let name = VarName::from_static(""); - self.mod_cache.register(name, Some(hir), ctx); + self.mod_cache.register(var_name, Some(hir), ctx); Ok(()) } } diff --git a/compiler/erg_compiler/check.rs b/compiler/erg_compiler/check.rs index 89716bbc..7e6ff692 100644 --- a/compiler/erg_compiler/check.rs +++ b/compiler/erg_compiler/check.rs @@ -1,4 +1,4 @@ -use erg_common::config::ErgConfig; +use erg_common::config::{ErgConfig, Input}; use erg_common::error::MultiErrorDisplay; use erg_common::traits::Runnable; @@ -48,8 +48,12 @@ impl Runnable for Checker { } fn eval(&mut self, src: String) -> Result { - let mut builder = ASTBuilder::new(self.cfg().copy()); - let ast = builder.build_with_str(src)?; + let cfg = ErgConfig { + input: Input::Str(src), + ..self.cfg().copy() + }; + let mut builder = ASTBuilder::new(cfg); + let ast = builder.build()?; let (hir, _) = self.check(ast, "eval")?; Ok(hir.to_string()) } diff --git a/compiler/erg_compiler/compile.rs b/compiler/erg_compiler/compile.rs index 1e411c1b..b62d2904 100644 --- a/compiler/erg_compiler/compile.rs +++ b/compiler/erg_compiler/compile.rs @@ -3,9 +3,10 @@ //! コンパイラーを定義する use std::path::Path; -use erg_common::config::ErgConfig; +use erg_common::config::{ErgConfig, Input}; use erg_common::log; use erg_common::traits::{Runnable, Stream}; +use erg_parser::ast::VarName; use erg_type::codeobj::CodeObj; use crate::builder::HIRBuilder; @@ -148,8 +149,12 @@ impl Compiler { pub fn compile(&mut self, src: String, mode: &str) -> Result { log!(info "the compiling process has started."); - let mut hir_builder = HIRBuilder::new(self.cfg.copy(), self.mod_cache.clone()); - hir_builder.build_and_cache_main(src, mode)?; + let cfg = ErgConfig { + input: Input::Str(src), + ..self.cfg.copy() + }; + let mut hir_builder = HIRBuilder::new(cfg, self.mod_cache.clone()); + hir_builder.build_and_cache(VarName::from_static(""), mode)?; let hir = Linker::link(self.mod_cache.clone()); let codeobj = self.code_generator.emit(hir); log!(info "code object:\n{}", codeobj.code_info()); diff --git a/compiler/erg_compiler/context/initialize/mod.rs b/compiler/erg_compiler/context/initialize/mod.rs index 67e40645..57f4566c 100644 --- a/compiler/erg_compiler/context/initialize/mod.rs +++ b/compiler/erg_compiler/context/initialize/mod.rs @@ -1770,7 +1770,7 @@ impl Context { // ord.register_impl("__ge__", op_t, Const, Public); } - pub(crate) fn init_builtins() -> Self { + pub(crate) fn init_builtins(mod_cache: &SharedModuleCache) { // TODO: capacityを正確に把握する let mut ctx = Context::module("".into(), None, 40); ctx.init_builtin_funcs(); @@ -1780,15 +1780,15 @@ impl Context { ctx.init_builtin_traits(); ctx.init_builtin_classes(); ctx.init_builtin_patches(); - ctx + mod_cache.register(VarName::from_static(""), None, ctx); } - pub fn new_main_module(mod_cache: SharedModuleCache) -> Self { + pub fn new_module(mod_cache: SharedModuleCache) -> Self { Context::new( - "".into(), + "".into(), // TODO: ContextKind::Module, vec![], - Some(Context::init_builtins()), + None, Some(mod_cache), Context::TOP_LEVEL, ) diff --git a/compiler/erg_compiler/context/inquire.rs b/compiler/erg_compiler/context/inquire.rs index 94ae3b95..6b1cb3b2 100644 --- a/compiler/erg_compiler/context/inquire.rs +++ b/compiler/erg_compiler/context/inquire.rs @@ -206,7 +206,7 @@ impl Context { self.validate_visibility(ident, vi, namespace)?; Ok(vi.t()) } else { - if let Some(parent) = self.outer.as_ref() { + if let Some(parent) = self.get_outer().or_else(|| self.get_builtins()) { return parent.rec_get_var_t(ident, namespace); } Err(TyCheckError::no_var_error( @@ -267,7 +267,7 @@ impl Context { } } // TODO: dependent type widening - if let Some(parent) = self.outer.as_ref() { + if let Some(parent) = self.get_outer().or_else(|| self.get_builtins()) { parent.rec_get_attr_t(obj, ident, namespace) } else { Err(TyCheckError::no_attr_error( @@ -849,7 +849,7 @@ impl Context { if let Some(obj) = self.consts.get(name.inspect()) { Ok(obj.clone()) } else { - if let Some(parent) = self.outer.as_ref() { + if let Some(parent) = self.get_outer().or_else(|| self.get_builtins()) { return parent.get_const_local(name, namespace); } Err(TyCheckError::no_var_error( @@ -883,7 +883,7 @@ impl Context { } } // TODO: dependent type widening - if let Some(parent) = self.outer.as_ref() { + if let Some(parent) = self.get_outer().or_else(|| self.get_builtins()) { parent._get_const_attr(obj, name, namespace) } else { Err(TyCheckError::no_attr_error( @@ -912,7 +912,7 @@ impl Context { .inspect(); let len = most_similar_name.len(); if levenshtein(most_similar_name, name) >= len / 2 { - let outer = self.outer.as_ref()?; + let outer = self.get_outer().or_else(|| self.get_builtins())?; outer.get_similar_name(name) } else { Some(most_similar_name) @@ -1209,7 +1209,7 @@ impl Context { } else { vec![] }; - if let Some(outer) = &self.outer { + if let Some(outer) = self.get_outer().or_else(|| self.get_builtins()) { [current, outer.rec_get_trait_impls(name)].concat() } else { current @@ -1219,7 +1219,7 @@ impl Context { pub(crate) fn _rec_get_patch(&self, name: &VarName) -> Option<&Context> { if let Some(patch) = self.patches.get(name) { Some(patch) - } else if let Some(outer) = &self.outer { + } else if let Some(outer) = self.get_outer().or_else(|| self.get_builtins()) { outer._rec_get_patch(name) } else { None @@ -1243,7 +1243,7 @@ impl Context { return Some(val); } } - if let Some(outer) = &self.outer { + if let Some(outer) = self.get_outer().or_else(|| self.get_builtins()) { outer.rec_get_const_obj(name) } else { None @@ -1253,7 +1253,7 @@ impl Context { pub(crate) fn rec_get_const_param_defaults(&self, name: &str) -> Option<&Vec> { if let Some(impls) = self.const_param_defaults.get(name) { Some(impls) - } else if let Some(outer) = &self.outer { + } else if let Some(outer) = self.get_outer().or_else(|| self.get_builtins()) { outer.rec_get_const_param_defaults(name) } else { None @@ -1271,7 +1271,7 @@ impl Context { } else { None } - } else if let Some(outer) = &self.outer { + } else if let Some(outer) = self.get_outer().or_else(|| self.get_builtins()) { outer.rec_get_self_t() } else { None @@ -1281,7 +1281,7 @@ impl Context { fn rec_get_mono_type(&self, name: &str) -> Option<(&Type, &Context)> { if let Some((t, ctx)) = self.mono_types.get(name) { Some((t, ctx)) - } else if let Some(outer) = &self.outer { + } else if let Some(outer) = self.get_outer().or_else(|| self.get_builtins()) { outer.rec_get_mono_type(name) } else { None @@ -1291,7 +1291,7 @@ impl Context { fn rec_get_poly_type(&self, name: &str) -> Option<(&Type, &Context)> { if let Some((t, ctx)) = self.poly_types.get(name) { Some((t, ctx)) - } else if let Some(outer) = &self.outer { + } else if let Some(outer) = self.get_outer().or_else(|| self.get_builtins()) { outer.rec_get_poly_type(name) } else { None @@ -1302,6 +1302,7 @@ impl Context { if let Some((t, ctx)) = self.mono_types.get_mut(name) { Some((t, ctx)) } else if let Some(outer) = self.outer.as_mut() { + // builtins cannot be got as mutable outer.rec_get_mut_mono_type(name) } else { None @@ -1323,7 +1324,7 @@ impl Context { Some((t, ctx)) } else if let Some((t, ctx)) = self.poly_types.get(name) { Some((t, ctx)) - } else if let Some(outer) = &self.outer { + } else if let Some(outer) = self.get_outer().or_else(|| self.get_builtins()) { outer.rec_get_type(name) } else { None diff --git a/compiler/erg_compiler/context/mod.rs b/compiler/erg_compiler/context/mod.rs index 1ca3a86e..38abd27c 100644 --- a/compiler/erg_compiler/context/mod.rs +++ b/compiler/erg_compiler/context/mod.rs @@ -19,7 +19,6 @@ use std::option::Option; // conflicting to Type::Option use erg_common::astr::AtomicStr; use erg_common::dict::Dict; -use erg_common::error::Location; use erg_common::impl_display_from_debug; use erg_common::traits::{Locational, Stream}; use erg_common::vis::Visibility; @@ -554,6 +553,23 @@ impl Context { AtomicStr::arc(&self.name[..]) } + pub(crate) fn get_outer(&self) -> Option<&Context> { + self.outer.as_ref().map(|x| x.as_ref()) + } + + /// Returns None if self is ``. + /// This avoids infinite loops. + pub(crate) fn get_builtins(&self) -> Option<&Context> { + // builtins中で定義した型等はmod_cacheがNoneになっている + if &self.name[..] != "" { + self.mod_cache + .as_ref() + .map(|cache| cache.ref_ctx("").unwrap()) + } else { + None + } + } + pub(crate) fn grow( &mut self, name: &str, @@ -567,7 +583,7 @@ impl Context { }; log!(info "{}: current namespace: {name}", fn_name!()); self.outer = Some(Box::new(mem::take(self))); - self.mod_cache = self.outer.as_ref().unwrap().mod_cache.clone(); + self.mod_cache = self.get_outer().unwrap().mod_cache.clone(); self.name = name.into(); self.kind = kind; Ok(()) @@ -584,7 +600,7 @@ impl Context { &vi.t, )); } - if let Some(parent) = &mut self.outer { + if let Some(parent) = self.outer.as_mut() { let parent = mem::take(parent); let ctx = mem::take(self); *self = *parent; @@ -595,12 +611,14 @@ impl Context { Ok(ctx) } } else { - Err(TyCheckErrors::from(TyCheckError::checker_bug( - 0, - Location::Unknown, - fn_name!(), - line!(), - ))) + // toplevel + let ctx = mem::take(self); + log!(info "{}: current namespace: {}", fn_name!(), self.name); + if !uninited_errs.is_empty() { + Err(uninited_errs) + } else { + Ok(ctx) + } } } } diff --git a/compiler/erg_compiler/context/register.rs b/compiler/erg_compiler/context/register.rs index c4a0a83c..a35a6ea0 100644 --- a/compiler/erg_compiler/context/register.rs +++ b/compiler/erg_compiler/context/register.rs @@ -48,7 +48,7 @@ impl Context { return Some((name, vi)); } if is_const { - if let Some(outer) = &self.outer { + if let Some(outer) = self.get_outer().or_else(|| self.get_builtins()) { outer.registered_info(name, is_const) } else { None @@ -871,7 +871,7 @@ impl Context { ..ErgConfig::default() }; let mut hir_builder = HIRBuilder::new(cfg, mod_cache.clone()); - if let Err(errs) = hir_builder.build_and_cache(var_name.clone()) { + if let Err(errs) = hir_builder.build_and_cache(var_name.clone(), "exec") { errs.fmt_all_stderr(); } } diff --git a/compiler/erg_compiler/lower.rs b/compiler/erg_compiler/lower.rs index 89e9c6df..52c65c26 100644 --- a/compiler/erg_compiler/lower.rs +++ b/compiler/erg_compiler/lower.rs @@ -3,7 +3,7 @@ //! ASTLowerer(ASTからHIRへの変換器)を実装 use erg_common::astr::AtomicStr; -use erg_common::config::ErgConfig; +use erg_common::config::{ErgConfig, Input}; use erg_common::error::{Location, MultiErrorDisplay}; use erg_common::set::Set; use erg_common::traits::{Locational, Runnable, Stream}; @@ -81,8 +81,12 @@ impl Runnable for ASTLowerer { } fn eval(&mut self, src: String) -> Result { - let mut ast_builder = ASTBuilder::new(self.cfg.copy()); - let ast = ast_builder.build_with_str(src)?; + let cfg = ErgConfig { + input: Input::Str(src), + ..self.cfg.copy() + }; + let mut ast_builder = ASTBuilder::new(cfg); + let ast = ast_builder.build()?; let (hir, ..) = self.lower(ast, "eval").map_err(|errs| self.convert(errs))?; Ok(format!("{hir}")) } @@ -92,7 +96,7 @@ impl ASTLowerer { pub fn new_with_cache(cfg: ErgConfig, mod_cache: SharedModuleCache) -> Self { Self { cfg, - ctx: Context::new_main_module(mod_cache), + ctx: Context::new_module(mod_cache), errs: LowerErrors::empty(), warns: LowerWarnings::empty(), } diff --git a/compiler/erg_compiler/mod_cache.rs b/compiler/erg_compiler/mod_cache.rs index 8c508277..57aedd28 100644 --- a/compiler/erg_compiler/mod_cache.rs +++ b/compiler/erg_compiler/mod_cache.rs @@ -128,7 +128,9 @@ impl fmt::Display for SharedModuleCache { impl SharedModuleCache { pub fn new() -> Self { - Self(Shared::new(ModuleCache::new())) + let self_ = Self(Shared::new(ModuleCache::new())); + Context::init_builtins(&self_); + self_ } pub fn get_ctx(&self, name: &Q) -> Option> diff --git a/compiler/erg_compiler/tests/test.rs b/compiler/erg_compiler/tests/test.rs index fa286655..d3539589 100644 --- a/compiler/erg_compiler/tests/test.rs +++ b/compiler/erg_compiler/tests/test.rs @@ -3,14 +3,14 @@ use erg_compiler::mod_cache::SharedModuleCache; #[test] fn test_subtyping() -> Result<(), ()> { - let context = Context::new_main_module(SharedModuleCache::new()); + let context = Context::new_module(SharedModuleCache::new()); context.test_refinement_subtyping()?; Ok(()) } #[test] fn test_instantiation_and_generalization() -> Result<(), ()> { - let context = Context::new_main_module(SharedModuleCache::new()); + let context = Context::new_module(SharedModuleCache::new()); context.test_instantiation_and_generalization()?; Ok(()) } diff --git a/compiler/erg_parser/builder.rs b/compiler/erg_parser/builder.rs index bd7c24c9..68723b67 100644 --- a/compiler/erg_parser/builder.rs +++ b/compiler/erg_parser/builder.rs @@ -25,17 +25,7 @@ impl ASTBuilder { let module = desugarer.desugar(module); let mut desugarer = Desugarer::new(); let module = desugarer.desugar(module); - let ast = AST::new(Str::ever(self.runner.cfg().module), module); - Ok(ast) - } - - pub fn build_with_str(&mut self, src: String) -> Result { - let module = self.runner.parse_with_str(src)?; - let mut desugarer = Desugarer::new(); - let module = desugarer.desugar(module); - let mut desugarer = Desugarer::new(); - let module = desugarer.desugar(module); - let ast = AST::new(Str::ever(self.runner.cfg().module), module); + let ast = AST::new(Str::rc(self.runner.cfg().input.filename()), module); Ok(ast) } } diff --git a/compiler/erg_type/free.rs b/compiler/erg_type/free.rs index d5477352..4dea787a 100644 --- a/compiler/erg_type/free.rs +++ b/compiler/erg_type/free.rs @@ -337,6 +337,20 @@ impl FreeKind { _ => None, } } + + pub const fn linked(&self) -> Option<&T> { + match self { + Self::Linked(typ) => Some(typ), + _ => None, + } + } + + pub fn linked_mut(&mut self) -> Option<&mut T> { + match self { + Self::Linked(typ) => Some(typ), + _ => None, + } + } } #[derive(Debug, Clone, PartialEq, Eq, Hash)] diff --git a/compiler/erg_type/lib.rs b/compiler/erg_type/lib.rs index 2784a7df..453bcdd0 100644 --- a/compiler/erg_type/lib.rs +++ b/compiler/erg_type/lib.rs @@ -1104,6 +1104,10 @@ pub enum Type { Ellipsis, // これはクラスのほうで型推論用のマーカーではない Never, // {} Mono(Str), + ForeignMono { + path: Str, + name: Str, + }, /* Polymorphic types */ Ref(Box), RefMut { @@ -1174,6 +1178,10 @@ impl PartialEq for Type { | (Self::Ellipsis, Self::Ellipsis) | (Self::Never, Self::Never) => true, (Self::Mono(l), Self::Mono(r)) => l == r, + ( + Self::ForeignMono { path: lp, name: ln }, + Self::ForeignMono { path: rp, name: rn }, + ) => lp == rp && ln == rn, (Self::MonoQVar(l), Self::MonoQVar(r)) => l == r, (Self::Ref(l), Self::Ref(r)) => l == r, ( @@ -1269,6 +1277,7 @@ impl LimitedDisplay for Type { } match self { Self::Mono(name) => write!(f, "{name}"), + Self::ForeignMono { path, name } => write!(f, "{name}(of {path})"), Self::Ref(t) => { write!(f, "{}(", self.name())?; t.limited_fmt(f, limit - 1)?; @@ -1758,7 +1767,9 @@ impl Type { Self::Error => Str::ever("Error"), Self::Inf => Str::ever("Inf"), Self::NegInf => Str::ever("NegInf"), - Self::Mono(name) | Self::MonoQVar(name) => name.clone(), + Self::Mono(name) | Self::MonoQVar(name) | Self::ForeignMono { name, .. } => { + name.clone() + } Self::And(_, _) => Str::ever("And"), Self::Not(_, _) => Str::ever("Not"), Self::Or(_, _) => Str::ever("Or"), @@ -1991,16 +2002,22 @@ impl Type { pub fn self_t(&self) -> Option<&Type> { match self { - Self::FreeVar(fv) if fv.is_linked() => todo!("linked: {fv}"), + Self::FreeVar(fv) if fv.is_linked() => unsafe { fv.as_ptr().as_ref() } + .unwrap() + .linked() + .and_then(|t| t.self_t()), Self::Refinement(refine) => refine.t.self_t(), Self::Subr(subr) => subr.self_t(), _ => None, } } - pub const fn non_default_params(&self) -> Option<&Vec> { + pub fn non_default_params(&self) -> Option<&Vec> { match self { - Self::FreeVar(_) => panic!("fv"), + Self::FreeVar(fv) if fv.is_linked() => unsafe { fv.as_ptr().as_ref() } + .unwrap() + .linked() + .and_then(|t| t.non_default_params()), Self::Refinement(refine) => refine.t.non_default_params(), Self::Subr(SubrType { non_default_params, .. @@ -2012,7 +2029,10 @@ impl Type { pub fn var_args(&self) -> Option<&ParamTy> { match self { - Self::FreeVar(_) => panic!("fv"), + Self::FreeVar(fv) if fv.is_linked() => unsafe { fv.as_ptr().as_ref() } + .unwrap() + .linked() + .and_then(|t| t.var_args()), Self::Refinement(refine) => refine.t.var_args(), Self::Subr(SubrType { var_params: var_args, @@ -2023,18 +2043,24 @@ impl Type { } } - pub const fn default_params(&self) -> Option<&Vec> { + pub fn default_params(&self) -> Option<&Vec> { match self { - Self::FreeVar(_) => panic!("fv"), + Self::FreeVar(fv) if fv.is_linked() => unsafe { fv.as_ptr().as_ref() } + .unwrap() + .linked() + .and_then(|t| t.default_params()), Self::Refinement(refine) => refine.t.default_params(), Self::Subr(SubrType { default_params, .. }) => Some(default_params), _ => None, } } - pub const fn return_t(&self) -> Option<&Type> { + pub fn return_t(&self) -> Option<&Type> { match self { - Self::FreeVar(_) => panic!("fv"), + Self::FreeVar(fv) if fv.is_linked() => unsafe { fv.as_ptr().as_ref() } + .unwrap() + .linked() + .and_then(|t| t.return_t()), Self::Refinement(refine) => refine.t.return_t(), Self::Subr(SubrType { return_t, .. }) | Self::Callable { return_t, .. } => { Some(return_t) @@ -2045,7 +2071,10 @@ impl Type { pub fn mut_return_t(&mut self) -> Option<&mut Type> { match self { - Self::FreeVar(_) => panic!("fv"), + Self::FreeVar(fv) if fv.is_linked() => unsafe { fv.as_ptr().as_mut() } + .unwrap() + .linked_mut() + .and_then(|t| t.mut_return_t()), Self::Refinement(refine) => refine.t.mut_return_t(), Self::Subr(SubrType { return_t, .. }) | Self::Callable { return_t, .. } => { Some(return_t)