about summary refs log tree commit diff
path: root/tvix/eval/src/compiler/attrs.rs
diff options
context:
space:
mode:
authorVincent Ambo <mail@tazj.in>2022-09-22T21·31+0300
committertazjin <tazjin@tvl.su>2022-09-22T23·07+0000
commitc46025d52011632b9e53bc96cc115c1d74bfbf7a (patch)
tree7eb87f25117964deec072223cf39c6d85d880799 /tvix/eval/src/compiler/attrs.rs
parentee0b89c4029fe027174018c14dcf7fcff342c8bf (diff)
fix(tvix/eval): support string identifiers in inherits r/4958
This updates rnix-parser to a version where inherits provide an
iterator over `ast::Attr` instead of `ast::Ident`, which mirrors the
behaviour of Nix (inherits can have (statically known) strings as
their identifiers).

This actually required some fairly significant code reshuffling in the
compiler, as there was an implicit assumption in many places that we
would have an `ast::Ident` node available when dealing with variable
access (which is then explicitly only not true in this case).

Change-Id: I12f1e786c0030c85107b1aa409bd49adb5465546
Reviewed-on: https://cl.tvl.fyi/c/depot/+/6747
Tested-by: BuildkiteCI
Reviewed-by: sterni <sternenseemann@systemli.org>
Diffstat (limited to 'tvix/eval/src/compiler/attrs.rs')
-rw-r--r--tvix/eval/src/compiler/attrs.rs47
1 files changed, 34 insertions, 13 deletions
diff --git a/tvix/eval/src/compiler/attrs.rs b/tvix/eval/src/compiler/attrs.rs
index 5dee3a905d01..b4d183c51df8 100644
--- a/tvix/eval/src/compiler/attrs.rs
+++ b/tvix/eval/src/compiler/attrs.rs
@@ -36,14 +36,25 @@ impl Compiler<'_> {
         for inherit in inherits {
             match inherit.from() {
                 Some(from) => {
-                    for ident in inherit.idents() {
+                    for attr in inherit.attrs() {
                         count += 1;
 
+                        let name = match self.expr_static_attr_str(&attr) {
+                            Some(name) => name,
+                            None => {
+                                // TODO(tazjin): error variant for dynamic
+                                // key in *inherit* (or generalise it)
+                                self.emit_error(&attr, ErrorKind::DynamicKeyInLet);
+                                continue;
+                            }
+                        };
+
+                        let name_span = self.span_for(&attr);
+
                         // First emit the identifier itself (this
                         // becomes the new key).
-                        self.emit_literal_ident(&ident);
-                        let ident_span = self.span_for(&ident);
-                        self.scope_mut().declare_phantom(ident_span, true);
+                        self.emit_constant(Value::String(SmolStr::new(&name).into()), &attr);
+                        self.scope_mut().declare_phantom(name_span, true);
 
                         // Then emit the node that we're inheriting
                         // from.
@@ -53,27 +64,37 @@ impl Compiler<'_> {
                         // instruction followed by a merge, rather
                         // than pushing/popping the same attrs
                         // potentially a lot of times.
-                        let val_idx = self.scope_mut().declare_phantom(ident_span, false);
+                        let val_idx = self.scope_mut().declare_phantom(name_span, false);
                         self.compile(val_idx, from.expr().unwrap());
                         self.emit_force(&from.expr().unwrap());
-                        self.emit_literal_ident(&ident);
-                        self.push_op(OpCode::OpAttrsSelect, &ident);
+                        self.emit_constant(Value::String(name.into()), &attr);
+                        self.push_op(OpCode::OpAttrsSelect, &attr);
                         self.scope_mut().mark_initialised(val_idx);
                     }
                 }
 
                 None => {
-                    for ident in inherit.idents() {
-                        let ident_span = self.span_for(&ident);
+                    for attr in inherit.attrs() {
                         count += 1;
 
                         // Emit the key to use for OpAttrs
-                        self.emit_literal_ident(&ident);
-                        self.scope_mut().declare_phantom(ident_span, true);
+                        let name = match self.expr_static_attr_str(&attr) {
+                            Some(name) => name,
+                            None => {
+                                // TODO(tazjin): error variant for dynamic
+                                // key in *inherit* (or generalise it)
+                                self.emit_error(&attr, ErrorKind::DynamicKeyInLet);
+                                continue;
+                            }
+                        };
+
+                        let name_span = self.span_for(&attr);
+                        self.emit_constant(Value::String(SmolStr::new(&name).into()), &attr);
+                        self.scope_mut().declare_phantom(name_span, true);
 
                         // Emit the value.
-                        self.compile_ident(slot, ident);
-                        self.scope_mut().declare_phantom(ident_span, true);
+                        self.compile_identifier_access(slot, &name, &attr);
+                        self.scope_mut().declare_phantom(name_span, true);
                     }
                 }
             }