about summary refs log tree commit diff
path: root/tvix/eval/src/vm.rs
diff options
context:
space:
mode:
authorVincent Ambo <mail@tazj.in>2022-08-14T22·13+0300
committertazjin <tazjin@tvl.su>2022-08-31T22·26+0000
commit59f50dc81a6afe8d2cd77d96ffb1d92f40c971cc (patch)
tree452ca647895b8bd13804b0c10a98101d19ccf5f0 /tvix/eval/src/vm.rs
parent911fb96eca84a3059ecc11af9c3ac6fdacc28166 (diff)
feat(tvix/eval): Implement OpResolveWith instruction r/4556
Change-Id: I4d2a69f28a6b6199b3ff48ef81135e7da9fe1c3b
Reviewed-on: https://cl.tvl.fyi/c/depot/+/6222
Tested-by: BuildkiteCI
Reviewed-by: sterni <sternenseemann@systemli.org>
Reviewed-by: grfn <grfn@gws.fyi>
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")]