refactor(tvix/eval): extract compiler's upvalue logic into helper
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>
This commit is contained in:
		
							parent
							
								
									70b27a6080
								
							
						
					
					
						commit
						49296cebe3
					
				
					 1 changed files with 20 additions and 14 deletions
				
			
		|  | @ -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.
 | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue