-
Notifications
You must be signed in to change notification settings - Fork 5
Open
Description
The Callable::match_args() (
Lines 39 to 104 in 79d788a
| fn match_args(&self, args: List, stack: &mut CallStack) -> Result<(List, List), Signal> { | |
| let mut formals = self.formals(); | |
| let ellipsis: List = List::new(); | |
| let matched_args: List = List::new(); | |
| // assign named args to corresponding formals | |
| let mut indices: Vec<i32> = Vec::new(); | |
| for (i, (maybe_name, value)) in args.pairs_ref().iter().enumerate() { | |
| if let Character::Some(name) = maybe_name { | |
| if let Some((Some(_), _)) = formals.remove_named(name) { | |
| matched_args.push_named(Character::Some(name.clone()), value.clone()); | |
| continue; | |
| } | |
| } | |
| indices.push(i as i32); | |
| } | |
| let indices: Vec<Integer> = indices.into_iter().map(Integer::Some).collect(); | |
| let subset = Subset::Indices(indices.into()); | |
| let args = args.subset(subset).materialize(); | |
| // TODO(bug): need to evaluate trailing unassigned params that have | |
| // a default value before popping off remaining trailing params | |
| // remove any Ellipsis param, and any trailing unassigned params | |
| let remainder = formals.pop_trailing(); | |
| // backfill unnamed args, populating ellipsis with overflow | |
| for (key, value) in args.iter_pairs() { | |
| match key { | |
| // named args go directly to ellipsis, they did not match a formal | |
| Character::Some(arg) => ellipsis.push_named(Character::Some(arg), value), | |
| // unnamed args populate next formal, or ellipsis if formals exhausted | |
| Character::NA => { | |
| let next_unassigned_formal = formals.remove(0); | |
| if let Some((Some(param), _)) = next_unassigned_formal { | |
| matched_args.push_named(Character::Some(param), value); | |
| } else { | |
| ellipsis.push_named(Character::NA, value); | |
| } | |
| } | |
| } | |
| } | |
| // add back in parameter defaults that weren't filled with args | |
| for (param, default) in formals.into_iter() { | |
| matched_args.push_named( | |
| param.into(), | |
| Obj::Promise(None, default, stack.last_frame().env().clone()), | |
| ) | |
| } | |
| if let Some(Expr::Ellipsis(Some(name))) = remainder.get(0) { | |
| matched_args.push_named(Character::Some(name), Obj::List(ellipsis.clone())); | |
| } else if !remainder.is_empty() { | |
| matched_args.push_named( | |
| Character::Some("...".to_string()), | |
| Obj::List(ellipsis.clone()), | |
| ); | |
| } | |
| Ok((matched_args, ellipsis)) | |
| } |
E.g.
f = fn(x) x
f(x = 1, 2)should throw an error because the second argument 2 is unused.
Metadata
Metadata
Assignees
Labels
No labels