about summary refs log tree commit diff
path: root/tvix/eval
diff options
context:
space:
mode:
authorVincent Ambo <mail@tazj.in>2022-09-28T14·47+0300
committertazjin <tazjin@tvl.su>2022-09-29T17·46+0000
commitccf9dd651b847aee96371b517a8375e7b4c040a6 (patch)
tree6bf6d6ac3d9585e8d6e4d7f4ae4142f86853474d /tvix/eval
parent18fcf0d79d5e299e9d4014a59d20a0e17dc90836 (diff)
refactor(tvix/eval): clean up representation flip in bindings r/4999
When encountering a nested binding for the first time, cleanly flip
the representation to `Binding::Set` in `Binding::merge` before
proceeding with the actual merge.

This reduces the number of points where we have to deal with the (soon
to be slightly more complex) construction of the nested binding
representation.

Change-Id: Ifd43aac7b59ebd15a72c3ec512386a5bcf26ec13
Reviewed-on: https://cl.tvl.fyi/c/depot/+/6802
Tested-by: BuildkiteCI
Reviewed-by: sterni <sternenseemann@systemli.org>
Diffstat (limited to 'tvix/eval')
-rw-r--r--tvix/eval/src/compiler/bindings.rs69
1 files changed, 32 insertions, 37 deletions
diff --git a/tvix/eval/src/compiler/bindings.rs b/tvix/eval/src/compiler/bindings.rs
index 96ee434a2c3b..91a2b8b535d5 100644
--- a/tvix/eval/src/compiler/bindings.rs
+++ b/tvix/eval/src/compiler/bindings.rs
@@ -77,44 +77,39 @@ impl Binding {
                 c.emit_error(span, ErrorKind::UnmergeableInherit { name: name.clone() })
             }
 
-            Binding::Plain { expr: existing } => match existing {
+            // If the value is not yet a nested binding, flip the representation
+            // and recurse.
+            Binding::Plain { expr } => match expr {
                 ast::Expr::AttrSet(existing) => {
-                    if let ast::Expr::AttrSet(new) = value {
-                        let merged = AttributeSet {
-                            nesting_level: 0, // TODO
-
-                            span: c.span_for(existing),
-
-                            // Kind of the attrs depends on the first time it is
-                            // encountered. We actually believe this to be a Nix
-                            // bug: https://github.com/NixOS/nix/issues/7111
-                            kind: if existing.rec_token().is_some() {
-                                BindingsKind::RecAttrs
-                            } else {
-                                BindingsKind::Attrs
-                            },
-
-                            inherits: ast::HasEntry::inherits(existing)
-                                .chain(ast::HasEntry::inherits(&new))
-                                .collect(),
-
-                            entries: ast::HasEntry::attrpath_values(existing)
-                                .chain(ast::HasEntry::attrpath_values(&new))
-                                .map(|entry| {
-                                    let span = c.span_for(&entry);
-                                    (
-                                        span,
-                                        entry.attrpath().unwrap().attrs(),
-                                        entry.value().unwrap(),
-                                    )
-                                })
-                                .collect(),
-                        };
-
-                        *self = Binding::Set(merged);
-                    } else {
-                        todo!()
-                    }
+                    let nested = AttributeSet {
+                        nesting_level: 0, // TODO
+                        span: c.span_for(existing),
+
+                        // Kind of the attrs depends on the first time it is
+                        // encountered. We actually believe this to be a Nix
+                        // bug: https://github.com/NixOS/nix/issues/7111
+                        kind: if existing.rec_token().is_some() {
+                            BindingsKind::RecAttrs
+                        } else {
+                            BindingsKind::Attrs
+                        },
+
+                        inherits: ast::HasEntry::inherits(existing).collect(),
+
+                        entries: ast::HasEntry::attrpath_values(existing)
+                            .map(|entry| {
+                                let span = c.span_for(&entry);
+                                (
+                                    span,
+                                    entry.attrpath().unwrap().attrs(),
+                                    entry.value().unwrap(),
+                                )
+                            })
+                            .collect(),
+                    };
+
+                    *self = Binding::Set(nested);
+                    self.merge(c, value);
                 }
 
                 _ => c.emit_error(&value, ErrorKind::UnmergeableValue),