From 6c895d4b280e6376e833cec80a387c0729b898a3 Mon Sep 17 00:00:00 2001 From: Vincent Ambo Date: Mon, 29 Aug 2022 18:24:09 +0300 Subject: [PATCH] feat(tvix/eval): implement OpThunk for runtime thunk construction Implements an operation very similar to `OpClosure` which populates a thunk's upvalues and leaves it on the stack. Change-Id: I753b4dfeeaae6919316c7028ec361aaa13d87646 Reviewed-on: https://cl.tvl.fyi/c/depot/+/6350 Tested-by: BuildkiteCI Reviewed-by: sterni --- tvix/eval/src/vm.rs | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/tvix/eval/src/vm.rs b/tvix/eval/src/vm.rs index 68f08b077..e32c0d7f6 100644 --- a/tvix/eval/src/vm.rs +++ b/tvix/eval/src/vm.rs @@ -8,7 +8,7 @@ use crate::{ errors::{Error, ErrorKind, EvalResult}, opcode::{ConstantIdx, Count, JumpOffset, OpCode, StackIdx, UpvalueIdx}, upvalues::UpvalueCarrier, - value::{Closure, Lambda, NixAttrs, NixList, Value}, + value::{Closure, Lambda, NixAttrs, NixList, Thunk, Value}, }; #[cfg(feature = "disassembler")] @@ -427,13 +427,28 @@ impl VM { self.populate_upvalues(upvalue_count, upvalues)?; } - OpCode::OpThunk(_idx) => todo!("runtime thunk construction"), + OpCode::OpThunk(idx) => { + let blueprint = match self.chunk().constant(idx) { + Value::Blueprint(lambda) => lambda.clone(), + _ => panic!("compiler bug: non-blueprint in blueprint slot"), + }; + + let upvalue_count = blueprint.upvalue_count; + let thunk = Thunk::new(blueprint); + let upvalues = thunk.upvalues_mut(); + + self.push(Value::Thunk(thunk.clone())); + self.populate_upvalues(upvalue_count, upvalues)?; + } OpCode::OpFinalise(StackIdx(idx)) => { match &self.stack[self.frame().stack_offset + idx] { Value::Closure(closure) => closure .resolve_deferred_upvalues(&self.stack[self.frame().stack_offset..]), + Value::Thunk(thunk) => thunk + .resolve_deferred_upvalues(&self.stack[self.frame().stack_offset..]), + v => { #[cfg(feature = "disassembler")] drop(tracer);