feat(tvix/eval): implement capture of self-recursive upvalues
With this change, it becomes possible for functions to call themselves as they are being defined in local bindings. Change-Id: Ib46a39ba17b1452b5673d96fa729d633d237241a Reviewed-on: https://cl.tvl.fyi/c/depot/+/6314 Tested-by: BuildkiteCI Reviewed-by: sterni <sternenseemann@systemli.org>
This commit is contained in:
parent
06b07f5c47
commit
ae531a2245
4 changed files with 22 additions and 7 deletions
|
|
@ -359,7 +359,15 @@ impl VM {
|
|||
}
|
||||
|
||||
OpCode::OpClosure(idx) => {
|
||||
let closure = self.chunk().constant(idx).clone().to_closure()?;
|
||||
let value = self.chunk().constant(idx).clone();
|
||||
self.push(value.clone());
|
||||
|
||||
// This refers to the same Rc, and from this point
|
||||
// on internally mutates the closure objects
|
||||
// upvalues. The closure is already in its stack
|
||||
// slot, which means that it can capture itself as
|
||||
// an upvalue for self-recursion.
|
||||
let closure = value.to_closure()?;
|
||||
|
||||
debug_assert!(
|
||||
closure.upvalue_count() > 0,
|
||||
|
|
@ -387,8 +395,6 @@ impl VM {
|
|||
_ => panic!("compiler error: missing closure operand"),
|
||||
}
|
||||
}
|
||||
|
||||
self.push(Value::Closure(closure));
|
||||
}
|
||||
|
||||
// Data-carrying operands should never be executed,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue