about summary refs log tree commit diff
path: root/tvix/eval/src/compiler/mod.rs
diff options
context:
space:
mode:
authorVincent Ambo <mail@tazj.in>2022-08-27T19·58+0300
committertazjin <tazjin@tvl.su>2022-09-06T07·29+0000
commitae531a2245e83d44ce58ba6c588713265984dbbf (patch)
tree64b32c14b9bd8ed6db4f24407e58f785a15c2f2b /tvix/eval/src/compiler/mod.rs
parent06b07f5c47cacca7c3e2d265ba23701f99ceabdf (diff)
feat(tvix/eval): implement capture of self-recursive upvalues r/4653
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>
Diffstat (limited to 'tvix/eval/src/compiler/mod.rs')
-rw-r--r--tvix/eval/src/compiler/mod.rs12
1 files changed, 8 insertions, 4 deletions
diff --git a/tvix/eval/src/compiler/mod.rs b/tvix/eval/src/compiler/mod.rs
index 520eb3bd64..6ba470a7af 100644
--- a/tvix/eval/src/compiler/mod.rs
+++ b/tvix/eval/src/compiler/mod.rs
@@ -709,9 +709,9 @@ impl Compiler {
                 self.chunk().push_op(OpCode::OpResolveWith)
             }
 
-            LocalPosition::Recursive(_) => todo!("self-recursive upvalue"),
-
             LocalPosition::Known(idx) => self.chunk().push_op(OpCode::OpGetLocal(idx)),
+
+            LocalPosition::Recursive(_) => panic!("TODO: unclear if this can happen"),
         };
     }
 
@@ -981,10 +981,14 @@ impl Compiler {
 
         // Determine whether the upvalue is a local in the enclosing context.
         match self.contexts[ctx_idx - 1].scope.resolve_local(name) {
-            LocalPosition::Known(idx) => {
+            // recursive upvalues are dealt with the same way as
+            // standard known ones, as thunks and closures are
+            // guaranteed to be placed on the stack (i.e. in the right
+            // position) *during* their runtime construction
+            LocalPosition::Known(idx) | LocalPosition::Recursive(idx) => {
                 return Some(self.add_upvalue(ctx_idx, Upvalue::Stack(idx)))
             }
-            LocalPosition::Recursive(_) => todo!("self-recursive upvalue"),
+
             LocalPosition::Unknown => { /* continue below */ }
         };