feat(tvix/eval): add initial stack-based VM

This can't do anything other than compute a single literal, for now

Change-Id: Ia28f9da51c906b590a198e77a4ca5d45a871106b
Reviewed-on: https://cl.tvl.fyi/c/depot/+/6071
Tested-by: BuildkiteCI
Reviewed-by: grfn <grfn@gws.fyi>
This commit is contained in:
Vincent Ambo 2022-08-07 23:42:14 +03:00 committed by tazjin
parent 34df2c8473
commit d59968649e
2 changed files with 56 additions and 0 deletions

View file

@ -10,6 +10,7 @@ mod errors;
mod eval;
mod opcode;
mod value;
mod vm;
fn main() {
let mut args = env::args();

55
tvix/eval/src/vm.rs Normal file
View file

@ -0,0 +1,55 @@
//! This module implements the virtual (or abstract) machine that runs
//! Tvix bytecode.
use crate::{chunk::Chunk, errors::EvalResult, opcode::OpCode, value::Value};
pub struct VM {
ip: usize,
chunk: Chunk,
stack: Vec<Value>,
}
impl VM {
fn push(&mut self, value: Value) {
self.stack.push(value)
}
fn pop(&mut self) -> Value {
self.stack.pop().expect("TODO")
}
fn inc_ip(&mut self) -> OpCode {
let op = self.chunk.code[self.ip];
self.ip += 1;
op
}
fn run(&mut self) -> EvalResult<Value> {
loop {
match self.inc_ip() {
OpCode::OpConstant(idx) => {
let c = self.chunk.constant(idx).clone();
self.push(c);
}
OpCode::OpNull => todo!(),
OpCode::OpTrue => todo!(),
OpCode::OpFalse => todo!(),
}
if self.ip == self.chunk.code.len() {
return Ok(self.pop());
}
}
}
}
pub fn run_chunk(chunk: Chunk) -> EvalResult<Value> {
let mut vm = VM {
chunk,
ip: 0,
stack: vec![],
};
vm.run()
}