Add `ASTBuilder`, `Checker`
This commit is contained in:
Shunsuke Shibayama 2022-09-20 14:42:37 +09:00
parent f12c2ba723
commit d8799f0895
14 changed files with 254 additions and 104 deletions

View file

@ -0,0 +1,72 @@
use erg_common::config::ErgConfig;
use erg_common::error::MultiErrorDisplay;
use erg_common::traits::Runnable;
use erg_parser::ast::AST;
use erg_parser::builder::ASTBuilder;
use crate::effectcheck::SideEffectChecker;
use crate::error::{TyCheckError, TyCheckErrors};
use crate::hir::HIR;
use crate::lower::ASTLowerer;
use crate::ownercheck::OwnershipChecker;
/// Summarize lowering, side-effect checking, and ownership checking
#[derive(Debug)]
pub struct Checker {
cfg: ErgConfig,
lowerer: ASTLowerer,
ownership_checker: OwnershipChecker,
}
impl Runnable for Checker {
type Err = TyCheckError;
type Errs = TyCheckErrors;
const NAME: &'static str = "Erg type-checker";
fn new(cfg: ErgConfig) -> Self {
Self {
ownership_checker: OwnershipChecker::new(),
lowerer: ASTLowerer::new(),
cfg,
}
}
#[inline]
fn cfg(&self) -> &ErgConfig {
&self.cfg
}
#[inline]
fn finish(&mut self) {}
fn clear(&mut self) {}
fn exec(&mut self) -> Result<(), Self::Errs> {
let mut builder = ASTBuilder::new(self.cfg.copy());
let ast = builder.build()?;
let hir = self.check(ast, "exec")?;
println!("{hir}");
Ok(())
}
fn eval(&mut self, src: String) -> Result<String, TyCheckErrors> {
let mut builder = ASTBuilder::new(self.cfg.copy());
let ast = builder.build_with_input(src)?;
let hir = self.check(ast, "eval")?;
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

@ -4,19 +4,15 @@
use std::path::Path; use std::path::Path;
use erg_common::config::{ErgConfig, Input}; use erg_common::config::{ErgConfig, Input};
use erg_common::error::MultiErrorDisplay;
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::ParserRunner; use erg_parser::builder::ASTBuilder;
use crate::checker::Checker;
use crate::codegen::CodeGenerator; use crate::codegen::CodeGenerator;
use crate::effectcheck::SideEffectChecker;
use crate::error::{CompileError, CompileErrors, TyCheckErrors}; use crate::error::{CompileError, CompileErrors, TyCheckErrors};
use crate::lower::ASTLowerer;
use crate::ownercheck::OwnershipChecker;
use crate::reorder::Reorderer;
/// * 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,13 +87,11 @@ impl AccessKind {
} }
} }
/// Generates a `CodeObj` from an `AST`. /// Generates a `CodeObj` from an String or other File inputs.
/// The input AST is not typed, so it's typed by `ASTLowerer` according to the cfg.opt_level.
#[derive(Debug)] #[derive(Debug)]
pub struct Compiler { pub struct Compiler {
cfg: ErgConfig, cfg: ErgConfig,
lowerer: ASTLowerer, checker: Checker,
ownership_checker: OwnershipChecker,
code_generator: CodeGenerator, code_generator: CodeGenerator,
} }
@ -108,9 +102,8 @@ impl Runnable for Compiler {
fn new(cfg: ErgConfig) -> Self { fn new(cfg: ErgConfig) -> Self {
Self { Self {
checker: Checker::new(cfg.copy()),
code_generator: CodeGenerator::new(cfg.copy()), code_generator: CodeGenerator::new(cfg.copy()),
ownership_checker: OwnershipChecker::new(),
lowerer: ASTLowerer::new(),
cfg, cfg,
} }
} }
@ -163,25 +156,11 @@ impl Compiler {
log!(info "the compiling process has started."); log!(info "the compiling process has started.");
let mut cfg = self.cfg.copy(); let mut cfg = self.cfg.copy();
cfg.input = Input::Str(src); cfg.input = Input::Str(src);
let mut parser = ParserRunner::new(cfg); let mut ast_builder = ASTBuilder::new(cfg);
let ast = parser.parse()?; let ast = ast_builder.build()?;
let linker = Reorderer::new();
let ast = linker.link(ast).map_err(|errs| self.convert(errs))?;
let (hir, warns) = self
.lowerer
.lower(ast, mode)
.map_err(|errs| self.convert(errs))?;
if self.cfg.verbose >= 2 {
let warns = self.convert(warns);
warns.fmt_all_stderr();
}
let effect_checker = SideEffectChecker::new();
let hir = effect_checker
.check(hir)
.map_err(|errs| self.convert(errs))?;
let hir = self let hir = self
.ownership_checker .checker
.check(hir) .check(ast, mode)
.map_err(|errs| self.convert(errs))?; .map_err(|errs| self.convert(errs))?;
let codeobj = self.code_generator.codegen(hir); let codeobj = self.code_generator.codegen(hir);
log!(info "code object:\n{}", codeobj.code_info()); log!(info "code object:\n{}", codeobj.code_info());

View file

@ -559,10 +559,15 @@ impl Context {
if sub == Type::Never { if sub == Type::Never {
return Ok(mono_proj(*lhs, rhs)); return Ok(mono_proj(*lhs, rhs));
} }
for (_ty, ty_ctx) in self for (_ty, ty_ctx) in self.get_nominal_super_type_ctxs(&sub).ok_or_else(|| {
.get_nominal_super_type_ctxs(&sub) EvalError::no_var_error(
.ok_or_else(|| todo!("{sub}"))? line!() as usize,
{ t_loc,
self.caused_by(),
&rhs,
None, // TODO:
)
})? {
if let Ok(obj) = ty_ctx.get_const_local(&Token::symbol(&rhs), &self.name) { if let Ok(obj) = ty_ctx.get_const_local(&Token::symbol(&rhs), &self.name) {
if let ValueObj::Type(quant_t) = obj { if let ValueObj::Type(quant_t) = obj {
let subst_ctx = SubstContext::new(&sub, ty_ctx); let subst_ctx = SubstContext::new(&sub, ty_ctx);

View file

@ -246,10 +246,15 @@ impl Context {
} }
} }
} }
for (_, ctx) in self for (_, ctx) in self.get_nominal_super_type_ctxs(&self_t).ok_or_else(|| {
.get_nominal_super_type_ctxs(&self_t) TyCheckError::no_var_error(
.ok_or_else(|| todo!())? line!() as usize,
{ obj.loc(),
self.caused_by(),
&self_t.to_string(),
None, // TODO:
)
})? {
match ctx.rec_get_var_t(ident, namespace) { match ctx.rec_get_var_t(ident, namespace) {
Ok(t) => { Ok(t) => {
return Ok(t); return Ok(t);
@ -348,7 +353,15 @@ impl Context {
if let Some(method_name) = method_name.as_ref() { if let Some(method_name) = method_name.as_ref() {
for (_, ctx) in self for (_, ctx) in self
.get_nominal_super_type_ctxs(obj.ref_t()) .get_nominal_super_type_ctxs(obj.ref_t())
.ok_or_else(|| todo!())? .ok_or_else(|| {
TyCheckError::no_var_error(
line!() as usize,
obj.loc(),
self.caused_by(),
&obj.to_string(),
None, // TODO:
)
})?
{ {
if let Some(vi) = ctx if let Some(vi) = ctx
.locals .locals
@ -856,10 +869,15 @@ impl Context {
namespace: &Str, namespace: &Str,
) -> TyCheckResult<ValueObj> { ) -> TyCheckResult<ValueObj> {
let self_t = obj.ref_t(); let self_t = obj.ref_t();
for (_, ctx) in self for (_, ctx) in self.get_nominal_super_type_ctxs(self_t).ok_or_else(|| {
.get_nominal_super_type_ctxs(self_t) TyCheckError::no_var_error(
.ok_or_else(|| todo!())? line!() as usize,
{ obj.loc(),
self.caused_by(),
&self_t.to_string(),
None, // TODO:
)
})? {
if let Ok(t) = ctx.get_const_local(name, namespace) { if let Ok(t) = ctx.get_const_local(name, namespace) {
return Ok(t); return Ok(t);
} }

View file

@ -237,6 +237,15 @@ pub struct TyCheckError {
pub caused_by: AtomicStr, pub caused_by: AtomicStr,
} }
impl From<ParserRunnerError> for TyCheckError {
fn from(err: ParserRunnerError) -> Self {
Self {
core: err.core,
caused_by: "".into(),
}
}
}
impl ErrorDisplay for TyCheckError { impl ErrorDisplay for TyCheckError {
fn core(&self) -> &ErrorCore { fn core(&self) -> &ErrorCore {
&self.core &self.core
@ -1169,6 +1178,7 @@ passed keyword args: {RED}{kw_args_len}{RESET}"
pub struct TyCheckErrors(Vec<TyCheckError>); pub struct TyCheckErrors(Vec<TyCheckError>);
impl_stream_for_wrapper!(TyCheckErrors, TyCheckError); impl_stream_for_wrapper!(TyCheckErrors, TyCheckError);
impl MultiErrorDisplay<TyCheckError> for TyCheckErrors {}
impl From<Vec<TyCheckError>> for TyCheckErrors { impl From<Vec<TyCheckError>> for TyCheckErrors {
fn from(errs: Vec<TyCheckError>) -> Self { fn from(errs: Vec<TyCheckError>) -> Self {
@ -1189,6 +1199,12 @@ impl From<TyCheckError> for TyCheckErrors {
} }
} }
impl From<ParserRunnerErrors> for TyCheckErrors {
fn from(err: ParserRunnerErrors) -> Self {
Self(err.into_iter().map(TyCheckError::from).collect())
}
}
pub type TyCheckResult<T> = Result<T, TyCheckError>; pub type TyCheckResult<T> = Result<T, TyCheckError>;
pub type TyCheckWarning = TyCheckError; pub type TyCheckWarning = TyCheckError;
pub type TyCheckWarnings = TyCheckErrors; pub type TyCheckWarnings = TyCheckErrors;

View file

@ -3,6 +3,7 @@
extern crate erg_common; extern crate erg_common;
pub extern crate erg_parser; pub extern crate erg_parser;
mod checker;
mod compile; mod compile;
pub use compile::*; pub use compile::*;
mod codegen; mod codegen;
@ -14,5 +15,4 @@ pub mod lower;
pub mod mod_cache; pub mod mod_cache;
pub mod optimize; pub mod optimize;
pub mod ownercheck; pub mod ownercheck;
pub mod reorder;
pub mod varinfo; pub mod varinfo;

View file

@ -2,7 +2,7 @@
//! //!
//! ASTLowerer(ASTからHIRへの変換器)を実装 //! ASTLowerer(ASTからHIRへの変換器)を実装
use erg_common::astr::AtomicStr; use erg_common::astr::AtomicStr;
use erg_common::config::{ErgConfig, Input}; use erg_common::config::ErgConfig;
use erg_common::error::{Location, MultiErrorDisplay}; use erg_common::error::{Location, MultiErrorDisplay};
use erg_common::traits::{Locational, Runnable, Stream}; use erg_common::traits::{Locational, Runnable, Stream};
use erg_common::vis::Visibility; use erg_common::vis::Visibility;
@ -10,10 +10,8 @@ use erg_common::{enum_unwrap, fmt_option, fn_name, get_hash, log, switch_lang, S
use erg_parser::ast; use erg_parser::ast;
use erg_parser::ast::AST; use erg_parser::ast::AST;
use erg_parser::error::ParserRunnerErrors; use erg_parser::builder::ASTBuilder;
use erg_parser::lex::Lexer;
use erg_parser::token::{Token, TokenKind}; use erg_parser::token::{Token, TokenKind};
use erg_parser::Parser;
use erg_type::constructors::{array, array_mut, free_var, func, mono, poly, proc, quant}; use erg_type::constructors::{array, array_mut, free_var, func, mono, poly, proc, quant};
use erg_type::free::Constraint; use erg_type::free::Constraint;
@ -27,7 +25,6 @@ use crate::error::{
}; };
use crate::hir; use crate::hir;
use crate::hir::HIR; use crate::hir::HIR;
use crate::reorder::Reorderer;
use crate::varinfo::VarKind; use crate::varinfo::VarKind;
use Visibility::*; use Visibility::*;
@ -62,14 +59,8 @@ impl Runnable for ASTLowererRunner {
} }
fn exec(&mut self) -> Result<(), Self::Errs> { fn exec(&mut self) -> Result<(), Self::Errs> {
let ts = Lexer::new(self.input().clone()) let mut ast_builder = ASTBuilder::new(self.cfg.copy());
.lex() let ast = ast_builder.build()?;
.map_err(|errs| ParserRunnerErrors::convert(self.input(), errs))?;
let ast = Parser::new(ts)
.parse(Str::ever(self.cfg.module))
.map_err(|errs| ParserRunnerErrors::convert(self.input(), errs))?;
let linker = Reorderer::new();
let ast = linker.link(ast).map_err(|errs| self.convert(errs))?;
let (hir, warns) = self let (hir, warns) = self
.lowerer .lowerer
.lower(ast, "exec") .lower(ast, "exec")
@ -83,14 +74,8 @@ impl Runnable for ASTLowererRunner {
} }
fn eval(&mut self, src: String) -> Result<String, CompileErrors> { fn eval(&mut self, src: String) -> Result<String, CompileErrors> {
let ts = Lexer::new(Input::Str(src)) let mut ast_builder = ASTBuilder::new(self.cfg.copy());
.lex() let ast = ast_builder.build_with_input(src)?;
.map_err(|errs| ParserRunnerErrors::convert(self.input(), errs))?;
let ast = Parser::new(ts)
.parse(Str::ever(self.cfg.module))
.map_err(|errs| ParserRunnerErrors::convert(self.input(), errs))?;
let linker = Reorderer::new();
let ast = linker.link(ast).map_err(|errs| self.convert(errs))?;
let (hir, _) = self let (hir, _) = self
.lowerer .lowerer
.lower(ast, "eval") .lower(ast, "eval")

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>, _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),
} }
} }

View file

@ -0,0 +1,50 @@
use erg_common::config::ErgConfig;
use erg_common::traits::Runnable;
use erg_common::Str;
use crate::ast::AST;
use crate::desugar::Desugarer;
use crate::error::ParserRunnerErrors;
use crate::parse::ParserRunner;
use crate::reorder::Reorderer;
/// Summarize parsing, desugaring, and reordering
pub struct ASTBuilder {
runner: ParserRunner,
}
impl ASTBuilder {
pub fn new(cfg: ErgConfig) -> Self {
Self {
runner: ParserRunner::new(cfg),
}
}
pub fn build(&mut self) -> Result<AST, ParserRunnerErrors> {
let module = self.runner.parse()?;
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 reorderer = Reorderer::new();
let ast = reorderer
.reorder(ast)
.map_err(|errs| ParserRunnerErrors::convert(self.runner.input(), errs))?;
Ok(ast)
}
pub fn build_with_input(&mut self, src: String) -> Result<AST, ParserRunnerErrors> {
let module = self.runner.parse_with_input(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 reorderer = Reorderer::new();
let ast = reorderer
.reorder(ast)
.map_err(|errs| ParserRunnerErrors::convert(self.runner.input(), errs))?;
Ok(ast)
}
}

View file

@ -8,7 +8,7 @@
use erg_common::set::Set; use erg_common::set::Set;
use erg_common::traits::{Locational, Stream}; use erg_common::traits::{Locational, Stream};
use erg_common::Str; use erg_common::Str;
use erg_common::{enum_unwrap, get_hash, set}; use erg_common::{enum_unwrap, get_hash, log, set};
use crate::ast::{ use crate::ast::{
Accessor, Args, Array, ArrayComprehension, ArrayWithLength, BinOp, Block, Call, DataPack, Def, Accessor, Args, Array, ArrayComprehension, ArrayWithLength, BinOp, Block, Call, DataPack, Def,
@ -48,10 +48,12 @@ impl Desugarer {
#[allow(clippy::let_and_return)] #[allow(clippy::let_and_return)]
pub fn desugar(&mut self, module: Module) -> Module { pub fn desugar(&mut self, module: Module) -> Module {
log!(info "the desugaring process has started.");
let module = self.desugar_multiple_pattern_def(module); let module = self.desugar_multiple_pattern_def(module);
let module = self.desugar_pattern(module); let module = self.desugar_pattern(module);
let module = self.desugar_shortened_record(module); let module = self.desugar_shortened_record(module);
// let module = self.desugar_self(module); log!(info "AST (desugared):\n{module}");
log!(info "the desugaring process has completed.");
module module
} }

View file

@ -2,6 +2,7 @@
//! //!
//! パーサーが出すエラーを定義 //! パーサーが出すエラーを定義
use erg_common::astr::AtomicStr; use erg_common::astr::AtomicStr;
use erg_common::color::{RED, RESET};
use erg_common::config::Input; use erg_common::config::Input;
use erg_common::error::{ErrorCore, ErrorDisplay, ErrorKind::*, Location, MultiErrorDisplay}; use erg_common::error::{ErrorCore, ErrorDisplay, ErrorKind::*, Location, MultiErrorDisplay};
use erg_common::traits::Stream; use erg_common::traits::Stream;
@ -82,6 +83,35 @@ impl LexError {
) -> Self { ) -> Self {
Self::new(ErrorCore::new(errno, SyntaxWarning, loc, desc, hint)) Self::new(ErrorCore::new(errno, SyntaxWarning, loc, desc, hint))
} }
pub fn no_var_error(
errno: usize,
loc: Location,
name: &str,
similar_name: Option<String>,
) -> Self {
let hint = similar_name.map(|n| {
switch_lang!(
"japanese" => format!("似た名前の変数があります: {n}"),
"simplified_chinese" => format!("存在相同名称变量:{n}"),
"traditional_chinese" => format!("存在相同名稱變量:{n}"),
"english" => format!("exists a similar name variable: {n}"),
)
.into()
});
Self::new(ErrorCore::new(
errno,
NameError,
loc,
switch_lang!(
"japanese" => format!("{RED}{name}{RESET}という変数は定義されていません"),
"simplified_chinese" => format!("{RED}{name}{RESET}未定义"),
"traditional_chinese" => format!("{RED}{name}{RESET}未定義"),
"english" => format!("{RED}{name}{RESET} is not defined"),
),
hint,
))
}
} }
pub type LexResult<T> = Result<T, LexError>; pub type LexResult<T> = Result<T, LexError>;

View file

@ -4,10 +4,12 @@
extern crate erg_common; extern crate erg_common;
pub mod ast; pub mod ast;
pub mod builder;
pub mod desugar; 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

@ -12,13 +12,11 @@ use erg_common::option_enum_unwrap;
use erg_common::set::Set as HashSet; use erg_common::set::Set as HashSet;
use erg_common::traits::Runnable; use erg_common::traits::Runnable;
use erg_common::traits::{Locational, Stream}; use erg_common::traits::{Locational, Stream};
use erg_common::Str;
use erg_common::{ use erg_common::{
caused_by, debug_power_assert, enum_unwrap, fn_name, log, set, switch_lang, switch_unreachable, caused_by, debug_power_assert, enum_unwrap, fn_name, log, set, switch_lang, switch_unreachable,
}; };
use crate::ast::*; use crate::ast::*;
use crate::desugar::Desugarer;
use crate::error::{ParseError, ParseErrors, ParseResult, ParserRunnerError, ParserRunnerErrors}; use crate::error::{ParseError, ParseErrors, ParseResult, ParserRunnerError, ParserRunnerErrors};
use crate::lex::Lexer; use crate::lex::Lexer;
use crate::token::{Token, TokenCategory, TokenKind, TokenStream}; use crate::token::{Token, TokenCategory, TokenKind, TokenStream};
@ -201,13 +199,13 @@ impl Runnable for ParserRunner {
} }
impl ParserRunner { impl ParserRunner {
pub fn parse_token_stream(&mut self, ts: TokenStream) -> Result<AST, ParserRunnerErrors> { pub fn parse_token_stream(&mut self, ts: TokenStream) -> Result<Module, ParserRunnerErrors> {
Parser::new(ts) Parser::new(ts)
.parse(Str::ever(self.cfg.module)) .parse()
.map_err(|errs| ParserRunnerErrors::convert(self.input(), errs)) .map_err(|errs| ParserRunnerErrors::convert(self.input(), errs))
} }
pub fn parse(&mut self) -> Result<AST, ParserRunnerErrors> { pub fn parse(&mut self) -> Result<Module, ParserRunnerErrors> {
let ts = Lexer::new(self.input().clone()) let ts = Lexer::new(self.input().clone())
.lex() .lex()
.map_err(|errs| ParserRunnerErrors::convert(self.input(), errs))?; .map_err(|errs| ParserRunnerErrors::convert(self.input(), errs))?;
@ -215,7 +213,7 @@ impl ParserRunner {
} }
/// Parses with default configuration /// Parses with default configuration
pub fn parse_with_default_config(input: Input) -> Result<AST, ParserRunnerErrors> { pub fn parse_with_default_config(input: Input) -> Result<Module, ParserRunnerErrors> {
let cfg = ErgConfig { let cfg = ErgConfig {
input, input,
..Default::default() ..Default::default()
@ -224,20 +222,20 @@ impl ParserRunner {
self_.parse() self_.parse()
} }
fn parse_with_input(&mut self, src: String) -> Result<AST, ParserRunnerErrors> { pub fn parse_with_input(&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))?;
Parser::new(ts) Parser::new(ts)
.parse(Str::ever(self.cfg.module)) .parse()
.map_err(|errs| ParserRunnerErrors::convert(self.input(), errs)) .map_err(|errs| ParserRunnerErrors::convert(self.input(), errs))
} }
} }
impl Parser { impl Parser {
pub fn parse(&mut self, mod_name: Str) -> Result<AST, ParseErrors> { pub fn parse(&mut self) -> Result<Module, ParseErrors> {
if self.tokens.is_empty() { if self.tokens.is_empty() {
return Ok(AST::new(mod_name, Module::empty())); return Ok(Module::empty());
} }
log!(info "the parsing process has started."); log!(info "the parsing process has started.");
log!(info "token stream: {}", self.tokens); log!(info "token stream: {}", self.tokens);
@ -255,13 +253,8 @@ impl Parser {
} }
log!(info "the parsing process has completed."); log!(info "the parsing process has completed.");
log!(info "AST:\n{module}"); log!(info "AST:\n{module}");
log!(info "the desugaring process has started.");
let mut desugarer = Desugarer::new();
let module = desugarer.desugar(module);
log!(info "AST (desugared):\n{module}");
log!(info "the desugaring process has completed.{RESET}");
if self.errs.is_empty() { if self.errs.is_empty() {
Ok(AST::new(mod_name, module)) Ok(module)
} else { } else {
Err(mem::take(&mut self.errs)) Err(mem::take(&mut self.errs))
} }

View file

@ -3,9 +3,9 @@ use erg_common::log;
use erg_common::traits::{Locational, Stream}; use erg_common::traits::{Locational, Stream};
use erg_common::Str; use erg_common::Str;
use erg_parser::ast::{ClassDef, Expr, Module, PreDeclTypeSpec, TypeSpec, AST}; use crate::ast::{ClassDef, Expr, Module, PreDeclTypeSpec, TypeSpec, AST};
use crate::error::{TyCheckError, TyCheckErrors}; use crate::error::{ParseError, ParseErrors};
/// Combine method definitions across multiple modules, specialized class contexts, etc. /// Combine method definitions across multiple modules, specialized class contexts, etc.
#[derive(Debug, Default)] #[derive(Debug, Default)]
@ -13,7 +13,7 @@ pub struct Reorderer {
// TODO: inner scope types // TODO: inner scope types
pub def_root_pos_map: Dict<Str, usize>, pub def_root_pos_map: Dict<Str, usize>,
pub deps: Dict<Str, Vec<Str>>, pub deps: Dict<Str, Vec<Str>>,
pub errs: TyCheckErrors, pub errs: ParseErrors,
} }
impl Reorderer { impl Reorderer {
@ -21,12 +21,12 @@ impl Reorderer {
Self { Self {
def_root_pos_map: Dict::new(), def_root_pos_map: Dict::new(),
deps: Dict::new(), deps: Dict::new(),
errs: TyCheckErrors::empty(), errs: ParseErrors::empty(),
} }
} }
pub fn link(mut self, mut ast: AST) -> Result<AST, TyCheckErrors> { pub fn reorder(mut self, mut ast: AST) -> Result<AST, ParseErrors> {
log!(info "the linking process has started."); log!(info "the reordering process has started.");
let mut new = vec![]; let mut new = vec![];
while let Some(chunk) = ast.module.lpop() { while let Some(chunk) = ast.module.lpop() {
match chunk { match chunk {
@ -63,17 +63,15 @@ impl Reorderer {
class_def.methods_list.push(methods); class_def.methods_list.push(methods);
new.insert(*pos, Expr::ClassDef(class_def)); new.insert(*pos, Expr::ClassDef(class_def));
} else { } else {
let similar_name = Str::from( let similar_name = self
self.def_root_pos_map .def_root_pos_map
.keys() .keys()
.fold("".to_string(), |acc, key| acc + &key[..] + ","), .fold("".to_string(), |acc, key| acc + &key[..] + ",");
); self.errs.push(ParseError::no_var_error(
self.errs.push(TyCheckError::no_var_error(
line!() as usize, line!() as usize,
methods.class.loc(), methods.class.loc(),
"".into(),
simple.name.inspect(), simple.name.inspect(),
Some(&similar_name), Some(similar_name),
)); ));
} }
} }
@ -85,7 +83,7 @@ impl Reorderer {
} }
} }
let ast = AST::new(ast.name, Module::new(new)); let ast = AST::new(ast.name, Module::new(new));
log!(info "the linking process has completed:\n{}", ast); log!(info "the reordering process has completed:\n{}", ast);
if self.errs.is_empty() { if self.errs.is_empty() {
Ok(ast) Ok(ast)
} else { } else {