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:
parent
d0636f1e24
commit
3d9eb14e7a
1 changed files with 29 additions and 14 deletions
|
@ -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 {
|
||||||
|
|
Loading…
Reference in a new issue