feat: implement default-parameter & keyword-arg

This commit is contained in:
Shunsuke Shibayama 2023-04-30 00:28:10 +09:00
parent 9e85a85428
commit b301a298b6
6 changed files with 57 additions and 24 deletions

16
Cargo.lock generated
View File

@ -252,9 +252,9 @@ checksum = "7fcaabb2fef8c910e7f4c7ce9f67a1283a1715879a7c230ca9d6d1ae31f16d91"
[[package]]
name = "els"
version = "0.1.24-nightly.2"
version = "0.1.24-nightly.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5c0ce88e92029277b465cd25b78f2415b9000ee624a4129adf306355cd640ade"
checksum = "61f3764c26581de3f7c346d73429ccccb8bc644c04590c426e6a762ef4b306b6"
dependencies = [
"erg_common",
"erg_compiler",
@ -274,9 +274,9 @@ dependencies = [
[[package]]
name = "erg_common"
version = "0.6.12-nightly.2"
version = "0.6.12-nightly.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "073d7c283921a4831d934f1f9f2ca743e183da85323eb8cb8f293bf1c39399c5"
checksum = "0af4f3dd859b94446be12295a587c1a0315772da8f4782c6e412c7b0ee6e6619"
dependencies = [
"backtrace-on-stack-overflow",
"hermit-abi",
@ -286,9 +286,9 @@ dependencies = [
[[package]]
name = "erg_compiler"
version = "0.6.12-nightly.2"
version = "0.6.12-nightly.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7a39ae989726eb329476188bd8a34192e2cfc9b88a8addb6b3ec0e3583c39ba5"
checksum = "d6058e923f99ab3f901256d4c005e675a9bd66b5b7c502535f27d41d66afc3c0"
dependencies = [
"erg_common",
"erg_parser",
@ -296,9 +296,9 @@ dependencies = [
[[package]]
name = "erg_parser"
version = "0.6.12-nightly.2"
version = "0.6.12-nightly.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "570f9a7d896c5e1a6d7b6f4f57a2eb5e6effe63ded4c264d9a59bb16c721a1b1"
checksum = "ecdcb02393d790e952ac55c9e49eb1e7485c86199bc770659915512e7647d9b3"
dependencies = [
"erg_common",
"unicode-xid 0.2.4",

View File

@ -22,9 +22,9 @@ edition = "2021"
repository = "https://github.com/mtshiba/pylyzer"
[workspace.dependencies]
erg_common = { version = "0.6.12-nightly.2", features = ["py_compat", "els"] }
erg_compiler = { version = "0.6.12-nightly.2", features = ["py_compat", "els"] }
els = { version = "0.1.24-nightly.2", features = ["py_compat"] }
erg_common = { version = "0.6.12-nightly.3", features = ["py_compat", "els"] }
erg_compiler = { version = "0.6.12-nightly.3", features = ["py_compat", "els"] }
els = { version = "0.1.24-nightly.3", features = ["py_compat"] }
rustpython-parser = "0.1.2"
# erg_compiler = { git = "https://github.com/erg-lang/erg", branch = "main", features = ["py_compat", "els"] }
# erg_common = { git = "https://github.com/erg-lang/erg", branch = "main", features = ["py_compat", "els"] }

View File

@ -19,7 +19,7 @@ use erg_compiler::erg_parser::ast::{
use erg_compiler::erg_parser::desugar::Desugarer;
use erg_compiler::erg_parser::token::{Token, TokenKind, AS, DOT, EQUAL};
use erg_compiler::error::{CompileErrors, CompileError};
use rustpython_parser::ast::Location as PyLocation;
use rustpython_parser::ast::{Location as PyLocation, Keyword};
use rustpython_parser::ast::{
BooleanOperator, Comparison, ExpressionType, Located, Number, Operator, Parameter, Parameters,
Program, StatementType, StringGroup, Suite, UnaryOperator,
@ -369,19 +369,24 @@ impl ASTConverter {
NonDefaultParamSignature::new(pat, t_spec)
}
fn _convert_default_param(_param: Parameter) -> DefaultParamSignature {
todo!()
fn convert_default_param(&mut self, kw: Parameter, default: Located<ExpressionType>) -> DefaultParamSignature {
let sig = self.convert_nd_param(kw);
let default = self.convert_expr(default);
DefaultParamSignature::new(sig, default)
}
// TODO: defaults
fn convert_params(&mut self, args: Parameters) -> Params {
let non_defaults = args
.args
fn convert_params(&mut self, params: Parameters) -> Params {
let non_defaults_len = params.args.len() - params.defaults.len();
let mut non_default_names = params.args;
let defaults_names = non_default_names.split_off(non_defaults_len);
let non_defaults = non_default_names
.into_iter()
.map(|p| self.convert_nd_param(p))
.collect();
// let defaults = args. args.defaults.into_iter().map(convert_default_param).collect();
Params::new(non_defaults, None, vec![], None)
let defaults = defaults_names.into_iter().zip(params.defaults.into_iter())
.map(|(kw, default)| self.convert_default_param(kw, default))
.collect();
Params::new(non_defaults, None, defaults, None)
}
fn convert_for_param(&mut self, name: String, loc: PyLocation) -> NonDefaultParamSignature {
@ -779,13 +784,22 @@ impl ASTConverter {
ExpressionType::Call {
function,
args,
keywords: _,
keywords,
} => {
let function = self.convert_expr(*function);
let pos_args = args
.into_iter()
.map(|ex| PosArg::new(self.convert_expr(ex)))
.collect::<Vec<_>>();
let kw_args = keywords
.into_iter()
.map(|Keyword { name, value }| {
let name = name.unwrap_or_default();
let name = Token::symbol_with_loc(&name, pyloc_to_ergloc(value.location, name.len()));
let ex = self.convert_expr(value);
KwArg::new(name, None, ex)
})
.collect::<Vec<_>>();
let last_col = pos_args
.last()
.and_then(|last| last.col_end())
@ -805,7 +819,7 @@ impl ASTConverter {
);
(lp, rp)
};
let args = Args::pos_only(pos_args, Some(paren));
let args = Args::new(pos_args, None, kw_args, Some(paren));
function.call_expr(args)
}
ExpressionType::Binop { a, op, b } => {
@ -1213,7 +1227,7 @@ impl ASTConverter {
fn convert_funcdef(
&mut self,
name: String,
args: Parameters,
params: Parameters,
body: Vec<Located<StatementType>>,
decorator_list: Vec<Located<ExpressionType>>,
returns: Option<Located<ExpressionType>>,
@ -1246,7 +1260,7 @@ impl ASTConverter {
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 params = self.convert_params(params);
let return_t = returns.map(|ret| self.convert_type_spec(ret));
let sig = Signature::Subr(SubrSignature::new(
decos,

10
tests/call.py Normal file
View File

@ -0,0 +1,10 @@
print("aaa", sep = ";", end = "") # OK
print("a", sep=1) # ERR
print("a", foo=None) # ERR
def f(x, y=1):
return x + y
print(f(1, 2)) # OK
print(f(1)) # OK
print(f(1, y="a")) # ERR

View File

@ -37,3 +37,7 @@ print(arr[4]) # ERR
i, j = 1, 2
assert i == 1
assert j == 2
with open("test.py") as f:
for line in f.readlines():
print("line: " + line)

View File

@ -98,3 +98,8 @@ fn exec_casting() {
fn exec_collections() {
expect("tests/collections.py", 0, 4);
}
#[test]
fn exec_call() {
expect("tests/call.py", 0, 3);
}