about summary refs log tree commit diff
path: root/tvix/eval/src/vm.rs
diff options
context:
space:
mode:
Diffstat (limited to 'tvix/eval/src/vm.rs')
-rw-r--r--tvix/eval/src/vm.rs21
1 files changed, 20 insertions, 1 deletions
diff --git a/tvix/eval/src/vm.rs b/tvix/eval/src/vm.rs
index 8a6959114f..09e3aa2475 100644
--- a/tvix/eval/src/vm.rs
+++ b/tvix/eval/src/vm.rs
@@ -98,7 +98,7 @@ impl VM {
         #[cfg(feature = "disassembler")]
         let mut tracer = Tracer::new();
 
-        loop {
+        'dispatch: loop {
             let op = self.inc_ip();
             match op {
                 OpCode::OpConstant(idx) => {
@@ -285,6 +285,25 @@ impl VM {
                 OpCode::OpPopWith => {
                     self.with_stack.pop();
                 }
+
+                OpCode::OpResolveWith => {
+                    let ident = self.pop().to_string()?;
+
+                    // Attempt to resolve the variable, starting at
+                    // the back of the with_stack.
+                    'with: for idx in self.with_stack.iter().rev() {
+                        let with = self.stack[*idx].as_attrs()?;
+                        match with.select(ident.as_str()) {
+                            None => continue 'with,
+                            Some(val) => {
+                                self.push(val.clone());
+                                continue 'dispatch;
+                            }
+                        }
+                    }
+
+                    return Err(Error::UnknownDynamicVariable(ident.to_string()));
+                }
             }
 
             #[cfg(feature = "disassembler")]