Skip to content

Commit

Permalink
Merge pull request #466 from erg-lang/kw_var
Browse files Browse the repository at this point in the history
Add variable keyword arguments
  • Loading branch information
mtshiba authored Nov 13, 2023
2 parents d3dfaf8 + 663a082 commit 40ee0de
Show file tree
Hide file tree
Showing 36 changed files with 676 additions and 227 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/rust.yml
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ jobs:
python-version: ${{ matrix.python-version }}
- uses: Swatinem/rust-cache@v2
- run: rustup update stable
- run: cargo test --all --verbose -- --include-ignored --nocapture
- run: cargo test --features backtrace --all --verbose -- --include-ignored --nocapture

build-check:
strategy:
Expand Down
3 changes: 3 additions & 0 deletions crates/els/tests/test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,7 @@ fn test_completion_retrigger() -> Result<(), Box<dyn std::error::Error>> {
}

#[test]
#[exec_new_thread]
fn test_rename() -> Result<(), Box<dyn std::error::Error>> {
let mut client = Server::bind_fake_client();
client.request_initialize()?;
Expand Down Expand Up @@ -202,6 +203,7 @@ fn test_hover() -> Result<(), Box<dyn std::error::Error>> {
}

#[test]
#[exec_new_thread]
fn test_references() -> Result<(), Box<dyn std::error::Error>> {
let mut client = Server::bind_fake_client();
client.request_initialize()?;
Expand Down Expand Up @@ -298,6 +300,7 @@ fn test_inlay_hint() -> Result<(), Box<dyn std::error::Error>> {
}

#[test]
#[exec_new_thread]
fn test_dependents_check() -> Result<(), Box<dyn std::error::Error>> {
let mut client = Server::bind_fake_client();
client.request_initialize()?;
Expand Down
22 changes: 16 additions & 6 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 Expand Up @@ -3432,7 +3442,7 @@ impl PyCodeGenerator {
"?".into(),
);
let param = NonDefaultParamSignature::new(raw, vi, None);
let params = Params::new(vec![self_param, param], None, vec![], vec![], None);
let params = Params::new(vec![self_param, param], None, vec![], None, vec![], None);
(param_name, params)
} else {
("_".into(), Params::single(self_param))
Expand Down
28 changes: 28 additions & 0 deletions crates/erg_compiler/context/eval.rs
Original file line number Diff line number Diff line change
Expand Up @@ -941,6 +941,24 @@ impl Context {
}
}
}
let kw_var_params = if let Some(p) = lambda.sig.params.kw_var_params.as_ref() {
match self.instantiate_param_ty(
p,
None,
&mut tmp_tv_cache,
RegistrationMode::Normal,
ParamKind::KwVarParams,
false,
) {
Ok(pt) => Some(pt),
Err((pt, err)) => {
errs.extend(err);
Some(pt)
}
}
} else {
None
};
// HACK: should avoid cloning
let mut lambda_ctx = Context::instant(
Str::ever("<lambda>"),
Expand All @@ -955,6 +973,7 @@ impl Context {
non_default_params.clone(),
var_params,
default_params.clone(),
kw_var_params,
return_t,
);
let block =
Expand Down Expand Up @@ -1600,12 +1619,20 @@ impl Context {
Err((_, errs)) => return Err((Subr(subr), errs)),
};
}
if let Some(kw_var_args) = subr.kw_var_params.as_mut() {
*kw_var_args.typ_mut() =
match self.eval_t_params(mem::take(kw_var_args.typ_mut()), level, t_loc) {
Ok(t) => t,
Err((_, errs)) => return Err((Subr(subr), errs)),
};
}
match self.eval_t_params(*subr.return_t, level, t_loc) {
Ok(return_t) => Ok(subr_t(
subr.kind,
subr.non_default_params,
subr.var_params.map(|v| *v),
subr.default_params,
subr.kw_var_params.map(|v| *v),
return_t,
)),
Err((_, errs)) => {
Expand All @@ -1614,6 +1641,7 @@ impl Context {
subr.non_default_params,
subr.var_params.map(|v| *v),
subr.default_params,
subr.kw_var_params.map(|v| *v),
Failure,
);
Err((subr, errs))
Expand Down
10 changes: 10 additions & 0 deletions crates/erg_compiler/context/generalize.rs
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,9 @@ impl Generalizer {
.into_iter()
.map(|pt| pt.map_type(|t| self.generalize_t(t, uninit)))
.collect::<Vec<_>>();
let kw_var_params = lambda
.kw_var_params
.map(|pt| pt.map_type(|t| self.generalize_t(t, uninit)));
let body = lambda
.body
.into_iter()
Expand All @@ -109,6 +112,7 @@ impl Generalizer {
nd_params,
var_params,
d_params,
kw_var_params,
body,
))
}
Expand Down Expand Up @@ -213,6 +217,7 @@ impl Generalizer {
subr.non_default_params,
subr.var_params.map(|x| *x),
subr.default_params,
subr.kw_var_params.map(|x| *x),
return_t,
)
}
Expand Down Expand Up @@ -496,6 +501,10 @@ impl<'c, 'q, 'l, L: Locational> Dereferencer<'c, 'q, 'l, L> {
.into_iter()
.map(|pt| pt.try_map_type(|t| self.deref_tyvar(t)))
.collect::<TyCheckResult<_>>()?;
let kw_var_params = lambda
.kw_var_params
.map(|pt| pt.try_map_type(|t| self.deref_tyvar(t)))
.transpose()?;
let body = lambda
.body
.into_iter()
Expand All @@ -506,6 +515,7 @@ impl<'c, 'q, 'l, L: Locational> Dereferencer<'c, 'q, 'l, L> {
nd_params,
var_params,
d_params,
kw_var_params,
body,
)))
}
Expand Down
Loading

0 comments on commit 40ee0de

Please sign in to comment.