in starlark/src/eval/bc/instr_impl.rs [1413:1497]
fn run_with_args<'v>(
eval: &mut Evaluator<'v, '_>,
stack: &mut BcStackPtr<'v, '_>,
_ip: BcPtrAddr,
(pops, def_data): &Self::Arg,
_pops: (),
) -> anyhow::Result<Value<'v>> {
let pop = stack.pop_slice(*pops);
let mut parameters =
ParametersSpec::with_capacity(def_data.function_name.clone(), def_data.params.len());
let mut parameter_types = Vec::new();
let mut parameter_captures = Vec::new();
let mut pop_index = 0;
// count here rather than enumerate because '*' doesn't get a real
// index in the parameter mapping, and it messes up the indexes
let mut i = 0;
for x in &def_data.params {
if let Some(t) = x.ty() {
assert!(*t == pop_index);
let v = pop[pop_index as usize];
pop_index += 1;
let name = x.name().unwrap_or("unknown").to_owned();
parameter_types.push((
i,
name,
v,
expr_throw(TypeCompiled::new(v, eval.heap()), x.span, eval).map_err(|e| e.0)?,
));
}
match &x.node {
ParameterCompiled::Normal(n, _) => parameters.required(&n.name),
ParameterCompiled::WithDefaultValue(n, ty, v) => {
assert!(*v == pop_index);
let value = pop[pop_index as usize];
pop_index += 1;
if ty.is_some() {
// Check the type of the default
let (_, _, ty_value, ty_compiled) = parameter_types.last().unwrap();
expr_throw(
value.check_type_compiled(*ty_value, ty_compiled, Some(&n.name)),
x.span,
eval,
)
.map_err(|e| e.0)?;
}
parameters.defaulted(&n.name, value);
}
ParameterCompiled::NoArgs => parameters.no_args(),
ParameterCompiled::Args(_, _) => parameters.args(),
ParameterCompiled::KwArgs(_, _) => parameters.kwargs(),
};
if let Captured::Yes = x.captured() {
parameter_captures.push(i);
}
if !matches!(x.node, ParameterCompiled::NoArgs) {
i += 1;
}
}
let return_type = match &def_data.return_type {
None => None,
Some(v) => {
assert!(v.node == pop_index);
let value = pop[pop_index as usize];
pop_index += 1;
Some((
value,
expr_throw(TypeCompiled::new(value, eval.heap()), v.span, eval)
.map_err(|e| e.0)?,
))
}
};
assert!(pop_index as usize == pop.len());
Ok(eval.heap().alloc(Def::new(
parameters,
parameter_captures,
parameter_types,
return_type,
def_data.info,
eval,
)))
}