refactor(tvix/eval): introduce TrackedBindings struct

This struct will be the key to correctly compiling nested bindings, by
having insertions flow through some logic that will attempt to bind
attribute-set-like things when encountering them.

Change-Id: I8b5b20798de60688f3b6dc4526a460ebb2079f6e
Reviewed-on: https://cl.tvl.fyi/c/depot/+/6795
Reviewed-by: sterni <sternenseemann@systemli.org>
Tested-by: BuildkiteCI
This commit is contained in:
Vincent Ambo 2022-09-28 13:11:15 +03:00 committed by tazjin
parent e96f94ac88
commit 82df0b432a

View file

@ -38,6 +38,29 @@ struct TrackedBinding {
binding: Binding, binding: Binding,
} }
struct TrackedBindings {
kind: BindingsKind,
bindings: Vec<TrackedBinding>,
}
impl TrackedBindings {
fn new(kind: BindingsKind) -> Self {
TrackedBindings {
kind,
bindings: vec![],
}
}
/// Add a completely new binding to the tracked bindings.
fn track_new(&mut self, key_slot: KeySlot, value_slot: LocalIdx, binding: Binding) {
self.bindings.push(TrackedBinding {
key_slot,
value_slot,
binding,
});
}
}
/// What kind of bindings scope is being compiled? /// What kind of bindings scope is being compiled?
#[derive(Clone, Copy, PartialEq)] #[derive(Clone, Copy, PartialEq)]
enum BindingsKind { enum BindingsKind {
@ -168,7 +191,7 @@ impl Compiler<'_> {
&mut self, &mut self,
kind: BindingsKind, kind: BindingsKind,
inherit_froms: Vec<(ast::Expr, SmolStr, Span)>, inherit_froms: Vec<(ast::Expr, SmolStr, Span)>,
bindings: &mut Vec<TrackedBinding>, bindings: &mut TrackedBindings,
) { ) {
for (from, name, span) in inherit_froms { for (from, name, span) in inherit_froms {
let key_slot = if kind.is_attrs() { let key_slot = if kind.is_attrs() {
@ -195,15 +218,15 @@ impl Compiler<'_> {
BindingsKind::Attrs => self.scope_mut().declare_phantom(span, false), BindingsKind::Attrs => self.scope_mut().declare_phantom(span, false),
}; };
bindings.push(TrackedBinding { bindings.track_new(
key_slot, key_slot,
value_slot, value_slot,
binding: Binding::InheritFrom { Binding::InheritFrom {
namespace: from, namespace: from,
name, name,
span, span,
}, },
}); );
} }
} }
@ -213,7 +236,7 @@ impl Compiler<'_> {
&mut self, &mut self,
kind: BindingsKind, kind: BindingsKind,
count: &mut usize, count: &mut usize,
bindings: &mut Vec<TrackedBinding>, bindings: &mut TrackedBindings,
node: &N, node: &N,
) where ) where
N: ToSpan + ast::HasEntry, N: ToSpan + ast::HasEntry,
@ -267,13 +290,13 @@ impl Compiler<'_> {
BindingsKind::Attrs => self.scope_mut().declare_phantom(key_span, false), BindingsKind::Attrs => self.scope_mut().declare_phantom(key_span, false),
}; };
bindings.push(TrackedBinding { bindings.track_new(
key_slot, key_slot,
value_slot, value_slot,
binding: Binding::Plain { Binding::Plain {
expr: entry.value().unwrap(), expr: entry.value().unwrap(),
}, },
}); );
} }
} }
@ -306,10 +329,10 @@ impl Compiler<'_> {
/// Actually binds all tracked bindings by emitting the bytecode that places /// Actually binds all tracked bindings by emitting the bytecode that places
/// them in their stack slots. /// them in their stack slots.
fn bind_values(&mut self, bindings: Vec<TrackedBinding>) { fn bind_values(&mut self, bindings: TrackedBindings) {
let mut value_indices: Vec<LocalIdx> = vec![]; let mut value_indices: Vec<LocalIdx> = vec![];
for binding in bindings.into_iter() { for binding in bindings.bindings.into_iter() {
value_indices.push(binding.value_slot); value_indices.push(binding.value_slot);
match binding.key_slot { match binding.key_slot {
@ -374,7 +397,7 @@ impl Compiler<'_> {
self.scope_mut().begin_scope(); self.scope_mut().begin_scope();
// Vector to track all observed bindings. // Vector to track all observed bindings.
let mut bindings: Vec<TrackedBinding> = vec![]; let mut bindings = TrackedBindings::new(kind);
let inherit_froms = self.compile_plain_inherits(slot, kind, &mut count, node); let inherit_froms = self.compile_plain_inherits(slot, kind, &mut count, node);
self.declare_namespaced_inherits(kind, inherit_froms, &mut bindings); self.declare_namespaced_inherits(kind, inherit_froms, &mut bindings);