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-09T15·49+0300
committertazjin <tazjin@tvl.su>2022-08-13T20·24+0000
commit175eb975059e5a36444453d7b63839c5339cd003 (patch)
tree6d6b0d5a8435654920c78b65e0512b24b22eb9e2 /tvix/eval/src/vm.rs
parentec1770f95ac33e3cfdb57c84f2b94fa63fbc0fb2 (diff)
feat(tvix/eval): construct internal attribute path representation r/4439
This is required for constructing nested attribute sets at runtime.

There'll be quite a lot of optimisation potential with this solution
eventually, if it should turn out to be a bottleneck.

This introduces a conceptual change, in that the `Value` enum is now
an enum representing "all runtime values" instead of "all Nix language
types". This makes sense in general, as this type will also contain
Chunk representations etc. which are not exposed to users.

Change-Id: Ic5f72b2a0965b146c6a451efad34c6a81ca1aad8
Reviewed-on: https://cl.tvl.fyi/c/depot/+/6103
Reviewed-by: grfn <grfn@gws.fyi>
Tested-by: BuildkiteCI
Diffstat (limited to '')
-rw-r--r--tvix/eval/src/vm.rs18
1 files changed, 18 insertions, 0 deletions
diff --git a/tvix/eval/src/vm.rs b/tvix/eval/src/vm.rs
index d6d3de154c..58ef67cb55 100644
--- a/tvix/eval/src/vm.rs
+++ b/tvix/eval/src/vm.rs
@@ -121,6 +121,7 @@ impl VM {
                 OpCode::OpTrue => self.push(Value::Bool(true)),
                 OpCode::OpFalse => self.push(Value::Bool(false)),
                 OpCode::OpAttrs(count) => self.run_attrset(count)?,
+                OpCode::OpAttrPath(count) => self.run_attr_path(count)?,
                 OpCode::OpList(count) => self.run_list(count)?,
                 OpCode::OpInterpolate(count) => self.run_interpolate(count)?,
             }
@@ -218,6 +219,23 @@ impl VM {
         Ok(())
     }
 
+    // Construct runtime representation of an attr path (essentially
+    // just a list of strings).
+    //
+    // The difference to the list construction operation is that this
+    // forces all elements into strings, as attribute set keys are
+    // required to be strict in Nix.
+    fn run_attr_path(&mut self, count: usize) -> EvalResult<()> {
+        let mut path = vec![NixString(String::new()); count];
+
+        for idx in 0..count {
+            path[count - idx - 1] = self.pop().as_string()?
+        }
+
+        self.push(Value::AttrPath(path));
+        Ok(())
+    }
+
     // Construct runtime representation of a list. Because the list
     // items are on the stack in reverse order, the vector is created
     // initialised and elements are directly assigned to their