feat(tvix/eval): add KeySlot::Dynamic variant for dynamic keys

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>
This commit is contained in:
Vincent Ambo 2022-09-24 15:18:37 +03:00 committed by tazjin
parent d0636f1e24
commit 3d9eb14e7a

View file

@ -20,13 +20,20 @@ enum Binding {
}, },
} }
struct KeySlot { enum KeySlot {
slot: LocalIdx, /// There is no key slot (`let`-expressions do not emit their key).
name: SmolStr, 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 { struct TrackedBinding {
key_slot: Option<KeySlot>, key_slot: KeySlot,
value_slot: LocalIdx, value_slot: LocalIdx,
binding: Binding, binding: Binding,
} }
@ -168,12 +175,12 @@ impl Compiler<'_> {
// In an attribute set, the keys themselves are placed on the // In an attribute set, the keys themselves are placed on the
// stack but their stack slot is inaccessible (it is only // stack but their stack slot is inaccessible (it is only
// consumed by `OpAttrs`). // consumed by `OpAttrs`).
Some(KeySlot { KeySlot::Static {
slot: self.scope_mut().declare_phantom(span, false), slot: self.scope_mut().declare_phantom(span, false),
name: name.clone(), name: name.clone(),
}) }
} else { } else {
None KeySlot::None
}; };
let value_slot = match kind { let value_slot = match kind {
@ -239,12 +246,12 @@ impl Compiler<'_> {
let key_span = self.span_for(&path[0]); let key_span = self.span_for(&path[0]);
let key_slot = if kind.is_attrs() { let key_slot = if kind.is_attrs() {
Some(KeySlot { KeySlot::Static {
name: name.clone(), name: name.clone(),
slot: self.scope_mut().declare_phantom(key_span, false), slot: self.scope_mut().declare_phantom(key_span, false),
}) }
} else { } else {
None KeySlot::None
}; };
let value_slot = match kind { let value_slot = match kind {
@ -431,10 +438,18 @@ impl Compiler<'_> {
for binding in bindings.into_iter() { for binding in bindings.into_iter() {
value_indices.push(binding.value_slot); value_indices.push(binding.value_slot);
if let Some(key_slot) = binding.key_slot { match binding.key_slot {
let span = self.scope()[key_slot.slot].span; KeySlot::None => {} // nothing to do here
self.emit_constant(Value::String(key_slot.name.into()), &span);
self.scope_mut().mark_initialised(key_slot.slot); 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 { match binding.binding {