refactor(tvix/eval): use call frame for top-level lambda
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>
This commit is contained in:
parent
0b37b3f2a9
commit
a060c8f467
1 changed files with 29 additions and 14 deletions
|
@ -21,8 +21,6 @@ struct CallFrame {
|
||||||
|
|
||||||
pub struct VM {
|
pub struct VM {
|
||||||
frames: Vec<CallFrame>,
|
frames: Vec<CallFrame>,
|
||||||
ip: usize,
|
|
||||||
chunk: Chunk,
|
|
||||||
stack: Vec<Value>,
|
stack: Vec<Value>,
|
||||||
|
|
||||||
// Stack indices of attribute sets from which variables should be
|
// Stack indices of attribute sets from which variables should be
|
||||||
|
@ -83,9 +81,22 @@ macro_rules! cmp_op {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl VM {
|
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 {
|
fn inc_ip(&mut self) -> OpCode {
|
||||||
let op = self.chunk.code[self.ip];
|
let op = self.chunk().code[self.frame().ip];
|
||||||
self.ip += 1;
|
self.frame_mut().ip += 1;
|
||||||
op
|
op
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -109,7 +120,7 @@ impl VM {
|
||||||
let op = self.inc_ip();
|
let op = self.inc_ip();
|
||||||
match op {
|
match op {
|
||||||
OpCode::OpConstant(idx) => {
|
OpCode::OpConstant(idx) => {
|
||||||
let c = self.chunk.constant(idx).clone();
|
let c = self.chunk().constant(idx).clone();
|
||||||
self.push(c);
|
self.push(c);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -235,25 +246,25 @@ impl VM {
|
||||||
OpCode::OpInterpolate(count) => self.run_interpolate(count)?,
|
OpCode::OpInterpolate(count) => self.run_interpolate(count)?,
|
||||||
|
|
||||||
OpCode::OpJump(offset) => {
|
OpCode::OpJump(offset) => {
|
||||||
self.ip += offset;
|
self.frame_mut().ip += offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
OpCode::OpJumpIfTrue(offset) => {
|
OpCode::OpJumpIfTrue(offset) => {
|
||||||
if self.peek(0).as_bool()? {
|
if self.peek(0).as_bool()? {
|
||||||
self.ip += offset;
|
self.frame_mut().ip += offset;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
OpCode::OpJumpIfFalse(offset) => {
|
OpCode::OpJumpIfFalse(offset) => {
|
||||||
if !self.peek(0).as_bool()? {
|
if !self.peek(0).as_bool()? {
|
||||||
self.ip += offset;
|
self.frame_mut().ip += offset;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
OpCode::OpJumpIfNotFound(offset) => {
|
OpCode::OpJumpIfNotFound(offset) => {
|
||||||
if matches!(self.peek(0), Value::NotFound) {
|
if matches!(self.peek(0), Value::NotFound) {
|
||||||
self.pop();
|
self.pop();
|
||||||
self.ip += offset;
|
self.frame_mut().ip += offset;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -324,10 +335,10 @@ impl VM {
|
||||||
|
|
||||||
#[cfg(feature = "disassembler")]
|
#[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());
|
return Ok(self.pop());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -373,10 +384,14 @@ impl VM {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn run_lambda(lambda: Lambda) -> EvalResult<Value> {
|
pub fn run_lambda(lambda: Lambda) -> EvalResult<Value> {
|
||||||
let mut vm = VM {
|
let frame = CallFrame {
|
||||||
frames: vec![],
|
lambda,
|
||||||
chunk: Rc::<Chunk>::try_unwrap(lambda.chunk).unwrap(),
|
|
||||||
ip: 0,
|
ip: 0,
|
||||||
|
stack_offset: 0,
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut vm = VM {
|
||||||
|
frames: vec![frame],
|
||||||
stack: vec![],
|
stack: vec![],
|
||||||
with_stack: vec![],
|
with_stack: vec![],
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in a new issue