Merge pull request #37 from youknowone/trial

upgrade rustpython-parser (not going to be finished)
This commit is contained in:
Shunsuke Shibayama 2023-06-10 23:29:53 +09:00 committed by GitHub
commit 58c1245b72
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 894 additions and 1359 deletions

773
Cargo.lock generated

File diff suppressed because it is too large Load Diff

View File

@ -22,10 +22,11 @@ edition = "2021"
repository = "https://github.com/mtshiba/pylyzer" repository = "https://github.com/mtshiba/pylyzer"
[workspace.dependencies] [workspace.dependencies]
erg_common = { version = "0.6.14-nightly.4", features = ["py_compat", "els"] } erg_common = { version = "0.6.15-nightly.0", features = ["py_compat", "els"] }
erg_compiler = { version = "0.6.14-nightly.4", features = ["py_compat", "els"] } erg_compiler = { version = "0.6.15-nightly.0", features = ["py_compat", "els"] }
els = { version = "0.1.26-nightly.4", features = ["py_compat"] } els = { version = "0.1.27-nightly.0", features = ["py_compat"] }
rustpython-parser = "0.1.2" rustpython-parser = { git = "https://github.com/RustPython/Parser", version = "0.2.0", features = ["all-nodes-with-ranges", "location"] }
rustpython-ast = { git = "https://github.com/RustPython/Parser", version = "0.2.0", features = ["all-nodes-with-ranges", "location"] }
# erg_compiler = { git = "https://github.com/erg-lang/erg", branch = "main", features = ["py_compat", "els"] } # erg_compiler = { git = "https://github.com/erg-lang/erg", branch = "main", features = ["py_compat", "els"] }
# erg_common = { git = "https://github.com/erg-lang/erg", branch = "main", features = ["py_compat", "els"] } # erg_common = { git = "https://github.com/erg-lang/erg", branch = "main", features = ["py_compat", "els"] }
# els = { git = "https://github.com/erg-lang/erg", branch = "main", features = ["py_compat"] } # els = { git = "https://github.com/erg-lang/erg", branch = "main", features = ["py_compat"] }
@ -45,6 +46,7 @@ erg_compiler = { workspace = true }
erg_common = { workspace = true } erg_common = { workspace = true }
els = { workspace = true } els = { workspace = true }
rustpython-parser = { workspace = true } rustpython-parser = { workspace = true }
rustpython-ast = { workspace = true }
py2erg = { version = "0.0.31", path = "./crates/py2erg" } py2erg = { version = "0.0.31", path = "./crates/py2erg" }
[lib] [lib]

View File

@ -14,6 +14,7 @@ debug = ["erg_compiler/debug", "erg_common/debug"]
[dependencies] [dependencies]
rustpython-parser = { workspace = true } rustpython-parser = { workspace = true }
rustpython-ast = { workspace = true }
erg_common = { workspace = true } erg_common = { workspace = true }
erg_compiler = { workspace = true } erg_compiler = { workspace = true }

View File

