refactor(tvix/eval): Abstract away calling functions
The process of calling a function from a builtin, especially if it's got more than 1 arrgument, is reasonably involved and easy to get wrong due to having to interact directly with the stack - instead of having that done entirely manually in builtins, this wraps it up in a new `call_with` function which handles pushing arguments onto the stack and recursively calling the (partially applied) function. Change-Id: I14700c639a0deca53b9a060f6d70dbc7762e9007 Reviewed-on: https://cl.tvl.fyi/c/depot/+/6910 Autosubmit: grfn <grfn@gws.fyi> Reviewed-by: tazjin <tazjin@tvl.su> Tested-by: BuildkiteCI
This commit is contained in:
parent
ba8ec1910b
commit
0b06d94606
2 changed files with 32 additions and 27 deletions
|
|
@ -229,6 +229,31 @@ impl<'o> VM<'o> {
|
|||
}
|
||||
}
|
||||
|
||||
/// Call the given `callable` value with the given list of `args`
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// Panics if the passed list of `args` is empty
|
||||
#[track_caller]
|
||||
pub fn call_with<I>(&mut self, callable: &Value, args: I) -> EvalResult<Value>
|
||||
where
|
||||
I: IntoIterator<Item = Value>,
|
||||
{
|
||||
let mut num_args = 0_usize;
|
||||
for arg in args {
|
||||
num_args += 1;
|
||||
self.push(arg);
|
||||
}
|
||||
if num_args == 0 {
|
||||
panic!("call_with called with an empty list of args");
|
||||
}
|
||||
let mut res = self.call_value(callable)?;
|
||||
for _ in 0..(num_args - 1) {
|
||||
res = self.call_value(&res)?;
|
||||
}
|
||||
Ok(res)
|
||||
}
|
||||
|
||||
fn tail_call_value(&mut self, callable: Value) -> EvalResult<()> {
|
||||
match callable {
|
||||
Value::Builtin(builtin) => self.call_builtin(builtin),
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue