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-09T13·53+0300
committertazjin <tazjin@tvl.su>2022-08-13T15·31+0000
commit57a723aaa991b91f58a9a2b64c641d60bdbee2bb (patch)
tree2ea87ca1595a0d5bc318c0802151fa5af1a181ad /tvix/eval/src/vm.rs
parent20fc7bc0b264f4904e0855b6b29513092118fdae (diff)
feat(tvix/eval): implement trivial attribute set literals r/4427
Implements attribute set literals without nesting. Technically this
already supports dynamic key fragments (evaluating to strings), though
the only way to create these (interpolation) is not yet implemented.

However, creating simple attribute sets like `{ }`, or `{ a = 15; }`
or `{ a = 10 * 2; }` works.

Recursive attribute sets are not yet implemented as we do not have any
kind of scope access yet anyways.

This is implemented using a new instruction that creates an attribute
set with a given number of elements by popping key/value pairs off the
stack.

Change-Id: I0f9aac7a131a112d3f66b131297686b38aaeddf2
Reviewed-on: https://cl.tvl.fyi/c/depot/+/6091
Tested-by: BuildkiteCI
Reviewed-by: grfn <grfn@gws.fyi>
Diffstat (limited to 'tvix/eval/src/vm.rs')
-rw-r--r--tvix/eval/src/vm.rs19
1 files changed, 18 insertions, 1 deletions
diff --git a/tvix/eval/src/vm.rs b/tvix/eval/src/vm.rs
index 9a718500b5f1..e8c0551caf67 100644
--- a/tvix/eval/src/vm.rs
+++ b/tvix/eval/src/vm.rs
@@ -1,11 +1,13 @@
 //! This module implements the virtual (or abstract) machine that runs
 //! Tvix bytecode.
 
+use std::{collections::BTreeMap, rc::Rc};
+
 use crate::{
     chunk::Chunk,
     errors::{Error, EvalResult},
     opcode::OpCode,
-    value::Value,
+    value::{NixAttrs, NixString, Value},
 };
 
 pub struct VM {
@@ -114,6 +116,7 @@ impl VM {
                 OpCode::OpNull => self.push(Value::Null),
                 OpCode::OpTrue => self.push(Value::Bool(true)),
                 OpCode::OpFalse => self.push(Value::Bool(false)),
+                OpCode::OpAttrs(count) => self.run_attrset(count)?,
             }
 
             if self.ip == self.chunk.code.len() {
@@ -121,6 +124,20 @@ impl VM {
             }
         }
     }
+
+    fn run_attrset(&mut self, count: usize) -> EvalResult<()> {
+        let mut attrs: BTreeMap<NixString, Value> = BTreeMap::new();
+
+        for _ in 0..count {
+            let value = self.pop();
+            let key = self.pop().as_string()?; // TODO(tazjin): attrpath
+            attrs.insert(key, value);
+        }
+        // TODO(tazjin): extend_reserve(count) (rust#72631)
+
+        self.push(Value::Attrs(Rc::new(NixAttrs::Map(attrs))));
+        Ok(())
+    }
 }
 
 #[derive(Clone, Copy, Debug, PartialEq)]