Skip to content

Commit

Permalink
feat: var-kwargs codegen
Browse files Browse the repository at this point in the history
  • Loading branch information
mtshiba committed Nov 13, 2023
1 parent 88940aa commit 663a082
Show file tree
Hide file tree
Showing 7 changed files with 47 additions and 13 deletions.
20 changes: 15 additions & 5 deletions crates/erg_compiler/codegen.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1026,6 +1026,14 @@ impl PyCodeGenerator {
.iter()
.map(|p| (p.inspect().map(|s| &s[..]).unwrap_or("_"), &p.sig.vi)),
)
.chain(if let Some(kw_var_args) = &params.kw_var_params {
vec![(
kw_var_args.inspect().map(|s| &s[..]).unwrap_or("_"),
&kw_var_args.vi,
)]
} else {
vec![]
})
.enumerate()
.map(|(i, (s, vi))| {
if s == "_" {
Expand Down Expand Up @@ -1405,11 +1413,13 @@ impl PyCodeGenerator {
self.stack_dec_n(defaults_len - 1);
make_function_flag += MakeFunctionFlags::Defaults as usize;
}
let flags = if sig.params.var_params.is_some() {
CodeObjFlags::VarArgs as u32
} else {
0
};
let mut flags = 0;
if sig.params.var_params.is_some() {
flags += CodeObjFlags::VarArgs as u32;
}
if sig.params.kw_var_params.is_some() {
flags += CodeObjFlags::VarKeywords as u32;
}
let code = self.emit_block(
body.block,
sig.params.guards,
Expand Down
10 changes: 5 additions & 5 deletions crates/erg_compiler/context/register.rs
Original file line number Diff line number Diff line change
Expand Up @@ -390,16 +390,16 @@ impl Context {
opt_decl_t,
&mut dummy_tv_cache,
Normal,
kind,
kind.clone(),
false,
) {
Ok(ty) => (ty, TyCheckErrors::empty()),
Err((ty, errs)) => (ty, errs),
};
let spec_t = if is_var_params {
unknown_len_array_t(spec_t)
} else {
spec_t
let spec_t = match kind {
ParamKind::VarParams => unknown_len_array_t(spec_t),
ParamKind::KwVarParams => str_dict_t(spec_t),
_ => spec_t,
};
if &name.inspect()[..] == "self" {
self.type_self_param(&sig.raw.pat, name, &spec_t, &mut errs);
Expand Down
3 changes: 2 additions & 1 deletion crates/erg_compiler/ty/codeobj.rs
Original file line number Diff line number Diff line change
Expand Up @@ -280,8 +280,9 @@ impl CodeObj {
) -> Self {
let name = name.into();
let var_args_defined = (flags & CodeObjFlags::VarArgs as u32 != 0) as u32;
let kw_var_args_defined = (flags & CodeObjFlags::VarKeywords as u32 != 0) as u32;
Self {
argcount: params.len() as u32 - var_args_defined,
argcount: params.len() as u32 - var_args_defined - kw_var_args_defined,
posonlyargcount: 0,
kwonlyargcount: 0,
nlocals: params.len() as u32,
Expand Down
10 changes: 8 additions & 2 deletions crates/erg_parser/parse.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2415,7 +2415,8 @@ impl Parser {
debug_exit_info!(self);
Ok(call_or_acc)
}
Some(t) if t.is(PreStar) => {
Some(t) if t.is(PreStar) || t.is(PreDblStar) => {
let kind = t.kind;
let _ = self.lpop();
let expr = self
.try_reduce_expr(false, in_type_args, in_brace, false)
Expand All @@ -2430,8 +2431,13 @@ impl Parser {
}
self.stack_dec(fn_name!())
})?;
let arg = match kind {
PreStar => ArgKind::Var(PosArg::new(expr)),
PreDblStar => ArgKind::KwVar(PosArg::new(expr)),
_ => switch_unreachable!(),
};
let tuple = self
.try_reduce_nonempty_tuple(ArgKind::Var(PosArg::new(expr)), false)
.try_reduce_nonempty_tuple(arg, false)
.map_err(|_| self.stack_dec(fn_name!()))?;
debug_exit_info!(self);
Ok(Expr::Tuple(tuple))
Expand Down
4 changes: 4 additions & 0 deletions tests/should_err/var_kwargs.er
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
kw_var(**x: Int) = x["::a"] + x["::b"]

_ = kw_var(a:="1", b:=2) # ERR
_ = kw_var(a:=1, b:="2") # ERR
3 changes: 3 additions & 0 deletions tests/should_ok/var_kwargs.er
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
kw_var(**x: Int) = x["::a"] + x["::b"]

assert kw_var(a:=1, b:=2) == 3
10 changes: 10 additions & 0 deletions tests/test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -410,6 +410,11 @@ fn exec_var_args() -> Result<(), ()> {
expect_success("tests/should_ok/var_args.er", 0)
}

#[test]
fn exec_var_kwargs() -> Result<(), ()> {
expect_success("tests/should_ok/var_kwargs.er", 0)
}

#[test]
fn exec_with() -> Result<(), ()> {
expect_success("examples/with.er", 0)
Expand Down Expand Up @@ -621,6 +626,11 @@ fn exec_var_args_err() -> Result<(), ()> {
expect_failure("tests/should_err/var_args.er", 0, 3)
}

#[test]
fn exec_var_kwargs_err() -> Result<(), ()> {
expect_failure("tests/should_err/var_kwargs.er", 0, 2)
}

#[test]
fn exec_visibility() -> Result<(), ()> {
expect_failure("tests/should_err/visibility.er", 2, 7)
Expand Down

0 comments on commit 663a082

Please sign in to comment.