diff --git a/compiler/erg_compiler/lib.rs b/compiler/erg_compiler/lib.rs index ab265b19c..c8dc9a464 100644 --- a/compiler/erg_compiler/lib.rs +++ b/compiler/erg_compiler/lib.rs @@ -6,13 +6,12 @@ pub extern crate erg_parser; mod compile; pub use compile::*; mod codegen; +pub mod context; pub mod effectcheck; pub mod error; pub mod hir; pub mod link; pub mod lower; -pub use lower::ASTLowerer; -pub mod context; pub mod optimize; pub mod ownercheck; pub mod varinfo; diff --git a/compiler/erg_compiler/lower.rs b/compiler/erg_compiler/lower.rs index 0abf14212..dec97bd10 100644 --- a/compiler/erg_compiler/lower.rs +++ b/compiler/erg_compiler/lower.rs @@ -1,15 +1,19 @@ //! implements `ASTLowerer`. //! //! ASTLowerer(ASTからHIRへの変換器)を実装 -use erg_common::error::Location; -use erg_common::traits::{Locational, Stream}; +use erg_common::config::{ErgConfig, Input}; +use erg_common::error::{Location, MultiErrorDisplay}; +use erg_common::traits::{Locational, Runnable, Stream}; use erg_common::vis::Visibility; use erg_common::{enum_unwrap, fmt_option, fn_name, get_hash, log, switch_lang, Str}; use erg_parser::ast; use erg_parser::ast::AST; - +use erg_parser::error::ParserRunnerErrors; +use erg_parser::lex::Lexer; 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; use erg_type::typaram::TyParam; @@ -17,9 +21,12 @@ use erg_type::value::{TypeObj, ValueObj}; use erg_type::{HasType, ParamTy, Type}; use crate::context::{Context, ContextKind, RegistrationMode}; -use crate::error::{LowerError, LowerErrors, LowerResult, LowerWarnings}; +use crate::error::{ + CompileError, CompileErrors, LowerError, LowerErrors, LowerResult, LowerWarnings, +}; use crate::hir; use crate::hir::HIR; +use crate::link::Linker; use crate::varinfo::VarKind; use Visibility::*; @@ -51,6 +58,83 @@ macro_rules! check_inheritable { }; } +pub struct ASTLowererRunner { + cfg: ErgConfig, + lowerer: ASTLowerer, +} + +impl Runnable for ASTLowererRunner { + type Err = CompileError; + type Errs = CompileErrors; + const NAME: &'static str = "Erg lowerer"; + + fn new(cfg: ErgConfig) -> Self { + Self { + cfg, + lowerer: ASTLowerer::new(), + } + } + + #[inline] + fn input(&self) -> &Input { + &self.cfg.input + } + + #[inline] + fn finish(&mut self) {} + + fn clear(&mut self) { + self.lowerer.errs.clear(); + self.lowerer.warns.clear(); + } + + 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 = Linker::new(); + let ast = linker.link(ast).map_err(|errs| self.convert(errs))?; + let (hir, warns) = self + .lowerer + .lower(ast, "exec") + .map_err(|errs| self.convert(errs))?; + if self.cfg.verbose >= 2 { + let warns = self.convert(warns); + warns.fmt_all_stderr(); + } + println!("{hir}"); + Ok(()) + } + + fn eval(&mut self, src: Str) -> Result { + 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 = Linker::new(); + let ast = linker.link(ast).map_err(|errs| self.convert(errs))?; + let (hir, _) = self + .lowerer + .lower(ast, "eval") + .map_err(|errs| self.convert(errs))?; + Ok(format!("{hir}")) + } +} + +impl ASTLowererRunner { + fn convert(&self, errs: LowerErrors) -> CompileErrors { + errs.into_iter() + .map(|e| CompileError::new(e.core, self.input().clone(), e.caused_by)) + .collect::>() + .into() + } +} + /// Singleton that checks types of an AST, and convert (lower) it into a HIR #[derive(Debug)] pub struct ASTLowerer { @@ -59,6 +143,12 @@ pub struct ASTLowerer { warns: LowerWarnings, } +impl Default for ASTLowerer { + fn default() -> Self { + Self::new() + } +} + impl ASTLowerer { pub fn new() -> Self { Self { @@ -806,9 +896,3 @@ impl ASTLowerer { } } } - -impl Default for ASTLowerer { - fn default() -> Self { - Self::new() - } -} diff --git a/compiler/erg_compiler/main.rs b/compiler/erg_compiler/main.rs index 89cae1043..efda3b46c 100644 --- a/compiler/erg_compiler/main.rs +++ b/compiler/erg_compiler/main.rs @@ -8,6 +8,7 @@ use std::thread; use erg_common::config::ErgConfig; use erg_common::traits::Runnable; +use erg_compiler::lower::ASTLowererRunner; use erg_compiler::Compiler; use erg_parser::lex::LexerRunner; @@ -24,6 +25,9 @@ fn run() { "parse" => { ParserRunner::run(cfg); } + "lower" => { + ASTLowererRunner::run(cfg); + } "compile" | "exec" => { Compiler::run(cfg); } diff --git a/compiler/erg_parser/parse.rs b/compiler/erg_parser/parse.rs index d08b6e04d..c64f2a706 100644 --- a/compiler/erg_parser/parse.rs +++ b/compiler/erg_parser/parse.rs @@ -82,7 +82,7 @@ pub struct Parser { } impl Parser { - const fn new(ts: TokenStream) -> Self { + pub const fn new(ts: TokenStream) -> Self { Self { counter: DefId(0), level: 0, diff --git a/src/main.rs b/src/main.rs index 3eba2e589..b60e3a3e0 100644 --- a/src/main.rs +++ b/src/main.rs @@ -11,6 +11,7 @@ use erg_common::traits::Runnable; use erg_parser::lex::LexerRunner; use erg_parser::ParserRunner; +use erg_compiler::lower::ASTLowererRunner; use erg_compiler::Compiler; use erg_type::deserialize::Deserializer; @@ -26,6 +27,9 @@ fn run() { "parse" => { ParserRunner::run(cfg); } + "lower" => { + ASTLowererRunner::run(cfg); + } "compile" => { Compiler::run(cfg); }