mirror of https://github.com/mtshiba/pylyzer
feat: calculate exact location
This commit is contained in:
parent
1e4f4e5d75
commit
19c776ee43
|
|
@ -252,8 +252,9 @@ checksum = "7fcaabb2fef8c910e7f4c7ce9f67a1283a1715879a7c230ca9d6d1ae31f16d91"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "els"
|
name = "els"
|
||||||
version = "0.1.16-nightly.1"
|
version = "0.1.17-nightly.1"
|
||||||
source = "git+https://github.com/erg-lang/erg?branch=main#42ceab31e6a5be018682392565d2169b7096fe02"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f1673baf84122a20bdd635dbe9a354a637fdbed48d015dede90524106d2f58d1"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"erg_common",
|
"erg_common",
|
||||||
"erg_compiler",
|
"erg_compiler",
|
||||||
|
|
@ -273,8 +274,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "erg_common"
|
name = "erg_common"
|
||||||
version = "0.6.4-nightly.1"
|
version = "0.6.5-nightly.1"
|
||||||
source = "git+https://github.com/erg-lang/erg?branch=main#42ceab31e6a5be018682392565d2169b7096fe02"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "bef5341295c84d749e574c0d358993f8be7799aed9ed9e137f690c2c38042547"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"backtrace-on-stack-overflow",
|
"backtrace-on-stack-overflow",
|
||||||
"hermit-abi",
|
"hermit-abi",
|
||||||
|
|
@ -284,8 +286,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "erg_compiler"
|
name = "erg_compiler"
|
||||||
version = "0.6.4-nightly.1"
|
version = "0.6.5-nightly.1"
|
||||||
source = "git+https://github.com/erg-lang/erg?branch=main#42ceab31e6a5be018682392565d2169b7096fe02"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "56f13f38e0c160e52d13ecbf45a69a6a3e8b048415ce8ba0a434ca6f1ef418d1"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"erg_common",
|
"erg_common",
|
||||||
"erg_parser",
|
"erg_parser",
|
||||||
|
|
@ -293,8 +296,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "erg_parser"
|
name = "erg_parser"
|
||||||
version = "0.6.4-nightly.1"
|
version = "0.6.5-nightly.1"
|
||||||
source = "git+https://github.com/erg-lang/erg?branch=main#42ceab31e6a5be018682392565d2169b7096fe02"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "158c517a502b751bfefd0a2d233a6987d8b667854cd5398c4880a4f39ff81c5c"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"erg_common",
|
"erg_common",
|
||||||
"unicode-xid 0.2.4",
|
"unicode-xid 0.2.4",
|
||||||
|
|
@ -598,7 +602,7 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "py2erg"
|
name = "py2erg"
|
||||||
version = "0.0.5"
|
version = "0.0.6"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"erg_common",
|
"erg_common",
|
||||||
"erg_compiler",
|
"erg_compiler",
|
||||||
|
|
@ -607,7 +611,7 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "pylyzer"
|
name = "pylyzer"
|
||||||
version = "0.0.5"
|
version = "0.0.6"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"els",
|
"els",
|
||||||
"erg_common",
|
"erg_common",
|
||||||
|
|
@ -836,9 +840,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "serde_json"
|
name = "serde_json"
|
||||||
version = "1.0.92"
|
version = "1.0.93"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "7434af0dc1cbd59268aa98b4c22c131c0584d2232f6fb166efb993e2832e896a"
|
checksum = "cad406b69c91885b5107daf2c29572f6c8cdb3c66826821e286c533490c0bc76"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"itoa",
|
"itoa",
|
||||||
"ryu",
|
"ryu",
|
||||||
|
|
|
||||||
16
Cargo.toml
16
Cargo.toml
|
|
@ -15,20 +15,20 @@ members = [
|
||||||
]
|
]
|
||||||
|
|
||||||
[workspace.package]
|
[workspace.package]
|
||||||
version = "0.0.5"
|
version = "0.0.6"
|
||||||
authors = ["Shunsuke Shibayama <sbym1346@gmail.com>"]
|
authors = ["Shunsuke Shibayama <sbym1346@gmail.com>"]
|
||||||
license = "MIT OR Apache-2.0"
|
license = "MIT OR Apache-2.0"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
repository = "https://github.com/mtshiba/pylyzer"
|
repository = "https://github.com/mtshiba/pylyzer"
|
||||||
|
|
||||||
[workspace.dependencies]
|
[workspace.dependencies]
|
||||||
# erg_common = "0.6.1"
|
erg_common = { version = "0.6.5-nightly.1", features = ["py_compatible", "els"] }
|
||||||
# erg_compiler = "0.6.1"
|
erg_compiler = { version = "0.6.5-nightly.1", features = ["py_compatible", "els"] }
|
||||||
# els = "0.1.13"
|
els = { version = "0.1.17-nightly.1", features = ["py_compatible"] }
|
||||||
rustpython-parser = "0.1.2"
|
rustpython-parser = "0.1.2"
|
||||||
erg_compiler = { version = "0.6.4-nightly.1", git = "https://github.com/erg-lang/erg", branch = "main", features = ["py_compatible", "els"] }
|
# erg_compiler = { git = "https://github.com/erg-lang/erg", branch = "main", features = ["py_compatible", "els"] }
|
||||||
erg_common = { version = "0.6.4-nightly.1", git = "https://github.com/erg-lang/erg", branch = "main", features = ["py_compatible", "els"] }
|
# erg_common = { git = "https://github.com/erg-lang/erg", branch = "main", features = ["py_compatible", "els"] }
|
||||||
els = { version = "0.1.16-nightly.1", git = "https://github.com/erg-lang/erg", branch = "main", features = ["py_compatible"] }
|
# els = { git = "https://github.com/erg-lang/erg", branch = "main", features = ["py_compatible"] }
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
debug = ["erg_compiler/debug", "erg_common/debug", "py2erg/debug"]
|
debug = ["erg_compiler/debug", "erg_common/debug", "py2erg/debug"]
|
||||||
|
|
@ -38,7 +38,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 }
|
||||||
py2erg = { version = "0.0.5", path = "./crates/py2erg" }
|
py2erg = { version = "0.0.6", path = "./crates/py2erg" }
|
||||||
|
|
||||||
[lib]
|
[lib]
|
||||||
path = "src/lib.rs"
|
path = "src/lib.rs"
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,133 @@
|
||||||
|
use erg_common::log;
|
||||||
|
use rustpython_parser::ast::{
|
||||||
|
BooleanOperator, Comparison, ExpressionType, Keyword, Number, StringGroup,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub fn number_to_string(num: &Number) -> 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 {
|
||||||
|
ExpressionType::Identifier { name } => name.len(),
|
||||||
|
ExpressionType::Number { value } => number_to_string(value).len(),
|
||||||
|
ExpressionType::String { value } => string_length(value),
|
||||||
|
ExpressionType::Attribute { value, name } => length(&value.node) + name.len() + 1,
|
||||||
|
ExpressionType::Subscript { a, b } => length(&a.node) + length(&b.node) + 2,
|
||||||
|
ExpressionType::Tuple { elements } => elements
|
||||||
|
.iter()
|
||||||
|
.map(|elem| length(&elem.node))
|
||||||
|
.fold(0, |acc, x| acc + x + 2),
|
||||||
|
// - 2 + 2,
|
||||||
|
ExpressionType::List { elements } => elements
|
||||||
|
.iter()
|
||||||
|
.map(|elem| length(&elem.node))
|
||||||
|
.fold(0, |acc, x| acc + x + 2),
|
||||||
|
ExpressionType::Set { elements } => elements
|
||||||
|
.iter()
|
||||||
|
.map(|elem| length(&elem.node))
|
||||||
|
.fold(0, |acc, x| acc + x + 2),
|
||||||
|
ExpressionType::Call {
|
||||||
|
function,
|
||||||
|
args,
|
||||||
|
keywords,
|
||||||
|
} => {
|
||||||
|
let args_len = if args.is_empty() {
|
||||||
|
0
|
||||||
|
} else {
|
||||||
|
args.iter()
|
||||||
|
.map(|arg| length(&arg.node))
|
||||||
|
.fold(0, |acc, x| acc + x + 2)
|
||||||
|
- 2 // ,
|
||||||
|
};
|
||||||
|
let kw_len = if keywords.is_empty() {
|
||||||
|
0
|
||||||
|
} else {
|
||||||
|
keywords
|
||||||
|
.iter()
|
||||||
|
.map(keyword_length)
|
||||||
|
.fold(0, |acc, x| acc + x + 2)
|
||||||
|
- 2 // ,
|
||||||
|
};
|
||||||
|
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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,223 @@
|
||||||
|
use rustpython_parser::ast::{
|
||||||
|
BooleanOperator, Comparison, 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),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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::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::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)),
|
||||||
|
},
|
||||||
|
other => todo!("clone_expr: {:?}", other),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -14,7 +14,6 @@ use erg_compiler::erg_parser::ast::{
|
||||||
TypeBoundSpecs, TypeSpec, TypeSpecWithOp, UnaryOp, VarName, VarPattern, VarSignature,
|
TypeBoundSpecs, TypeSpec, TypeSpecWithOp, UnaryOp, VarName, VarPattern, VarSignature,
|
||||||
};
|
};
|
||||||
use erg_compiler::erg_parser::token::{Token, TokenKind, COLON, DOT, EQUAL};
|
use erg_compiler::erg_parser::token::{Token, TokenKind, COLON, DOT, EQUAL};
|
||||||
use erg_compiler::erg_parser::Parser;
|
|
||||||
use erg_compiler::error::CompileErrors;
|
use erg_compiler::error::CompileErrors;
|
||||||
use rustpython_parser::ast::Location as PyLocation;
|
use rustpython_parser::ast::Location as PyLocation;
|
||||||
use rustpython_parser::ast::{
|
use rustpython_parser::ast::{
|
||||||
|
|
@ -22,6 +21,8 @@ use rustpython_parser::ast::{
|
||||||
Program, StatementType, StringGroup, Suite, UnaryOperator,
|
Program, StatementType, StringGroup, Suite, UnaryOperator,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
use crate::ast_util::length;
|
||||||
|
use crate::clone::clone_loc_expr;
|
||||||
use crate::error::*;
|
use crate::error::*;
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
||||||
|
|
@ -372,8 +373,13 @@ impl ASTConverter {
|
||||||
let pat = self.convert_param_pattern(param.arg, param.location);
|
let pat = self.convert_param_pattern(param.arg, param.location);
|
||||||
let t_spec = param
|
let t_spec = param
|
||||||
.annotation
|
.annotation
|
||||||
.map(|anot| self.convert_type_spec(*anot))
|
.map(|anot| {
|
||||||
.map(|t_spec| TypeSpecWithOp::new(COLON, t_spec));
|
(
|
||||||
|
self.convert_type_spec(clone_loc_expr(&anot)),
|
||||||
|
self.convert_expr(*anot),
|
||||||
|
)
|
||||||
|
})
|
||||||
|
.map(|(t_spec, expr)| TypeSpecWithOp::new(COLON, t_spec, expr));
|
||||||
NonDefaultParamSignature::new(pat, t_spec)
|
NonDefaultParamSignature::new(pat, t_spec)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -551,13 +557,14 @@ impl ASTConverter {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn convert_expr(&mut self, expr: Located<ExpressionType>) -> Expr {
|
fn convert_expr(&mut self, expr: Located<ExpressionType>) -> Expr {
|
||||||
|
let expr_len = length(&expr.node);
|
||||||
match expr.node {
|
match expr.node {
|
||||||
ExpressionType::Number { value } => {
|
ExpressionType::Number { value } => {
|
||||||
let (kind, cont) = match value {
|
let (kind, cont) = match value {
|
||||||
Number::Integer { value } => (TokenKind::IntLit, value.to_string()),
|
Number::Integer { value } => (TokenKind::IntLit, value.to_string()),
|
||||||
Number::Float { value } => (TokenKind::RatioLit, value.to_string()),
|
Number::Float { value } => (TokenKind::RatioLit, value.to_string()),
|
||||||
Number::Complex { .. } => {
|
Number::Complex { .. } => {
|
||||||
return Expr::Dummy(Dummy::new(vec![]));
|
return Expr::Dummy(Dummy::new(None, vec![]));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
let token = Token::new(
|
let token = Token::new(
|
||||||
|
|
@ -570,7 +577,7 @@ impl ASTConverter {
|
||||||
}
|
}
|
||||||
ExpressionType::String { value } => {
|
ExpressionType::String { value } => {
|
||||||
let StringGroup::Constant{ value } = value else {
|
let StringGroup::Constant{ value } = value else {
|
||||||
return Expr::Dummy(Dummy::new(vec![]));
|
return Expr::Dummy(Dummy::new(None, vec![]));
|
||||||
};
|
};
|
||||||
let value = format!("\"{value}\"");
|
let value = format!("\"{value}\"");
|
||||||
// column - 2 because of the quotes
|
// column - 2 because of the quotes
|
||||||
|
|
@ -638,7 +645,22 @@ impl ASTConverter {
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|ex| PosArg::new(self.convert_expr(ex)))
|
.map(|ex| PosArg::new(self.convert_expr(ex)))
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
let args = Args::pos_only(pos_args, None);
|
let paren = {
|
||||||
|
let lp = Token::new(
|
||||||
|
TokenKind::LParen,
|
||||||
|
"(",
|
||||||
|
expr.location.row() as u32,
|
||||||
|
expr.location.column() as u32 - 1,
|
||||||
|
);
|
||||||
|
let rp = Token::new(
|
||||||
|
TokenKind::RParen,
|
||||||
|
")",
|
||||||
|
expr.location.row() as u32,
|
||||||
|
(expr.location.column() + expr_len) as u32 - 1,
|
||||||
|
);
|
||||||
|
(lp, rp)
|
||||||
|
};
|
||||||
|
let args = Args::pos_only(pos_args, Some(paren));
|
||||||
function.call_expr(args)
|
function.call_expr(args)
|
||||||
}
|
}
|
||||||
ExpressionType::Binop { a, op, b } => {
|
ExpressionType::Binop { a, op, b } => {
|
||||||
|
|
@ -654,7 +676,7 @@ impl ASTConverter {
|
||||||
// UnaryOperator::Not => (TokenKind::PreBitNot, "not"),
|
// UnaryOperator::Not => (TokenKind::PreBitNot, "not"),
|
||||||
UnaryOperator::Neg => (TokenKind::PreMinus, "-"),
|
UnaryOperator::Neg => (TokenKind::PreMinus, "-"),
|
||||||
UnaryOperator::Inv => (TokenKind::PreBitNot, "~"),
|
UnaryOperator::Inv => (TokenKind::PreBitNot, "~"),
|
||||||
_ => return Expr::Dummy(Dummy::new(vec![rhs])),
|
_ => return Expr::Dummy(Dummy::new(None, vec![rhs])),
|
||||||
};
|
};
|
||||||
let op = Token::from_str(kind, cont);
|
let op = Token::from_str(kind, cont);
|
||||||
Expr::UnaryOp(UnaryOp::new(op, rhs))
|
Expr::UnaryOp(UnaryOp::new(op, rhs))
|
||||||
|
|
@ -694,8 +716,12 @@ impl ASTConverter {
|
||||||
Expr::Accessor(Accessor::Ident(ident))
|
Expr::Accessor(Accessor::Ident(ident))
|
||||||
}
|
}
|
||||||
ExpressionType::Attribute { value, name } => {
|
ExpressionType::Attribute { value, name } => {
|
||||||
|
let attr_name_loc = PyLocation::new(
|
||||||
|
value.location.row(),
|
||||||
|
value.location.column() + length(&value.node) + 1,
|
||||||
|
);
|
||||||
let obj = self.convert_expr(*value);
|
let obj = self.convert_expr(*value);
|
||||||
let name = self.convert_attr_ident(name, expr.location);
|
let name = self.convert_attr_ident(name, attr_name_loc);
|
||||||
obj.attr_expr(name)
|
obj.attr_expr(name)
|
||||||
}
|
}
|
||||||
ExpressionType::Lambda { args, body } => {
|
ExpressionType::Lambda { args, body } => {
|
||||||
|
|
@ -740,7 +766,7 @@ impl ASTConverter {
|
||||||
.map(|(k, v)| {
|
.map(|(k, v)| {
|
||||||
KeyValue::new(
|
KeyValue::new(
|
||||||
k.map(|k| self.convert_expr(k))
|
k.map(|k| self.convert_expr(k))
|
||||||
.unwrap_or(Expr::Dummy(Dummy::empty())),
|
.unwrap_or(Expr::Dummy(Dummy::new(None, vec![]))),
|
||||||
self.convert_expr(v),
|
self.convert_expr(v),
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
@ -765,7 +791,7 @@ impl ASTConverter {
|
||||||
}
|
}
|
||||||
_other => {
|
_other => {
|
||||||
log!(err "unimplemented: {:?}", _other);
|
log!(err "unimplemented: {:?}", _other);
|
||||||
Expr::Dummy(Dummy::empty())
|
Expr::Dummy(Dummy::new(None, vec![]))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -859,7 +885,8 @@ impl ASTConverter {
|
||||||
let param_typ_spec = TypeSpec::PreDeclTy(PreDeclTypeSpec::Simple(
|
let param_typ_spec = TypeSpec::PreDeclTy(PreDeclTypeSpec::Simple(
|
||||||
SimpleTypeSpec::new(param_typ_ident.clone(), ConstArgs::empty()),
|
SimpleTypeSpec::new(param_typ_ident.clone(), ConstArgs::empty()),
|
||||||
));
|
));
|
||||||
let param_typ_spec = TypeSpecWithOp::new(COLON, param_typ_spec);
|
let expr = Expr::Accessor(Accessor::Ident(param_typ_ident.clone()));
|
||||||
|
let param_typ_spec = TypeSpecWithOp::new(COLON, param_typ_spec, expr);
|
||||||
let arg_typ_ident = Identifier::public_with_line(
|
let arg_typ_ident = Identifier::public_with_line(
|
||||||
DOT,
|
DOT,
|
||||||
arg_typ_name.into(),
|
arg_typ_name.into(),
|
||||||
|
|
@ -976,9 +1003,7 @@ impl ASTConverter {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
let Ok(expr) = Parser::type_spec_to_expr(type_asc.t_spec.clone()) else {
|
let expr = *type_asc.t_spec.t_spec_as_expr;
|
||||||
continue;
|
|
||||||
};
|
|
||||||
let body = DefBody::new(EQUAL, Block::new(vec![expr]), DefId(0));
|
let body = DefBody::new(EQUAL, Block::new(vec![expr]), DefId(0));
|
||||||
let def = Def::new(sig, body);
|
let def = Def::new(sig, body);
|
||||||
match &mut base_type {
|
match &mut base_type {
|
||||||
|
|
@ -1057,14 +1082,15 @@ impl ASTConverter {
|
||||||
&name,
|
&name,
|
||||||
);
|
);
|
||||||
self.errs.push(err);
|
self.errs.push(err);
|
||||||
Expr::Dummy(Dummy::empty())
|
Expr::Dummy(Dummy::new(None, vec![]))
|
||||||
} else {
|
} else {
|
||||||
let decos = decorator_list
|
let decos = decorator_list
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|ex| Decorator(self.convert_expr(ex)))
|
.map(|ex| Decorator(self.convert_expr(ex)))
|
||||||
.collect::<HashSet<_>>();
|
.collect::<HashSet<_>>();
|
||||||
self.register_name_info(&name, NameKind::Function);
|
self.register_name_info(&name, NameKind::Function);
|
||||||
let ident = self.convert_ident(name, loc);
|
let func_name_loc = PyLocation::new(loc.row(), loc.column() + 4);
|
||||||
|
let ident = self.convert_ident(name, func_name_loc);
|
||||||
self.namespace.push(ident.inspect().to_string());
|
self.namespace.push(ident.inspect().to_string());
|
||||||
let params = self.convert_params(args);
|
let params = self.convert_params(args);
|
||||||
let return_t = returns.map(|ret| self.convert_type_spec(ret));
|
let return_t = returns.map(|ret| self.convert_type_spec(ret));
|
||||||
|
|
@ -1107,7 +1133,8 @@ impl ASTConverter {
|
||||||
.map(|base| self.convert_expr(base))
|
.map(|base| self.convert_expr(base))
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
self.register_name_info(&name, NameKind::Class);
|
self.register_name_info(&name, NameKind::Class);
|
||||||
let ident = self.convert_ident(name, loc);
|
let class_name_loc = PyLocation::new(loc.row(), loc.column() + 6);
|
||||||
|
let ident = self.convert_ident(name, class_name_loc);
|
||||||
let sig = Signature::Var(VarSignature::new(VarPattern::Ident(ident.clone()), None));
|
let sig = Signature::Var(VarSignature::new(VarPattern::Ident(ident.clone()), None));
|
||||||
self.namespace.push(ident.inspect().to_string());
|
self.namespace.push(ident.inspect().to_string());
|
||||||
let (base_type, methods) = self.extract_method_list(ident, body);
|
let (base_type, methods) = self.extract_method_list(ident, body);
|
||||||
|
|
@ -1141,6 +1168,7 @@ impl ASTConverter {
|
||||||
annotation,
|
annotation,
|
||||||
value,
|
value,
|
||||||
} => {
|
} => {
|
||||||
|
let anot = self.convert_expr(clone_loc_expr(&annotation));
|
||||||
let t_spec = self.convert_type_spec(*annotation);
|
let t_spec = self.convert_type_spec(*annotation);
|
||||||
match target.node {
|
match target.node {
|
||||||
ExpressionType::Identifier { name } => {
|
ExpressionType::Identifier { name } => {
|
||||||
|
|
@ -1159,11 +1187,9 @@ impl ASTConverter {
|
||||||
} else {
|
} else {
|
||||||
// no registration because it's just a type ascription
|
// no registration because it's just a type ascription
|
||||||
let ident = self.convert_ident(name, stmt.location);
|
let ident = self.convert_ident(name, stmt.location);
|
||||||
let tasc = TypeAscription::new(
|
let t_spec = TypeSpecWithOp::new(COLON, t_spec, anot);
|
||||||
Expr::Accessor(Accessor::Ident(ident)),
|
let tasc =
|
||||||
COLON,
|
TypeAscription::new(Expr::Accessor(Accessor::Ident(ident)), t_spec);
|
||||||
t_spec,
|
|
||||||
);
|
|
||||||
Expr::TypeAscription(tasc)
|
Expr::TypeAscription(tasc)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1176,11 +1202,12 @@ impl ASTConverter {
|
||||||
let redef = ReDef::new(attr, expr);
|
let redef = ReDef::new(attr, expr);
|
||||||
Expr::ReDef(redef)
|
Expr::ReDef(redef)
|
||||||
} else {
|
} else {
|
||||||
let tasc = TypeAscription::new(Expr::Accessor(attr), COLON, t_spec);
|
let t_spec = TypeSpecWithOp::new(COLON, t_spec, anot);
|
||||||
|
let tasc = TypeAscription::new(Expr::Accessor(attr), t_spec);
|
||||||
Expr::TypeAscription(tasc)
|
Expr::TypeAscription(tasc)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_other => Expr::Dummy(Dummy::empty()),
|
_other => Expr::Dummy(Dummy::new(None, vec![])),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
StatementType::Assign { mut targets, value } => {
|
StatementType::Assign { mut targets, value } => {
|
||||||
|
|
@ -1198,9 +1225,13 @@ impl ASTConverter {
|
||||||
Expr::Def(def)
|
Expr::Def(def)
|
||||||
}
|
}
|
||||||
ExpressionType::Attribute { value: attr, name } => {
|
ExpressionType::Attribute { value: attr, name } => {
|
||||||
|
let attr_name_loc = PyLocation::new(
|
||||||
|
attr.location.row(),
|
||||||
|
attr.location.column() + length(&attr.node) + 1,
|
||||||
|
);
|
||||||
let attr = self
|
let attr = self
|
||||||
.convert_expr(*attr)
|
.convert_expr(*attr)
|
||||||
.attr(self.convert_attr_ident(name, lhs.location));
|
.attr(self.convert_attr_ident(name, attr_name_loc));
|
||||||
let expr = self.convert_expr(value);
|
let expr = self.convert_expr(value);
|
||||||
let adef = ReDef::new(attr, expr);
|
let adef = ReDef::new(attr, expr);
|
||||||
Expr::ReDef(adef)
|
Expr::ReDef(adef)
|
||||||
|
|
@ -1251,9 +1282,9 @@ impl ASTConverter {
|
||||||
defs.push(def);
|
defs.push(def);
|
||||||
defs.append(&mut blocks);
|
defs.append(&mut blocks);
|
||||||
}
|
}
|
||||||
Expr::Dummy(Dummy::new(defs))
|
Expr::Dummy(Dummy::new(None, defs))
|
||||||
}
|
}
|
||||||
_other => Expr::Dummy(Dummy::empty()),
|
_other => Expr::Dummy(Dummy::new(None, vec![])),
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
let value = self.convert_expr(value);
|
let value = self.convert_expr(value);
|
||||||
|
|
@ -1273,11 +1304,11 @@ impl ASTConverter {
|
||||||
defs.push(def);
|
defs.push(def);
|
||||||
}
|
}
|
||||||
_other => {
|
_other => {
|
||||||
defs.push(Expr::Dummy(Dummy::empty()));
|
defs.push(Expr::Dummy(Dummy::new(None, vec![])));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Expr::Dummy(Dummy::new(defs))
|
Expr::Dummy(Dummy::new(None, defs))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
StatementType::AugAssign { target, op, value } => {
|
StatementType::AugAssign { target, op, value } => {
|
||||||
|
|
@ -1318,7 +1349,7 @@ impl ASTConverter {
|
||||||
let adef = ReDef::new(attr, Expr::BinOp(bin));
|
let adef = ReDef::new(attr, Expr::BinOp(bin));
|
||||||
Expr::ReDef(adef)
|
Expr::ReDef(adef)
|
||||||
}
|
}
|
||||||
_other => Expr::Dummy(Dummy::empty()),
|
_other => Expr::Dummy(Dummy::new(None, vec![])),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
StatementType::FunctionDef {
|
StatementType::FunctionDef {
|
||||||
|
|
@ -1464,7 +1495,7 @@ impl ASTConverter {
|
||||||
};
|
};
|
||||||
imports.push(Expr::Def(def));
|
imports.push(Expr::Def(def));
|
||||||
}
|
}
|
||||||
Expr::Dummy(Dummy::new(imports))
|
Expr::Dummy(Dummy::new(None, imports))
|
||||||
}
|
}
|
||||||
StatementType::ImportFrom {
|
StatementType::ImportFrom {
|
||||||
level: _,
|
level: _,
|
||||||
|
|
@ -1521,6 +1552,7 @@ impl ASTConverter {
|
||||||
imports.push(Expr::Def(def));
|
imports.push(Expr::Def(def));
|
||||||
}
|
}
|
||||||
let imports = Dummy::new(
|
let imports = Dummy::new(
|
||||||
|
None,
|
||||||
vec![moddef]
|
vec![moddef]
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.chain(imports.into_iter())
|
.chain(imports.into_iter())
|
||||||
|
|
@ -1548,7 +1580,7 @@ impl ASTConverter {
|
||||||
.collect(),
|
.collect(),
|
||||||
(None, None) => chunks.collect(),
|
(None, None) => chunks.collect(),
|
||||||
};
|
};
|
||||||
Expr::Dummy(Dummy::new(dummy))
|
Expr::Dummy(Dummy::new(None, dummy))
|
||||||
}
|
}
|
||||||
StatementType::With {
|
StatementType::With {
|
||||||
is_async: _,
|
is_async: _,
|
||||||
|
|
@ -1567,7 +1599,7 @@ impl ASTConverter {
|
||||||
}
|
}
|
||||||
_other => {
|
_other => {
|
||||||
log!(err "unimplemented: {:?}", _other);
|
log!(err "unimplemented: {:?}", _other);
|
||||||
Expr::Dummy(Dummy::empty())
|
Expr::Dummy(Dummy::new(None, vec![]))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,5 @@
|
||||||
|
mod ast_util;
|
||||||
|
mod clone;
|
||||||
mod convert;
|
mod convert;
|
||||||
mod error;
|
mod error;
|
||||||
mod gen_decl;
|
mod gen_decl;
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue