mirror of
https://github.com/erg-lang/erg.git
synced 2025-09-29 04:24:43 +00:00
Add "check" mode
Input::File(String) -> Input::file(PathBuf)
This commit is contained in:
parent
c1d92bc0f4
commit
9b0d66a63a
16 changed files with 200 additions and 184 deletions
|
@ -4,7 +4,9 @@
|
|||
use std::env;
|
||||
use std::fs::File;
|
||||
use std::io::{stdin, BufRead, BufReader, Read};
|
||||
use std::path::PathBuf;
|
||||
use std::process;
|
||||
use std::str::FromStr;
|
||||
|
||||
use crate::stdin::GLOBAL_STDIN;
|
||||
use crate::{power_assert, read_file};
|
||||
|
@ -17,8 +19,7 @@ pub const BUILD_DATE: &str = env!("BUILD_DATE");
|
|||
/// Inputで操作を一本化する
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
||||
pub enum Input {
|
||||
/// filename
|
||||
File(String),
|
||||
File(PathBuf),
|
||||
REPL,
|
||||
/// same content as cfg.command
|
||||
Pipe(String),
|
||||
|
@ -34,7 +35,7 @@ impl Input {
|
|||
|
||||
pub fn enclosed_name(&self) -> &str {
|
||||
match self {
|
||||
Self::File(filename) => &filename[..],
|
||||
Self::File(filename) => filename.as_os_str().to_str().unwrap_or("???"),
|
||||
Self::REPL | Self::Pipe(_) => "<stdin>",
|
||||
Self::Str(_) => "<string>",
|
||||
Self::Dummy => "<dummy>",
|
||||
|
@ -44,7 +45,7 @@ impl Input {
|
|||
/// ファイルに書き出すとき使う
|
||||
pub fn filename(&self) -> &str {
|
||||
match self {
|
||||
Self::File(filename) => &filename[..],
|
||||
Self::File(filename) => filename.as_os_str().to_str().unwrap_or("???"),
|
||||
Self::REPL | Self::Pipe(_) => "stdin",
|
||||
Self::Str(_) => "string",
|
||||
Self::Dummy => "dummy",
|
||||
|
@ -54,11 +55,14 @@ impl Input {
|
|||
pub fn read(&self) -> String {
|
||||
match self {
|
||||
Self::File(filename) => {
|
||||
let file = match File::open(&filename[..]) {
|
||||
let file = match File::open(filename) {
|
||||
Ok(f) => f,
|
||||
Err(e) => {
|
||||
let code = e.raw_os_error().unwrap_or(1);
|
||||
println!("cannot open '{filename}': [Errno {code}] {e}");
|
||||
println!(
|
||||
"cannot open '{}': [Errno {code}] {e}",
|
||||
filename.to_string_lossy()
|
||||
);
|
||||
process::exit(code);
|
||||
}
|
||||
};
|
||||
|
@ -66,7 +70,10 @@ impl Input {
|
|||
Ok(s) => s,
|
||||
Err(e) => {
|
||||
let code = e.raw_os_error().unwrap_or(1);
|
||||
println!("cannot read '{filename}': [Errno {code}] {e}");
|
||||
println!(
|
||||
"cannot read '{}': [Errno {code}] {e}",
|
||||
filename.to_string_lossy()
|
||||
);
|
||||
process::exit(code);
|
||||
}
|
||||
}
|
||||
|
@ -80,7 +87,7 @@ impl Input {
|
|||
pub fn reread_lines(&self, ln_begin: usize, ln_end: usize) -> Vec<String> {
|
||||
power_assert!(ln_begin, >=, 1);
|
||||
match self {
|
||||
Self::File(filename) => match File::open(&filename[..]) {
|
||||
Self::File(filename) => match File::open(filename) {
|
||||
Ok(file) => {
|
||||
let mut codes = vec![];
|
||||
let mut lines = BufReader::new(file).lines().skip(ln_begin - 1);
|
||||
|
@ -238,7 +245,10 @@ impl ErgConfig {
|
|||
panic!("invalid option: {other}");
|
||||
}
|
||||
_ => {
|
||||
cfg.input = Input::File(arg);
|
||||
cfg.input = Input::File(
|
||||
PathBuf::from_str(&arg[..])
|
||||
.unwrap_or_else(|_| panic!("invalid file path: {}", arg)),
|
||||
);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -218,6 +218,12 @@ macro_rules! impl_stream_for_wrapper {
|
|||
}
|
||||
}
|
||||
|
||||
impl From<$Strc> for Vec<$Inner> {
|
||||
fn from(item: $Strc) -> Vec<$Inner> {
|
||||
item.payload()
|
||||
}
|
||||
}
|
||||
|
||||
impl $crate::traits::Stream<$Inner> for $Strc {
|
||||
#[inline]
|
||||
fn payload(self) -> Vec<$Inner> {
|
||||
|
@ -259,6 +265,12 @@ macro_rules! impl_stream {
|
|||
erg_common::traits::Stream::get(self, idx).unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
impl From<$Strc> for Vec<$Inner> {
|
||||
fn from(item: $Strc) -> Vec<$Inner> {
|
||||
item.payload()
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
use erg_common::config::{ErgConfig, Input};
|
||||
use erg_common::traits::Stream;
|
||||
use erg_common::traits::{Runnable, Stream};
|
||||
|
||||
use erg_parser::ast::VarName;
|
||||
use erg_parser::builder::ASTBuilder;
|
||||
|
@ -19,20 +19,20 @@ pub struct HIRBuilder {
|
|||
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))
|
||||
.map(|e| CompileError::new(e.core, self.checker.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()),
|
||||
checker: Checker::new_with_cache(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 mut ast_builder = ASTBuilder::new(self.checker.cfg().copy());
|
||||
let ast = ast_builder.build()?;
|
||||
let ast = Reorderer::new()
|
||||
.reorder(ast)
|
||||
|
@ -46,7 +46,7 @@ impl HIRBuilder {
|
|||
}
|
||||
|
||||
pub fn build_and_cache_main(&mut self, src: String, mode: &str) -> Result<(), CompileErrors> {
|
||||
let mut cfg = self.checker.cfg.copy();
|
||||
let mut cfg = self.checker.cfg().copy();
|
||||
cfg.input = Input::Str(src);
|
||||
let mut ast_builder = ASTBuilder::new(cfg);
|
||||
let ast = ast_builder.build()?;
|
||||
|
|
|
@ -16,50 +16,22 @@ use crate::ownercheck::OwnershipChecker;
|
|||
/// Summarize lowering, side-effect checking, and ownership checking
|
||||
#[derive(Debug)]
|
||||
pub struct Checker {
|
||||
pub cfg: ErgConfig,
|
||||
lowerer: ASTLowerer,
|
||||
ownership_checker: OwnershipChecker,
|
||||
}
|
||||
|
||||
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 {
|
||||
impl Runnable for Checker {
|
||||
type Err = TyCheckError;
|
||||
type Errs = TyCheckErrors;
|
||||
const NAME: &'static str = "Erg type-checker";
|
||||
|
||||
fn new(cfg: ErgConfig) -> Self {
|
||||
Self {
|
||||
checker: Checker::new(cfg, SharedModuleCache::new()),
|
||||
}
|
||||
Checker::new_with_cache(cfg, SharedModuleCache::new())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn cfg(&self) -> &ErgConfig {
|
||||
&self.checker.cfg
|
||||
self.lowerer.cfg()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
|
@ -70,7 +42,7 @@ impl Runnable for CheckerRunner {
|
|||
fn exec(&mut self) -> Result<(), Self::Errs> {
|
||||
let mut builder = ASTBuilder::new(self.cfg().copy());
|
||||
let ast = builder.build()?;
|
||||
let (hir, _) = self.checker.check(ast, "exec")?;
|
||||
let (hir, _) = self.check(ast, "exec")?;
|
||||
println!("{hir}");
|
||||
Ok(())
|
||||
}
|
||||
|
@ -78,7 +50,27 @@ impl Runnable for CheckerRunner {
|
|||
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 (hir, _) = self.checker.check(ast, "eval")?;
|
||||
let (hir, _) = self.check(ast, "eval")?;
|
||||
Ok(hir.to_string())
|
||||
}
|
||||
}
|
||||
|
||||
impl Checker {
|
||||
pub fn new_with_cache(cfg: ErgConfig, mod_cache: SharedModuleCache) -> Self {
|
||||
Self {
|
||||
lowerer: ASTLowerer::new_with_cache(cfg, 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))
|
||||
}
|
||||
}
|
||||
|
|
|
@ -996,7 +996,7 @@ impl CodeGenerator {
|
|||
self.write_instr(Opcode::LOAD_BUILD_CLASS);
|
||||
self.write_arg(0);
|
||||
self.stack_inc();
|
||||
let code = self.emit_typedef_block(class_def);
|
||||
let code = self.emit_class_block(class_def);
|
||||
self.emit_load_const(code);
|
||||
self.emit_load_const(ident.inspect().clone());
|
||||
self.write_instr(Opcode::MAKE_FUNCTION);
|
||||
|
@ -1014,6 +1014,7 @@ impl CodeGenerator {
|
|||
// NOTE: use `TypeVar`, `Generic` in `typing` module
|
||||
// fn emit_poly_type_def(&mut self, sig: SubrSignature, body: DefBody) {}
|
||||
|
||||
/// Y = Inherit X => class Y(X): ...
|
||||
fn emit_require_type(&mut self, kind: TypeKind, require_or_sup: Expr) -> usize {
|
||||
log!(info "entered {} ({kind:?}, {require_or_sup})", fn_name!());
|
||||
match kind {
|
||||
|
@ -1638,17 +1639,13 @@ impl CodeGenerator {
|
|||
self.cancel_pop_top();
|
||||
}
|
||||
|
||||
fn emit_typedef_block(&mut self, class: ClassDef) -> CodeObj {
|
||||
fn emit_class_block(&mut self, class: ClassDef) -> CodeObj {
|
||||
log!(info "entered {}", fn_name!());
|
||||
let name = class.sig.ident().inspect().clone();
|
||||
self.unit_size += 1;
|
||||
let firstlineno = match (
|
||||
class.private_methods.get(0).and_then(|def| def.ln_begin()),
|
||||
class.public_methods.get(0).and_then(|def| def.ln_begin()),
|
||||
) {
|
||||
(Some(l), Some(r)) => l.min(r),
|
||||
(Some(line), None) | (None, Some(line)) => line,
|
||||
(None, None) => class.sig.ln_begin().unwrap(),
|
||||
let firstlineno = match class.methods.get(0).and_then(|def| def.ln_begin()) {
|
||||
Some(l) => l,
|
||||
None => class.sig.ln_begin().unwrap(),
|
||||
};
|
||||
self.units.push(CodeGenUnit::new(
|
||||
self.unit_size,
|
||||
|
@ -1660,33 +1657,13 @@ impl CodeGenerator {
|
|||
let mod_name = self.toplevel_block_codeobj().name.clone();
|
||||
self.emit_load_const(mod_name);
|
||||
self.emit_store_instr(Identifier::public("__module__"), Name);
|
||||
self.emit_load_const(name.clone());
|
||||
self.emit_load_const(name);
|
||||
self.emit_store_instr(Identifier::public("__qualname__"), Name);
|
||||
self.emit_init_method(&class.sig, class.__new__.clone());
|
||||
if class.need_to_gen_new {
|
||||
self.emit_new_func(&class.sig, class.__new__);
|
||||
}
|
||||
for def in class.private_methods.into_iter() {
|
||||
match def.sig {
|
||||
Signature::Subr(sig) => self.emit_subr_def(Some(&name[..]), sig, def.body),
|
||||
Signature::Var(sig) => self.emit_var_def(sig, def.body),
|
||||
}
|
||||
// TODO: discard
|
||||
if self.cur_block().stack_len == 1 {
|
||||
self.emit_pop_top();
|
||||
}
|
||||
}
|
||||
for mut def in class.public_methods.into_iter() {
|
||||
def.sig.ident_mut().dot = Some(Token::dummy());
|
||||
match def.sig {
|
||||
Signature::Subr(sig) => self.emit_subr_def(Some(&name[..]), sig, def.body),
|
||||
Signature::Var(sig) => self.emit_var_def(sig, def.body),
|
||||
}
|
||||
// TODO: discard
|
||||
if self.cur_block().stack_len == 1 {
|
||||
self.emit_pop_top();
|
||||
}
|
||||
}
|
||||
self.emit_frameless_block(class.methods, vec![]);
|
||||
self.emit_load_const(ValueObj::None);
|
||||
self.write_instr(RETURN_VALUE);
|
||||
self.write_arg(0u8);
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
use std::option::Option; // conflicting to Type::Option
|
||||
use std::option::Option;
|
||||
use std::path::PathBuf; // conflicting to Type::Option
|
||||
|
||||
use erg_common::config::{ErgConfig, Input};
|
||||
use erg_common::error::MultiErrorDisplay;
|
||||
|
@ -762,6 +763,7 @@ impl Context {
|
|||
|
||||
pub(crate) fn import_mod(
|
||||
&mut self,
|
||||
current_input: Input,
|
||||
var_name: &VarName,
|
||||
mod_name: &hir::Expr,
|
||||
) -> TyCheckResult<()> {
|
||||
|
@ -812,7 +814,12 @@ impl Context {
|
|||
Self::init_py_time_mod(),
|
||||
);
|
||||
}
|
||||
_ => self.import_user_module(var_name, __name__, mod_cache),
|
||||
_ => self.import_user_module(
|
||||
current_input,
|
||||
var_name,
|
||||
__name__,
|
||||
mod_cache,
|
||||
),
|
||||
}
|
||||
} else {
|
||||
// maybe unreachable
|
||||
|
@ -843,9 +850,16 @@ impl Context {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
fn import_user_module(&self, var_name: &VarName, __name__: Str, mod_cache: &SharedModuleCache) {
|
||||
fn import_user_module(
|
||||
&self,
|
||||
_current_input: Input,
|
||||
var_name: &VarName,
|
||||
__name__: Str,
|
||||
mod_cache: &SharedModuleCache,
|
||||
) {
|
||||
let path = PathBuf::from(format!("{__name__}.er"));
|
||||
let cfg = ErgConfig {
|
||||
input: Input::File(format!("{__name__}.er")),
|
||||
input: Input::File(path),
|
||||
..ErgConfig::default()
|
||||
};
|
||||
let mut hir_builder = HIRBuilder::new(cfg, mod_cache.clone());
|
||||
|
|
|
@ -476,19 +476,9 @@ impl Context {
|
|||
}
|
||||
Ok(())
|
||||
}
|
||||
hir::Expr::ClassDef(type_def) => {
|
||||
for def in type_def.public_methods.iter_mut() {
|
||||
match &mut def.sig {
|
||||
hir::Signature::Var(var) => {
|
||||
var.t = self.deref_tyvar(mem::take(&mut var.t), var.loc())?;
|
||||
}
|
||||
hir::Signature::Subr(subr) => {
|
||||
subr.t = self.deref_tyvar(mem::take(&mut subr.t), subr.loc())?;
|
||||
}
|
||||
}
|
||||
for chunk in def.body.block.iter_mut() {
|
||||
self.resolve_expr_t(chunk)?;
|
||||
}
|
||||
hir::Expr::ClassDef(class_def) => {
|
||||
for def in class_def.methods.iter_mut() {
|
||||
self.resolve_expr_t(def)?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
|
|
@ -84,10 +84,10 @@ impl SideEffectChecker {
|
|||
Expr::Def(def) => {
|
||||
self.check_def(def);
|
||||
}
|
||||
Expr::ClassDef(type_def) => {
|
||||
Expr::ClassDef(class_def) => {
|
||||
// TODO: grow
|
||||
for def in type_def.public_methods.iter() {
|
||||
self.check_def(def);
|
||||
for def in class_def.methods.iter() {
|
||||
self.check_expr(def);
|
||||
}
|
||||
}
|
||||
Expr::Call(call) => {
|
||||
|
@ -211,9 +211,9 @@ impl SideEffectChecker {
|
|||
Expr::Def(def) => {
|
||||
self.check_def(def);
|
||||
}
|
||||
Expr::ClassDef(type_def) => {
|
||||
for def in type_def.public_methods.iter() {
|
||||
self.check_def(def);
|
||||
Expr::ClassDef(class_def) => {
|
||||
for def in class_def.methods.iter() {
|
||||
self.check_expr(def);
|
||||
}
|
||||
}
|
||||
Expr::Array(array) => match array {
|
||||
|
|
|
@ -1390,16 +1390,14 @@ pub struct ClassDef {
|
|||
/// The type of `new` that is automatically defined if not defined
|
||||
pub need_to_gen_new: bool,
|
||||
pub __new__: Type,
|
||||
pub private_methods: RecordAttrs,
|
||||
pub public_methods: RecordAttrs,
|
||||
pub methods: Block,
|
||||
}
|
||||
|
||||
impl NestedDisplay for ClassDef {
|
||||
fn fmt_nest(&self, f: &mut fmt::Formatter<'_>, level: usize) -> fmt::Result {
|
||||
self.sig.fmt_nest(f, level)?;
|
||||
writeln!(f, ":")?;
|
||||
self.private_methods.fmt_nest(f, level + 1)?;
|
||||
self.public_methods.fmt_nest(f, level + 1)
|
||||
self.methods.fmt_nest(f, level + 1)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1432,8 +1430,7 @@ impl ClassDef {
|
|||
require_or_sup: Expr,
|
||||
need_to_gen_new: bool,
|
||||
__new__: Type,
|
||||
private_methods: RecordAttrs,
|
||||
public_methods: RecordAttrs,
|
||||
methods: Block,
|
||||
) -> Self {
|
||||
Self {
|
||||
kind,
|
||||
|
@ -1441,8 +1438,7 @@ impl ClassDef {
|
|||
require_or_sup: Box::new(require_or_sup),
|
||||
need_to_gen_new,
|
||||
__new__,
|
||||
private_methods,
|
||||
public_methods,
|
||||
methods,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,8 +3,8 @@
|
|||
extern crate erg_common;
|
||||
pub extern crate erg_parser;
|
||||
|
||||
mod builder;
|
||||
mod check;
|
||||
pub mod builder;
|
||||
pub mod check;
|
||||
mod compile;
|
||||
pub use compile::*;
|
||||
mod codegen;
|
||||
|
|
|
@ -1,19 +1,58 @@
|
|||
use erg_common::log;
|
||||
use erg_common::traits::Stream;
|
||||
|
||||
use crate::hir::{Expr, HIR};
|
||||
use crate::mod_cache::SharedModuleCache;
|
||||
use erg_parser::token::Token;
|
||||
|
||||
use erg_type::value::TypeKind;
|
||||
use erg_type::{SubrKind, SubrType, Type};
|
||||
|
||||
use crate::hir::{Block, ClassDef, Expr, Record, RecordAttrs, HIR};
|
||||
use crate::mod_cache::{ModuleEntry, SharedModuleCache};
|
||||
|
||||
pub struct Linker {}
|
||||
|
||||
impl Linker {
|
||||
pub fn link(mod_cache: SharedModuleCache) -> HIR {
|
||||
log!(info "the linking process has started.");
|
||||
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() => {}
|
||||
// x = import "mod"
|
||||
// ↓
|
||||
// class x:
|
||||
// ...
|
||||
Expr::Def(ref def) if def.def_kind().is_module() => {
|
||||
// let sig = option_enum_unwrap!(&def.sig, Signature::Var)
|
||||
// .unwrap_or_else(|| todo!("module subroutines are not allowed"));
|
||||
if let Some(ModuleEntry { hir: Some(hir), .. }) =
|
||||
mod_cache.remove(def.sig.ident().inspect())
|
||||
{
|
||||
let block = Block::new(Vec::from(hir.module));
|
||||
let def = ClassDef::new(
|
||||
TypeKind::Class,
|
||||
def.sig.clone(),
|
||||
Expr::Record(Record::new(
|
||||
Token::dummy(),
|
||||
Token::dummy(),
|
||||
RecordAttrs::empty(),
|
||||
)),
|
||||
false,
|
||||
Type::Subr(SubrType::new(
|
||||
SubrKind::Func,
|
||||
vec![],
|
||||
None,
|
||||
vec![],
|
||||
Type::Failure,
|
||||
)),
|
||||
block,
|
||||
);
|
||||
*chunk = Expr::ClassDef(def);
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
log!(info "linked: {main_mod_hir}");
|
||||
main_mod_hir
|
||||
}
|
||||
}
|
||||
|
|
|
@ -31,12 +31,22 @@ use crate::mod_cache::SharedModuleCache;
|
|||
use crate::varinfo::VarKind;
|
||||
use Visibility::*;
|
||||
|
||||
pub struct ASTLowererRunner {
|
||||
/// Singleton that checks types of an AST, and convert (lower) it into a HIR
|
||||
#[derive(Debug)]
|
||||
pub struct ASTLowerer {
|
||||
cfg: ErgConfig,
|
||||
lowerer: ASTLowerer,
|
||||
pub(crate) ctx: Context,
|
||||
errs: LowerErrors,
|
||||
warns: LowerWarnings,
|
||||
}
|
||||
|
||||
impl Runnable for ASTLowererRunner {
|
||||
impl Default for ASTLowerer {
|
||||
fn default() -> Self {
|
||||
Self::new_with_cache(ErgConfig::default(), SharedModuleCache::new())
|
||||
}
|
||||
}
|
||||
|
||||
impl Runnable for ASTLowerer {
|
||||
type Err = CompileError;
|
||||
type Errs = CompileErrors;
|
||||
const NAME: &'static str = "Erg lowerer";
|
||||
|
@ -47,27 +57,21 @@ impl Runnable for ASTLowererRunner {
|
|||
}
|
||||
|
||||
fn new(cfg: ErgConfig) -> Self {
|
||||
Self {
|
||||
cfg,
|
||||
lowerer: ASTLowerer::new(SharedModuleCache::new()),
|
||||
}
|
||||
Self::new_with_cache(cfg, SharedModuleCache::new())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn finish(&mut self) {}
|
||||
|
||||
fn clear(&mut self) {
|
||||
self.lowerer.errs.clear();
|
||||
self.lowerer.warns.clear();
|
||||
self.errs.clear();
|
||||
self.warns.clear();
|
||||
}
|
||||
|
||||
fn exec(&mut self) -> Result<(), Self::Errs> {
|
||||
let mut ast_builder = ASTBuilder::new(self.cfg.copy());
|
||||
let ast = ast_builder.build()?;
|
||||
let (hir, _, warns) = self
|
||||
.lowerer
|
||||
.lower(ast, "exec")
|
||||
.map_err(|errs| self.convert(errs))?;
|
||||
let (hir, _, warns) = self.lower(ast, "exec").map_err(|errs| self.convert(errs))?;
|
||||
if self.cfg.verbose >= 2 {
|
||||
let warns = self.convert(warns);
|
||||
warns.fmt_all_stderr();
|
||||
|
@ -79,45 +83,27 @@ impl Runnable for ASTLowererRunner {
|
|||
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 (hir, ..) = self
|
||||
.lowerer
|
||||
.lower(ast, "eval")
|
||||
.map_err(|errs| self.convert(errs))?;
|
||||
let (hir, ..) = self.lower(ast, "eval").map_err(|errs| self.convert(errs))?;
|
||||
Ok(format!("{hir}"))
|
||||
}
|
||||
}
|
||||
|
||||
impl ASTLowererRunner {
|
||||
impl ASTLowerer {
|
||||
pub fn new_with_cache(cfg: ErgConfig, mod_cache: SharedModuleCache) -> Self {
|
||||
Self {
|
||||
cfg,
|
||||
ctx: Context::new_main_module(mod_cache),
|
||||
errs: LowerErrors::empty(),
|
||||
warns: LowerWarnings::empty(),
|
||||
}
|
||||
}
|
||||
|
||||
fn convert(&self, errs: LowerErrors) -> CompileErrors {
|
||||
errs.into_iter()
|
||||
.map(|e| CompileError::new(e.core, self.input().clone(), e.caused_by))
|
||||
.collect::<Vec<_>>()
|
||||
.into()
|
||||
}
|
||||
}
|
||||
|
||||
/// Singleton that checks types of an AST, and convert (lower) it into a HIR
|
||||
#[derive(Debug)]
|
||||
pub struct ASTLowerer {
|
||||
pub(crate) ctx: Context,
|
||||
errs: LowerErrors,
|
||||
warns: LowerWarnings,
|
||||
}
|
||||
|
||||
impl Default for ASTLowerer {
|
||||
fn default() -> Self {
|
||||
Self::new(SharedModuleCache::new())
|
||||
}
|
||||
}
|
||||
|
||||
impl ASTLowerer {
|
||||
pub fn new(mod_cache: SharedModuleCache) -> Self {
|
||||
Self {
|
||||
ctx: Context::new_main_module(mod_cache),
|
||||
errs: LowerErrors::empty(),
|
||||
warns: LowerWarnings::empty(),
|
||||
}
|
||||
}
|
||||
|
||||
fn return_t_check(
|
||||
&self,
|
||||
|
@ -601,11 +587,12 @@ impl ASTLowerer {
|
|||
match block.first().unwrap() {
|
||||
hir::Expr::Call(call) => {
|
||||
if call.is_import_call() {
|
||||
self.ctx
|
||||
.outer
|
||||
.as_mut()
|
||||
.unwrap()
|
||||
.import_mod(&ident.name, &call.args.pos_args.first().unwrap().expr)?;
|
||||
let current_input = self.input().clone();
|
||||
self.ctx.outer.as_mut().unwrap().import_mod(
|
||||
current_input,
|
||||
&ident.name,
|
||||
&call.args.pos_args.first().unwrap().expr,
|
||||
)?;
|
||||
}
|
||||
}
|
||||
_other => {}
|
||||
|
@ -660,8 +647,7 @@ impl ASTLowerer {
|
|||
fn lower_class_def(&mut self, class_def: ast::ClassDef) -> LowerResult<hir::ClassDef> {
|
||||
log!(info "entered {}({class_def})", fn_name!());
|
||||
let mut hir_def = self.lower_def(class_def.def)?;
|
||||
let mut private_methods = hir::RecordAttrs::empty();
|
||||
let mut public_methods = hir::RecordAttrs::empty();
|
||||
let mut hir_methods = hir::Block::empty();
|
||||
for mut methods in class_def.methods_list.into_iter() {
|
||||
let (class, impl_trait) = match &methods.class {
|
||||
ast::TypeSpec::TypeApp { spec, args } => {
|
||||
|
@ -731,19 +717,11 @@ impl ASTLowerer {
|
|||
self.ctx.preregister_def(def)?;
|
||||
}
|
||||
for def in methods.defs.into_iter() {
|
||||
if methods.vis.is(TokenKind::Dot) {
|
||||
let def = self.lower_def(def).map_err(|e| {
|
||||
self.pop_append_errs();
|
||||
e
|
||||
})?;
|
||||
public_methods.push(def);
|
||||
} else {
|
||||
let def = self.lower_def(def).map_err(|e| {
|
||||
self.pop_append_errs();
|
||||
e
|
||||
})?;
|
||||
private_methods.push(def);
|
||||
}
|
||||
hir_methods.push(hir::Expr::Def(def));
|
||||
}
|
||||
match self.ctx.pop() {
|
||||
Ok(methods) => {
|
||||
|
@ -782,8 +760,7 @@ impl ASTLowerer {
|
|||
require_or_sup,
|
||||
need_to_gen_new,
|
||||
__new__,
|
||||
private_methods,
|
||||
public_methods,
|
||||
hir_methods,
|
||||
))
|
||||
}
|
||||
|
||||
|
|
|
@ -8,7 +8,8 @@ use std::thread;
|
|||
use erg_common::config::ErgConfig;
|
||||
use erg_common::traits::Runnable;
|
||||
|
||||
use erg_compiler::lower::ASTLowererRunner;
|
||||
use erg_compiler::check::Checker;
|
||||
use erg_compiler::lower::ASTLowerer;
|
||||
use erg_compiler::Compiler;
|
||||
|
||||
use erg_parser::lex::LexerRunner;
|
||||
|
@ -26,7 +27,10 @@ fn run() {
|
|||
ParserRunner::run(cfg);
|
||||
}
|
||||
"lower" => {
|
||||
ASTLowererRunner::run(cfg);
|
||||
ASTLowerer::run(cfg);
|
||||
}
|
||||
"check" => {
|
||||
Checker::run(cfg);
|
||||
}
|
||||
"compile" | "exec" => {
|
||||
Compiler::run(cfg);
|
||||
|
|
|
@ -2916,6 +2916,7 @@ impl Def {
|
|||
DefKind::Other
|
||||
}
|
||||
}
|
||||
Some("import") => DefKind::Module,
|
||||
_ => DefKind::Other,
|
||||
},
|
||||
_ => DefKind::Other,
|
||||
|
|
|
@ -124,8 +124,8 @@ impl Deserializer {
|
|||
eprintln!("{:?} is not a filename", cfg.input);
|
||||
process::exit(1);
|
||||
};
|
||||
let codeobj = CodeObj::from_pyc(&filename[..])
|
||||
.unwrap_or_else(|_| panic!("failed to deserialize {filename}"));
|
||||
let codeobj = CodeObj::from_pyc(&filename)
|
||||
.unwrap_or_else(|_| panic!("failed to deserialize {}", filename.to_string_lossy()));
|
||||
println!("{}", codeobj.code_info());
|
||||
}
|
||||
|
||||
|
|
|
@ -11,7 +11,8 @@ use erg_common::traits::Runnable;
|
|||
use erg_parser::lex::LexerRunner;
|
||||
use erg_parser::ParserRunner;
|
||||
|
||||
use erg_compiler::lower::ASTLowererRunner;
|
||||
use erg_compiler::check::Checker;
|
||||
use erg_compiler::lower::ASTLowerer;
|
||||
use erg_compiler::Compiler;
|
||||
|
||||
use erg_type::deserialize::Deserializer;
|
||||
|
@ -28,7 +29,10 @@ fn run() {
|
|||
ParserRunner::run(cfg);
|
||||
}
|
||||
"lower" => {
|
||||
ASTLowererRunner::run(cfg);
|
||||
ASTLowerer::run(cfg);
|
||||
}
|
||||
"check" => {
|
||||
Checker::run(cfg);
|
||||
}
|
||||
"compile" => {
|
||||
Compiler::run(cfg);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue