feat: calculate exact location

This commit is contained in:
Shunsuke Shibayama 2023-02-13 23:34:37 +09:00
parent 1e4f4e5d75
commit 19c776ee43
6 changed files with 447 additions and 53 deletions

28
Cargo.lock generated
View File

@ -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",

View File

@ -15,20 +15,20 @@ members = [
]
[workspace.package]
version = "0.0.5"
version = "0.0.6"
authors = ["Shunsuke Shibayama <sbym1346@gmail.com>"]
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"

133
crates/py2erg/ast_util.rs Normal file
View File

@ -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
}
}
}

223
crates/py2erg/clone.rs Normal file
View File

@ -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(&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),
}
}
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),
}
}

View File

@ -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<ExpressionType>) -> 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::<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)
}
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::<HashSet<_>>();
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::<Vec<_>>();
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![]))
}
}
}

View File

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