diff options
author | Vincent Ambo <mail@tazj.in> | 2022-08-28T20·44+0300 |
---|---|---|
committer | tazjin <tazjin@tvl.su> | 2022-09-06T14·58+0000 |
commit | 49296cebe3c1b5644e24f6c3017a75db7c85683d (patch) | |
tree | fe964b108a076afc3f2e0a4a028b989a55714703 | |
parent | 70b27a608090b29b6ae8e455d8f18c7099b2b39d (diff) |
refactor(tvix/eval): extract compiler's upvalue logic into helper r/4672
This exact same logic is reused for thunk creation. Change-Id: I731db9cc659a1f2ca87db55d58d6ff632f417812 Reviewed-on: https://cl.tvl.fyi/c/depot/+/6342 Tested-by: BuildkiteCI Reviewed-by: sterni <sternenseemann@systemli.org>
-rw-r--r-- | tvix/eval/src/compiler/mod.rs | 34 |
1 files changed, 20 insertions, 14 deletions
diff --git a/tvix/eval/src/compiler/mod.rs b/tvix/eval/src/compiler/mod.rs index 3f11661a97ab..c9cd66aca78f 100644 --- a/tvix/eval/src/compiler/mod.rs +++ b/tvix/eval/src/compiler/mod.rs @@ -657,7 +657,7 @@ impl Compiler { // First pass to ensure that all identifiers are known; // required for resolving recursion. - let mut entries: Vec<(LocalIdx, rnix::ast::Expr)> = vec![]; + let mut entries: Vec<(LocalIdx, ast::Expr)> = vec![]; for entry in node.attrpath_values() { let mut path = match normalise_ident_path(entry.attrpath().unwrap().attrs()) { Ok(p) => p, @@ -830,12 +830,28 @@ impl Compiler { // number of operands that allow the runtime to close over the // upvalues and leave a blueprint in the constant index from // which the runtime closure can be constructed. - let closure_idx = self + let blueprint_idx = self .chunk() .push_constant(Value::Blueprint(Rc::new(compiled.lambda))); - self.chunk().push_op(OpCode::OpClosure(closure_idx)); - for upvalue in compiled.scope.upvalues { + self.chunk().push_op(OpCode::OpClosure(blueprint_idx)); + self.emit_upvalue_data(slot, compiled.scope.upvalues); + } + + fn compile_apply(&mut self, node: ast::Apply) { + // To call a function, we leave its arguments on the stack, + // followed by the function expression itself, and then emit a + // call instruction. This way, the stack is perfectly laid out + // to enter the function call straight away. + self.compile(None, node.argument().unwrap()); + self.compile(None, node.lambda().unwrap()); + self.chunk().push_op(OpCode::OpCall); + } + + /// Emit the data instructions that the runtime needs to correctly + /// assemble the provided upvalues array. + fn emit_upvalue_data(&mut self, slot: Option<LocalIdx>, upvalues: Vec<Upvalue>) { + for upvalue in upvalues { match upvalue { Upvalue::Local(idx) if slot.is_none() => { let stack_idx = self.scope().stack_index(idx); @@ -871,16 +887,6 @@ impl Compiler { } } - fn compile_apply(&mut self, node: ast::Apply) { - // To call a function, we leave its arguments on the stack, - // followed by the function expression itself, and then emit a - // call instruction. This way, the stack is perfectly laid out - // to enter the function call straight away. - self.compile(None, node.argument().unwrap()); - self.compile(None, node.lambda().unwrap()); - self.chunk().push_op(OpCode::OpCall); - } - /// Emit the literal string value of an identifier. Required for /// several operations related to attribute sets, where /// identifiers are used as string keys. |