feat: Add EvalState::call_multi
(cherry picked from commit e1866f0c61011ffb57b607abe871340aca294f19)
This commit is contained in:
parent
8a437b71a0
commit
dc01d3731f
1 changed files with 82 additions and 0 deletions
|
|
@ -433,6 +433,24 @@ impl EvalState {
|
||||||
Ok(value)
|
Ok(value)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Eagerly apply a function with multiple curried arguments.
|
||||||
|
#[doc(alias = "nix_value_call_multi")]
|
||||||
|
pub fn call_multi(&mut self, f: &Value, args: &[Value]) -> Result<Value> {
|
||||||
|
let value = self.new_value_uninitialized()?;
|
||||||
|
let mut args_ptrs = args.iter().map(|a| a.raw_ptr()).collect::<Vec<_>>();
|
||||||
|
unsafe {
|
||||||
|
check_call!(raw::value_call_multi(
|
||||||
|
&mut self.context,
|
||||||
|
self.eval_state.as_ptr(),
|
||||||
|
f.raw_ptr(),
|
||||||
|
args_ptrs.len(),
|
||||||
|
args_ptrs.as_mut_ptr(),
|
||||||
|
value.raw_ptr()
|
||||||
|
))
|
||||||
|
}?;
|
||||||
|
Ok(value)
|
||||||
|
}
|
||||||
|
|
||||||
/// Apply a function to an argument, but don't evaluate the result just yet.
|
/// Apply a function to an argument, but don't evaluate the result just yet.
|
||||||
///
|
///
|
||||||
/// For an eager version, see [`call`][`EvalState::call`].
|
/// For an eager version, see [`call`][`EvalState::call`].
|
||||||
|
|
@ -1166,6 +1184,24 @@ mod tests {
|
||||||
.unwrap();
|
.unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn eval_state_call_multi() {
|
||||||
|
gc_registering_current_thread(|| {
|
||||||
|
let store = Store::open("auto", HashMap::new()).unwrap();
|
||||||
|
let mut es = EvalState::new(store, []).unwrap();
|
||||||
|
// This is a function that takes two arguments.
|
||||||
|
let f = es.eval_from_string("x: y: x - y", "<test>").unwrap();
|
||||||
|
let a = es.eval_from_string("2", "<test>").unwrap();
|
||||||
|
let b = es.eval_from_string("3", "<test>").unwrap();
|
||||||
|
let v = es.call_multi(&f, &[a, b]).unwrap();
|
||||||
|
let t = es.value_type_unforced(&v);
|
||||||
|
assert!(t == Some(ValueType::Int));
|
||||||
|
let i = es.require_int(&v).unwrap();
|
||||||
|
assert!(i == -1);
|
||||||
|
})
|
||||||
|
.unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn eval_state_apply() {
|
fn eval_state_apply() {
|
||||||
gc_registering_current_thread(|| {
|
gc_registering_current_thread(|| {
|
||||||
|
|
@ -1206,6 +1242,29 @@ mod tests {
|
||||||
.unwrap();
|
.unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn eval_state_call_multi_fail_body() {
|
||||||
|
gc_registering_current_thread(|| {
|
||||||
|
let store = Store::open("auto", HashMap::new()).unwrap();
|
||||||
|
let mut es = EvalState::new(store, []).unwrap();
|
||||||
|
// This is a function that takes two arguments.
|
||||||
|
let f = es.eval_from_string("x: y: x - y", "<test>").unwrap();
|
||||||
|
let a = es.eval_from_string("2", "<test>").unwrap();
|
||||||
|
let b = es.eval_from_string("true", "<test>").unwrap();
|
||||||
|
let r = es.call_multi(&f, &[a, b]);
|
||||||
|
match r {
|
||||||
|
Ok(_) => panic!("expected an error"),
|
||||||
|
Err(e) => {
|
||||||
|
if !e.to_string().contains("expected an integer but found") {
|
||||||
|
eprintln!("{}", e);
|
||||||
|
assert!(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn eval_state_apply_fail_body() {
|
fn eval_state_apply_fail_body() {
|
||||||
gc_registering_current_thread(|| {
|
gc_registering_current_thread(|| {
|
||||||
|
|
@ -1252,6 +1311,29 @@ mod tests {
|
||||||
.unwrap();
|
.unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn eval_state_call_multi_fail_args() {
|
||||||
|
gc_registering_current_thread(|| {
|
||||||
|
let store = Store::open("auto", HashMap::new()).unwrap();
|
||||||
|
let mut es = EvalState::new(store, []).unwrap();
|
||||||
|
// This is a function that takes two arguments.
|
||||||
|
let f = es.eval_from_string("{x}: {y}: x - y", "<test>").unwrap();
|
||||||
|
let a = es.eval_from_string("{x = 2;}", "<test>").unwrap();
|
||||||
|
let b = es.eval_from_string("{}", "<test>").unwrap();
|
||||||
|
let r = es.call_multi(&f, &[a, b]);
|
||||||
|
match r {
|
||||||
|
Ok(_) => panic!("expected an error"),
|
||||||
|
Err(e) => {
|
||||||
|
if !e.to_string().contains("called without required argument") {
|
||||||
|
eprintln!("{}", e);
|
||||||
|
assert!(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
/// This tests the behavior of `new_value_apply`, which is lazy, unlike `call`.
|
/// This tests the behavior of `new_value_apply`, which is lazy, unlike `call`.
|
||||||
#[test]
|
#[test]
|
||||||
fn eval_state_apply_fail_args_lazy() {
|
fn eval_state_apply_fail_args_lazy() {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue