mirror of https://github.com/mtshiba/pylyzer
Merge pull request #37 from youknowone/trial
upgrade rustpython-parser (not going to be finished)
This commit is contained in:
commit
58c1245b72
File diff suppressed because it is too large
Load Diff
10
Cargo.toml
10
Cargo.toml
|
|
@ -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]
|
||||||
|
|
|
||||||
|
|
@ -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 }
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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,
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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(¶ms.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(¶ms.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
|
|
@ -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;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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};
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
|
|
||||||
|
|
@ -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(),
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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};
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue