feat: EvalState.call
(cherry picked from commit f3aa6e523c0c5214533d0005d8c3f85a0579b1de)
This commit is contained in:
parent
fbbc7cb490
commit
52778c37e9
1 changed files with 76 additions and 0 deletions
|
|
@ -192,6 +192,23 @@ impl EvalState {
|
||||||
Ok(RealisedString { s, paths })
|
Ok(RealisedString { s, paths })
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Eagerly apply a function to an argument.
|
||||||
|
pub fn call(&self, f: Value, a: Value) -> Result<Value> {
|
||||||
|
let v = unsafe {
|
||||||
|
let value = self.new_value_uninitialized();
|
||||||
|
raw::value_call(
|
||||||
|
self.context.ptr(),
|
||||||
|
self.raw_ptr(),
|
||||||
|
f.raw_ptr(),
|
||||||
|
a.raw_ptr(),
|
||||||
|
value.raw_ptr(),
|
||||||
|
);
|
||||||
|
value
|
||||||
|
};
|
||||||
|
self.context.check_err()?;
|
||||||
|
Ok(v)
|
||||||
|
}
|
||||||
|
|
||||||
fn new_value_uninitialized(&self) -> Value {
|
fn new_value_uninitialized(&self) -> Value {
|
||||||
let value = unsafe { raw::alloc_value(self.context.ptr(), self.raw_ptr()) };
|
let value = unsafe { raw::alloc_value(self.context.ptr(), self.raw_ptr()) };
|
||||||
Value::new(value)
|
Value::new(value)
|
||||||
|
|
@ -490,4 +507,63 @@ mod tests {
|
||||||
})
|
})
|
||||||
.unwrap();
|
.unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn eval_state_call() {
|
||||||
|
gc_registering_current_thread(|| {
|
||||||
|
let store = Store::open("auto").unwrap();
|
||||||
|
let es = EvalState::new(store).unwrap();
|
||||||
|
let f = es.eval_from_string("x: x + 1", "<test>").unwrap();
|
||||||
|
let a = es.eval_from_string("2", "<test>").unwrap();
|
||||||
|
let v = es.call(f, a).unwrap();
|
||||||
|
es.force(&v).unwrap();
|
||||||
|
let t = es.value_type(&v).unwrap();
|
||||||
|
assert!(t == ValueType::Int);
|
||||||
|
let i = es.require_int(&v).unwrap();
|
||||||
|
assert!(i == 3);
|
||||||
|
})
|
||||||
|
.unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn eval_state_call_fail_body() {
|
||||||
|
gc_registering_current_thread(|| {
|
||||||
|
let store = Store::open("auto").unwrap();
|
||||||
|
let es = EvalState::new(store).unwrap();
|
||||||
|
let f = es.eval_from_string("x: x + 1", "<test>").unwrap();
|
||||||
|
let a = es.eval_from_string("true", "<test>").unwrap();
|
||||||
|
let r = es.call(f, a);
|
||||||
|
match r {
|
||||||
|
Ok(_) => panic!("expected an error"),
|
||||||
|
Err(e) => {
|
||||||
|
if !e.to_string().contains("cannot coerce") {
|
||||||
|
eprintln!("{}", e);
|
||||||
|
assert!(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn eval_state_call_fail_args() {
|
||||||
|
gc_registering_current_thread(|| {
|
||||||
|
let store = Store::open("auto").unwrap();
|
||||||
|
let es = EvalState::new(store).unwrap();
|
||||||
|
let f = es.eval_from_string("{x}: x + 1", "<test>").unwrap();
|
||||||
|
let a = es.eval_from_string("{}", "<test>").unwrap();
|
||||||
|
let r = es.call(f, a);
|
||||||
|
match r {
|
||||||
|
Ok(_) => panic!("expected an error"),
|
||||||
|
Err(e) => {
|
||||||
|
if !e.to_string().contains("called without required argument") {
|
||||||
|
eprintln!("{}", e);
|
||||||
|
assert!(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.unwrap();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue