about summary refs log tree commit diff
path: root/tvix/eval/src/compiler
diff options
context:
space:
mode:
authorVincent Ambo <mail@tazj.in>2022-08-30T16·55+0300
committertazjin <tazjin@tvl.su>2022-09-07T15·25+0000
commit23a5caabec5617c01d5629bd50dd7e7649cbe5a6 (patch)
tree996c1740febd8297a39bcf287a2c2e3c96663928 /tvix/eval/src/compiler
parent727845645d4b6032e6b16dcfa997e14da9806084 (diff)
feat(tvix/eval): construct attribute sets lazily r/4699
This thunks the construction of attribute sets. Because Tvix does not
currently have a "strict output" mode, a test had to be disabled that
now displays a thunk representation.

The test will be re-enabled once that is available.

Change-Id: I360332be64cd5c154f9caea21828f6f1b37a265c
Reviewed-on: https://cl.tvl.fyi/c/depot/+/6363
Tested-by: BuildkiteCI
Reviewed-by: sterni <sternenseemann@systemli.org>
Diffstat (limited to 'tvix/eval/src/compiler')
-rw-r--r--tvix/eval/src/compiler/mod.rs12
1 files changed, 10 insertions, 2 deletions
diff --git a/tvix/eval/src/compiler/mod.rs b/tvix/eval/src/compiler/mod.rs
index 96c864110137..b1dec5df1db2 100644
--- a/tvix/eval/src/compiler/mod.rs
+++ b/tvix/eval/src/compiler/mod.rs
@@ -115,7 +115,7 @@ impl Compiler {
             ast::Expr::BinOp(op) => self.compile_binop(slot, op),
             ast::Expr::HasAttr(has_attr) => self.compile_has_attr(slot, has_attr),
             ast::Expr::List(list) => self.compile_list(slot, list),
-            ast::Expr::AttrSet(attrs) => self.compile_attr_set(slot, attrs),
+            ast::Expr::AttrSet(attrs) => self.thunk(slot, move |c, s| c.compile_attr_set(s, attrs)),
             ast::Expr::Select(select) => self.compile_select(slot, select),
             ast::Expr::Assert(assert) => self.compile_assert(slot, assert),
             ast::Expr::IfElse(if_else) => self.compile_if_else(slot, if_else),
@@ -422,7 +422,8 @@ impl Compiler {
                     for ident in inherit.idents() {
                         count += 1;
 
-                        // First emit the identifier itself
+                        // First emit the identifier itself (this
+                        // becomes the new key).
                         self.emit_literal_ident(&ident);
 
                         // Then emit the node that we're inheriting
@@ -434,6 +435,7 @@ impl Compiler {
                         // than pushing/popping the same attrs
                         // potentially a lot of times.
                         self.compile(slot, from.expr().unwrap());
+                        self.emit_force();
                         self.emit_literal_ident(&ident);
                         self.chunk().push_op(OpCode::OpAttrsSelect);
                     }
@@ -494,6 +496,7 @@ impl Compiler {
 
         // Push the set onto the stack
         self.compile(slot, set);
+        self.emit_force();
 
         // Compile each key fragment and emit access instructions.
         //
@@ -542,6 +545,7 @@ impl Compiler {
         default: ast::Expr,
     ) {
         self.compile(slot, set);
+        self.emit_force();
         let mut jumps = vec![];
 
         for fragment in path.attrs() {
@@ -645,6 +649,8 @@ impl Compiler {
                 Some(from) => {
                     for ident in inherit.idents() {
                         self.compile(slot, from.expr().unwrap());
+                        self.emit_force();
+
                         self.emit_literal_ident(&ident);
                         self.chunk().push_op(OpCode::OpAttrsSelect);
                         let idx = self.declare_local(
@@ -788,6 +794,8 @@ impl Compiler {
         // resolve that directly (thus avoiding duplication on the
         // stack).
         self.compile(slot, node.namespace().unwrap());
+        self.emit_force();
+
         let local_idx = self.scope_mut().declare_phantom();
         let with_idx = self.scope().stack_index(local_idx);