mirror of
https://github.com/erg-lang/erg.git
synced 2025-09-30 12:51:10 +00:00
Fix kw args bugs & add a test
This commit is contained in:
parent
38d69e6b96
commit
2f7d810685
3 changed files with 54 additions and 16 deletions
|
@ -1019,6 +1019,20 @@ impl Context {
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// pos_args.len() < non_default_params_len
|
// pos_args.len() < non_default_params_len
|
||||||
|
let mut params = non_default_params.chain(subr.default_params.iter());
|
||||||
|
for pos_arg in pos_args.iter() {
|
||||||
|
if let Err(mut es) = self.substitute_pos_arg(
|
||||||
|
&callee,
|
||||||
|
attr_name,
|
||||||
|
&pos_arg.expr,
|
||||||
|
nth,
|
||||||
|
params.next().unwrap(),
|
||||||
|
&mut passed_params,
|
||||||
|
) {
|
||||||
|
errs.append(&mut es);
|
||||||
|
}
|
||||||
|
nth += 1;
|
||||||
|
}
|
||||||
for kw_arg in kw_args.iter() {
|
for kw_arg in kw_args.iter() {
|
||||||
if let Err(mut es) = self.substitute_kw_arg(
|
if let Err(mut es) = self.substitute_kw_arg(
|
||||||
&callee,
|
&callee,
|
||||||
|
@ -1032,7 +1046,7 @@ impl Context {
|
||||||
}
|
}
|
||||||
nth += 1;
|
nth += 1;
|
||||||
}
|
}
|
||||||
let missing_len = non_default_params_len - pos_args.len() - passed_params.len();
|
let missing_len = params_len - passed_params.len();
|
||||||
if missing_len > 0 {
|
if missing_len > 0 {
|
||||||
let missing_params = subr
|
let missing_params = subr
|
||||||
.non_default_params
|
.non_default_params
|
||||||
|
@ -1040,7 +1054,7 @@ impl Context {
|
||||||
.rev()
|
.rev()
|
||||||
.take(missing_len)
|
.take(missing_len)
|
||||||
.rev()
|
.rev()
|
||||||
.map(|pt| pt.name().cloned().unwrap_or(Str::ever("")))
|
.map(|pt| pt.name().cloned().unwrap_or(Str::ever("_")))
|
||||||
.filter(|pt| !passed_params.contains(pt))
|
.filter(|pt| !passed_params.contains(pt))
|
||||||
.collect();
|
.collect();
|
||||||
return Err(TyCheckErrors::from(TyCheckError::args_missing_error(
|
return Err(TyCheckErrors::from(TyCheckError::args_missing_error(
|
||||||
|
@ -1173,6 +1187,20 @@ impl Context {
|
||||||
) -> TyCheckResult<()> {
|
) -> TyCheckResult<()> {
|
||||||
let arg_t = arg.ref_t();
|
let arg_t = arg.ref_t();
|
||||||
let param_t = ¶m.typ();
|
let param_t = ¶m.typ();
|
||||||
|
if let Some(name) = param.name() {
|
||||||
|
if passed_params.contains(name) {
|
||||||
|
return Err(TyCheckErrors::from(TyCheckError::multiple_args_error(
|
||||||
|
self.cfg.input.clone(),
|
||||||
|
line!() as usize,
|
||||||
|
callee.loc(),
|
||||||
|
&callee.to_string(),
|
||||||
|
self.caused_by(),
|
||||||
|
name,
|
||||||
|
)));
|
||||||
|
} else {
|
||||||
|
passed_params.insert(name.clone());
|
||||||
|
}
|
||||||
|
}
|
||||||
self.sub_unify(arg_t, param_t, arg.loc(), param.name())
|
self.sub_unify(arg_t, param_t, arg.loc(), param.name())
|
||||||
.map_err(|errs| {
|
.map_err(|errs| {
|
||||||
log!(err "semi-unification failed with {callee}\n{arg_t} !<: {param_t}");
|
log!(err "semi-unification failed with {callee}\n{arg_t} !<: {param_t}");
|
||||||
|
@ -1201,20 +1229,6 @@ impl Context {
|
||||||
.collect(),
|
.collect(),
|
||||||
)
|
)
|
||||||
})?;
|
})?;
|
||||||
if let Some(name) = param.name() {
|
|
||||||
if passed_params.contains(name) {
|
|
||||||
return Err(TyCheckErrors::from(TyCheckError::multiple_args_error(
|
|
||||||
self.cfg.input.clone(),
|
|
||||||
line!() as usize,
|
|
||||||
callee.loc(),
|
|
||||||
&callee.to_string(),
|
|
||||||
self.caused_by(),
|
|
||||||
name,
|
|
||||||
)));
|
|
||||||
} else {
|
|
||||||
passed_params.insert(name.clone());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1287,6 +1301,7 @@ impl Context {
|
||||||
.chain(subr_ty.default_params.iter())
|
.chain(subr_ty.default_params.iter())
|
||||||
.find(|pt| pt.name().unwrap() == kw_name)
|
.find(|pt| pt.name().unwrap() == kw_name)
|
||||||
{
|
{
|
||||||
|
passed_params.insert(kw_name.clone());
|
||||||
self.sub_unify(arg_t, pt.typ(), arg.loc(), Some(kw_name))
|
self.sub_unify(arg_t, pt.typ(), arg.loc(), Some(kw_name))
|
||||||
.map_err(|errs| {
|
.map_err(|errs| {
|
||||||
log!(err "semi-unification failed with {callee}\n{arg_t} !<: {}", pt.typ());
|
log!(err "semi-unification failed with {callee}\n{arg_t} !<: {}", pt.typ());
|
||||||
|
|
18
tests/should_err/args.er
Normal file
18
tests/should_err/args.er
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
print! sep:="" # OK
|
||||||
|
print! 1, "", sep:="" # OK
|
||||||
|
print! end:="", sep:="" # OK
|
||||||
|
print! 1, end:="", sep:="" # OK
|
||||||
|
|
||||||
|
add x: Int!, y: Int = x - y
|
||||||
|
print! add !1, 1 # OK
|
||||||
|
print! add x:=!1, y:=2 # OK
|
||||||
|
print! add y:=1, x:=!2 # OK
|
||||||
|
print! add !1, y:=1 # OK
|
||||||
|
print! add x:=!1, y:="" # ERR, the type of y is wrong
|
||||||
|
print! add x:=!1, y:=2, z:=1 # ERR, z is unexpected
|
||||||
|
print! add x:=!1, y:=2, x:=!2 # ERR, x is passed twice
|
||||||
|
print! add x:=!1, y:=2, x:=!2, z:=1 # ERR, x is passed twice, z is unexpected
|
||||||
|
print! add "", y:=1 # ERR, the type of x is wrong
|
||||||
|
print! add !1, 1, y:=1 # ERR, too many args
|
||||||
|
print! add "", y:=1, x:=1 # ERR, the type of x is wrong, x is passed twice (or args are too many)
|
||||||
|
print! add "", y:="" # ERR, the types of x, y are wrong
|
|
@ -124,6 +124,11 @@ fn exec_addition_err() -> Result<(), ()> {
|
||||||
expect_failure("tests/should_err/addition.er", 1)
|
expect_failure("tests/should_err/addition.er", 1)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn exec_args() -> Result<(), ()> {
|
||||||
|
expect_failure("tests/should_err/args.er", 10)
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn exec_invalid_param() -> Result<(), ()> {
|
fn exec_invalid_param() -> Result<(), ()> {
|
||||||
expect_failure("tests/should_err/invalid_param.er", 3)
|
expect_failure("tests/should_err/invalid_param.er", 3)
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue