about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--tvix/eval/src/compiler/mod.rs59
-rw-r--r--tvix/eval/src/compiler/scope.rs1
2 files changed, 43 insertions, 17 deletions
diff --git a/tvix/eval/src/compiler/mod.rs b/tvix/eval/src/compiler/mod.rs
index 07b68061c831..92507b5703f3 100644
--- a/tvix/eval/src/compiler/mod.rs
+++ b/tvix/eval/src/compiler/mod.rs
@@ -773,14 +773,16 @@ impl Compiler<'_> {
         match self.scope_mut().resolve_local(ident.text()) {
             LocalPosition::Unknown => {
                 // Are we possibly dealing with an upvalue?
-                if let Some(idx) = self.resolve_upvalue(self.contexts.len() - 1, ident.text()) {
+                if let Some(idx) =
+                    self.resolve_upvalue(self.contexts.len() - 1, ident.text(), &node)
+                {
                     self.push_op(OpCode::OpGetUpvalue(idx), &node);
                     return;
                 }
 
                 // Even worse - are we dealing with a dynamic upvalue?
                 if let Some(idx) =
-                    self.resolve_dynamic_upvalue(self.contexts.len() - 1, ident.text())
+                    self.resolve_dynamic_upvalue(self.contexts.len() - 1, ident.text(), &node)
                 {
                     // Edge case: Current scope *also* has a non-empty
                     // `with`-stack. This means we need to resolve
@@ -815,8 +817,11 @@ impl Compiler<'_> {
             // scope which is not yet defined. This identifier access
             // must be thunked.
             LocalPosition::Recursive(idx) => self.thunk(slot, &node, move |compiler, node, _| {
-                let upvalue_idx =
-                    compiler.add_upvalue(compiler.contexts.len() - 1, UpvalueKind::Local(idx));
+                let upvalue_idx = compiler.add_upvalue(
+                    compiler.contexts.len() - 1,
+                    &node,
+                    UpvalueKind::Local(idx),
+                );
                 compiler.push_op(OpCode::OpGetUpvalue(upvalue_idx), node);
             }),
         };
@@ -959,7 +964,7 @@ impl Compiler<'_> {
             match upvalue.kind {
                 UpvalueKind::Local(idx) if slot.is_none() => {
                     let stack_idx = self.scope().stack_index(idx);
-                    self.push_op_old(OpCode::DataLocalIdx(stack_idx));
+                    self.push_op(OpCode::DataLocalIdx(stack_idx), &upvalue.node);
                 }
 
                 UpvalueKind::Local(idx) => {
@@ -970,21 +975,22 @@ impl Compiler<'_> {
                     // deferred until the scope is fully initialised
                     // and can be finalised.
                     if slot.unwrap() < idx {
-                        self.push_op_old(OpCode::DataDeferredLocal(stack_idx));
+                        self.push_op(OpCode::DataDeferredLocal(stack_idx), &upvalue.node);
                         self.scope_mut().mark_needs_finaliser(slot.unwrap());
                     } else {
-                        self.push_op_old(OpCode::DataLocalIdx(stack_idx));
+                        self.push_op(OpCode::DataLocalIdx(stack_idx), &upvalue.node);
                     }
                 }
 
                 UpvalueKind::Upvalue(idx) => {
-                    self.push_op_old(OpCode::DataUpvalueIdx(idx));
+                    self.push_op(OpCode::DataUpvalueIdx(idx), &upvalue.node);
                 }
+
                 UpvalueKind::Dynamic { name, up } => {
                     let idx = self.chunk().push_constant(Value::String(name.into()));
-                    self.push_op_old(OpCode::DataDynamicIdx(idx));
+                    self.push_op(OpCode::DataDynamicIdx(idx), &upvalue.node);
                     if let Some(up) = up {
-                        self.push_op_old(OpCode::DataDynamicAncestor(up));
+                        self.push_op(OpCode::DataDynamicAncestor(up), &upvalue.node);
                     }
                 }
             };
@@ -1106,7 +1112,12 @@ impl Compiler<'_> {
         self.scope_mut().declare_local(name, node)
     }
 
-    fn resolve_upvalue(&mut self, ctx_idx: usize, name: &str) -> Option<UpvalueIdx> {
+    fn resolve_upvalue(
+        &mut self,
+        ctx_idx: usize,
+        name: &str,
+        node: &rnix::ast::Ident,
+    ) -> Option<UpvalueIdx> {
         if ctx_idx == 0 {
             // There can not be any upvalue at the outermost context.
             return None;
@@ -1119,7 +1130,7 @@ impl Compiler<'_> {
             // 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, UpvalueKind::Local(idx)))
+                return Some(self.add_upvalue(ctx_idx, node, UpvalueKind::Local(idx)))
             }
 
             LocalPosition::Unknown => { /* continue below */ }
@@ -1128,8 +1139,8 @@ impl Compiler<'_> {
         // If the upvalue comes from even further up, we need to
         // recurse to make sure that the upvalues are created at each
         // level.
-        if let Some(idx) = self.resolve_upvalue(ctx_idx - 1, name) {
-            return Some(self.add_upvalue(ctx_idx, UpvalueKind::Upvalue(idx)));
+        if let Some(idx) = self.resolve_upvalue(ctx_idx - 1, name, node) {
+            return Some(self.add_upvalue(ctx_idx, node, UpvalueKind::Upvalue(idx)));
         }
 
         None
@@ -1146,7 +1157,12 @@ impl Compiler<'_> {
     /// As such an upvalue is actually accessed, an error is produced
     /// when the sentinel is found. See the runtime's handling of
     /// dynamic upvalues for details.
-    fn resolve_dynamic_upvalue(&mut self, at: usize, name: &str) -> Option<UpvalueIdx> {
+    fn resolve_dynamic_upvalue(
+        &mut self,
+        at: usize,
+        name: &str,
+        node: &rnix::ast::Ident,
+    ) -> Option<UpvalueIdx> {
         if at == 0 {
             // There can not be any upvalue at the outermost context.
             return None;
@@ -1168,6 +1184,7 @@ impl Compiler<'_> {
             for idx in lowest_idx..=at {
                 upvalue_idx = Some(self.add_upvalue(
                     idx,
+                    node,
                     UpvalueKind::Dynamic {
                         name: name.clone(),
                         up: upvalue_idx,
@@ -1183,7 +1200,12 @@ impl Compiler<'_> {
         None
     }
 
-    fn add_upvalue(&mut self, ctx_idx: usize, kind: UpvalueKind) -> UpvalueIdx {
+    fn add_upvalue(
+        &mut self,
+        ctx_idx: usize,
+        node: &rnix::ast::Ident,
+        kind: UpvalueKind,
+    ) -> UpvalueIdx {
         // If there is already an upvalue closing over the specified
         // index, retrieve that instead.
         for (idx, existing) in self.contexts[ctx_idx].scope.upvalues.iter().enumerate() {
@@ -1192,7 +1214,10 @@ impl Compiler<'_> {
             }
         }
 
-        self.contexts[ctx_idx].scope.upvalues.push(Upvalue { kind });
+        self.contexts[ctx_idx].scope.upvalues.push(Upvalue {
+            kind,
+            node: node.clone(),
+        });
 
         let idx = UpvalueIdx(self.contexts[ctx_idx].lambda.upvalue_count);
         self.contexts[ctx_idx].lambda.upvalue_count += 1;
diff --git a/tvix/eval/src/compiler/scope.rs b/tvix/eval/src/compiler/scope.rs
index 01e0801e65c6..7614fc2b2b11 100644
--- a/tvix/eval/src/compiler/scope.rs
+++ b/tvix/eval/src/compiler/scope.rs
@@ -94,6 +94,7 @@ pub enum UpvalueKind {
 #[derive(Clone, Debug)]
 pub struct Upvalue {
     pub kind: UpvalueKind,
+    pub node: rnix::ast::Ident,
 }
 
 /// Represents the index of a local in the scope's local array, which