diff options
author | Vincent Ambo <mail@tazj.in> | 2022-08-23T20·09+0300 |
---|---|---|
committer | tazjin <tazjin@tvl.su> | 2022-09-01T21·56+0000 |
commit | a060c8f4674a1ace310a3c0b48f22d461bbc5c30 (patch) | |
tree | bd6daad0d45f5e9e39cf8eb6722c0decd214cd2a | |
parent | 0b37b3f2a9b3cd59f609b41f7c72f1a4d7dce39c (diff) |
refactor(tvix/eval): use call frame for top-level lambda r/4578
This wires up most of the machinery for executing different call frames inside of the VM and stuffs the top-level lambda which the compiler outputs in there, as well. Change-Id: Ib6201b3e3be1af96a4d195f6eb147f452860ffc3 Reviewed-on: https://cl.tvl.fyi/c/depot/+/6242 Tested-by: BuildkiteCI Reviewed-by: grfn <grfn@gws.fyi>
-rw-r--r-- | tvix/eval/src/vm.rs | 43 |
1 files changed, 29 insertions, 14 deletions
diff --git a/tvix/eval/src/vm.rs b/tvix/eval/src/vm.rs index 99e2ba91327c..63e5e4ad7387 100644 --- a/tvix/eval/src/vm.rs +++ b/tvix/eval/src/vm.rs @@ -21,8 +21,6 @@ struct CallFrame { pub struct VM { frames: Vec<CallFrame>, - ip: usize, - chunk: Chunk, stack: Vec<Value>, // Stack indices of attribute sets from which variables should be @@ -83,9 +81,22 @@ macro_rules! cmp_op { } impl VM { + fn frame(&self) -> &CallFrame { + &self.frames[self.frames.len() - 1] + } + + fn chunk(&self) -> &Chunk { + &self.frame().lambda.chunk + } + + fn frame_mut(&mut self) -> &mut CallFrame { + let idx = self.frames.len() - 1; + &mut self.frames[idx] + } + fn inc_ip(&mut self) -> OpCode { - let op = self.chunk.code[self.ip]; - self.ip += 1; + let op = self.chunk().code[self.frame().ip]; + self.frame_mut().ip += 1; op } @@ -109,7 +120,7 @@ impl VM { let op = self.inc_ip(); match op { OpCode::OpConstant(idx) => { - let c = self.chunk.constant(idx).clone(); + let c = self.chunk().constant(idx).clone(); self.push(c); } @@ -235,25 +246,25 @@ impl VM { OpCode::OpInterpolate(count) => self.run_interpolate(count)?, OpCode::OpJump(offset) => { - self.ip += offset; + self.frame_mut().ip += offset; } OpCode::OpJumpIfTrue(offset) => { if self.peek(0).as_bool()? { - self.ip += offset; + self.frame_mut().ip += offset; } } OpCode::OpJumpIfFalse(offset) => { if !self.peek(0).as_bool()? { - self.ip += offset; + self.frame_mut().ip += offset; } } OpCode::OpJumpIfNotFound(offset) => { if matches!(self.peek(0), Value::NotFound) { self.pop(); - self.ip += offset; + self.frame_mut().ip += offset; } } @@ -324,10 +335,10 @@ impl VM { #[cfg(feature = "disassembler")] { - tracer.trace(&op, self.ip, &self.stack); + tracer.trace(&op, self.frame().ip, &self.stack); } - if self.ip == self.chunk.code.len() { + if self.frame().ip == self.chunk().code.len() { return Ok(self.pop()); } } @@ -373,10 +384,14 @@ impl VM { } pub fn run_lambda(lambda: Lambda) -> EvalResult<Value> { - let mut vm = VM { - frames: vec![], - chunk: Rc::<Chunk>::try_unwrap(lambda.chunk).unwrap(), + let frame = CallFrame { + lambda, ip: 0, + stack_offset: 0, + }; + + let mut vm = VM { + frames: vec![frame], stack: vec![], with_stack: vec![], }; |