Add builder & linker

This commit is contained in:
Shunsuke Shibayama 2022-09-21 01:21:17 +09:00
parent 671fbee518
commit 201b313cd2
19 changed files with 241 additions and 109 deletions

View file

@ -126,6 +126,7 @@ pub struct ErgConfig {
pub py_server_timeout: u64, pub py_server_timeout: u64,
pub quiet_startup: bool, pub quiet_startup: bool,
pub input: Input, pub input: Input,
/// module name to be executed
pub module: &'static str, pub module: &'static str,
/// verbosity level for system messages. /// verbosity level for system messages.
/// * 0: display errors /// * 0: display errors

View file

@ -0,0 +1,57 @@
use erg_common::config::{ErgConfig, Input};
use erg_common::traits::Stream;
use erg_parser::ast::VarName;
use erg_parser::builder::ASTBuilder;
use crate::error::{CompileError, CompileErrors, TyCheckErrors};
// use crate::hir::HIR;
use crate::check::Checker;
use crate::mod_cache::SharedModuleCache;
#[derive(Debug)]
pub struct HIRBuilder {
checker: Checker,
mod_cache: SharedModuleCache,
}
impl HIRBuilder {
fn convert(&self, errs: TyCheckErrors) -> CompileErrors {
errs.into_iter()
.map(|e| CompileError::new(e.core, self.checker.cfg.input.clone(), e.caused_by))
.collect::<Vec<_>>()
.into()
}
pub fn new(cfg: ErgConfig, mod_cache: SharedModuleCache) -> Self {
Self {
checker: Checker::new(cfg, mod_cache.clone()),
mod_cache,
}
}
pub fn build_and_cache(&mut self, var_name: VarName) -> Result<(), CompileErrors> {
let mut ast_builder = ASTBuilder::new(self.checker.cfg.copy());
let ast = ast_builder.build()?;
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 (hir, ctx) = self
.checker
.check(ast, mode)
.map_err(|errs| self.convert(errs))?;
let name = VarName::from_static("<module>");
self.mod_cache.register(name, Some(hir), ctx);
Ok(())
}
}

View file

@ -5,36 +5,61 @@ use erg_common::traits::Runnable;
use erg_parser::ast::AST; use erg_parser::ast::AST;
use erg_parser::builder::ASTBuilder; use erg_parser::builder::ASTBuilder;
use crate::context::Context;
use crate::effectcheck::SideEffectChecker; use crate::effectcheck::SideEffectChecker;
use crate::error::{TyCheckError, TyCheckErrors}; use crate::error::{TyCheckError, TyCheckErrors};
use crate::hir::HIR; use crate::hir::HIR;
use crate::lower::ASTLowerer; use crate::lower::ASTLowerer;
use crate::mod_cache::SharedModuleCache;
use crate::ownercheck::OwnershipChecker; use crate::ownercheck::OwnershipChecker;
/// Summarize lowering, side-effect checking, and ownership checking /// Summarize lowering, side-effect checking, and ownership checking
#[derive(Debug)] #[derive(Debug)]
pub struct Checker { pub struct Checker {
cfg: ErgConfig, pub cfg: ErgConfig,
lowerer: ASTLowerer, lowerer: ASTLowerer,
ownership_checker: OwnershipChecker, ownership_checker: OwnershipChecker,
} }
impl Runnable for Checker { impl Checker {
pub fn new(cfg: ErgConfig, mod_cache: SharedModuleCache) -> Self {
Self {
cfg,
lowerer: ASTLowerer::new(mod_cache),
ownership_checker: OwnershipChecker::new(),
}
}
pub fn check(&mut self, ast: AST, mode: &str) -> Result<(HIR, Context), TyCheckErrors> {
let (hir, ctx, warns) = self.lowerer.lower(ast, mode)?;
if self.cfg.verbose >= 2 {
warns.fmt_all_stderr();
}
let effect_checker = SideEffectChecker::new();
let hir = effect_checker.check(hir)?;
let hir = self.ownership_checker.check(hir)?;
Ok((hir, ctx))
}
}
pub struct CheckerRunner {
checker: Checker,
}
impl Runnable for CheckerRunner {
type Err = TyCheckError; type Err = TyCheckError;
type Errs = TyCheckErrors; type Errs = TyCheckErrors;
const NAME: &'static str = "Erg type-checker"; const NAME: &'static str = "Erg type-checker";
fn new(cfg: ErgConfig) -> Self { fn new(cfg: ErgConfig) -> Self {
Self { Self {
ownership_checker: OwnershipChecker::new(), checker: Checker::new(cfg, SharedModuleCache::new()),
lowerer: ASTLowerer::new(),
cfg,
} }
} }
#[inline] #[inline]
fn cfg(&self) -> &ErgConfig { fn cfg(&self) -> &ErgConfig {
&self.cfg &self.checker.cfg
} }
#[inline] #[inline]
@ -43,30 +68,17 @@ impl Runnable for Checker {
fn clear(&mut self) {} fn clear(&mut self) {}
fn exec(&mut self) -> Result<(), Self::Errs> { fn exec(&mut self) -> Result<(), Self::Errs> {
let mut builder = ASTBuilder::new(self.cfg.copy()); let mut builder = ASTBuilder::new(self.cfg().copy());
let ast = builder.build()?; let ast = builder.build()?;
let hir = self.check(ast, "exec")?; let (hir, _) = self.checker.check(ast, "exec")?;
println!("{hir}"); println!("{hir}");
Ok(()) Ok(())
} }
fn eval(&mut self, src: String) -> Result<String, TyCheckErrors> { fn eval(&mut self, src: String) -> Result<String, TyCheckErrors> {
let mut builder = ASTBuilder::new(self.cfg.copy()); let mut builder = ASTBuilder::new(self.cfg().copy());
let ast = builder.build_with_input(src)?; let ast = builder.build_with_str(src)?;
let hir = self.check(ast, "eval")?; let (hir, _) = self.checker.check(ast, "eval")?;
Ok(hir.to_string()) Ok(hir.to_string())
} }
} }
impl Checker {
pub fn check(&mut self, ast: AST, mode: &str) -> Result<HIR, TyCheckErrors> {
let (hir, warns) = self.lowerer.lower(ast, mode)?;
if self.cfg.verbose >= 2 {
warns.fmt_all_stderr();
}
let effect_checker = SideEffectChecker::new();
let hir = effect_checker.check(hir)?;
let hir = self.ownership_checker.check(hir)?;
Ok(hir)
}
}

View file

@ -3,16 +3,16 @@
//! コンパイラーを定義する //! コンパイラーを定義する
use std::path::Path; use std::path::Path;
use erg_common::config::{ErgConfig, Input}; use erg_common::config::ErgConfig;
use erg_common::log; use erg_common::log;
use erg_common::traits::{Runnable, Stream}; use erg_common::traits::{Runnable, Stream};
use erg_type::codeobj::CodeObj; use erg_type::codeobj::CodeObj;
use erg_parser::builder::ASTBuilder; use crate::builder::HIRBuilder;
use crate::checker::Checker;
use crate::codegen::CodeGenerator; use crate::codegen::CodeGenerator;
use crate::error::{CompileError, CompileErrors, TyCheckErrors}; use crate::error::{CompileError, CompileErrors};
use crate::link::Linker;
use crate::mod_cache::SharedModuleCache;
/// * registered as global -> Global /// * registered as global -> Global
/// * defined in the toplevel scope (and called in the inner scope) -> Global /// * defined in the toplevel scope (and called in the inner scope) -> Global
@ -91,7 +91,7 @@ impl AccessKind {
#[derive(Debug)] #[derive(Debug)]
pub struct Compiler { pub struct Compiler {
cfg: ErgConfig, cfg: ErgConfig,
checker: Checker, mod_cache: SharedModuleCache,
code_generator: CodeGenerator, code_generator: CodeGenerator,
} }
@ -101,9 +101,10 @@ impl Runnable for Compiler {
const NAME: &'static str = "Erg compiler"; const NAME: &'static str = "Erg compiler";
fn new(cfg: ErgConfig) -> Self { fn new(cfg: ErgConfig) -> Self {
let mod_cache = SharedModuleCache::new();
Self { Self {
checker: Checker::new(cfg.copy()),
code_generator: CodeGenerator::new(cfg.copy()), code_generator: CodeGenerator::new(cfg.copy()),
mod_cache,
cfg, cfg,
} }
} }
@ -133,13 +134,6 @@ impl Runnable for Compiler {
} }
impl Compiler { impl Compiler {
fn convert(&self, errs: TyCheckErrors) -> CompileErrors {
errs.into_iter()
.map(|e| CompileError::new(e.core, self.input().clone(), e.caused_by))
.collect::<Vec<_>>()
.into()
}
pub fn compile_and_dump_as_pyc<P: AsRef<Path>>( pub fn compile_and_dump_as_pyc<P: AsRef<Path>>(
&mut self, &mut self,
src: String, src: String,
@ -154,14 +148,9 @@ impl Compiler {
pub fn compile(&mut self, src: String, mode: &str) -> Result<CodeObj, CompileErrors> { pub fn compile(&mut self, src: String, mode: &str) -> Result<CodeObj, CompileErrors> {
log!(info "the compiling process has started."); log!(info "the compiling process has started.");
let mut cfg = self.cfg.copy(); let mut hir_builder = HIRBuilder::new(self.cfg.copy(), self.mod_cache.clone());
cfg.input = Input::Str(src); hir_builder.build_and_cache_main(src, mode)?;
let mut ast_builder = ASTBuilder::new(cfg); let hir = Linker::link(self.mod_cache.clone());
let ast = ast_builder.build()?;
let hir = self
.checker
.check(ast, mode)
.map_err(|errs| self.convert(errs))?;
let codeobj = self.code_generator.emit(hir); let codeobj = self.code_generator.emit(hir);
log!(info "code object:\n{}", codeobj.code_info()); log!(info "code object:\n{}", codeobj.code_info());
log!( log!(

View file

@ -1783,13 +1783,13 @@ impl Context {
ctx ctx
} }
pub fn new_main_module() -> Self { pub fn new_main_module(mod_cache: SharedModuleCache) -> Self {
Context::new( Context::new(
"<module>".into(), "<module>".into(),
ContextKind::Module, ContextKind::Module,
vec![], vec![],
Some(Context::init_builtins()), Some(Context::init_builtins()),
Some(SharedModuleCache::new()), Some(mod_cache),
Context::TOP_LEVEL, Context::TOP_LEVEL,
) )
} }

View file

@ -238,6 +238,7 @@ impl From<DefKind> for ContextKind {
DefKind::Class | DefKind::Inherit => Self::Class, DefKind::Class | DefKind::Inherit => Self::Class,
DefKind::Trait | DefKind::Subsume => Self::Trait, DefKind::Trait | DefKind::Subsume => Self::Trait,
DefKind::StructuralTrait => Self::StructuralTrait, DefKind::StructuralTrait => Self::StructuralTrait,
DefKind::Module => Self::Module,
DefKind::Other => Self::Instant, DefKind::Other => Self::Instant,
} }
} }

View file

@ -1,5 +1,7 @@
use std::option::Option; // conflicting to Type::Option use std::option::Option; // conflicting to Type::Option
use erg_common::config::{ErgConfig, Input};
use erg_common::error::MultiErrorDisplay;
use erg_common::traits::{Locational, Stream}; use erg_common::traits::{Locational, Stream};
use erg_common::vis::Visibility; use erg_common::vis::Visibility;
use erg_common::Str; use erg_common::Str;
@ -14,11 +16,12 @@ use erg_type::value::{GenTypeObj, TypeKind, TypeObj, ValueObj};
use erg_type::{HasType, ParamTy, SubrType, TyBound, Type}; use erg_type::{HasType, ParamTy, SubrType, TyBound, Type};
use Type::*; use Type::*;
use crate::builder::HIRBuilder;
use crate::context::{ClassDefType, Context, DefaultInfo, RegistrationMode, TraitInstance}; use crate::context::{ClassDefType, Context, DefaultInfo, RegistrationMode, TraitInstance};
use crate::error::readable_name; use crate::error::readable_name;
use crate::error::{TyCheckError, TyCheckResult}; use crate::error::{TyCheckError, TyCheckResult};
use crate::hir; use crate::hir;
use crate::mod_cache::ModuleEntry; use crate::mod_cache::SharedModuleCache;
use crate::varinfo::{Mutability, ParamIdx, VarInfo, VarKind}; use crate::varinfo::{Mutability, ParamIdx, VarInfo, VarKind};
use Mutability::*; use Mutability::*;
use RegistrationMode::*; use RegistrationMode::*;
@ -763,56 +766,55 @@ impl Context {
match mod_name { match mod_name {
hir::Expr::Lit(lit) => { hir::Expr::Lit(lit) => {
if self.subtype_of(&lit.value.class(), &Str) { if self.subtype_of(&lit.value.class(), &Str) {
let name = enum_unwrap!(lit.value.clone(), ValueObj::Str); let __name__ = enum_unwrap!(lit.value.clone(), ValueObj::Str);
if let Some(mod_cache) = self.mod_cache.as_mut() { if let Some(mod_cache) = self.mod_cache.as_ref() {
match &name[..] { match &__name__[..] {
"importlib" => { "importlib" => {
mod_cache.register( mod_cache.register(
var_name.clone(), var_name.clone(),
ModuleEntry::builtin(Self::init_py_importlib_mod()), None,
Self::init_py_importlib_mod(),
); );
} }
"io" => { "io" => {
mod_cache.register( mod_cache.register(var_name.clone(), None, Self::init_py_io_mod());
var_name.clone(),
ModuleEntry::builtin(Self::init_py_io_mod()),
);
} }
"math" => { "math" => {
mod_cache.register( mod_cache.register(
var_name.clone(), var_name.clone(),
ModuleEntry::builtin(Self::init_py_math_mod()), None,
Self::init_py_math_mod(),
); );
} }
"random" => { "random" => {
mod_cache.register( mod_cache.register(
var_name.clone(), var_name.clone(),
ModuleEntry::builtin(Self::init_py_random_mod()), None,
Self::init_py_random_mod(),
); );
} }
"socket" => { "socket" => {
mod_cache.register( mod_cache.register(
var_name.clone(), var_name.clone(),
ModuleEntry::builtin(Self::init_py_socket_mod()), None,
Self::init_py_socket_mod(),
); );
} }
"sys" => { "sys" => {
mod_cache.register( mod_cache.register(var_name.clone(), None, Self::init_py_sys_mod());
var_name.clone(),
ModuleEntry::builtin(Self::init_py_sys_mod()),
);
} }
"time" => { "time" => {
mod_cache.register( mod_cache.register(
var_name.clone(), var_name.clone(),
ModuleEntry::builtin(Self::init_py_time_mod()), None,
Self::init_py_time_mod(),
); );
} }
other => todo!("importing {other}"), _ => self.import_user_module(var_name, __name__, mod_cache),
} }
} else { } else {
// maybe unreachable // maybe unreachable
todo!("importing {name} in the builtin module") todo!("importing {__name__} in the builtin module")
} }
} else { } else {
return Err(TyCheckError::type_mismatch_error( return Err(TyCheckError::type_mismatch_error(
@ -839,6 +841,17 @@ impl Context {
Ok(()) Ok(())
} }
fn import_user_module(&self, var_name: &VarName, __name__: Str, mod_cache: &SharedModuleCache) {
let cfg = ErgConfig {
input: Input::File(format!("{__name__}.er")),
..ErgConfig::default()
};
let mut hir_builder = HIRBuilder::new(cfg, mod_cache.clone());
if let Err(errs) = hir_builder.build_and_cache(var_name.clone()) {
errs.fmt_all_stderr();
}
}
pub(crate) fn _push_subtype_bound(&mut self, sub: Type, sup: Type) { pub(crate) fn _push_subtype_bound(&mut self, sub: Type, sup: Type) {
self.bounds.push(TyBound::subtype_of(sub, sup)); self.bounds.push(TyBound::subtype_of(sub, sup));
} }

View file

@ -1332,6 +1332,7 @@ impl Def {
DefKind::Other DefKind::Other
} }
} }
Some("import") => DefKind::Module,
_ => DefKind::Other, _ => DefKind::Other,
}, },
_ => DefKind::Other, _ => DefKind::Other,

View file

@ -3,7 +3,8 @@
extern crate erg_common; extern crate erg_common;
pub extern crate erg_parser; pub extern crate erg_parser;
mod checker; mod builder;
mod check;
mod compile; mod compile;
pub use compile::*; pub use compile::*;
mod codegen; mod codegen;
@ -11,8 +12,10 @@ pub mod context;
pub mod effectcheck; pub mod effectcheck;
pub mod error; pub mod error;
pub mod hir; pub mod hir;
pub mod link;
pub mod lower; pub mod lower;
pub mod mod_cache; pub mod mod_cache;
// pub mod name_resolve;
pub mod optimize; pub mod optimize;
pub mod ownercheck; pub mod ownercheck;
pub mod varinfo; pub mod varinfo;

View file

@ -0,0 +1,19 @@
use erg_common::traits::Stream;
use crate::hir::{Expr, HIR};
use crate::mod_cache::SharedModuleCache;
pub struct Linker {}
impl Linker {
pub fn link(mod_cache: SharedModuleCache) -> HIR {
let mut main_mod_hir = mod_cache.remove("<module>").unwrap().hir.unwrap();
for chunk in main_mod_hir.module.iter_mut() {
match chunk {
Expr::Def(def) if def.def_kind().is_module() => {}
_ => {}
}
}
main_mod_hir
}
}

View file

@ -27,6 +27,7 @@ use crate::error::{
}; };
use crate::hir; use crate::hir;
use crate::hir::HIR; use crate::hir::HIR;
use crate::mod_cache::SharedModuleCache;
use crate::varinfo::VarKind; use crate::varinfo::VarKind;
use Visibility::*; use Visibility::*;
@ -48,7 +49,7 @@ impl Runnable for ASTLowererRunner {
fn new(cfg: ErgConfig) -> Self { fn new(cfg: ErgConfig) -> Self {
Self { Self {
cfg, cfg,
lowerer: ASTLowerer::new(), lowerer: ASTLowerer::new(SharedModuleCache::new()),
} }
} }
@ -63,7 +64,7 @@ impl Runnable for ASTLowererRunner {
fn exec(&mut self) -> Result<(), Self::Errs> { fn exec(&mut self) -> Result<(), Self::Errs> {
let mut ast_builder = ASTBuilder::new(self.cfg.copy()); let mut ast_builder = ASTBuilder::new(self.cfg.copy());
let ast = ast_builder.build()?; let ast = ast_builder.build()?;
let (hir, warns) = self let (hir, _, warns) = self
.lowerer .lowerer
.lower(ast, "exec") .lower(ast, "exec")
.map_err(|errs| self.convert(errs))?; .map_err(|errs| self.convert(errs))?;
@ -77,8 +78,8 @@ impl Runnable for ASTLowererRunner {
fn eval(&mut self, src: String) -> Result<String, CompileErrors> { fn eval(&mut self, src: String) -> Result<String, CompileErrors> {
let mut ast_builder = ASTBuilder::new(self.cfg.copy()); let mut ast_builder = ASTBuilder::new(self.cfg.copy());
let ast = ast_builder.build_with_input(src)?; let ast = ast_builder.build_with_str(src)?;
let (hir, _) = self let (hir, ..) = self
.lowerer .lowerer
.lower(ast, "eval") .lower(ast, "eval")
.map_err(|errs| self.convert(errs))?; .map_err(|errs| self.convert(errs))?;
@ -105,14 +106,14 @@ pub struct ASTLowerer {
impl Default for ASTLowerer { impl Default for ASTLowerer {
fn default() -> Self { fn default() -> Self {
Self::new() Self::new(SharedModuleCache::new())
} }
} }
impl ASTLowerer { impl ASTLowerer {
pub fn new() -> Self { pub fn new(mod_cache: SharedModuleCache) -> Self {
Self { Self {
ctx: Context::new_main_module(), ctx: Context::new_main_module(mod_cache),
errs: LowerErrors::empty(), errs: LowerErrors::empty(),
warns: LowerWarnings::empty(), warns: LowerWarnings::empty(),
} }
@ -1008,7 +1009,11 @@ impl ASTLowerer {
Ok(hir::Block::new(hir_block)) Ok(hir::Block::new(hir_block))
} }
pub fn lower(&mut self, ast: AST, mode: &str) -> Result<(HIR, LowerWarnings), LowerErrors> { pub fn lower(
&mut self,
ast: AST,
mode: &str,
) -> Result<(HIR, Context, LowerWarnings), LowerErrors> {
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.");
let mut module = hir::Module::with_capacity(ast.module.len()); let mut module = hir::Module::with_capacity(ast.module.len());
@ -1035,7 +1040,11 @@ impl ASTLowerer {
if self.errs.is_empty() { if self.errs.is_empty() {
log!(info "HIR:\n{hir}"); log!(info "HIR:\n{hir}");
log!(info "the AST lowering process has completed."); log!(info "the AST lowering process has completed.");
Ok((hir, LowerWarnings::from(self.warns.take_all()))) Ok((
hir,
self.ctx.pop()?,
LowerWarnings::from(self.warns.take_all()),
))
} else { } else {
log!(err "the AST lowering process has failed."); log!(err "the AST lowering process has failed.");
Err(LowerErrors::from(self.errs.take_all())) Err(LowerErrors::from(self.errs.take_all()))

View file

@ -27,24 +27,24 @@ impl ModId {
#[derive(Debug)] #[derive(Debug)]
pub struct ModuleEntry { pub struct ModuleEntry {
_id: ModId, // builtin == 0, __main__ == 1 id: ModId, // builtin == 0, __main__ == 1
_hir: Option<HIR>, pub hir: Option<HIR>,
ctx: Rc<Context>, ctx: Rc<Context>,
} }
impl ModuleEntry { impl ModuleEntry {
pub fn new(id: ModId, hir: Option<HIR>, ctx: Context) -> Self { pub fn new(id: ModId, hir: Option<HIR>, ctx: Context) -> Self {
Self { Self {
_id: id, id,
_hir: hir, hir,
ctx: Rc::new(ctx), ctx: Rc::new(ctx),
} }
} }
pub fn builtin(ctx: Context) -> Self { pub fn builtin(ctx: Context) -> Self {
Self { Self {
_id: ModId::builtin(), id: ModId::builtin(),
_hir: None, hir: None,
ctx: Rc::new(ctx), ctx: Rc::new(ctx),
} }
} }
@ -53,11 +53,15 @@ impl ModuleEntry {
#[derive(Debug, Default)] #[derive(Debug, Default)]
pub struct ModuleCache { pub struct ModuleCache {
cache: Dict<VarName, ModuleEntry>, cache: Dict<VarName, ModuleEntry>,
last_id: usize,
} }
impl ModuleCache { impl ModuleCache {
pub fn new() -> Self { pub fn new() -> Self {
Self { cache: Dict::new() } Self {
cache: Dict::new(),
last_id: 0,
}
} }
pub fn get<Q: Eq + Hash + ?Sized>(&self, name: &Q) -> Option<&ModuleEntry> pub fn get<Q: Eq + Hash + ?Sized>(&self, name: &Q) -> Option<&ModuleEntry>
@ -67,7 +71,10 @@ impl ModuleCache {
self.cache.get(name) self.cache.get(name)
} }
pub fn register(&mut self, name: VarName, entry: ModuleEntry) { pub fn register(&mut self, name: VarName, hir: Option<HIR>, ctx: Context) {
self.last_id += 1;
let id = ModId::new(self.last_id);
let entry = ModuleEntry::new(id, hir, ctx);
self.cache.insert(name, entry); self.cache.insert(name, entry);
} }
@ -77,6 +84,20 @@ impl ModuleCache {
{ {
self.cache.remove(name) self.cache.remove(name)
} }
pub fn remove_by_id(&mut self, id: ModId) -> Option<ModuleEntry> {
if let Some(name) = self.cache.iter().find_map(|(name, ent)| {
if ent.id == id {
Some(name.clone())
} else {
None
}
}) {
self.remove(&name)
} else {
None
}
}
} }
#[derive(Debug, Clone, Default)] #[derive(Debug, Clone, Default)]
@ -102,14 +123,18 @@ impl SharedModuleCache {
ref_.get(name).map(|entry| entry.ctx.as_ref()) ref_.get(name).map(|entry| entry.ctx.as_ref())
} }
pub fn register(&self, name: VarName, entry: ModuleEntry) { pub fn register(&self, name: VarName, hir: Option<HIR>, ctx: Context) {
self.0.borrow_mut().register(name, entry); self.0.borrow_mut().register(name, hir, ctx);
} }
pub fn remove<Q: Eq + Hash + ?Sized>(&mut self, name: &Q) -> Option<ModuleEntry> pub fn remove<Q: Eq + Hash + ?Sized>(&self, name: &Q) -> Option<ModuleEntry>
where where
VarName: Borrow<Q>, VarName: Borrow<Q>,
{ {
self.0.borrow_mut().remove(name) self.0.borrow_mut().remove(name)
} }
pub fn remove_by_id(&self, id: ModId) -> Option<ModuleEntry> {
self.0.borrow_mut().remove_by_id(id)
}
} }

View file

@ -1,15 +1,16 @@
use erg_compiler::context::Context; use erg_compiler::context::Context;
use erg_compiler::mod_cache::SharedModuleCache;
#[test] #[test]
fn test_subtyping() -> Result<(), ()> { fn test_subtyping() -> Result<(), ()> {
let context = Context::new_main_module(); let context = Context::new_main_module(SharedModuleCache::new());
context.test_refinement_subtyping()?; context.test_refinement_subtyping()?;
Ok(()) Ok(())
} }
#[test] #[test]
fn test_instantiation_and_generalization() -> Result<(), ()> { fn test_instantiation_and_generalization() -> Result<(), ()> {
let context = Context::new_main_module(); let context = Context::new_main_module(SharedModuleCache::new());
context.test_instantiation_and_generalization()?; context.test_instantiation_and_generalization()?;
Ok(()) Ok(())
} }

View file

@ -2839,6 +2839,7 @@ pub enum DefKind {
Trait, Trait,
Subsume, Subsume,
StructuralTrait, StructuralTrait,
Module,
Other, Other,
} }
@ -2846,6 +2847,10 @@ impl DefKind {
pub const fn is_trait(&self) -> bool { pub const fn is_trait(&self) -> bool {
matches!(self, Self::Trait | Self::Subsume | Self::StructuralTrait) matches!(self, Self::Trait | Self::Subsume | Self::StructuralTrait)
} }
pub fn is_module(&self) -> bool {
matches!(self, Self::Module)
}
} }
#[derive(Clone, Debug, PartialEq, Eq, Hash)] #[derive(Clone, Debug, PartialEq, Eq, Hash)]

View file

@ -6,9 +6,8 @@ use crate::ast::AST;
use crate::desugar::Desugarer; use crate::desugar::Desugarer;
use crate::error::ParserRunnerErrors; use crate::error::ParserRunnerErrors;
use crate::parse::ParserRunner; use crate::parse::ParserRunner;
use crate::reorder::Reorderer;
/// Summarize parsing, desugaring, and reordering /// Summarize parsing and desugaring
pub struct ASTBuilder { pub struct ASTBuilder {
runner: ParserRunner, runner: ParserRunner,
} }
@ -27,24 +26,16 @@ impl ASTBuilder {
let mut desugarer = Desugarer::new(); let mut desugarer = Desugarer::new();
let module = desugarer.desugar(module); let module = desugarer.desugar(module);
let ast = AST::new(Str::ever(self.runner.cfg().module), module); let ast = AST::new(Str::ever(self.runner.cfg().module), module);
let reorderer = Reorderer::new();
let ast = reorderer
.reorder(ast)
.map_err(|errs| ParserRunnerErrors::convert(self.runner.input(), errs))?;
Ok(ast) Ok(ast)
} }
pub fn build_with_input(&mut self, src: String) -> Result<AST, ParserRunnerErrors> { pub fn build_with_str(&mut self, src: String) -> Result<AST, ParserRunnerErrors> {
let module = self.runner.parse_with_input(src)?; let module = self.runner.parse_with_str(src)?;
let mut desugarer = Desugarer::new(); let mut desugarer = Desugarer::new();
let module = desugarer.desugar(module); let module = desugarer.desugar(module);
let mut desugarer = Desugarer::new(); let mut desugarer = Desugarer::new();
let module = desugarer.desugar(module); let module = desugarer.desugar(module);
let ast = AST::new(Str::ever(self.runner.cfg().module), module); let ast = AST::new(Str::ever(self.runner.cfg().module), module);
let reorderer = Reorderer::new();
let ast = reorderer
.reorder(ast)
.map_err(|errs| ParserRunnerErrors::convert(self.runner.input(), errs))?;
Ok(ast) Ok(ast)
} }
} }

View file

@ -9,7 +9,6 @@ pub mod desugar;
pub mod error; pub mod error;
pub mod lex; pub mod lex;
pub mod parse; pub mod parse;
pub mod reorder;
pub mod token; pub mod token;
pub use parse::{Parser, ParserRunner}; pub use parse::{Parser, ParserRunner};

View file

@ -193,7 +193,7 @@ impl Runnable for ParserRunner {
} }
fn eval(&mut self, src: String) -> Result<String, ParserRunnerErrors> { fn eval(&mut self, src: String) -> Result<String, ParserRunnerErrors> {
let ast = self.parse_with_input(src)?; let ast = self.parse_with_str(src)?;
Ok(format!("{ast}")) Ok(format!("{ast}"))
} }
} }
@ -212,7 +212,6 @@ impl ParserRunner {
self.parse_token_stream(ts) self.parse_token_stream(ts)
} }
/// Parses with default configuration
pub fn parse_with_default_config(input: Input) -> Result<Module, ParserRunnerErrors> { pub fn parse_with_default_config(input: Input) -> Result<Module, ParserRunnerErrors> {
let cfg = ErgConfig { let cfg = ErgConfig {
input, input,
@ -222,7 +221,7 @@ impl ParserRunner {
self_.parse() self_.parse()
} }
pub fn parse_with_input(&mut self, src: String) -> Result<Module, ParserRunnerErrors> { pub fn parse_with_str(&mut self, src: String) -> Result<Module, ParserRunnerErrors> {
let ts = Lexer::new(Input::Str(src)) let ts = Lexer::new(Input::Str(src))
.lex() .lex()
.map_err(|errs| ParserRunnerErrors::convert(self.input(), errs))?; .map_err(|errs| ParserRunnerErrors::convert(self.input(), errs))?;

View file

@ -16,15 +16,22 @@
* `Parser``Lexer` と同様に `Parser::new``Parser::from_str` の 2 つのコンストラクタを持ち、`Parser::parse``AST` を返す。 * `Parser``Lexer` と同様に `Parser::new``Parser::from_str` の 2 つのコンストラクタを持ち、`Parser::parse``AST` を返す。
* `AST``Vec<Expr>`のラッパー型で、「抽象構文木」を表す。 * `AST``Vec<Expr>`のラッパー型で、「抽象構文木」を表す。
### 2.5 `AST`の脱糖 ### 2.1 `AST`の脱糖
* ネストされた変数を展開 (`Desugarer::desugar_nest_vars_pattern`) * ネストされた変数を展開 (`Desugarer::desugar_nest_vars_pattern`)
* 複数パターン定義構文をmatchへ変換 (`Desugarer::desugar_multiple_pattern_def`) * 複数パターン定義構文をmatchへ変換 (`Desugarer::desugar_multiple_pattern_def`)
## 3. 型チェックと推論、 `AST` -> `HIR` を変換 (compiler/lower.rs) ## 3. `AST` -> `HIR` (compiler/lower.rs)
## 3.1 名前解決
* 型推論の前に全てのAST(importされたモジュール含む)を走査し、名前解決を行う
* 定数の循環検査や並び替えなどが行われるほか、型推論のためのContextが作成される(ただし、このContextに登録された変数の情報ははまだ殆どが未確定)
### 3.2 型チェックと推論 (compiler/lower.rs)
* `HIR` は、すべての変数の型情報を持っており、「高レベルの中間表現」を表す。 * `HIR` は、すべての変数の型情報を持っており、「高レベルの中間表現」を表す。
* `ASTLowerer は Parser や Lexer と同じように構築できる。 * `ASTLowerer` は Parser や Lexer と同じように構築できる。
* `ASTLowerer::lower` は、エラーが発生しなければ、`HIR``CompileWarnings` のタプルを出力する。 * `ASTLowerer::lower` は、エラーが発生しなければ、`HIR``CompileWarnings` のタプルを出力する。
* `ASTLowerer``Compiler` によって所有されている。 `ASTLowerer` は従来の構造体とは異なり、文脈を保持し、1 回限りの使い捨てではない。 * `ASTLowerer``Compiler` によって所有されている。 `ASTLowerer` は従来の構造体とは異なり、文脈を保持し、1 回限りの使い捨てではない。
* 型推論の結果が不完全な場合(未知の型変数がある場合)、名前解決時にエラーが発生する。 * 型推論の結果が不完全な場合(未知の型変数がある場合)、名前解決時にエラーが発生する。