From 84c72e6ef6700cf8c01966f1f464c47c9a456d72 Mon Sep 17 00:00:00 2001 From: Shunsuke Shibayama Date: Sat, 9 Dec 2023 20:58:10 +0900 Subject: [PATCH] feat: support varargs --- Cargo.lock | 88 ++++++++++++++++++++++----------------- Cargo.toml | 6 +-- crates/py2erg/convert.rs | 34 ++++++++------- crates/py2erg/gen_decl.rs | 4 +- src/analyze.rs | 2 +- tests/func.py | 5 +++ 6 files changed, 81 insertions(+), 58 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 66be313..e9750e0 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -121,9 +121,9 @@ checksum = "a26ae43d7bcc3b814de94796a5e736d4029efb0ee900c12e2d54c993ad1a1e07" [[package]] name = "els" -version = "0.1.37-nightly.1" +version = "0.1.39-nightly.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ee6ddd6641e1e40061947a859149f5f0e65d620288fcabb07117f702e4bb831a" +checksum = "e35e675cfa42fba9067fce99587dbfc396596cd0231bb84f5fc58b8564845ff8" dependencies = [ "erg_common", "erg_compiler", @@ -147,9 +147,9 @@ dependencies = [ [[package]] name = "erg_common" -version = "0.6.25-nightly.1" +version = "0.6.27-nightly.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7cc1c8a91c85f8b2501f0e600551e4468f896e477fc7721da1a3802ca7f223ce" +checksum = "4ac75e02434b08efb90ff903ac462e453637043b3a6d35b306efbc83ca375ce6" dependencies = [ "backtrace-on-stack-overflow", "parking_lot", @@ -158,9 +158,9 @@ dependencies = [ [[package]] name = "erg_compiler" -version = "0.6.25-nightly.1" +version = "0.6.27-nightly.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "551419179c1f2f7587956f5983bcb59d06b5e3650b7294cd7c38cabf46c68dac" +checksum = "627ed3f352f4159a859ec13f97ad945b9837dd09aa24261498674296a6ca367c" dependencies = [ "erg_common", "erg_parser", @@ -168,34 +168,46 @@ dependencies = [ [[package]] name = "erg_parser" -version = "0.6.25-nightly.1" +version = "0.6.27-nightly.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d83edffb962792280d35bc43287e0507ba1ed7995acde42c1ffae1e77b83fa6c" +checksum = "741691700b21dda252eb47d21967e44347320520ee263529241739da165a5718" dependencies = [ "erg_common", + "erg_proc_macros", "unicode-xid", ] +[[package]] +name = "erg_proc_macros" +version = "0.6.27-nightly.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c204aeef3905b06ecddf20812e18c43e3c4bcc10690cc3485511b8871f63922a" +dependencies = [ + "erg_common", + "quote", + "syn 1.0.109", +] + [[package]] name = "form_urlencoded" -version = "1.2.0" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a62bc1cf6f830c2ec14a513a9fb124d0a213a629668a4186f329db21fe045652" +checksum = "e13624c2627564efccf4934284bdd98cbaa14e79b0b5a141218e507b3a823456" dependencies = [ "percent-encoding", ] [[package]] name = "gimli" -version = "0.28.0" +version = "0.28.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6fb8d784f27acf97159b40fc4db5ecd8aa23b9ad5ef69cdd136d3bc80665f0c0" +checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253" [[package]] name = "idna" -version = "0.4.0" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d20d6b07bfbc108882d88ed8e37d39636dcc260e15e30c45e6ba089610b917c" +checksum = "634d9b1461af396cad843f47fdba5597a4f9e6ddd4bfb6ff5d85028c25cb12f6" dependencies = [ "unicode-bidi", "unicode-normalization", @@ -234,9 +246,9 @@ dependencies = [ [[package]] name = "itoa" -version = "1.0.9" +version = "1.0.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af150ab688ff2122fcef229be89cb50dd66af9e01a4ff320cc137eecc9bacc38" +checksum = "b1a46d1a171d865aa5f83f92695765caa047a9b4cbae2cbf37dbd613a793fd4c" [[package]] name = "lalrpop-util" @@ -246,9 +258,9 @@ checksum = "3f35c735096c0293d313e8f2a641627472b83d01b937177fe76e5e2708d31e0d" [[package]] name = "libc" -version = "0.2.149" +version = "0.2.150" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a08173bc88b7955d1b3145aa561539096c421ac8debde8cbc3612ec635fee29b" +checksum = "89d92a4743f9a61002fae18374ed11e7973f530cb3a3255fb354818118b2203c" [[package]] name = "lock_api" @@ -413,9 +425,9 @@ dependencies = [ [[package]] name = "once_cell" -version = "1.18.0" +version = "1.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d" +checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" [[package]] name = "parking_lot" @@ -448,9 +460,9 @@ checksum = "de3145af08024dea9fa9914f381a17b8fc6034dfb00f3a84013f7ff43f29ed4c" [[package]] name = "percent-encoding" -version = "2.3.0" +version = "2.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b2a4787296e9989611394c33f193f676704af1686e70b8f8033ab5ba9a35a94" +checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" [[package]] name = "phf" @@ -503,9 +515,9 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.69" +version = "1.0.70" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "134c189feb4956b20f6f547d2cf727d4c0fe06722b20a0eec87ed445a97f92da" +checksum = "39278fbbf5fb4f646ce651690877f89d1c5811a3d4acb27700c1cb3cdb78fd3b" dependencies = [ "unicode-ident", ] @@ -663,22 +675,22 @@ checksum = "836fa6a3e1e547f9a2c4040802ec865b5d85f4014efe00555d7090a3dcaa1090" [[package]] name = "serde" -version = "1.0.190" +version = "1.0.193" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91d3c334ca1ee894a2c6f6ad698fe8c435b76d504b13d436f0685d648d6d96f7" +checksum = "25dd9975e68d0cb5aa1120c288333fc98731bd1dd12f561e468ea4728c042b89" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.190" +version = "1.0.193" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67c5609f394e5c2bd7fc51efda478004ea80ef42fee983d5c67a65e34f32c0e3" +checksum = "43576ca501357b9b071ac53cdc7da8ef0cbd9493d8df094cd821777ea6e894d3" dependencies = [ "proc-macro2", "quote", - "syn 2.0.38", + "syn 2.0.39", ] [[package]] @@ -700,7 +712,7 @@ checksum = "3081f5ffbb02284dda55132aa26daecedd7372a42417bbbab6f14ab7d6bb9145" dependencies = [ "proc-macro2", "quote", - "syn 2.0.38", + "syn 2.0.39", ] [[package]] @@ -711,9 +723,9 @@ checksum = "38b58827f4464d87d377d175e90bf58eb00fd8716ff0a62f80356b5e61555d0d" [[package]] name = "smallvec" -version = "1.11.1" +version = "1.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "942b4a808e05215192e39f4ab80813e599068285906cc91aa64f923db842bd5a" +checksum = "4dccd0940a2dcdf68d092b8cbab7dc0ad8fa938bf95787e1b916b0e3d0e8e970" [[package]] name = "static_assertions" @@ -734,9 +746,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.38" +version = "2.0.39" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e96b79aaa137db8f61e26363a0c9b47d8b4ec75da28b7d1d614c2303e232408b" +checksum = "23e78b90f2fcf45d3e842032ce32e3f2d1545ba6636271dcbf24fa306d87be7a" dependencies = [ "proc-macro2", "quote", @@ -831,9 +843,9 @@ dependencies = [ [[package]] name = "unicode-bidi" -version = "0.3.13" +version = "0.3.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "92888ba5573ff080736b3648696b70cafad7d250551175acbaa4e0385b3e1460" +checksum = "6f2528f27a9eb2b21e69c95319b30bd0efd85d09c379741b0f78ea1d86be2416" [[package]] name = "unicode-ident" @@ -864,9 +876,9 @@ checksum = "446c96c6dd42604779487f0a981060717156648c1706aa1f464677f03c6cc059" [[package]] name = "url" -version = "2.4.1" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "143b538f18257fac9cad154828a57c6bf5157e1aa604d4816b5995bf6de87ae5" +checksum = "31e6302e3bb753d46e83516cae55ae196fc0c309407cf11ab35cc51a4c2a4633" dependencies = [ "form_urlencoded", "idna", diff --git a/Cargo.toml b/Cargo.toml index f586131..11f3fb1 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -22,9 +22,9 @@ edition = "2021" repository = "https://github.com/mtshiba/pylyzer" [workspace.dependencies] -erg_common = { version = "0.6.25-nightly.1", features = ["py_compat", "els"] } -erg_compiler = { version = "0.6.25-nightly.1", features = ["py_compat", "els"] } -els = { version = "0.1.37-nightly.1", features = ["py_compat"] } +erg_common = { version = "0.6.27-nightly.0", features = ["py_compat", "els"] } +erg_compiler = { version = "0.6.27-nightly.0", features = ["py_compat", "els"] } +els = { version = "0.1.39-nightly.0", features = ["py_compat"] } rustpython-parser = { version = "0.3.0", features = ["all-nodes-with-ranges", "location"] } rustpython-ast = { version = "0.3.0", features = ["all-nodes-with-ranges", "location"] } # rustpython-parser = { git = "https://github.com/RustPython/Parser", version = "0.3.0", features = ["all-nodes-with-ranges", "location"] } diff --git a/crates/py2erg/convert.rs b/crates/py2erg/convert.rs index d31e3bf..acd6b1c 100644 --- a/crates/py2erg/convert.rs +++ b/crates/py2erg/convert.rs @@ -452,9 +452,12 @@ impl ASTConverter { } fn convert_params(&mut self, params: Arguments) -> Params { - fn split_args(params: Arguments) -> (Vec, Vec<(Arg, py_ast::Expr)>) { + #[allow(clippy::type_complexity)] + fn split_args(params: Arguments) -> (Vec, Option, Vec<(Arg, py_ast::Expr)>, Option) { let mut args = Vec::new(); let mut with_defaults = Vec::new(); + let var_args = params.vararg.map(|x| *x); + let kw_args = params.kwarg.map(|x| *x); for arg in params .posonlyargs .into_iter() @@ -467,18 +470,20 @@ impl ASTConverter { args.push(arg.def); } } - (args, with_defaults) + (args, var_args, with_defaults, kw_args) } - let (non_defaults, defaults) = split_args(params); + let (non_defaults, var_args, defaults, kw_args) = split_args(params); let non_defaults = non_defaults .into_iter() .map(|p| self.convert_nd_param(p)) .collect(); + let var_params = var_args.map(|p| self.convert_nd_param(p)); let defaults = defaults .into_iter() .map(|(kw, default)| self.convert_default_param(kw, default)) .collect(); - Params::new(non_defaults, None, defaults, None) + let kw_var_params = kw_args.map(|p| self.convert_nd_param(p)); + Params::new(non_defaults, var_params, defaults, kw_var_params, None) } fn convert_for_param(&mut self, name: String, loc: PyLocation) -> NonDefaultParamSignature { @@ -572,7 +577,7 @@ impl ASTConverter { fn convert_for_body(&mut self, lhs: Option, body: Suite) -> Lambda { let (param, block) = self.convert_opt_expr_to_param(lhs); - let params = Params::new(vec![param], None, vec![], None); + let params = Params::new(vec![param], None, vec![], None, None); self.block_id_counter += 1; self.block_ids.push(self.block_id_counter); let body = body @@ -652,7 +657,7 @@ impl ASTConverter { } } } - let elems = ConstArgs::new(elems, None, vec![], None); + let elems = ConstArgs::new(elems, None, vec![], None, None); TypeSpec::Enum(elems) } // TODO: distinguish from collections.abc.Callable @@ -688,6 +693,7 @@ impl ASTConverter { non_defaults, None, vec![], + None, ARROW, ret, )) @@ -790,7 +796,7 @@ impl ASTConverter { global, Identifier::private("Array!".into()), )); - TypeSpec::poly(acc, ConstArgs::new(vec![elem_t, len], None, vec![], None)) + TypeSpec::poly(acc, ConstArgs::new(vec![elem_t, len], None, vec![], None, None)) } "dict" => { let py_ast::Expr::Tuple(mut tuple) = args else { @@ -834,7 +840,7 @@ impl ASTConverter { global, Identifier::private("Dict!".into()), )); - TypeSpec::poly(acc, ConstArgs::new(vec![dict], None, vec![], None)) + TypeSpec::poly(acc, ConstArgs::new(vec![dict], None, vec![], None, None)) } "tuple" => { let py_ast::Expr::Tuple(tuple) = args else { @@ -1022,7 +1028,7 @@ impl ASTConverter { py_ast::Expr::IfExp(if_) => { let loc = if_.location(); let block = self.convert_expr(*if_.body); - let params = Params::new(vec![], None, vec![], None); + let params = Params::new(vec![], None, vec![], None, None); let sig = LambdaSignature::new(params.clone(), None, TypeBoundSpecs::empty()); let body = Lambda::new(sig, Token::DUMMY, Block::new(vec![block]), DefId(0)); let test = self.convert_expr(*if_.test); @@ -1074,7 +1080,7 @@ impl ASTConverter { let rp = Token::new(TokenKind::RParen, ")", loc.row.get(), last_col); (lp, rp) }; - let args = Args::new(pos_args, None, kw_args, Some(paren)); + let args = Args::new(pos_args, None, kw_args, None, Some(paren)); function.call_expr(args) } py_ast::Expr::BinOp(bin) => { @@ -1374,7 +1380,7 @@ impl ASTConverter { VisModifierSpec::Public(DOT), VarName::from_static("__call__"), ); - let params = Params::new(params, None, vec![], None); + let params = Params::new(params, None, vec![], None, None); let class_ident = Identifier::public_with_line( DOT, self.namespace.last().unwrap().into(), @@ -1402,7 +1408,7 @@ impl ASTConverter { VisModifierSpec::Public(DOT), VarName::from_static("__call__"), ); - let params = Params::new(vec![], None, vec![], None); + let params = Params::empty(); let class_ident = Identifier::public_with_line(DOT, self.namespace.last().unwrap().into(), line as u32); let class_ident_expr = Expr::Accessor(Accessor::Ident(class_ident.clone())); @@ -1896,7 +1902,7 @@ impl ASTConverter { py_ast::Stmt::While(while_) => { let loc = while_.location(); let test = self.convert_expr(*while_.test); - let params = Params::new(vec![], None, vec![], None); + let params = Params::empty(); let empty_sig = LambdaSignature::new(params, None, TypeBoundSpecs::empty()); let block = self.convert_block(while_.body, BlockKind::While); let body = Lambda::new(empty_sig, Token::DUMMY, block, DefId(0)); @@ -1907,7 +1913,7 @@ impl ASTConverter { py_ast::Stmt::If(if_) => { let loc = if_.location(); let block = self.convert_block(if_.body, BlockKind::If); - let params = Params::new(vec![], None, vec![], None); + let params = Params::empty(); let sig = LambdaSignature::new(params.clone(), None, TypeBoundSpecs::empty()); let body = Lambda::new(sig, Token::DUMMY, block, DefId(0)); let test = self.convert_expr(*if_.test); diff --git a/crates/py2erg/gen_decl.rs b/crates/py2erg/gen_decl.rs index 803c0ed..51eb1ce 100644 --- a/crates/py2erg/gen_decl.rs +++ b/crates/py2erg/gen_decl.rs @@ -5,7 +5,7 @@ use erg_common::io::Input; use erg_common::log; use erg_common::traits::LimitedDisplay; use erg_compiler::build_package::{CheckStatus, PylyzerStatus}; -use erg_compiler::hir::{Expr, HIR}; +use erg_compiler::hir::{Expr, HIR, ClassDef}; use erg_compiler::ty::value::{GenTypeObj, TypeObj}; use erg_compiler::ty::{HasType, Type}; @@ -123,7 +123,7 @@ impl DeclFileGenerator { self.code += &decl; } } - for attr in def.methods.into_iter() { + for attr in ClassDef::take_all_methods(def.methods_list) { self.gen_chunk_decl(attr); } self.namespace = stash; diff --git a/src/analyze.rs b/src/analyze.rs index 18252e5..83897db 100644 --- a/src/analyze.rs +++ b/src/analyze.rs @@ -192,7 +192,7 @@ impl PythonAnalyzer { } fn check(&mut self, erg_ast: AST, mut errors: CompileErrors, mut warns: CompileErrors, mode: &str) -> Result { - match self.checker.build_module(erg_ast, mode) { + match self.checker.build_from_ast(erg_ast, mode) { Ok(mut artifact) => { artifact.warns.extend(warns); artifact.warns = diff --git a/tests/func.py b/tests/func.py index 64736d3..306b1b5 100644 --- a/tests/func.py +++ b/tests/func.py @@ -15,3 +15,8 @@ def h(x: str): if True: x = "a" # OK return x + +def var(*varargs, **kwargs): + return varargs, kwargs + +_ = var(1, 2, 3, a=1, b=2, c=3)