feat(tvix/eval): Implement builtins.deepSeq
This is done via a new `deepForce` function on Value. Since values can be cyclical (for example, see the test-case), we need to do some extra work to avoid RefCell borrow errors if we ever hit a graph cycle: While deep-forcing values, we keep a set of thunks that we have already seen and avoid doing any work on the same thunk twice. The set is encapsulated in a separate type to stop potentially invalid pointers from leaking out. Finally, since deep_force is conceptually similar to `VM::force_for_output` (but more suited to usage in eval since it doesn't clone the values) this removes the latter, replacing it with the former. Co-Authored-By: Vincent Ambo <tazjin@tvl.su> Change-Id: Iefddefcf09fae3b6a4d161a5873febcff54b9157 Reviewed-on: https://cl.tvl.fyi/c/depot/+/7000 Tested-by: BuildkiteCI Reviewed-by: grfn <grfn@gws.fyi> Reviewed-by: tazjin <tazjin@tvl.su>
This commit is contained in:
parent
8724d2fff8
commit
d4fa3152e9
10 changed files with 100 additions and 62 deletions
|
@ -191,6 +191,16 @@ fn pure_builtins() -> Vec<Builtin> {
|
|||
Ok(res.into())
|
||||
},
|
||||
),
|
||||
Builtin::new(
|
||||
"deepSeq",
|
||||
&[true, true],
|
||||
|mut args: Vec<Value>, vm: &mut VM| {
|
||||
let arg2 = args.pop().unwrap();
|
||||
let arg1 = args.pop().unwrap();
|
||||
arg1.deep_force(vm, &mut Default::default())?;
|
||||
Ok(arg2)
|
||||
},
|
||||
),
|
||||
Builtin::new(
|
||||
"div",
|
||||
&[false, false],
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue