Allow multiple definition

This commit is contained in:
Shunsuke Shibayama 2022-12-23 11:31:14 +09:00
parent ca5604f67b
commit 0fc2348eb7
3 changed files with 166 additions and 94 deletions

12
Cargo.lock generated
View File

@ -206,7 +206,7 @@ checksum = "90e5c1c8368803113bf0c9584fc495a58b86dc8a29edbf8fe877d21d9507e797"
[[package]] [[package]]
name = "els" name = "els"
version = "0.1.11" version = "0.1.11"
source = "git+https://github.com/erg-lang/erg-language-server?branch=main#53928792101fc6e0768a1fffaa3decad3fd1ee36" source = "git+https://github.com/erg-lang/erg-language-server?branch=main#5b27e12f10581a40b170742dfd61a19c0796b8aa"
dependencies = [ dependencies = [
"erg_common", "erg_common",
"erg_compiler", "erg_compiler",
@ -227,7 +227,7 @@ dependencies = [
[[package]] [[package]]
name = "erg_common" name = "erg_common"
version = "0.6.0-beta.3" version = "0.6.0-beta.3"
source = "git+https://github.com/erg-lang/erg?branch=main#08aa4054a19828511ae36514276f42f35ad502ff" source = "git+https://github.com/erg-lang/erg?branch=main#da2ff544f9cc4f6b1f875c24e513599d5d7fc4f7"
dependencies = [ dependencies = [
"hermit-abi", "hermit-abi",
"libc", "libc",
@ -237,7 +237,7 @@ dependencies = [
[[package]] [[package]]
name = "erg_compiler" name = "erg_compiler"
version = "0.6.0-beta.3" version = "0.6.0-beta.3"
source = "git+https://github.com/erg-lang/erg?branch=main#08aa4054a19828511ae36514276f42f35ad502ff" source = "git+https://github.com/erg-lang/erg?branch=main#da2ff544f9cc4f6b1f875c24e513599d5d7fc4f7"
dependencies = [ dependencies = [
"erg_common", "erg_common",
"erg_parser", "erg_parser",
@ -246,7 +246,7 @@ dependencies = [
[[package]] [[package]]
name = "erg_parser" name = "erg_parser"
version = "0.6.0-beta.3" version = "0.6.0-beta.3"
source = "git+https://github.com/erg-lang/erg?branch=main#08aa4054a19828511ae36514276f42f35ad502ff" source = "git+https://github.com/erg-lang/erg?branch=main#da2ff544f9cc4f6b1f875c24e513599d5d7fc4f7"
dependencies = [ dependencies = [
"erg_common", "erg_common",
"unicode-xid 0.2.4", "unicode-xid 0.2.4",
@ -372,9 +372,9 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
[[package]] [[package]]
name = "libc" name = "libc"
version = "0.2.138" version = "0.2.139"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "db6d7e329c562c5dfab7a46a2afabc8b987ab9a4834c9d1ca04dc54c1546cef8" checksum = "201de327520df007757c1f0adce6e827fe8562fbc28bfd9c15571c66ca1f5f79"
[[package]] [[package]]
name = "log" name = "log"

View File

@ -52,10 +52,12 @@ pylyzer converts Python ASTs to Erg ASTs and passes them to Erg's type checker.
## Limitation ## Limitation
* pylyzer's type inspector only assumes (potentially) statically typed code, so you cannot use `exec`, etc. * pylyzer's type inspector only assumes (potentially) statically typed code, so you cannot check any code uses reflections, such as `exec`, `setattr`, etc.
* Type checking of compound types such as Union types is not supported yet (will be implemented soon). * Type checking of compound types such as Union types is not supported yet (will be implemented soon).
* pylyzer has its own type declarations for the Python standard APIs. Typing of all APIs is not complete and may result in an error that such an API does not exist.
## TODOs ## TODOs
* [x] type checking * [x] type checking

View File

@ -4,6 +4,7 @@ use rustpython_parser::ast::{StatementType, ExpressionType, Located, Program, Nu
use rustpython_parser::ast::Location as PyLocation; use rustpython_parser::ast::Location as PyLocation;
use erg_common::set::Set as HashSet; use erg_common::set::Set as HashSet;
use erg_common::dict::Dict as HashMap;
use erg_compiler::erg_parser::token::{Token, TokenKind, EQUAL, COLON, DOT}; use erg_compiler::erg_parser::token::{Token, TokenKind, EQUAL, COLON, DOT};
use erg_compiler::erg_parser::ast::{ use erg_compiler::erg_parser::ast::{
Expr, Module, Signature, VarSignature, VarPattern, Params, Identifier, VarName, DefBody, DefId, Block, Def, Literal, Args, PosArg, Accessor, ClassAttrs, ClassAttr, RecordAttrs, Expr, Module, Signature, VarSignature, VarPattern, Params, Identifier, VarName, DefBody, DefId, Block, Def, Literal, Args, PosArg, Accessor, ClassAttrs, ClassAttr, RecordAttrs,
@ -70,20 +71,73 @@ fn op_to_token(op: Operator) -> Token {
Token::from_str(kind, cont) Token::from_str(kind, cont)
} }
#[derive(Debug, Default)] #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct NameInfo {
// last_defined_line: usize,
defined_times: usize,
}
impl NameInfo {
pub const fn new(defined_times: usize) -> Self {
Self {
// last_defined_line,
defined_times,
}
}
}
#[derive(Debug)]
pub struct ASTConverter { pub struct ASTConverter {
namespace: Vec<String>, namespace: Vec<String>,
/// Erg does not allow variables to be defined multiple times, so rename them using this
names: Vec<HashMap<String, NameInfo>>,
}
impl Default for ASTConverter {
fn default() -> Self {
Self::new()
}
} }
impl ASTConverter { impl ASTConverter {
pub fn new() -> Self { pub fn new() -> Self {
Self { Self {
namespace: vec![String::from("<module>")], namespace: vec![String::from("<module>")],
names: vec![HashMap::new()],
} }
} }
fn convert_ident(name: String, loc: PyLocation) -> Identifier { fn get_name_global(&self, name: &str) -> Option<&NameInfo> {
let token = Token::new(TokenKind::Symbol, escape_name(name), loc.row(), loc.column() - 1); for space in self.names.iter().rev() {
if let Some(name) = space.get(name) {
return Some(name);
}
}
None
}
fn _get_mut_name_global(&mut self, name: &str) -> Option<&mut NameInfo> {
for space in self.names.iter_mut().rev() {
if let Some(name) = space.get_mut(name) {
return Some(name);
}
}
None
}
fn convert_ident(&self, name: String, loc: PyLocation) -> Identifier {
let name = escape_name(name);
let cont = if let Some(name_info) = self.get_name_global(&name) {
if name_info.defined_times > 1 {
// HACK: add zero-width characters as postfix
format!("{name}{}", "\0".repeat(name_info.defined_times))
} else {
name
}
} else {
name
};
let token = Token::new(TokenKind::Symbol, cont, loc.row(), loc.column() - 1);
let name = VarName::new(token); let name = VarName::new(token);
let dot = Token::new(TokenKind::Dot, ".", loc.row(), loc.column() - 1); let dot = Token::new(TokenKind::Dot, ".", loc.row(), loc.column() - 1);
Identifier::new(Some(dot), name) Identifier::new(Some(dot), name)
@ -95,10 +149,10 @@ impl ASTConverter {
ParamPattern::VarName(name) ParamPattern::VarName(name)
} }
fn convert_nd_param(param: Parameter) -> NonDefaultParamSignature { fn convert_nd_param(&self, param: Parameter) -> NonDefaultParamSignature {
let pat = Self::convert_param_pattern(param.arg, param.location); let pat = Self::convert_param_pattern(param.arg, param.location);
let t_spec = param.annotation let t_spec = param.annotation
.map(|anot| Self::convert_type_spec(*anot)) .map(|anot| self.convert_type_spec(*anot))
.map(|t_spec| TypeSpecWithOp::new(COLON, t_spec)); .map(|t_spec| TypeSpecWithOp::new(COLON, t_spec));
NonDefaultParamSignature::new(pat, t_spec) NonDefaultParamSignature::new(pat, t_spec)
} }
@ -108,8 +162,8 @@ impl ASTConverter {
} }
// TODO: defaults // TODO: defaults
fn convert_params(args: Box<Parameters>) -> Params { fn convert_params(&self, args: Box<Parameters>) -> Params {
let non_defaults = args.args.into_iter().map(Self::convert_nd_param).collect(); let non_defaults = args.args.into_iter().map(|p| self.convert_nd_param(p)).collect();
// let defaults = args. args.defaults.into_iter().map(convert_default_param).collect(); // let defaults = args. args.defaults.into_iter().map(convert_default_param).collect();
Params::new(non_defaults, None, vec![], None) Params::new(non_defaults, None, vec![], None)
} }
@ -128,7 +182,7 @@ impl ASTConverter {
} }
/// (i, j) => $1 (i = $1[0]; j = $1[1]) /// (i, j) => $1 (i = $1[0]; j = $1[1])
fn convert_expr_to_param(expr: Located<ExpressionType>) -> (NonDefaultParamSignature, Vec<Expr>) { fn convert_expr_to_param(&self, expr: Located<ExpressionType>) -> (NonDefaultParamSignature, Vec<Expr>) {
match expr.node { match expr.node {
ExpressionType::Identifier { name } => (Self::convert_for_param(name, expr.location), vec![]), ExpressionType::Identifier { name } => (Self::convert_for_param(name, expr.location), vec![]),
ExpressionType::Tuple { elements } => { ExpressionType::Tuple { elements } => {
@ -138,9 +192,9 @@ impl ASTConverter {
let mut block = vec![]; let mut block = vec![];
for (i, elem) in elements.into_iter().enumerate() { for (i, elem) in elements.into_iter().enumerate() {
let index = Literal::new(Token::new(TokenKind::NatLit, i.to_string(), elem.location.row(), elem.location.column() - 1)); let index = Literal::new(Token::new(TokenKind::NatLit, i.to_string(), elem.location.row(), elem.location.column() - 1));
let (param, mut blocks) = Self::convert_expr_to_param(elem); let (param, mut blocks) = self.convert_expr_to_param(elem);
let sig = Signature::Var(VarSignature::new(Self::param_pattern_to_var(param.pat), param.t_spec.map(|t| t.t_spec))); let sig = Signature::Var(VarSignature::new(Self::param_pattern_to_var(param.pat), param.t_spec.map(|t| t.t_spec)));
let method = tmp_expr.clone().attr_expr(Self::convert_ident("__Tuple_getitem__".to_string(), expr.location)); let method = tmp_expr.clone().attr_expr(self.convert_ident("__Tuple_getitem__".to_string(), expr.location));
let args = Args::new(vec![PosArg::new(Expr::Lit(index))], vec![], None); let args = Args::new(vec![PosArg::new(Expr::Lit(index))], vec![], None);
let tuple_acc = method.call_expr(args); let tuple_acc = method.call_expr(args);
let body = DefBody::new(EQUAL, Block::new(vec![tuple_acc]), DefId(0)); let body = DefBody::new(EQUAL, Block::new(vec![tuple_acc]), DefId(0));
@ -159,7 +213,7 @@ impl ASTConverter {
} }
fn convert_for_body(&mut self, lhs: Located<ExpressionType>, body: Suite) -> Lambda { fn convert_for_body(&mut self, lhs: Located<ExpressionType>, body: Suite) -> Lambda {
let (param, block) = Self::convert_expr_to_param(lhs); let (param, block) = self.convert_expr_to_param(lhs);
let params = Params::new(vec![param], None, vec![], None); let params = Params::new(vec![param], None, vec![], None);
let body = body.into_iter().map(|stmt| self.convert_statement(stmt, true)).collect::<Vec<_>>(); let body = body.into_iter().map(|stmt| self.convert_statement(stmt, true)).collect::<Vec<_>>();
let body = block.into_iter().chain(body).collect(); let body = block.into_iter().chain(body).collect();
@ -168,10 +222,10 @@ impl ASTConverter {
Lambda::new(sig, op, Block::new(body), DefId(0)) Lambda::new(sig, op, Block::new(body), DefId(0))
} }
fn convert_type_spec(expr: Located<ExpressionType>) -> TypeSpec { fn convert_type_spec(&self, expr: Located<ExpressionType>) -> TypeSpec {
match expr.node { match expr.node {
ExpressionType::Identifier { name } => ExpressionType::Identifier { name } =>
TypeSpec::PreDeclTy(PreDeclTypeSpec::Simple(SimpleTypeSpec::new(Self::convert_ident(name, expr.location), ConstArgs::empty()))), TypeSpec::PreDeclTy(PreDeclTypeSpec::Simple(SimpleTypeSpec::new(self.convert_ident(name, expr.location), ConstArgs::empty()))),
_other => TypeSpec::Infer(Token::new(TokenKind::UBar, "_", expr.location.row(), expr.location.column() - 1)), _other => TypeSpec::Infer(Token::new(TokenKind::UBar, "_", expr.location.row(), expr.location.column() - 1)),
} }
} }
@ -195,7 +249,7 @@ impl ASTConverter {
(l_brace, r_brace) (l_brace, r_brace)
} }
fn convert_expr(expr: Located<ExpressionType>) -> Expr { fn convert_expr(&self, expr: Located<ExpressionType>) -> Expr {
match expr.node { match expr.node {
ExpressionType::Number { value } => { ExpressionType::Number { value } => {
let (kind, cont) = match value { let (kind, cont) = match value {
@ -228,33 +282,33 @@ impl ASTConverter {
Expr::Lit(Literal::new(Token::new(TokenKind::EllipsisLit, "Ellipsis", expr.location.row(), expr.location.column() - 1))) Expr::Lit(Literal::new(Token::new(TokenKind::EllipsisLit, "Ellipsis", expr.location.row(), expr.location.column() - 1)))
} }
ExpressionType::IfExpression { test, body, orelse } => { ExpressionType::IfExpression { test, body, orelse } => {
let block = Self::convert_expr(*body); let block = self.convert_expr(*body);
let params = Params::new(vec![], None, vec![], None); let params = Params::new(vec![], None, vec![], None);
let sig = LambdaSignature::new(params.clone(), None, TypeBoundSpecs::empty()); let sig = LambdaSignature::new(params.clone(), None, TypeBoundSpecs::empty());
let body = Lambda::new(sig, Token::DUMMY, Block::new(vec![block]), DefId(0)); let body = Lambda::new(sig, Token::DUMMY, Block::new(vec![block]), DefId(0));
let test = Self::convert_expr(*test); let test = self.convert_expr(*test);
let if_ident = Self::convert_ident("if".to_string(), expr.location); let if_ident = self.convert_ident("if".to_string(), expr.location);
let if_acc = Expr::Accessor(Accessor::Ident(if_ident)); let if_acc = Expr::Accessor(Accessor::Ident(if_ident));
let else_block = Self::convert_expr(*orelse); let else_block = self.convert_expr(*orelse);
let sig = LambdaSignature::new(params, None, TypeBoundSpecs::empty()); let sig = LambdaSignature::new(params, None, TypeBoundSpecs::empty());
let else_body = Lambda::new(sig, Token::DUMMY, Block::new(vec![else_block]), DefId(0)); let else_body = Lambda::new(sig, Token::DUMMY, Block::new(vec![else_block]), DefId(0));
let args = Args::new(vec![PosArg::new(test), PosArg::new(Expr::Lambda(body)), PosArg::new(Expr::Lambda(else_body))], vec![], None); let args = Args::new(vec![PosArg::new(test), PosArg::new(Expr::Lambda(body)), PosArg::new(Expr::Lambda(else_body))], vec![], None);
if_acc.call_expr(args) if_acc.call_expr(args)
} }
ExpressionType::Call { function, args, keywords: _ } => { ExpressionType::Call { function, args, keywords: _ } => {
let function = Self::convert_expr(*function); let function = self.convert_expr(*function);
let pos_args = args.into_iter().map(|ex| PosArg::new(Self::convert_expr(ex))).collect::<Vec<_>>(); let pos_args = args.into_iter().map(|ex| PosArg::new(self.convert_expr(ex))).collect::<Vec<_>>();
let args = Args::new(pos_args, vec![], None); let args = Args::new(pos_args, vec![], None);
function.call_expr(args) function.call_expr(args)
} }
ExpressionType::Binop { a, op, b } => { ExpressionType::Binop { a, op, b } => {
let lhs = Self::convert_expr(*a); let lhs = self.convert_expr(*a);
let rhs = Self::convert_expr(*b); let rhs = self.convert_expr(*b);
let op = op_to_token(op); let op = op_to_token(op);
Expr::BinOp(BinOp::new(op, lhs, rhs)) Expr::BinOp(BinOp::new(op, lhs, rhs))
} }
ExpressionType::Unop { op, a } => { ExpressionType::Unop { op, a } => {
let rhs = Self::convert_expr(*a); let rhs = self.convert_expr(*a);
let (kind, cont) = match op { let (kind, cont) = match op {
UnaryOperator::Pos => (TokenKind::PrePlus, "+"), UnaryOperator::Pos => (TokenKind::PrePlus, "+"),
// UnaryOperator::Not => (TokenKind::PreBitNot, "not"), // UnaryOperator::Not => (TokenKind::PreBitNot, "not"),
@ -267,8 +321,8 @@ impl ASTConverter {
} }
// TODO // TODO
ExpressionType::BoolOp { op, mut values } => { ExpressionType::BoolOp { op, mut values } => {
let lhs = Self::convert_expr(values.remove(0)); let lhs = self.convert_expr(values.remove(0));
let rhs = Self::convert_expr(values.remove(0)); let rhs = self.convert_expr(values.remove(0));
let (kind, cont) = match op { let (kind, cont) = match op {
BooleanOperator::And => (TokenKind::AndOp, "and"), BooleanOperator::And => (TokenKind::AndOp, "and"),
BooleanOperator::Or => (TokenKind::OrOp, "or"), BooleanOperator::Or => (TokenKind::OrOp, "or"),
@ -278,8 +332,8 @@ impl ASTConverter {
} }
// TODO: multiple comparisons // TODO: multiple comparisons
ExpressionType::Compare { mut vals, mut ops } => { ExpressionType::Compare { mut vals, mut ops } => {
let lhs = Self::convert_expr(vals.remove(0)); let lhs = self.convert_expr(vals.remove(0));
let rhs = Self::convert_expr(vals.remove(0)); let rhs = self.convert_expr(vals.remove(0));
let (kind, cont) = match ops.remove(0) { let (kind, cont) = match ops.remove(0) {
Comparison::Equal => (TokenKind::Equal, "=="), Comparison::Equal => (TokenKind::Equal, "=="),
Comparison::NotEqual => (TokenKind::NotEq, "!="), Comparison::NotEqual => (TokenKind::NotEq, "!="),
@ -296,17 +350,17 @@ impl ASTConverter {
Expr::BinOp(BinOp::new(op, lhs, rhs)) Expr::BinOp(BinOp::new(op, lhs, rhs))
} }
ExpressionType::Identifier { name } => { ExpressionType::Identifier { name } => {
let ident = Self::convert_ident(name, expr.location); let ident = self.convert_ident(name, expr.location);
Expr::Accessor(Accessor::Ident(ident)) Expr::Accessor(Accessor::Ident(ident))
} }
ExpressionType::Attribute { value, name } => { ExpressionType::Attribute { value, name } => {
let obj = Self::convert_expr(*value); let obj = self.convert_expr(*value);
let name = Self::convert_ident(name, expr.location); let name = self.convert_ident(name, expr.location);
Expr::Accessor(Accessor::attr(obj, name)) Expr::Accessor(Accessor::attr(obj, name))
} }
ExpressionType::Lambda { args, body } => { ExpressionType::Lambda { args, body } => {
let params = Self::convert_params(args); let params = self.convert_params(args);
let body = vec![Self::convert_expr(*body)]; let body = vec![self.convert_expr(*body)];
let sig = LambdaSignature::new(params, None, TypeBoundSpecs::empty()); let sig = LambdaSignature::new(params, None, TypeBoundSpecs::empty());
let op = Token::from_str(TokenKind::ProcArrow, "=>"); let op = Token::from_str(TokenKind::ProcArrow, "=>");
Expr::Lambda(Lambda::new(sig, op, Block::new(body), DefId(0))) Expr::Lambda(Lambda::new(sig, op, Block::new(body), DefId(0)))
@ -314,7 +368,7 @@ impl ASTConverter {
ExpressionType::List { elements } => { ExpressionType::List { elements } => {
let (l_sqbr, r_sqbr) = Self::gen_enclosure_tokens(TokenKind::LSqBr, elements.iter(), expr.location); let (l_sqbr, r_sqbr) = Self::gen_enclosure_tokens(TokenKind::LSqBr, elements.iter(), expr.location);
let elements = elements.into_iter() let elements = elements.into_iter()
.map(|ex| PosArg::new(Self::convert_expr(ex))) .map(|ex| PosArg::new(self.convert_expr(ex)))
.collect::<Vec<_>>(); .collect::<Vec<_>>();
let elems = Args::new(elements, vec![], None); let elems = Args::new(elements, vec![], None);
Expr::Array(Array::Normal(NormalArray::new(l_sqbr, r_sqbr, elems))) Expr::Array(Array::Normal(NormalArray::new(l_sqbr, r_sqbr, elems)))
@ -322,7 +376,7 @@ impl ASTConverter {
ExpressionType::Set { elements } => { ExpressionType::Set { elements } => {
let (l_brace, r_brace) = Self::gen_enclosure_tokens(TokenKind::LBrace, elements.iter(), expr.location); let (l_brace, r_brace) = Self::gen_enclosure_tokens(TokenKind::LBrace, elements.iter(), expr.location);
let elements = elements.into_iter() let elements = elements.into_iter()
.map(|ex| PosArg::new(Self::convert_expr(ex))) .map(|ex| PosArg::new(self.convert_expr(ex)))
.collect::<Vec<_>>(); .collect::<Vec<_>>();
let elems = Args::new(elements, vec![], None); let elems = Args::new(elements, vec![], None);
Expr::Set(Set::Normal(NormalSet::new(l_brace, r_brace, elems))) Expr::Set(Set::Normal(NormalSet::new(l_brace, r_brace, elems)))
@ -331,21 +385,21 @@ impl ASTConverter {
let (l_brace, r_brace) = Self::gen_enclosure_tokens(TokenKind::LBrace, elements.iter().map(|(_, v)| v), expr.location); let (l_brace, r_brace) = Self::gen_enclosure_tokens(TokenKind::LBrace, elements.iter().map(|(_, v)| v), expr.location);
let kvs = elements.into_iter() let kvs = elements.into_iter()
.map(|(k, v)| .map(|(k, v)|
KeyValue::new(k.map(Self::convert_expr).unwrap_or(Expr::Dummy(Dummy::empty())), Self::convert_expr(v)) KeyValue::new(k.map(|k| self.convert_expr(k)).unwrap_or(Expr::Dummy(Dummy::empty())), self.convert_expr(v))
).collect::<Vec<_>>(); ).collect::<Vec<_>>();
Expr::Dict(Dict::Normal(NormalDict::new(l_brace, r_brace, kvs))) Expr::Dict(Dict::Normal(NormalDict::new(l_brace, r_brace, kvs)))
} }
ExpressionType::Tuple { elements } => { ExpressionType::Tuple { elements } => {
let elements = elements.into_iter() let elements = elements.into_iter()
.map(|ex| PosArg::new(Self::convert_expr(ex))) .map(|ex| PosArg::new(self.convert_expr(ex)))
.collect::<Vec<_>>(); .collect::<Vec<_>>();
let elems = Args::new(elements, vec![], None); let elems = Args::new(elements, vec![], None);
Expr::Tuple(Tuple::Normal(NormalTuple::new(elems))) Expr::Tuple(Tuple::Normal(NormalTuple::new(elems)))
} }
ExpressionType::Subscript { a, b } => { ExpressionType::Subscript { a, b } => {
let obj = Self::convert_expr(*a); let obj = self.convert_expr(*a);
let method = obj.attr_expr(Self::convert_ident("__getitem__".to_string(), expr.location)); let method = obj.attr_expr(self.convert_ident("__getitem__".to_string(), expr.location));
let args = Args::new(vec![PosArg::new(Self::convert_expr(*b))], vec![], None); let args = Args::new(vec![PosArg::new(self.convert_expr(*b))], vec![], None);
method.call_expr(args) method.call_expr(args)
} }
_other => { _other => {
@ -454,13 +508,14 @@ impl ASTConverter {
loc: PyLocation, loc: PyLocation,
) -> Expr { ) -> Expr {
self.namespace.push(name.clone()); self.namespace.push(name.clone());
let _decos = decorator_list.into_iter().map(Self::convert_expr).collect::<Vec<_>>(); let _decos = decorator_list.into_iter().map(|deco| self.convert_expr(deco)).collect::<Vec<_>>();
let _bases = bases.into_iter().map(Self::convert_expr).collect::<Vec<_>>(); let _bases = bases.into_iter().map(|base| self.convert_expr(base)).collect::<Vec<_>>();
let ident = Self::convert_ident(name, loc); self.register_name_info(&name);
let ident = self.convert_ident(name, loc);
let sig = Signature::Var(VarSignature::new(VarPattern::Ident(ident.clone()), None)); let sig = Signature::Var(VarSignature::new(VarPattern::Ident(ident.clone()), None));
let (base_type, methods) = self.extract_method_list(ident, body); let (base_type, methods) = self.extract_method_list(ident, body);
let args = Args::new(vec![PosArg::new(base_type)], vec![], None); let args = Args::new(vec![PosArg::new(base_type)], vec![], None);
let class_acc = Expr::Accessor(Accessor::Ident(Self::convert_ident("Class".to_string(), loc))); let class_acc = Expr::Accessor(Accessor::Ident(self.convert_ident("Class".to_string(), loc)));
let class_call = class_acc.call_expr(args); let class_call = class_acc.call_expr(args);
let body = DefBody::new(EQUAL, Block::new(vec![class_call]), DefId(0)); let body = DefBody::new(EQUAL, Block::new(vec![class_call]), DefId(0));
let def = Def::new(sig, body); let def = Def::new(sig, body);
@ -469,17 +524,27 @@ impl ASTConverter {
Expr::ClassDef(classdef) Expr::ClassDef(classdef)
} }
fn register_name_info(&mut self, name: &str) {
if let Some(name_info) = self.names.last_mut().unwrap().get_mut(name) {
// name_info.last_defined_line = loc.row();
name_info.defined_times += 1;
} else {
self.names.last_mut().unwrap().insert(String::from(name), NameInfo::new(1));
}
}
fn convert_statement(&mut self, stmt: Located<StatementType>, dont_call_return: bool) -> Expr { fn convert_statement(&mut self, stmt: Located<StatementType>, dont_call_return: bool) -> Expr {
match stmt.node { match stmt.node {
StatementType::Expression { expression } => Self::convert_expr(expression), StatementType::Expression { expression } => self.convert_expr(expression),
StatementType::AnnAssign { target, annotation, value } => { StatementType::AnnAssign { target, annotation, value } => {
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 } => {
let ident = Self::convert_ident(name, stmt.location); self.register_name_info(&name);
let ident = self.convert_ident(name, stmt.location);
if let Some(value) = value { if let Some(value) = value {
let sig = Signature::Var(VarSignature::new(VarPattern::Ident(ident), Some(t_spec))); let sig = Signature::Var(VarSignature::new(VarPattern::Ident(ident), Some(t_spec)));
let block = Block::new(vec![Self::convert_expr(value)]); let block = Block::new(vec![self.convert_expr(value)]);
let body = DefBody::new(EQUAL, block, DefId(0)); let body = DefBody::new(EQUAL, block, DefId(0));
let def = Def::new(sig, body); let def = Def::new(sig, body);
Expr::Def(def) Expr::Def(def)
@ -489,9 +554,9 @@ impl ASTConverter {
} }
} }
ExpressionType::Attribute { value: attr, name } => { ExpressionType::Attribute { value: attr, name } => {
let attr = Self::convert_expr(*attr).attr(Self::convert_ident(name, target.location)); let attr = self.convert_expr(*attr).attr(self.convert_ident(name, target.location));
if let Some(value) = value { if let Some(value) = value {
let expr = Self::convert_expr(value); let expr = self.convert_expr(value);
let adef = AttrDef::new(attr, expr); let adef = AttrDef::new(attr, expr);
Expr::AttrDef(adef) Expr::AttrDef(adef)
} else { } else {
@ -507,16 +572,17 @@ impl ASTConverter {
let lhs = targets.remove(0); let lhs = targets.remove(0);
match lhs.node { match lhs.node {
ExpressionType::Identifier { name } => { ExpressionType::Identifier { name } => {
let ident = Self::convert_ident(name, stmt.location); self.register_name_info(&name);
let ident = self.convert_ident(name, stmt.location);
let sig = Signature::Var(VarSignature::new(VarPattern::Ident(ident), None)); let sig = Signature::Var(VarSignature::new(VarPattern::Ident(ident), None));
let block = Block::new(vec![Self::convert_expr(value)]); let block = Block::new(vec![self.convert_expr(value)]);
let body = DefBody::new(EQUAL, block, DefId(0)); let body = DefBody::new(EQUAL, block, DefId(0));
let def = Def::new(sig, body); let def = Def::new(sig, body);
Expr::Def(def) Expr::Def(def)
} }
ExpressionType::Attribute { value: attr, name } => { ExpressionType::Attribute { value: attr, name } => {
let attr = Self::convert_expr(*attr).attr(Self::convert_ident(name, lhs.location)); let attr = self.convert_expr(*attr).attr(self.convert_ident(name, lhs.location));
let expr = Self::convert_expr(value); let expr = self.convert_expr(value);
let adef = AttrDef::new(attr, expr); let adef = AttrDef::new(attr, expr);
Expr::AttrDef(adef) Expr::AttrDef(adef)
} }
@ -526,14 +592,14 @@ impl ASTConverter {
let tmp_ident = Identifier::new(Some(DOT), tmp_name); let tmp_ident = Identifier::new(Some(DOT), tmp_name);
let tmp_expr = Expr::Accessor(Accessor::Ident(tmp_ident.clone())); let tmp_expr = Expr::Accessor(Accessor::Ident(tmp_ident.clone()));
let sig = Signature::Var(VarSignature::new(VarPattern::Ident(tmp_ident), None)); let sig = Signature::Var(VarSignature::new(VarPattern::Ident(tmp_ident), None));
let body = DefBody::new(EQUAL, Block::new(vec![Self::convert_expr(value)]), DefId(0)); let body = DefBody::new(EQUAL, Block::new(vec![self.convert_expr(value)]), DefId(0));
let tmp_def = Expr::Def(Def::new(sig, body)); let tmp_def = Expr::Def(Def::new(sig, body));
let mut defs = vec![tmp_def]; let mut defs = vec![tmp_def];
for (i, elem) in elements.into_iter().enumerate() { for (i, elem) in elements.into_iter().enumerate() {
let index = Literal::new(Token::new(TokenKind::NatLit, i.to_string(), elem.location.row(), elem.location.column() - 1)); let index = Literal::new(Token::new(TokenKind::NatLit, i.to_string(), elem.location.row(), elem.location.column() - 1));
let (param, mut blocks) = Self::convert_expr_to_param(elem); let (param, mut blocks) = self.convert_expr_to_param(elem);
let sig = Signature::Var(VarSignature::new(Self::param_pattern_to_var(param.pat), param.t_spec.map(|t| t.t_spec))); let sig = Signature::Var(VarSignature::new(Self::param_pattern_to_var(param.pat), param.t_spec.map(|t| t.t_spec)));
let method = tmp_expr.clone().attr_expr(Self::convert_ident("__Tuple_getitem__".to_string(), stmt.location)); let method = tmp_expr.clone().attr_expr(self.convert_ident("__Tuple_getitem__".to_string(), stmt.location));
let args = Args::new(vec![PosArg::new(Expr::Lit(index))], vec![], None); let args = Args::new(vec![PosArg::new(Expr::Lit(index))], vec![], None);
let tuple_acc = method.call_expr(args); let tuple_acc = method.call_expr(args);
let body = DefBody::new(EQUAL, Block::new(vec![tuple_acc]), DefId(0)); let body = DefBody::new(EQUAL, Block::new(vec![tuple_acc]), DefId(0));
@ -546,12 +612,13 @@ impl ASTConverter {
_other => Expr::Dummy(Dummy::empty()), _other => Expr::Dummy(Dummy::empty()),
} }
} else { } else {
let value = Self::convert_expr(value); let value = self.convert_expr(value);
let mut defs = vec![]; let mut defs = vec![];
for target in targets { for target in targets {
match target.node { match target.node {
ExpressionType::Identifier { name } => { ExpressionType::Identifier { name } => {
let ident = Self::convert_ident(name, stmt.location); self.register_name_info(&name);
let ident = self.convert_ident(name, stmt.location);
let sig = Signature::Var(VarSignature::new(VarPattern::Ident(ident), None)); let sig = Signature::Var(VarSignature::new(VarPattern::Ident(ident), None));
let body = DefBody::new(EQUAL, Block::new(vec![value.clone()]), DefId(0)); let body = DefBody::new(EQUAL, Block::new(vec![value.clone()]), DefId(0));
let def = Expr::Def(Def::new(sig, body)); let def = Expr::Def(Def::new(sig, body));
@ -569,9 +636,11 @@ impl ASTConverter {
let op = op_to_token(op); let op = op_to_token(op);
match target.node { match target.node {
ExpressionType::Identifier { name } => { ExpressionType::Identifier { name } => {
let ident = Self::convert_ident(name, stmt.location); let prev_ident = self.convert_ident(name.clone(), stmt.location);
let val = Self::convert_expr(*value); self.register_name_info(&name);
let bin = BinOp::new(op, Expr::Accessor(Accessor::Ident(ident.clone())), val); let ident = self.convert_ident(name, stmt.location);
let val = self.convert_expr(*value);
let bin = BinOp::new(op, Expr::Accessor(Accessor::Ident(prev_ident)), val);
let sig = Signature::Var(VarSignature::new(VarPattern::Ident(ident), None)); let sig = Signature::Var(VarSignature::new(VarPattern::Ident(ident), None));
let block = Block::new(vec![Expr::BinOp(bin)]); let block = Block::new(vec![Expr::BinOp(bin)]);
let body = DefBody::new(EQUAL, block, DefId(0)); let body = DefBody::new(EQUAL, block, DefId(0));
@ -579,8 +648,8 @@ impl ASTConverter {
Expr::Def(def) Expr::Def(def)
} }
ExpressionType::Attribute { value: attr, name } => { ExpressionType::Attribute { value: attr, name } => {
let attr = Self::convert_expr(*attr).attr(Self::convert_ident(name, target.location)); let attr = self.convert_expr(*attr).attr(self.convert_ident(name, target.location));
let val = Self::convert_expr(*value); let val = self.convert_expr(*value);
let bin = BinOp::new(op, Expr::Accessor(attr.clone()), val); let bin = BinOp::new(op, Expr::Accessor(attr.clone()), val);
let adef = AttrDef::new(attr, Expr::BinOp(bin)); let adef = AttrDef::new(attr, Expr::BinOp(bin));
Expr::AttrDef(adef) Expr::AttrDef(adef)
@ -597,10 +666,11 @@ impl ASTConverter {
returns returns
} => { } => {
self.namespace.push(name.clone()); self.namespace.push(name.clone());
let decos = decorator_list.into_iter().map(|ex| Decorator(Self::convert_expr(ex))).collect::<HashSet<_>>(); let decos = decorator_list.into_iter().map(|ex| Decorator(self.convert_expr(ex))).collect::<HashSet<_>>();
let ident = Self::convert_ident(name, stmt.location); self.register_name_info(&name);
let params = Self::convert_params(args); let ident = self.convert_ident(name, stmt.location);
let return_t = returns.map(Self::convert_type_spec); let params = self.convert_params(args);
let return_t = returns.map(|ret| self.convert_type_spec(ret));
let sig = Signature::Subr(SubrSignature::new(decos, ident, TypeBoundSpecs::empty(), params, return_t)); let sig = Signature::Subr(SubrSignature::new(decos, ident, TypeBoundSpecs::empty(), params, return_t));
let block = self.convert_block(body, BlockKind::Function); let block = self.convert_block(body, BlockKind::Function);
let body = DefBody::new(EQUAL, block, DefId(0)); let body = DefBody::new(EQUAL, block, DefId(0));
@ -613,8 +683,8 @@ impl ASTConverter {
} }
StatementType::For { is_async: _, target, iter, body, orelse: _ } => { StatementType::For { is_async: _, target, iter, body, orelse: _ } => {
let block = self.convert_for_body(*target, body); let block = self.convert_for_body(*target, body);
let iter = Self::convert_expr(*iter); let iter = self.convert_expr(*iter);
let for_ident = Self::convert_ident("for".to_string(), stmt.location); let for_ident = self.convert_ident("for".to_string(), stmt.location);
let for_acc = Expr::Accessor(Accessor::Ident(for_ident)); let for_acc = Expr::Accessor(Accessor::Ident(for_ident));
for_acc.call_expr(Args::new(vec![PosArg::new(iter), PosArg::new(Expr::Lambda(block))], vec![], None)) for_acc.call_expr(Args::new(vec![PosArg::new(iter), PosArg::new(Expr::Lambda(block))], vec![], None))
} }
@ -622,8 +692,8 @@ impl ASTConverter {
let block = self.convert_block(body, BlockKind::While); let block = self.convert_block(body, BlockKind::While);
let params = Params::new(vec![], None, vec![], None); let params = Params::new(vec![], None, vec![], None);
let body = Lambda::new(LambdaSignature::new(params, None, TypeBoundSpecs::empty()), Token::DUMMY, block, DefId(0)); let body = Lambda::new(LambdaSignature::new(params, None, TypeBoundSpecs::empty()), Token::DUMMY, block, DefId(0));
let test = Self::convert_expr(test); let test = self.convert_expr(test);
let while_ident = Self::convert_ident("while".to_string(), stmt.location); let while_ident = self.convert_ident("while".to_string(), stmt.location);
let while_acc = Expr::Accessor(Accessor::Ident(while_ident)); let while_acc = Expr::Accessor(Accessor::Ident(while_ident));
while_acc.call_expr(Args::new(vec![PosArg::new(test), PosArg::new(Expr::Lambda(body))], vec![], None)) while_acc.call_expr(Args::new(vec![PosArg::new(test), PosArg::new(Expr::Lambda(body))], vec![], None))
} }
@ -632,8 +702,8 @@ impl ASTConverter {
let params = Params::new(vec![], None, vec![], None); let params = Params::new(vec![], None, vec![], None);
let sig = LambdaSignature::new(params.clone(), None, TypeBoundSpecs::empty()); let sig = LambdaSignature::new(params.clone(), None, TypeBoundSpecs::empty());
let body = Lambda::new(sig, Token::DUMMY, block, DefId(0)); let body = Lambda::new(sig, Token::DUMMY, block, DefId(0));
let test = Self::convert_expr(test); let test = self.convert_expr(test);
let if_ident = Self::convert_ident("if".to_string(), stmt.location); let if_ident = self.convert_ident("if".to_string(), stmt.location);
let if_acc = Expr::Accessor(Accessor::Ident(if_ident)); let if_acc = Expr::Accessor(Accessor::Ident(if_ident));
if let Some(orelse) = orelse { if let Some(orelse) = orelse {
let else_block = self.convert_block(orelse, BlockKind::If); let else_block = self.convert_block(orelse, BlockKind::If);
@ -647,42 +717,42 @@ impl ASTConverter {
} }
} }
StatementType::Return { value } => { StatementType::Return { value } => {
let value = value.map(Self::convert_expr) let value = value.map(|val| self.convert_expr(val))
.unwrap_or_else(||Expr::Tuple(Tuple::Normal(NormalTuple::new(Args::empty())))); .unwrap_or_else(||Expr::Tuple(Tuple::Normal(NormalTuple::new(Args::empty()))));
if dont_call_return { if dont_call_return {
value value
} else { } else {
let func_acc = Expr::Accessor(Accessor::Ident(Self::convert_ident(self.namespace.last().unwrap().clone(), stmt.location))); let func_acc = Expr::Accessor(Accessor::Ident(self.convert_ident(self.namespace.last().unwrap().clone(), stmt.location)));
let return_acc = Self::convert_ident("return".to_string(), stmt.location); let return_acc = self.convert_ident("return".to_string(), stmt.location);
let return_acc = Expr::Accessor(Accessor::attr(func_acc, return_acc)); let return_acc = Expr::Accessor(Accessor::attr(func_acc, return_acc));
erg_common::log!(err "{return_acc}"); erg_common::log!(err "{return_acc}");
return_acc.call_expr(Args::new(vec![PosArg::new(value)], vec![], None)) return_acc.call_expr(Args::new(vec![PosArg::new(value)], vec![], None))
} }
} }
StatementType::Assert { test, msg } => { StatementType::Assert { test, msg } => {
let test = Self::convert_expr(test); let test = self.convert_expr(test);
let args = if let Some(msg) = msg { let args = if let Some(msg) = msg {
let msg = Self::convert_expr(msg); let msg = self.convert_expr(msg);
Args::new(vec![PosArg::new(test), PosArg::new(msg)], vec![], None) Args::new(vec![PosArg::new(test), PosArg::new(msg)], vec![], None)
} else { } else {
Args::new(vec![PosArg::new(test)], vec![], None) Args::new(vec![PosArg::new(test)], vec![], None)
}; };
let assert_acc = Expr::Accessor(Accessor::Ident(Self::convert_ident("assert".to_string(), stmt.location))); let assert_acc = Expr::Accessor(Accessor::Ident(self.convert_ident("assert".to_string(), stmt.location)));
assert_acc.call_expr(args) assert_acc.call_expr(args)
} }
StatementType::Import { names } => { StatementType::Import { names } => {
let mut imports = vec![]; let mut imports = vec![];
for name in names { for name in names {
let import_acc = Expr::Accessor(Accessor::Ident(Self::convert_ident("__import__".to_string(), stmt.location))); let import_acc = Expr::Accessor(Accessor::Ident(self.convert_ident("__import__".to_string(), stmt.location)));
let cont = format!("\"{}\"", name.symbol); let cont = format!("\"{}\"", name.symbol);
let mod_name = Expr::Lit(Literal::new(Token::new(TokenKind::StrLit, cont, stmt.location.row(), stmt.location.column() - 1))); let mod_name = Expr::Lit(Literal::new(Token::new(TokenKind::StrLit, cont, stmt.location.row(), stmt.location.column() - 1)));
let args = Args::new(vec![PosArg::new(mod_name)], vec![], None); let args = Args::new(vec![PosArg::new(mod_name)], vec![], None);
let call = import_acc.call_expr(args); let call = import_acc.call_expr(args);
let def = if let Some(alias) = name.alias { let def = if let Some(alias) = name.alias {
let var = VarSignature::new(VarPattern::Ident(Self::convert_ident(alias, stmt.location)), None); let var = VarSignature::new(VarPattern::Ident(self.convert_ident(alias, stmt.location)), None);
Def::new(Signature::Var(var), DefBody::new(EQUAL, Block::new(vec![call]), DefId(0))) Def::new(Signature::Var(var), DefBody::new(EQUAL, Block::new(vec![call]), DefId(0)))
} else { } else {
let var = VarSignature::new(VarPattern::Ident(Self::convert_ident(name.symbol, stmt.location)), None); let var = VarSignature::new(VarPattern::Ident(self.convert_ident(name.symbol, stmt.location)), None);
Def::new(Signature::Var(var), DefBody::new(EQUAL, Block::new(vec![call]), DefId(0))) Def::new(Signature::Var(var), DefBody::new(EQUAL, Block::new(vec![call]), DefId(0)))
}; };
imports.push(Expr::Def(def)); imports.push(Expr::Def(def));
@ -690,23 +760,23 @@ impl ASTConverter {
Expr::Dummy(Dummy::new(imports)) Expr::Dummy(Dummy::new(imports))
} }
StatementType::ImportFrom { level: _, module, names } => { StatementType::ImportFrom { level: _, module, names } => {
let import_acc = Expr::Accessor(Accessor::Ident(Self::convert_ident("__import__".to_string(), stmt.location))); let import_acc = Expr::Accessor(Accessor::Ident(self.convert_ident("__import__".to_string(), stmt.location)));
let cont = format!("\"{}\"", module.clone().unwrap()); let cont = format!("\"{}\"", module.clone().unwrap());
let mod_name = Expr::Lit(Literal::new(Token::new(TokenKind::StrLit, cont, stmt.location.row(), stmt.location.column() - 1))); let mod_name = Expr::Lit(Literal::new(Token::new(TokenKind::StrLit, cont, stmt.location.row(), stmt.location.column() - 1)));
let args = Args::new(vec![PosArg::new(mod_name)], vec![], None); let args = Args::new(vec![PosArg::new(mod_name)], vec![], None);
let call = import_acc.call_expr(args); let call = import_acc.call_expr(args);
let mod_ident = Self::convert_ident(module.unwrap(), stmt.location); let mod_ident = self.convert_ident(module.unwrap(), stmt.location);
let mod_expr = Expr::Accessor(Accessor::Ident(mod_ident.clone())); let mod_expr = Expr::Accessor(Accessor::Ident(mod_ident.clone()));
let var = VarSignature::new(VarPattern::Ident(mod_ident), None); let var = VarSignature::new(VarPattern::Ident(mod_ident), None);
let moddef = Expr::Def(Def::new(Signature::Var(var), DefBody::new(EQUAL, Block::new(vec![call]), DefId(0)))); let moddef = Expr::Def(Def::new(Signature::Var(var), DefBody::new(EQUAL, Block::new(vec![call]), DefId(0))));
let mut imports = vec![]; let mut imports = vec![];
for name in names { for name in names {
let var = if let Some(alias) = name.alias { let var = if let Some(alias) = name.alias {
VarSignature::new(VarPattern::Ident(Self::convert_ident(alias, stmt.location)), None) VarSignature::new(VarPattern::Ident(self.convert_ident(alias, stmt.location)), None)
} else { } else {
VarSignature::new(VarPattern::Ident(Self::convert_ident(name.symbol.clone(), stmt.location)), None) VarSignature::new(VarPattern::Ident(self.convert_ident(name.symbol.clone(), stmt.location)), None)
}; };
let attr = mod_expr.clone().attr_expr(Self::convert_ident(name.symbol, stmt.location)); let attr = mod_expr.clone().attr_expr(self.convert_ident(name.symbol, stmt.location));
let def = Def::new(Signature::Var(var), DefBody::new(EQUAL, Block::new(vec![attr]), DefId(0))); let def = Def::new(Signature::Var(var), DefBody::new(EQUAL, Block::new(vec![attr]), DefId(0)));
imports.push(Expr::Def(def)); imports.push(Expr::Def(def));
} }