From 19c776ee43b39322475bc4e23339163072ed7bf2 Mon Sep 17 00:00:00 2001 From: Shunsuke Shibayama Date: Mon, 13 Feb 2023 23:34:37 +0900 Subject: [PATCH] feat: calculate exact location --- Cargo.lock | 28 +++-- Cargo.toml | 16 +-- crates/py2erg/ast_util.rs | 133 +++++++++++++++++++++++ crates/py2erg/clone.rs | 223 ++++++++++++++++++++++++++++++++++++++ crates/py2erg/convert.rs | 98 +++++++++++------ crates/py2erg/lib.rs | 2 + 6 files changed, 447 insertions(+), 53 deletions(-) create mode 100644 crates/py2erg/ast_util.rs create mode 100644 crates/py2erg/clone.rs diff --git a/Cargo.lock b/Cargo.lock index a979b57..5f4a1b1 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -252,8 +252,9 @@ checksum = "7fcaabb2fef8c910e7f4c7ce9f67a1283a1715879a7c230ca9d6d1ae31f16d91" [[package]] name = "els" -version = "0.1.16-nightly.1" -source = "git+https://github.com/erg-lang/erg?branch=main#42ceab31e6a5be018682392565d2169b7096fe02" +version = "0.1.17-nightly.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1673baf84122a20bdd635dbe9a354a637fdbed48d015dede90524106d2f58d1" dependencies = [ "erg_common", "erg_compiler", @@ -273,8 +274,9 @@ dependencies = [ [[package]] name = "erg_common" -version = "0.6.4-nightly.1" -source = "git+https://github.com/erg-lang/erg?branch=main#42ceab31e6a5be018682392565d2169b7096fe02" +version = "0.6.5-nightly.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef5341295c84d749e574c0d358993f8be7799aed9ed9e137f690c2c38042547" dependencies = [ "backtrace-on-stack-overflow", "hermit-abi", @@ -284,8 +286,9 @@ dependencies = [ [[package]] name = "erg_compiler" -version = "0.6.4-nightly.1" -source = "git+https://github.com/erg-lang/erg?branch=main#42ceab31e6a5be018682392565d2169b7096fe02" +version = "0.6.5-nightly.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56f13f38e0c160e52d13ecbf45a69a6a3e8b048415ce8ba0a434ca6f1ef418d1" dependencies = [ "erg_common", "erg_parser", @@ -293,8 +296,9 @@ dependencies = [ [[package]] name = "erg_parser" -version = "0.6.4-nightly.1" -source = "git+https://github.com/erg-lang/erg?branch=main#42ceab31e6a5be018682392565d2169b7096fe02" +version = "0.6.5-nightly.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "158c517a502b751bfefd0a2d233a6987d8b667854cd5398c4880a4f39ff81c5c" dependencies = [ "erg_common", "unicode-xid 0.2.4", @@ -598,7 +602,7 @@ dependencies = [ [[package]] name = "py2erg" -version = "0.0.5" +version = "0.0.6" dependencies = [ "erg_common", "erg_compiler", @@ -607,7 +611,7 @@ dependencies = [ [[package]] name = "pylyzer" -version = "0.0.5" +version = "0.0.6" dependencies = [ "els", "erg_common", @@ -836,9 +840,9 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.92" +version = "1.0.93" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7434af0dc1cbd59268aa98b4c22c131c0584d2232f6fb166efb993e2832e896a" +checksum = "cad406b69c91885b5107daf2c29572f6c8cdb3c66826821e286c533490c0bc76" dependencies = [ "itoa", "ryu", diff --git a/Cargo.toml b/Cargo.toml index 52dfda8..dedccf4 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -15,20 +15,20 @@ members = [ ] [workspace.package] -version = "0.0.5" +version = "0.0.6" authors = ["Shunsuke Shibayama "] license = "MIT OR Apache-2.0" edition = "2021" repository = "https://github.com/mtshiba/pylyzer" [workspace.dependencies] -# erg_common = "0.6.1" -# erg_compiler = "0.6.1" -# els = "0.1.13" +erg_common = { version = "0.6.5-nightly.1", features = ["py_compatible", "els"] } +erg_compiler = { version = "0.6.5-nightly.1", features = ["py_compatible", "els"] } +els = { version = "0.1.17-nightly.1", features = ["py_compatible"] } 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_common = { version = "0.6.4-nightly.1", 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"] } +# erg_compiler = { 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 = { git = "https://github.com/erg-lang/erg", branch = "main", features = ["py_compatible"] } [features] debug = ["erg_compiler/debug", "erg_common/debug", "py2erg/debug"] @@ -38,7 +38,7 @@ erg_compiler = { workspace = true } erg_common = { workspace = true } els = { workspace = true } rustpython-parser = { workspace = true } -py2erg = { version = "0.0.5", path = "./crates/py2erg" } +py2erg = { version = "0.0.6", path = "./crates/py2erg" } [lib] path = "src/lib.rs" diff --git a/crates/py2erg/ast_util.rs b/crates/py2erg/ast_util.rs new file mode 100644 index 0000000..ecb3337 --- /dev/null +++ b/crates/py2erg/ast_util.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 + } + } +} diff --git a/crates/py2erg/clone.rs b/crates/py2erg/clone.rs new file mode 100644 index 0000000..97e5447 --- /dev/null +++ b/crates/py2erg/clone.rs @@ -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::>(), + }, + } +} + +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::>(), + vararg: clone_varargs(¶ms.vararg), + kwonlyargs: params + .kwonlyargs + .iter() + .map(clone_param) + .collect::>(), + kw_defaults: params + .kw_defaults + .iter() + .map(|def| def.as_ref().map(clone_loc_expr)) + .collect::>(), + kwarg: clone_varargs(¶ms.kwarg), + defaults: params + .defaults + .iter() + .map(clone_loc_expr) + .collect::>(), + } +} + +fn clone_kw(keyword: &Keyword) -> Keyword { + Keyword { + name: keyword.name.clone(), + value: clone_loc_expr(&keyword.value), + } +} + +pub fn clone_loc_expr(expr: &Located) -> Located { + 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::>(), + keywords: keywords.iter().map(clone_kw).collect::>(), + }, + 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::>(), + vals: vals.iter().map(clone_loc_expr).collect::>(), + }, + ExpressionType::BoolOp { op, values } => ExpressionType::BoolOp { + op: clone_bool_op(op), + values: values.iter().map(clone_loc_expr).collect::>(), + }, + 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::>(), + }, + ExpressionType::Set { elements } => ExpressionType::Set { + elements: elements.iter().map(clone_loc_expr).collect::>(), + }, + ExpressionType::List { elements } => ExpressionType::List { + elements: elements.iter().map(clone_loc_expr).collect::>(), + }, + ExpressionType::Tuple { elements } => ExpressionType::Tuple { + elements: elements.iter().map(clone_loc_expr).collect::>(), + }, + 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), + } +} diff --git a/crates/py2erg/convert.rs b/crates/py2erg/convert.rs index cab2368..829ef40 100644 --- a/crates/py2erg/convert.rs +++ b/crates/py2erg/convert.rs @@ -14,7 +14,6 @@ use erg_compiler::erg_parser::ast::{ TypeBoundSpecs, TypeSpec, TypeSpecWithOp, UnaryOp, VarName, VarPattern, VarSignature, }; use erg_compiler::erg_parser::token::{Token, TokenKind, COLON, DOT, EQUAL}; -use erg_compiler::erg_parser::Parser; use erg_compiler::error::CompileErrors; use rustpython_parser::ast::Location as PyLocation; use rustpython_parser::ast::{ @@ -22,6 +21,8 @@ use rustpython_parser::ast::{ Program, StatementType, StringGroup, Suite, UnaryOperator, }; +use crate::ast_util::length; +use crate::clone::clone_loc_expr; use crate::error::*; #[derive(Debug, Clone, PartialEq, Eq, Hash)] @@ -372,8 +373,13 @@ impl ASTConverter { let pat = self.convert_param_pattern(param.arg, param.location); let t_spec = param .annotation - .map(|anot| self.convert_type_spec(*anot)) - .map(|t_spec| TypeSpecWithOp::new(COLON, t_spec)); + .map(|anot| { + ( + 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) } @@ -551,13 +557,14 @@ impl ASTConverter { } fn convert_expr(&mut self, expr: Located) -> Expr { + let expr_len = length(&expr.node); match expr.node { ExpressionType::Number { value } => { let (kind, cont) = match value { Number::Integer { value } => (TokenKind::IntLit, value.to_string()), Number::Float { value } => (TokenKind::RatioLit, value.to_string()), Number::Complex { .. } => { - return Expr::Dummy(Dummy::new(vec![])); + return Expr::Dummy(Dummy::new(None, vec![])); } }; let token = Token::new( @@ -570,7 +577,7 @@ impl ASTConverter { } ExpressionType::String { value } => { let StringGroup::Constant{ value } = value else { - return Expr::Dummy(Dummy::new(vec![])); + return Expr::Dummy(Dummy::new(None, vec![])); }; let value = format!("\"{value}\""); // column - 2 because of the quotes @@ -638,7 +645,22 @@ impl ASTConverter { .into_iter() .map(|ex| PosArg::new(self.convert_expr(ex))) .collect::>(); - 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) } ExpressionType::Binop { a, op, b } => { @@ -654,7 +676,7 @@ impl ASTConverter { // UnaryOperator::Not => (TokenKind::PreBitNot, "not"), UnaryOperator::Neg => (TokenKind::PreMinus, "-"), 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); Expr::UnaryOp(UnaryOp::new(op, rhs)) @@ -694,8 +716,12 @@ impl ASTConverter { Expr::Accessor(Accessor::Ident(ident)) } 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 name = self.convert_attr_ident(name, expr.location); + let name = self.convert_attr_ident(name, attr_name_loc); obj.attr_expr(name) } ExpressionType::Lambda { args, body } => { @@ -740,7 +766,7 @@ impl ASTConverter { .map(|(k, v)| { KeyValue::new( 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), ) }) @@ -765,7 +791,7 @@ impl ASTConverter { } _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( 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( DOT, arg_typ_name.into(), @@ -976,9 +1003,7 @@ impl ASTConverter { continue; } }; - let Ok(expr) = Parser::type_spec_to_expr(type_asc.t_spec.clone()) else { - continue; - }; + let expr = *type_asc.t_spec.t_spec_as_expr; let body = DefBody::new(EQUAL, Block::new(vec![expr]), DefId(0)); let def = Def::new(sig, body); match &mut base_type { @@ -1057,14 +1082,15 @@ impl ASTConverter { &name, ); self.errs.push(err); - Expr::Dummy(Dummy::empty()) + Expr::Dummy(Dummy::new(None, vec![])) } else { let decos = decorator_list .into_iter() .map(|ex| Decorator(self.convert_expr(ex))) .collect::>(); 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()); let params = self.convert_params(args); let return_t = returns.map(|ret| self.convert_type_spec(ret)); @@ -1107,7 +1133,8 @@ impl ASTConverter { .map(|base| self.convert_expr(base)) .collect::>(); 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)); self.namespace.push(ident.inspect().to_string()); let (base_type, methods) = self.extract_method_list(ident, body); @@ -1141,6 +1168,7 @@ impl ASTConverter { annotation, value, } => { + let anot = self.convert_expr(clone_loc_expr(&annotation)); let t_spec = self.convert_type_spec(*annotation); match target.node { ExpressionType::Identifier { name } => { @@ -1159,11 +1187,9 @@ impl ASTConverter { } else { // no registration because it's just a type ascription let ident = self.convert_ident(name, stmt.location); - let tasc = TypeAscription::new( - Expr::Accessor(Accessor::Ident(ident)), - COLON, - t_spec, - ); + let t_spec = TypeSpecWithOp::new(COLON, t_spec, anot); + let tasc = + TypeAscription::new(Expr::Accessor(Accessor::Ident(ident)), t_spec); Expr::TypeAscription(tasc) } } @@ -1176,11 +1202,12 @@ impl ASTConverter { let redef = ReDef::new(attr, expr); Expr::ReDef(redef) } 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) } } - _other => Expr::Dummy(Dummy::empty()), + _other => Expr::Dummy(Dummy::new(None, vec![])), } } StatementType::Assign { mut targets, value } => { @@ -1198,9 +1225,13 @@ impl ASTConverter { Expr::Def(def) } ExpressionType::Attribute { value: attr, name } => { + let attr_name_loc = PyLocation::new( + attr.location.row(), + attr.location.column() + length(&attr.node) + 1, + ); let attr = self .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 adef = ReDef::new(attr, expr); Expr::ReDef(adef) @@ -1251,9 +1282,9 @@ impl ASTConverter { defs.push(def); 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 { let value = self.convert_expr(value); @@ -1273,11 +1304,11 @@ impl ASTConverter { defs.push(def); } _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 } => { @@ -1318,7 +1349,7 @@ impl ASTConverter { let adef = ReDef::new(attr, Expr::BinOp(bin)); Expr::ReDef(adef) } - _other => Expr::Dummy(Dummy::empty()), + _other => Expr::Dummy(Dummy::new(None, vec![])), } } StatementType::FunctionDef { @@ -1464,7 +1495,7 @@ impl ASTConverter { }; imports.push(Expr::Def(def)); } - Expr::Dummy(Dummy::new(imports)) + Expr::Dummy(Dummy::new(None, imports)) } StatementType::ImportFrom { level: _, @@ -1521,6 +1552,7 @@ impl ASTConverter { imports.push(Expr::Def(def)); } let imports = Dummy::new( + None, vec![moddef] .into_iter() .chain(imports.into_iter()) @@ -1548,7 +1580,7 @@ impl ASTConverter { .collect(), (None, None) => chunks.collect(), }; - Expr::Dummy(Dummy::new(dummy)) + Expr::Dummy(Dummy::new(None, dummy)) } StatementType::With { is_async: _, @@ -1567,7 +1599,7 @@ impl ASTConverter { } _other => { log!(err "unimplemented: {:?}", _other); - Expr::Dummy(Dummy::empty()) + Expr::Dummy(Dummy::new(None, vec![])) } } } diff --git a/crates/py2erg/lib.rs b/crates/py2erg/lib.rs index 093c98f..4436a4a 100644 --- a/crates/py2erg/lib.rs +++ b/crates/py2erg/lib.rs @@ -1,3 +1,5 @@ +mod ast_util; +mod clone; mod convert; mod error; mod gen_decl;