feat(tvix/eval): Add Compiler::thunk method for emitting thunks
The logic in this method is *very* similar to `compile_lambda`. It is intended to be called around any expression that should be thunked (such as function applications, attribute set values, etc.). Change-Id: Idfbb2daa9f4b735095378fb9c39a2fd07c8cff91 Reviewed-on: https://cl.tvl.fyi/c/depot/+/6344 Tested-by: BuildkiteCI Reviewed-by: sterni <sternenseemann@systemli.org>
This commit is contained in:
		
							parent
							
								
									1f37275cfb
								
							
						
					
					
						commit
						d1798444be
					
				
					 3 changed files with 41 additions and 1 deletions
				
			
		|  | @ -26,7 +26,7 @@ use std::rc::Rc; | |||
| use crate::chunk::Chunk; | ||||
| use crate::errors::{Error, ErrorKind, EvalResult}; | ||||
| use crate::opcode::{CodeIdx, Count, JumpOffset, OpCode, UpvalueIdx}; | ||||
| use crate::value::{Closure, Lambda, Value}; | ||||
| use crate::value::{Closure, Lambda, Thunk, Value}; | ||||
| use crate::warnings::{EvalWarning, WarningKind}; | ||||
| 
 | ||||
| use self::scope::{Local, LocalIdx, LocalPosition, Scope, Upvalue}; | ||||
|  | @ -848,6 +848,41 @@ impl Compiler { | |||
|         self.chunk().push_op(OpCode::OpCall); | ||||
|     } | ||||
| 
 | ||||
|     /// Compile an expression into a runtime thunk which should be
 | ||||
|     /// lazily evaluated when accessed.
 | ||||
|     // TODO: almost the same as Compiler::compile_lambda; unify?
 | ||||
|     fn thunk<F>(&mut self, slot: Option<LocalIdx>, content: F) | ||||
|     where | ||||
|         F: FnOnce(&mut Compiler, Option<LocalIdx>), | ||||
|     { | ||||
|         self.contexts.push(LambdaCtx::new()); | ||||
|         self.begin_scope(); | ||||
|         content(self, slot); | ||||
|         self.end_scope(); | ||||
| 
 | ||||
|         let thunk = self.contexts.pop().unwrap(); | ||||
| 
 | ||||
|         #[cfg(feature = "disassembler")] | ||||
|         { | ||||
|             crate::disassembler::disassemble_chunk(&thunk.lambda.chunk); | ||||
|         } | ||||
| 
 | ||||
|         // Emit the thunk directly if it does not close over the
 | ||||
|         // environment.
 | ||||
|         if thunk.lambda.upvalue_count == 0 { | ||||
|             self.emit_constant(Value::Thunk(Thunk::new(thunk.lambda))); | ||||
|             return; | ||||
|         } | ||||
| 
 | ||||
|         // Otherwise prepare for runtime construction of the thunk.
 | ||||
|         let blueprint_idx = self | ||||
|             .chunk() | ||||
|             .push_constant(Value::Blueprint(Rc::new(thunk.lambda))); | ||||
| 
 | ||||
|         self.chunk().push_op(OpCode::OpThunk(blueprint_idx)); | ||||
|         self.emit_upvalue_data(slot, thunk.scope.upvalues); | ||||
|     } | ||||
| 
 | ||||
|     /// 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>) { | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue