refactor(tvix/eval): Factor out bind_values
helper
This is responsible for actually setting up `TrackedBinding`s on the stack, i.e. in some sense "actually compiling" values in bindings. There is no functionality change to before, i.e. this is a salami slice. Change-Id: Idb0312038e004470a7d130c020ae0fe87c55c218 Reviewed-on: https://cl.tvl.fyi/c/depot/+/6774 Reviewed-by: sterni <sternenseemann@systemli.org> Tested-by: BuildkiteCI
This commit is contained in:
parent
7e9169bcf7
commit
f40283e098
1 changed files with 55 additions and 47 deletions
|
@ -434,6 +434,59 @@ impl Compiler<'_> {
|
|||
self.scope_mut().end_scope();
|
||||
}
|
||||
|
||||
/// Actually binds all tracked bindings by emitting the bytecode that places
|
||||
/// them in their stack slots.
|
||||
fn bind_values(&mut self, bindings: Vec<TrackedBinding>) {
|
||||
let mut value_indices: Vec<LocalIdx> = vec![];
|
||||
|
||||
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.binding {
|
||||
// This entry is an inherit (from) expr. The value is
|
||||
// placed on the stack by selecting an attribute.
|
||||
Binding::InheritFrom {
|
||||
namespace,
|
||||
name,
|
||||
span,
|
||||
} => {
|
||||
// Create a thunk wrapping value (which may be one as well) to
|
||||
// avoid forcing the from expr too early.
|
||||
self.thunk(binding.value_slot, &namespace, move |c, n, s| {
|
||||
c.compile(s, n.clone());
|
||||
c.emit_force(n);
|
||||
|
||||
c.emit_constant(Value::String(name.into()), &span);
|
||||
c.push_op(OpCode::OpAttrsSelect, &span);
|
||||
})
|
||||
}
|
||||
|
||||
// Binding is "just" a plain expression that needs to
|
||||
// be compiled.
|
||||
Binding::Plain { expr } => self.compile(binding.value_slot, expr),
|
||||
}
|
||||
|
||||
// Any code after this point will observe the value in the
|
||||
// right stack slot, so mark it as initialised.
|
||||
self.scope_mut().mark_initialised(binding.value_slot);
|
||||
}
|
||||
|
||||
// Final pass to emit finaliser instructions if necessary.
|
||||
for idx in value_indices {
|
||||
if self.scope()[idx].needs_finaliser {
|
||||
let stack_idx = self.scope().stack_index(idx);
|
||||
let span = self.scope()[idx].span;
|
||||
self.push_op(OpCode::OpFinalise(stack_idx), &span);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn compile_recursive_scope<N>(&mut self, slot: LocalIdx, kind: BindingsKind, node: &N) -> usize
|
||||
where
|
||||
N: ToSpan + ast::HasEntry,
|
||||
|
@ -488,53 +541,8 @@ impl Compiler<'_> {
|
|||
});
|
||||
}
|
||||
|
||||
// Third pass to place the values in the correct stack slots.
|
||||
let mut value_indices: Vec<LocalIdx> = vec![];
|
||||
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.binding {
|
||||
// This entry is an inherit (from) expr. The value is
|
||||
// placed on the stack by selecting an attribute.
|
||||
Binding::InheritFrom {
|
||||
namespace,
|
||||
name,
|
||||
span,
|
||||
} => {
|
||||
// Create a thunk wrapping value (which may be one as well) to
|
||||
// avoid forcing the from expr too early.
|
||||
self.thunk(binding.value_slot, &namespace, move |c, n, s| {
|
||||
c.compile(s, n.clone());
|
||||
c.emit_force(n);
|
||||
|
||||
c.emit_constant(Value::String(name.into()), &span);
|
||||
c.push_op(OpCode::OpAttrsSelect, &span);
|
||||
})
|
||||
}
|
||||
|
||||
// Binding is "just" a plain expression that needs to
|
||||
// be compiled.
|
||||
Binding::Plain { expr } => self.compile(binding.value_slot, expr),
|
||||
}
|
||||
|
||||
// Any code after this point will observe the value in the
|
||||
// right stack slot, so mark it as initialised.
|
||||
self.scope_mut().mark_initialised(binding.value_slot);
|
||||
}
|
||||
|
||||
// Fourth pass to emit finaliser instructions if necessary.
|
||||
for idx in value_indices {
|
||||
if self.scope()[idx].needs_finaliser {
|
||||
let stack_idx = self.scope().stack_index(idx);
|
||||
self.push_op(OpCode::OpFinalise(stack_idx), node);
|
||||
}
|
||||
}
|
||||
// Actually bind values and ensure they are on the stack.
|
||||
self.bind_values(bindings);
|
||||
|
||||
count
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue