Fixed to register <builtins> to mod_cache

This commit is contained in:
Shunsuke Shibayama 2022-09-22 10:37:39 +09:00
parent f815a7df7b
commit 6f3f00a369
13 changed files with 133 additions and 83 deletions

View file

@ -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("<module>");
self.mod_cache.register(name, Some(hir), ctx);
self.mod_cache.register(var_name, Some(hir), ctx);
Ok(())
}
}

View file

@ -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<String, TyCheckErrors> {
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())
}

View file

@ -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<CodeObj, CompileErrors> {
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("<module>"), mode)?;
let hir = Linker::link(self.mod_cache.clone());
let codeobj = self.code_generator.emit(hir);
log!(info "code object:\n{}", codeobj.code_info());

View file

@ -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("<builtins>".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("<builtins>"), None, ctx);
}
pub fn new_main_module(mod_cache: SharedModuleCache) -> Self {
pub fn new_module(mod_cache: SharedModuleCache) -> Self {
Context::new(
"<module>".into(),
"<module>".into(), // TODO:
ContextKind::Module,
vec![],
Some(Context::init_builtins()),
None,
Some(mod_cache),
Context::TOP_LEVEL,
)

View file

@ -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<ConstTemplate>> {
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

View file

@ -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 `<builtins>`.
/// This avoids infinite loops.
pub(crate) fn get_builtins(&self) -> Option<&Context> {
// builtins中で定義した型等はmod_cacheがNoneになっている
if &self.name[..] != "<builtins>" {
self.mod_cache
.as_ref()
.map(|cache| cache.ref_ctx("<builtins>").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)
}
}
}
}

View file

@ -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();
}
}

View file

@ -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<String, CompileErrors> {
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(),
}

View file

@ -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<Q: Eq + Hash + ?Sized>(&self, name: &Q) -> Option<Rc<Context>>

View file

@ -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(())
}

View file

@ -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<AST, ParserRunnerErrors> {
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)
}
}

View file

@ -337,6 +337,20 @@ impl<T> FreeKind<T> {
_ => 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)]

View file

@ -1104,6 +1104,10 @@ pub enum Type {
Ellipsis, // これはクラスのほうで型推論用のマーカーではない
Never, // {}
Mono(Str),
ForeignMono {
path: Str,
name: Str,
},
/* Polymorphic types */
Ref(Box<Type>),
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<ParamTy>> {
pub fn non_default_params(&self) -> Option<&Vec<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.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<ParamTy>> {
pub fn default_params(&self) -> Option<&Vec<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.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)