@ -1,131 +1,10 @@
use erg_common::log; use rustpython_parser::ast::located::Expr;
use rustpython_parser::ast::{
BooleanOperator, Comparison, ExpressionType, Keyword, Number, StringGroup,
};
pub fn number_to_string(num: &Number) -> String { pub fn accessor_name(expr: Expr) -> Option<String> {
match num {
Number::Integer { value } => value.to_string(),
Number::Float { value } => value.to_string(),
Number::Complex { real, imag } => format!("{real}+{imag}j"),
}
}
pub fn keyword_length(keyword: &Keyword) -> usize {
if let Some(name) = &keyword.name {
name.len() + 1 + length(&keyword.value.node)
} else {
length(&keyword.value.node)
}
}
pub fn string_length(string: &StringGroup) -> usize {
match string {
StringGroup::Constant { value } => value.len(),
StringGroup::Joined { values } => values.iter().map(string_length).sum(),
other => {
log!(err "{other:?}");
0
}
}
}
pub fn comp_to_string(comp: &Comparison) -> String {
match comp {
Comparison::In => "in".to_string(),
Comparison::NotIn => "not in".to_string(),
Comparison::Is => "is".to_string(),
Comparison::IsNot => "is not".to_string(),
Comparison::Less => "<".to_string(),
Comparison::Greater => ">".to_string(),
Comparison::Equal => "==".to_string(),
Comparison::NotEqual => "!=".to_string(),
Comparison::LessOrEqual => "<=".to_string(),
Comparison::GreaterOrEqual => ">=".to_string(),
}
}
pub fn length(expr: &ExpressionType) -> usize {
match expr { match expr {
ExpressionType::Identifier { name } => name.len(), Expr::Name(name) => Some(name.id.to_string()),
ExpressionType::Number { value } => number_to_string(value).len(), Expr::Attribute(attr) => {
ExpressionType::String { value } => string_length(value), accessor_name(*attr.value).map(|value| format!("{value}.{}", attr.attr))
ExpressionType::Attribute { value, name } => length(&value.node) + name.len() + 1,
ExpressionType::Subscript { a, b } => length(&a.node) + length(&b.node) + 2,
ExpressionType::Tuple { elements }
| ExpressionType::List { elements }
| ExpressionType::Set { elements } => {
if let (Some(first), Some(last)) = (elements.first(), elements.last()) {
2 + last.location.column() - first.location.column()
} else {
2
}
}
ExpressionType::Call {
function,
args,
keywords,
} => {
let args_len = if let (Some(first), Some(last)) = (args.first(), args.last()) {
last.location.column() - first.location.column()
} else {
0
};
let kw_len = if let (Some(first), Some(last)) = (keywords.first(), keywords.last()) {
last.value.location.column() - first.value.location.column()
} else {
0
};
length(&function.node) + args_len + kw_len + 2 // ()
}
ExpressionType::Unop { op: _, a } => 1 + length(&a.node),
ExpressionType::Binop { a, op: _, b } => length(&a.node) + 3 + length(&b.node),
ExpressionType::BoolOp { op, values } => match op {
BooleanOperator::And => values
.iter()
.map(|elem| length(&elem.node))
.fold(0, |acc, x| acc + x + 3),
BooleanOperator::Or => values
.iter()
.map(|elem| length(&elem.node))
.fold(0, |acc, x| acc + x + 2),
},
ExpressionType::Compare { vals, ops } => vals
.iter()
.zip(ops.iter())
.map(|(elem, op)| length(&elem.node) + comp_to_string(op).len())
.fold(0, |acc, x| acc + x + 2),
ExpressionType::IfExpression { test, body, orelse } => {
// x if y else z
length(&test.node) + 4 + length(&body.node) + 6 + length(&orelse.node)
}
ExpressionType::Lambda { args: _, body } => {
// lambda x: y
// TODO:
7 + 1 + length(&body.node)
}
ExpressionType::Await { value } => 5 + length(&value.node),
ExpressionType::Yield { value } => 5 + value.as_ref().map(|x| length(&x.node)).unwrap_or(0),
ExpressionType::NamedExpression { left, right } => {
// x := y
length(&left.node) + 4 + length(&right.node)
}
ExpressionType::Starred { value } => 1 + length(&value.node),
ExpressionType::False => 5,
ExpressionType::True | ExpressionType::None => 4,
ExpressionType::Ellipsis => 8,
other => {
log!(err "{other:?}");
0
}
}
}
pub fn accessor_name(expr: ExpressionType) -> Option<String> {
match expr {
ExpressionType::Identifier { name } => Some(name),
ExpressionType::Attribute { value, name } => {
accessor_name(value.node).map(|value| format!("{value}.{name}"))
} }
_ => None, _ => None,
} }

View File

@ -1,272 +0,0 @@
use rustpython_parser::ast::{
BooleanOperator, Comparison, Comprehension, ComprehensionKind, ExpressionType, Keyword,
Located, Number, Operator, Parameter, Parameters, StringGroup, UnaryOperator, Varargs,
};
fn clone_number(num: &Number) -> Number {
match num {
Number::Integer { value } => Number::Integer {
value: value.clone(),
},
Number::Float { value } => Number::Float { value: *value },
Number::Complex { real, imag } => Number::Complex {
real: *real,
imag: *imag,
},
}
}
fn clone_string_group(group: &StringGroup) -> StringGroup {
match group {
StringGroup::Constant { value } => StringGroup::Constant {
value: value.clone(),
},
StringGroup::FormattedValue {
value,
conversion,
spec,
} => StringGroup::FormattedValue {
value: Box::new(clone_loc_expr(value)),
conversion: *conversion,
spec: spec.as_deref().map(|sp| Box::new(clone_string_group(sp))),
},
StringGroup::Joined { values } => StringGroup::Joined {
values: values.iter().map(clone_string_group).collect::<Vec<_>>(),
},
}
}
fn clone_unary_op(op: &UnaryOperator) -> UnaryOperator {
match op {
UnaryOperator::Not => UnaryOperator::Not,
UnaryOperator::Inv => UnaryOperator::Inv,
UnaryOperator::Pos => UnaryOperator::Pos,
UnaryOperator::Neg => UnaryOperator::Neg,
}
}
fn clone_bin_op(op: &Operator) -> Operator {
match op {
Operator::Add => Operator::Add,
Operator::Sub => Operator::Sub,
Operator::Mult => Operator::Mult,
Operator::MatMult => Operator::MatMult,
Operator::Div => Operator::Div,
Operator::Mod => Operator::Mod,
Operator::Pow => Operator::Pow,
Operator::LShift => Operator::LShift,
Operator::RShift => Operator::RShift,
Operator::BitOr => Operator::BitOr,
Operator::BitXor => Operator::BitXor,
Operator::BitAnd => Operator::BitAnd,
Operator::FloorDiv => Operator::FloorDiv,
}
}
fn clone_comp_op(op: &Comparison) -> Comparison {
match op {
Comparison::Equal => Comparison::Equal,
Comparison::NotEqual => Comparison::NotEqual,
Comparison::Less => Comparison::Less,
Comparison::LessOrEqual => Comparison::LessOrEqual,
Comparison::Greater => Comparison::Greater,
Comparison::GreaterOrEqual => Comparison::GreaterOrEqual,
Comparison::Is => Comparison::Is,
Comparison::IsNot => Comparison::IsNot,
Comparison::In => Comparison::In,
Comparison::NotIn => Comparison::NotIn,
}
}
fn clone_bool_op(op: &BooleanOperator) -> BooleanOperator {
match op {
BooleanOperator::And => BooleanOperator::And,
BooleanOperator::Or => BooleanOperator::Or,
}
}
fn clone_param(param: &Parameter) -> Parameter {
Parameter {
location: param.location,
arg: param.arg.clone(),
annotation: param
.annotation
.as_deref()
.map(|a| Box::new(clone_loc_expr(a))),
}
}
fn clone_varargs(varargs: &Varargs) -> Varargs {
match varargs {
Varargs::None => Varargs::None,
Varargs::Unnamed => Varargs::Unnamed,
Varargs::Named(name) => Varargs::Named(clone_param(name)),
}
}
fn clone_params(params: &Parameters) -> Parameters {
Parameters {
posonlyargs_count: params.posonlyargs_count,
args: params.args.iter().map(clone_param).collect::<Vec<_>>(),
vararg: clone_varargs(&params.vararg),
kwonlyargs: params
.kwonlyargs
.iter()
.map(clone_param)
.collect::<Vec<_>>(),
kw_defaults: params
.kw_defaults
.iter()
.map(|def| def.as_ref().map(clone_loc_expr))
.collect::<Vec<_>>(),
kwarg: clone_varargs(&params.kwarg),
defaults: params
.defaults
.iter()
.map(clone_loc_expr)
.collect::<Vec<_>>(),
}
}
fn clone_kw(keyword: &Keyword) -> Keyword {
Keyword {
name: keyword.name.clone(),
value: clone_loc_expr(&keyword.value),
}
}
fn clone_comprehension_kind(kind: &ComprehensionKind) -> ComprehensionKind {
match kind {
ComprehensionKind::Dict { key, value } => ComprehensionKind::Dict {
key: clone_loc_expr(key),
value: clone_loc_expr(value),
},
ComprehensionKind::List { element } => ComprehensionKind::List {
element: clone_loc_expr(element),
},
ComprehensionKind::Set { element } => ComprehensionKind::Set {
element: clone_loc_expr(element),
},
ComprehensionKind::GeneratorExpression { element } => {
ComprehensionKind::GeneratorExpression {
element: clone_loc_expr(element),
}
}
}
}
pub fn clone_loc_expr(expr: &Located<ExpressionType>) -> Located<ExpressionType> {
Located {
node: clone_expr(&expr.node),
location: expr.location,
}
}
pub fn clone_expr(expr: &ExpressionType) -> ExpressionType {
match expr {
ExpressionType::None => ExpressionType::None,
ExpressionType::Ellipsis => ExpressionType::Ellipsis,
ExpressionType::True => ExpressionType::True,
ExpressionType::False => ExpressionType::False,
ExpressionType::Identifier { name } => ExpressionType::Identifier { name: name.clone() },
ExpressionType::Number { value } => ExpressionType::Number {
value: clone_number(value),
},
ExpressionType::String { value } => ExpressionType::String {
value: clone_string_group(value),
},
ExpressionType::Attribute { value, name } => ExpressionType::Attribute {
value: Box::new(clone_loc_expr(value)),
name: name.clone(),
},
ExpressionType::Subscript { a, b } => ExpressionType::Subscript {
a: Box::new(clone_loc_expr(a)),
b: Box::new(clone_loc_expr(b)),
},
ExpressionType::Slice { elements } => ExpressionType::Slice {
elements: elements.iter().map(clone_loc_expr).collect::<Vec<_>>(),
},
ExpressionType::Bytes { value } => ExpressionType::Bytes {
value: value.clone(),
},
ExpressionType::Call {
function,
args,
keywords,
} => ExpressionType::Call {
function: Box::new(clone_loc_expr(function)),
args: args.iter().map(clone_loc_expr).collect::<Vec<_>>(),
keywords: keywords.iter().map(clone_kw).collect::<Vec<_>>(),
},
ExpressionType::Unop { op, a } => ExpressionType::Unop {
op: clone_unary_op(op),
a: Box::new(clone_loc_expr(a)),
},
ExpressionType::Binop { a, op, b } => ExpressionType::Binop {
a: Box::new(clone_loc_expr(a)),
op: clone_bin_op(op),
b: Box::new(clone_loc_expr(b)),
},
ExpressionType::Compare { vals, ops } => ExpressionType::Compare {
ops: ops.iter().map(clone_comp_op).collect::<Vec<_>>(),
vals: vals.iter().map(clone_loc_expr).collect::<Vec<_>>(),
},
ExpressionType::BoolOp { op, values } => ExpressionType::BoolOp {
op: clone_bool_op(op),
values: values.iter().map(clone_loc_expr).collect::<Vec<_>>(),
},
ExpressionType::Lambda { args, body } => ExpressionType::Lambda {
args: Box::new(clone_params(args)),
body: Box::new(clone_loc_expr(body)),
},
ExpressionType::IfExpression { test, body, orelse } => ExpressionType::IfExpression {
test: Box::new(clone_loc_expr(test)),
body: Box::new(clone_loc_expr(body)),
orelse: Box::new(clone_loc_expr(orelse)),
},
ExpressionType::Dict { elements } => ExpressionType::Dict {
elements: elements
.iter()
.map(|(key, value)| (key.as_ref().map(clone_loc_expr), clone_loc_expr(value)))
.collect::<Vec<_>>(),
},
ExpressionType::Set { elements } => ExpressionType::Set {
elements: elements.iter().map(clone_loc_expr).collect::<Vec<_>>(),
},
ExpressionType::List { elements } => ExpressionType::List {
elements: elements.iter().map(clone_loc_expr).collect::<Vec<_>>(),
},
ExpressionType::Tuple { elements } => ExpressionType::Tuple {
elements: elements.iter().map(clone_loc_expr).collect::<Vec<_>>(),
},
ExpressionType::Yield { value } => ExpressionType::Yield {
value: value.as_ref().map(|val| Box::new(clone_loc_expr(val))),
},
ExpressionType::YieldFrom { value } => ExpressionType::YieldFrom {
value: Box::new(clone_loc_expr(value)),
},
ExpressionType::Await { value } => ExpressionType::Await {
value: Box::new(clone_loc_expr(value)),
},
ExpressionType::NamedExpression { left, right } => ExpressionType::NamedExpression {
left: Box::new(clone_loc_expr(left)),
right: Box::new(clone_loc_expr(right)),
},
ExpressionType::Starred { value } => ExpressionType::Starred {
value: Box::new(clone_loc_expr(value)),
},
ExpressionType::Comprehension { kind, generators } => ExpressionType::Comprehension {
kind: Box::new(clone_comprehension_kind(kind)),
generators: generators
.iter()
.map(|gen| Comprehension {
location: gen.location,
target: clone_loc_expr(&gen.target),
iter: clone_loc_expr(&gen.iter),
ifs: gen.ifs.iter().map(clone_loc_expr).collect::<Vec<_>>(),
is_async: gen.is_async,
})
.collect::<Vec<_>>(),
},
}
}

File diff suppressed because it is too large Load Diff

View File

@ -1,5 +1,5 @@
use erg_common::config::Input;
use erg_common::error::{ErrorCore, ErrorKind, Location, SubMessage}; use erg_common::error::{ErrorCore, ErrorKind, Location, SubMessage};
use erg_common::io::Input;
use erg_common::switch_lang; use erg_common::switch_lang;
use erg_compiler::error::CompileError; use erg_compiler::error::CompileError;

View File

@ -1,7 +1,7 @@
use std::fs::File; use std::fs::File;
use std::io::{BufWriter, Write}; use std::io::{BufWriter, Write};
use erg_common::config::Input; use erg_common::io::Input;
use erg_common::log; use erg_common::log;
use erg_compiler::context::register::{CheckStatus, PylyzerStatus}; use erg_compiler::context::register::{CheckStatus, PylyzerStatus};
use erg_compiler::hir::{Expr, HIR}; use erg_compiler::hir::{Expr, HIR};

View File

@ -1,5 +1,4 @@
pub mod ast_util; pub mod ast_util;
mod clone;
mod convert; mod convert;
mod error; mod error;
mod gen_decl; mod gen_decl;

View File

@ -8,32 +8,45 @@ use erg_compiler::artifact::{BuildRunnable, Buildable, CompleteArtifact, Incompl
use erg_compiler::context::register::CheckStatus; use erg_compiler::context::register::CheckStatus;
use erg_compiler::context::ModuleContext; use erg_compiler::context::ModuleContext;
use erg_compiler::erg_parser::ast::{Module, AST}; use erg_compiler::erg_parser::ast::{Module, AST};
use erg_compiler::erg_parser::error::ParseErrors; use erg_compiler::erg_parser::error::{
CompleteArtifact as ParseArtifact, IncompleteArtifact as IncompleteParseArtifact, ParseErrors,
};
use erg_compiler::erg_parser::parse::Parsable; use erg_compiler::erg_parser::parse::Parsable;
use erg_compiler::error::{CompileError, CompileErrors}; use erg_compiler::error::{CompileError, CompileErrors};
use erg_compiler::lower::ASTLowerer; use erg_compiler::lower::ASTLowerer;
use erg_compiler::module::SharedCompilerResource; use erg_compiler::module::SharedCompilerResource;
use py2erg::{dump_decl_er, reserve_decl_er, ShadowingMode}; use py2erg::{dump_decl_er, reserve_decl_er, ShadowingMode};
use rustpython_parser::parser; use rustpython_ast::source_code::RandomLocator;
use rustpython_ast::{Fold, ModModule};
use rustpython_parser::{Parse, ParseErrorType};
use crate::handle_err; use crate::handle_err;
pub struct SimplePythonParser {} pub struct SimplePythonParser {}
impl Parsable for SimplePythonParser { impl Parsable for SimplePythonParser {
fn parse(code: String) -> Result<Module, ParseErrors> { fn parse(code: String) -> Result<ParseArtifact, IncompleteParseArtifact<Module, ParseErrors>> {
let py_program = parser::parse_program(&code).map_err(|_err| ParseErrors::empty())?; let py_program = ModModule::parse(&code, "<stdin>").map_err(|_err| ParseErrors::empty())?;
let mut locator = RandomLocator::new(&code);
// let mut locator = LinearLocator::new(&code);
let py_program = locator
.fold(py_program)
.map_err(|_err| ParseErrors::empty())?;
let shadowing = if cfg!(feature = "debug") { let shadowing = if cfg!(feature = "debug") {
ShadowingMode::Visible ShadowingMode::Visible
} else { } else {
ShadowingMode::Invisible ShadowingMode::Invisible
}; };
let converter = py2erg::ASTConverter::new(ErgConfig::default(), shadowing); let converter = py2erg::ASTConverter::new(ErgConfig::default(), shadowing);
let IncompleteArtifact{ object: Some(erg_module), errors, .. } = converter.convert_program(py_program) else { unreachable!() }; let IncompleteArtifact{ object: Some(erg_module), errors, warns } = converter.convert_program(py_program) else { unreachable!() };
if errors.is_empty() { if errors.is_empty() {
Ok(erg_module) Ok(ParseArtifact::new(erg_module, warns.into()))
} else { } else {
Err(ParseErrors::empty()) Err(IncompleteParseArtifact::new(
Some(erg_module),
warns.into(),
errors.into(),
))
} }
} }
} }
@ -109,17 +122,30 @@ impl PythonAnalyzer {
mode: &str, mode: &str,
) -> Result<CompleteArtifact, IncompleteArtifact> { ) -> Result<CompleteArtifact, IncompleteArtifact> {
let filename = self.cfg.input.filename(); let filename = self.cfg.input.filename();
let py_program = parser::parse_program(&py_code).map_err(|err| { let py_program = ModModule::parse(&py_code, &filename).map_err(|err| {
let mut locator = RandomLocator::new(&py_code);
// let mut locator = LinearLocator::new(&py_code);
let err = locator.locate_error::<_, ParseErrorType>(err);
let msg = err.to_string();
let loc = err.location.unwrap();
let core = ErrorCore::new( let core = ErrorCore::new(
vec![], vec![],
err.to_string(), msg,
0, 0,
ErrorKind::SyntaxError, ErrorKind::SyntaxError,
erg_common::error::Location::Line(err.location.row() as u32), erg_common::error::Location::range(
loc.row.get(),
loc.column.to_zero_indexed(),
loc.row.get(),
loc.column.to_zero_indexed(),
),
); );
let err = CompileError::new(core, self.cfg.input.clone(), "".into()); let err = CompileError::new(core, self.cfg.input.clone(), "".into());
IncompleteArtifact::new(None, CompileErrors::from(err), CompileErrors::empty()) IncompleteArtifact::new(None, CompileErrors::from(err), CompileErrors::empty())
})?; })?;
let mut locator = RandomLocator::new(&py_code);
// let mut locator = LinearLocator::new(&py_code);
let py_program = locator.fold(py_program).unwrap();
let shadowing = if cfg!(feature = "debug") { let shadowing = if cfg!(feature = "debug") {
ShadowingMode::Visible ShadowingMode::Visible
} else { } else {
@ -155,7 +181,7 @@ impl PythonAnalyzer {
} }
pub fn run(&mut self) { pub fn run(&mut self) {
if self.cfg.output_dir.is_some() { if self.cfg.dist_dir.is_some() {
reserve_decl_er(self.cfg.input.clone()); reserve_decl_er(self.cfg.input.clone());
} }
let py_code = self.cfg.input.read(); let py_code = self.cfg.input.read();
@ -169,13 +195,13 @@ impl PythonAnalyzer {
artifact.warns.len(), artifact.warns.len(),
self.cfg.input.unescaped_filename() self.cfg.input.unescaped_filename()
); );
artifact.warns.fmt_all_stderr(); artifact.warns.write_all_stderr();
} }
println!( println!(
"{GREEN}All checks OK{RESET}: {}", "{GREEN}All checks OK{RESET}: {}",
self.cfg.input.unescaped_filename() self.cfg.input.unescaped_filename()
); );
if self.cfg.output_dir.is_some() { if self.cfg.dist_dir.is_some() {
dump_decl_er( dump_decl_er(
self.cfg.input.clone(), self.cfg.input.clone(),
artifact.object, artifact.object,
@ -192,7 +218,7 @@ impl PythonAnalyzer {
artifact.warns.len(), artifact.warns.len(),
self.cfg.input.unescaped_filename() self.cfg.input.unescaped_filename()
); );
artifact.warns.fmt_all_stderr(); artifact.warns.write_all_stderr();
} }
let code = if artifact.errors.is_empty() { let code = if artifact.errors.is_empty() {
println!( println!(
@ -206,11 +232,11 @@ impl PythonAnalyzer {
artifact.errors.len(), artifact.errors.len(),
self.cfg.input.unescaped_filename() self.cfg.input.unescaped_filename()
); );
artifact.errors.fmt_all_stderr(); artifact.errors.write_all_stderr();
1 1
}; };
// Even if type checking fails, some APIs are still valid, so generate a file // Even if type checking fails, some APIs are still valid, so generate a file
if self.cfg.output_dir.is_some() { if self.cfg.dist_dir.is_some() {
dump_decl_er( dump_decl_er(
self.cfg.input.clone(), self.cfg.input.clone(),
artifact.object.unwrap(), artifact.object.unwrap(),

View File

@ -2,7 +2,8 @@ use std::env;
use std::path::PathBuf; use std::path::PathBuf;
use std::str::FromStr; use std::str::FromStr;
use erg_common::config::{ErgConfig, ErgMode, Input}; use erg_common::config::{ErgConfig, ErgMode};
use erg_common::io::Input;
use erg_common::switch_lang; use erg_common::switch_lang;
fn command_message() -> &'static str { fn command_message() -> &'static str {
@ -94,7 +95,7 @@ pub(crate) fn parse_args() -> ErgConfig {
cfg.quiet_repl = true; cfg.quiet_repl = true;
} }
"--dump-decl" => { "--dump-decl" => {
cfg.output_dir = Some(""); cfg.dist_dir = Some("");
} }
"--verbose" => { "--verbose" => {
cfg.verbose = args cfg.verbose = args

View File

@ -1,6 +1,7 @@
use std::path::PathBuf; use std::path::PathBuf;
use erg_common::config::{ErgConfig, Input}; use erg_common::config::ErgConfig;
use erg_common::io::Input;
use erg_common::spawn::exec_new_thread; use erg_common::spawn::exec_new_thread;
use erg_common::traits::Stream; use erg_common::traits::Stream;
use erg_compiler::artifact::{CompleteArtifact, IncompleteArtifact}; use erg_compiler::artifact::{CompleteArtifact, IncompleteArtifact};