about summary refs log tree commit diff
path: root/tvix
diff options
context:
space:
mode:
authorVincent Ambo <mail@tazj.in>2022-09-24T12·18+0300
committertazjin <tazjin@tvl.su>2022-09-29T00·48+0000
commit3d9eb14e7ab929fb80b28f89b16bc2158c09399a (patch)
tree5c845cd2c7bc1f5479058ae24c50ac0d17ab80ed /tvix
parentd0636f1e2483bc85b0a1929fbb94c206ad45a7b7 (diff)
feat(tvix/eval): add KeySlot::Dynamic variant for dynamic keys r/4986
Another slice of the salami, but no functionality changes yet (other
than opening a code path that can reach a `todo!()`, but this will be
removed soon).

Change-Id: I56b4ed323f70754ed1ab27964ee3c99cf3bf3292
Reviewed-on: https://cl.tvl.fyi/c/depot/+/6780
Tested-by: BuildkiteCI
Reviewed-by: sterni <sternenseemann@systemli.org>
Diffstat (limited to 'tvix')
-rw-r--r--tvix/eval/src/compiler/bindings.rs43
1 files changed, 29 insertions, 14 deletions
diff --git a/tvix/eval/src/compiler/bindings.rs b/tvix/eval/src/compiler/bindings.rs
index d7a5513934a1..94dae5fb951a 100644
--- a/tvix/eval/src/compiler/bindings.rs
+++ b/tvix/eval/src/compiler/bindings.rs
@@ -20,13 +20,20 @@ enum Binding {
     },
 }
 
-struct KeySlot {
-    slot: LocalIdx,
-    name: SmolStr,
+enum KeySlot {
+    /// There is no key slot (`let`-expressions do not emit their key).
+    None,
+
+    /// The key is statically known and has a slot.
+    Static { slot: LocalIdx, name: SmolStr },
+
+    /// The key is dynamic, i.e. only known at runtime, and must be compiled
+    /// into its slot.
+    Dynamic { slot: LocalIdx, expr: ast::Expr },
 }
 
 struct TrackedBinding {
-    key_slot: Option<KeySlot>,
+    key_slot: KeySlot,
     value_slot: LocalIdx,
     binding: Binding,
 }
@@ -168,12 +175,12 @@ impl Compiler<'_> {
                 // In an attribute set, the keys themselves are placed on the
                 // stack but their stack slot is inaccessible (it is only
                 // consumed by `OpAttrs`).
-                Some(KeySlot {
+                KeySlot::Static {
                     slot: self.scope_mut().declare_phantom(span, false),
                     name: name.clone(),
-                })
+                }
             } else {
-                None
+                KeySlot::None
             };
 
             let value_slot = match kind {
@@ -239,12 +246,12 @@ impl Compiler<'_> {
 
             let key_span = self.span_for(&path[0]);
             let key_slot = if kind.is_attrs() {
-                Some(KeySlot {
+                KeySlot::Static {
                     name: name.clone(),
                     slot: self.scope_mut().declare_phantom(key_span, false),
-                })
+                }
             } else {
-                None
+                KeySlot::None
             };
 
             let value_slot = match kind {
@@ -431,10 +438,18 @@ impl Compiler<'_> {
         for binding in bindings.into_iter() {
             value_indices.push(binding.value_slot);
 
-            if let Some(key_slot) = binding.key_slot {
-                let span = self.scope()[key_slot.slot].span;
-                self.emit_constant(Value::String(key_slot.name.into()), &span);
-                self.scope_mut().mark_initialised(key_slot.slot);
+            match binding.key_slot {
+                KeySlot::None => {} // nothing to do here
+
+                KeySlot::Static { slot, name } => {
+                    let span = self.scope()[slot].span;
+                    self.emit_constant(Value::String(name.into()), &span);
+                    self.scope_mut().mark_initialised(slot);
+                }
+
+                KeySlot::Dynamic { .. } => {
+                    todo!("dynamic keys not ye timplemented")
+                }
             }
 
             match binding.binding {