mirror of
https://github.com/erg-lang/erg.git
synced 2025-09-29 20:34:44 +00:00
Refactor
Add `ASTBuilder`, `Checker`
This commit is contained in:
parent
f12c2ba723
commit
d8799f0895
14 changed files with 254 additions and 104 deletions
72
compiler/erg_compiler/checker.rs
Normal file
72
compiler/erg_compiler/checker.rs
Normal 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)
|
||||
}
|
||||
}
|
|
@ -4,19 +4,15 @@
|
|||
use std::path::Path;
|
||||
|
||||
use erg_common::config::{ErgConfig, Input};
|
||||
use erg_common::error::MultiErrorDisplay;
|
||||
use erg_common::log;
|
||||
use erg_common::traits::{Runnable, Stream};
|
||||
use erg_type::codeobj::CodeObj;
|
||||
|
||||
use erg_parser::ParserRunner;
|
||||
use erg_parser::builder::ASTBuilder;
|
||||
|
||||
use crate::checker::Checker;
|
||||
use crate::codegen::CodeGenerator;
|
||||
use crate::effectcheck::SideEffectChecker;
|
||||
use crate::error::{CompileError, CompileErrors, TyCheckErrors};
|
||||
use crate::lower::ASTLowerer;
|
||||
use crate::ownercheck::OwnershipChecker;
|
||||
use crate::reorder::Reorderer;
|
||||
|
||||
/// * registered as global -> 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`.
|
||||
/// The input AST is not typed, so it's typed by `ASTLowerer` according to the cfg.opt_level.
|
||||
/// Generates a `CodeObj` from an String or other File inputs.
|
||||
#[derive(Debug)]
|
||||
pub struct Compiler {
|
||||
cfg: ErgConfig,
|
||||
lowerer: ASTLowerer,
|
||||
ownership_checker: OwnershipChecker,
|
||||
checker: Checker,
|
||||
code_generator: CodeGenerator,
|
||||
}
|
||||
|
||||
|
@ -108,9 +102,8 @@ impl Runnable for Compiler {
|
|||
|
||||
fn new(cfg: ErgConfig) -> Self {
|
||||
Self {
|
||||
checker: Checker::new(cfg.copy()),
|
||||
code_generator: CodeGenerator::new(cfg.copy()),
|
||||
ownership_checker: OwnershipChecker::new(),
|
||||
lowerer: ASTLowerer::new(),
|
||||
cfg,
|
||||
}
|
||||
}
|
||||
|
@ -163,25 +156,11 @@ impl Compiler {
|
|||
log!(info "the compiling process has started.");
|
||||
let mut cfg = self.cfg.copy();
|
||||
cfg.input = Input::Str(src);
|
||||
let mut parser = ParserRunner::new(cfg);
|
||||
let ast = parser.parse()?;
|
||||
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 mut ast_builder = ASTBuilder::new(cfg);
|
||||
let ast = ast_builder.build()?;
|
||||
let hir = self
|
||||
.ownership_checker
|
||||
.check(hir)
|
||||
.checker
|
||||
.check(ast, mode)
|
||||
.map_err(|errs| self.convert(errs))?;
|
||||
let codeobj = self.code_generator.codegen(hir);
|
||||
log!(info "code object:\n{}", codeobj.code_info());
|
||||
|
|
|
@ -559,10 +559,15 @@ impl Context {
|
|||
if sub == Type::Never {
|
||||
return Ok(mono_proj(*lhs, rhs));
|
||||
}
|
||||
for (_ty, ty_ctx) in self
|
||||
.get_nominal_super_type_ctxs(&sub)
|
||||
.ok_or_else(|| todo!("{sub}"))?
|
||||
{
|
||||
for (_ty, ty_ctx) in self.get_nominal_super_type_ctxs(&sub).ok_or_else(|| {
|
||||
EvalError::no_var_error(
|
||||
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 ValueObj::Type(quant_t) = obj {
|
||||
let subst_ctx = SubstContext::new(&sub, ty_ctx);
|
||||
|
|
|
@ -246,10 +246,15 @@ impl Context {
|
|||
}
|
||||
}
|
||||
}
|
||||
for (_, ctx) in self
|
||||
.get_nominal_super_type_ctxs(&self_t)
|
||||
.ok_or_else(|| todo!())?
|
||||
{
|
||||
for (_, ctx) in self.get_nominal_super_type_ctxs(&self_t).ok_or_else(|| {
|
||||
TyCheckError::no_var_error(
|
||||
line!() as usize,
|
||||
obj.loc(),
|
||||
self.caused_by(),
|
||||
&self_t.to_string(),
|
||||
None, // TODO:
|
||||
)
|
||||
})? {
|
||||
match ctx.rec_get_var_t(ident, namespace) {
|
||||
Ok(t) => {
|
||||
return Ok(t);
|
||||
|
@ -348,7 +353,15 @@ impl Context {
|
|||
if let Some(method_name) = method_name.as_ref() {
|
||||
for (_, ctx) in self
|
||||
.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
|
||||
.locals
|
||||
|
@ -856,10 +869,15 @@ impl Context {
|
|||
namespace: &Str,
|
||||
) -> TyCheckResult<ValueObj> {
|
||||
let self_t = obj.ref_t();
|
||||
for (_, ctx) in self
|
||||
.get_nominal_super_type_ctxs(self_t)
|
||||
.ok_or_else(|| todo!())?
|
||||
{
|
||||
for (_, ctx) in self.get_nominal_super_type_ctxs(self_t).ok_or_else(|| {
|
||||
TyCheckError::no_var_error(
|
||||
line!() as usize,
|
||||
obj.loc(),
|
||||
self.caused_by(),
|
||||
&self_t.to_string(),
|
||||
None, // TODO:
|
||||
)
|
||||
})? {
|
||||
if let Ok(t) = ctx.get_const_local(name, namespace) {
|
||||
return Ok(t);
|
||||
}
|
||||
|
|
|
@ -237,6 +237,15 @@ pub struct TyCheckError {
|
|||
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 {
|
||||
fn core(&self) -> &ErrorCore {
|
||||
&self.core
|
||||
|
@ -1169,6 +1178,7 @@ passed keyword args: {RED}{kw_args_len}{RESET}"
|
|||
pub struct TyCheckErrors(Vec<TyCheckError>);
|
||||
|
||||
impl_stream_for_wrapper!(TyCheckErrors, TyCheckError);
|
||||
impl MultiErrorDisplay<TyCheckError> for TyCheckErrors {}
|
||||
|
||||
impl From<Vec<TyCheckError>> for TyCheckErrors {
|
||||
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 TyCheckWarning = TyCheckError;
|
||||
pub type TyCheckWarnings = TyCheckErrors;
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
extern crate erg_common;
|
||||
pub extern crate erg_parser;
|
||||
|
||||
mod checker;
|
||||
mod compile;
|
||||
pub use compile::*;
|
||||
mod codegen;
|
||||
|
@ -14,5 +15,4 @@ pub mod lower;
|
|||
pub mod mod_cache;
|
||||
pub mod optimize;
|
||||
pub mod ownercheck;
|
||||
pub mod reorder;
|
||||
pub mod varinfo;
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
//!
|
||||
//! ASTLowerer(ASTからHIRへの変換器)を実装
|
||||
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::traits::{Locational, Runnable, Stream};
|
||||
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::AST;
|
||||
use erg_parser::error::ParserRunnerErrors;
|
||||
use erg_parser::lex::Lexer;
|
||||
use erg_parser::builder::ASTBuilder;
|
||||
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::free::Constraint;
|
||||
|
@ -27,7 +25,6 @@ use crate::error::{
|
|||
};
|
||||
use crate::hir;
|
||||
use crate::hir::HIR;
|
||||
use crate::reorder::Reorderer;
|
||||
use crate::varinfo::VarKind;
|
||||
use Visibility::*;
|
||||
|
||||
|
@ -62,14 +59,8 @@ impl Runnable for ASTLowererRunner {
|
|||
}
|
||||
|
||||
fn exec(&mut self) -> Result<(), Self::Errs> {
|
||||
let ts = Lexer::new(self.input().clone())
|
||||
.lex()
|
||||
.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 mut ast_builder = ASTBuilder::new(self.cfg.copy());
|
||||
let ast = ast_builder.build()?;
|
||||
let (hir, warns) = self
|
||||
.lowerer
|
||||
.lower(ast, "exec")
|
||||
|
@ -83,14 +74,8 @@ impl Runnable for ASTLowererRunner {
|
|||
}
|
||||
|
||||
fn eval(&mut self, src: String) -> Result<String, CompileErrors> {
|
||||
let ts = Lexer::new(Input::Str(src))
|
||||
.lex()
|
||||
.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 mut ast_builder = ASTBuilder::new(self.cfg.copy());
|
||||
let ast = ast_builder.build_with_input(src)?;
|
||||
let (hir, _) = self
|
||||
.lowerer
|
||||
.lower(ast, "eval")
|
||||
|
|
|
@ -27,24 +27,24 @@ impl ModId {
|
|||
|
||||
#[derive(Debug)]
|
||||
pub struct ModuleEntry {
|
||||
id: ModId, // builtin == 0, __main__ == 1
|
||||
hir: Option<HIR>,
|
||||
_id: ModId, // builtin == 0, __main__ == 1
|
||||
_hir: Option<HIR>,
|
||||
ctx: Rc<Context>,
|
||||
}
|
||||
|
||||
impl ModuleEntry {
|
||||
pub fn new(id: ModId, hir: Option<HIR>, ctx: Context) -> Self {
|
||||
Self {
|
||||
id,
|
||||
hir,
|
||||
_id: id,
|
||||
_hir: hir,
|
||||
ctx: Rc::new(ctx),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn builtin(ctx: Context) -> Self {
|
||||
Self {
|
||||
id: ModId::builtin(),
|
||||
hir: None,
|
||||
_id: ModId::builtin(),
|
||||
_hir: None,
|
||||
ctx: Rc::new(ctx),
|
||||
}
|
||||
}
|
||||
|
|
50
compiler/erg_parser/builder.rs
Normal file
50
compiler/erg_parser/builder.rs
Normal 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)
|
||||
}
|
||||
}
|
|
@ -8,7 +8,7 @@
|
|||
use erg_common::set::Set;
|
||||
use erg_common::traits::{Locational, Stream};
|
||||
use erg_common::Str;
|
||||
use erg_common::{enum_unwrap, get_hash, set};
|
||||
use erg_common::{enum_unwrap, get_hash, log, set};
|
||||
|
||||
use crate::ast::{
|
||||
Accessor, Args, Array, ArrayComprehension, ArrayWithLength, BinOp, Block, Call, DataPack, Def,
|
||||
|
@ -48,10 +48,12 @@ impl Desugarer {
|
|||
|
||||
#[allow(clippy::let_and_return)]
|
||||
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_pattern(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
|
||||
}
|
||||
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
//!
|
||||
//! パーサーが出すエラーを定義
|
||||
use erg_common::astr::AtomicStr;
|
||||
use erg_common::color::{RED, RESET};
|
||||
use erg_common::config::Input;
|
||||
use erg_common::error::{ErrorCore, ErrorDisplay, ErrorKind::*, Location, MultiErrorDisplay};
|
||||
use erg_common::traits::Stream;
|
||||
|
@ -82,6 +83,35 @@ impl LexError {
|
|||
) -> Self {
|
||||
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>;
|
||||
|
|
|
@ -4,10 +4,12 @@
|
|||
extern crate erg_common;
|
||||
|
||||
pub mod ast;
|
||||
pub mod builder;
|
||||
pub mod desugar;
|
||||
pub mod error;
|
||||
pub mod lex;
|
||||
pub mod parse;
|
||||
pub mod reorder;
|
||||
pub mod token;
|
||||
|
||||
pub use parse::{Parser, ParserRunner};
|
||||
|
|
|
@ -12,13 +12,11 @@ use erg_common::option_enum_unwrap;
|
|||
use erg_common::set::Set as HashSet;
|
||||
use erg_common::traits::Runnable;
|
||||
use erg_common::traits::{Locational, Stream};
|
||||
use erg_common::Str;
|
||||
use erg_common::{
|
||||
caused_by, debug_power_assert, enum_unwrap, fn_name, log, set, switch_lang, switch_unreachable,
|
||||
};
|
||||
|
||||
use crate::ast::*;
|
||||
use crate::desugar::Desugarer;
|
||||
use crate::error::{ParseError, ParseErrors, ParseResult, ParserRunnerError, ParserRunnerErrors};
|
||||
use crate::lex::Lexer;
|
||||
use crate::token::{Token, TokenCategory, TokenKind, TokenStream};
|
||||
|
@ -201,13 +199,13 @@ impl Runnable for 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)
|
||||
.parse(Str::ever(self.cfg.module))
|
||||
.parse()
|
||||
.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())
|
||||
.lex()
|
||||
.map_err(|errs| ParserRunnerErrors::convert(self.input(), errs))?;
|
||||
|
@ -215,7 +213,7 @@ impl ParserRunner {
|
|||
}
|
||||
|
||||
/// 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 {
|
||||
input,
|
||||
..Default::default()
|
||||
|
@ -224,20 +222,20 @@ impl ParserRunner {
|
|||
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))
|
||||
.lex()
|
||||
.map_err(|errs| ParserRunnerErrors::convert(self.input(), errs))?;
|
||||
Parser::new(ts)
|
||||
.parse(Str::ever(self.cfg.module))
|
||||
.parse()
|
||||
.map_err(|errs| ParserRunnerErrors::convert(self.input(), errs))
|
||||
}
|
||||
}
|
||||
|
||||
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() {
|
||||
return Ok(AST::new(mod_name, Module::empty()));
|
||||
return Ok(Module::empty());
|
||||
}
|
||||
log!(info "the parsing process has started.");
|
||||
log!(info "token stream: {}", self.tokens);
|
||||
|
@ -255,13 +253,8 @@ impl Parser {
|
|||
}
|
||||
log!(info "the parsing process has completed.");
|
||||
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() {
|
||||
Ok(AST::new(mod_name, module))
|
||||
Ok(module)
|
||||
} else {
|
||||
Err(mem::take(&mut self.errs))
|
||||
}
|
||||
|
|
|
@ -3,9 +3,9 @@ use erg_common::log;
|
|||
use erg_common::traits::{Locational, Stream};
|
||||
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.
|
||||
#[derive(Debug, Default)]
|
||||
|
@ -13,7 +13,7 @@ pub struct Reorderer {
|
|||
// TODO: inner scope types
|
||||
pub def_root_pos_map: Dict<Str, usize>,
|
||||
pub deps: Dict<Str, Vec<Str>>,
|
||||
pub errs: TyCheckErrors,
|
||||
pub errs: ParseErrors,
|
||||
}
|
||||
|
||||
impl Reorderer {
|
||||
|
@ -21,12 +21,12 @@ impl Reorderer {
|
|||
Self {
|
||||
def_root_pos_map: Dict::new(),
|
||||
deps: Dict::new(),
|
||||
errs: TyCheckErrors::empty(),
|
||||
errs: ParseErrors::empty(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn link(mut self, mut ast: AST) -> Result<AST, TyCheckErrors> {
|
||||
log!(info "the linking process has started.");
|
||||
pub fn reorder(mut self, mut ast: AST) -> Result<AST, ParseErrors> {
|
||||
log!(info "the reordering process has started.");
|
||||
let mut new = vec![];
|
||||
while let Some(chunk) = ast.module.lpop() {
|
||||
match chunk {
|
||||
|
@ -63,17 +63,15 @@ impl Reorderer {
|
|||
class_def.methods_list.push(methods);
|
||||
new.insert(*pos, Expr::ClassDef(class_def));
|
||||
} else {
|
||||
let similar_name = Str::from(
|
||||
self.def_root_pos_map
|
||||
.keys()
|
||||
.fold("".to_string(), |acc, key| acc + &key[..] + ","),
|
||||
);
|
||||
self.errs.push(TyCheckError::no_var_error(
|
||||
let similar_name = self
|
||||
.def_root_pos_map
|
||||
.keys()
|
||||
.fold("".to_string(), |acc, key| acc + &key[..] + ",");
|
||||
self.errs.push(ParseError::no_var_error(
|
||||
line!() as usize,
|
||||
methods.class.loc(),
|
||||
"".into(),
|
||||
simple.name.inspect(),
|
||||
Some(&similar_name),
|
||||
Some(similar_name),
|
||||
));
|
||||
}
|
||||
}
|
||||
|
@ -85,7 +83,7 @@ impl Reorderer {
|
|||
}
|
||||
}
|
||||
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() {
|
||||
Ok(ast)
|
||||
} else {
|
Loading…
Add table
Add a link
Reference in a new issue