From d59968649e843371db7d83ac1e2b327c08e70093 Mon Sep 17 00:00:00 2001 From: Vincent Ambo Date: Sun, 7 Aug 2022 23:42:14 +0300 Subject: [PATCH] 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 --- tvix/eval/src/main.rs | 1 + tvix/eval/src/vm.rs | 55 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 56 insertions(+) create mode 100644 tvix/eval/src/vm.rs diff --git a/tvix/eval/src/main.rs b/tvix/eval/src/main.rs index bdb5818a3..55365efab 100644 --- a/tvix/eval/src/main.rs +++ b/tvix/eval/src/main.rs @@ -10,6 +10,7 @@ mod errors; mod eval; mod opcode; mod value; +mod vm; fn main() { let mut args = env::args(); diff --git a/tvix/eval/src/vm.rs b/tvix/eval/src/vm.rs new file mode 100644 index 000000000..e35cd99b1 --- /dev/null +++ b/tvix/eval/src/vm.rs @@ -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, +} + +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 { + 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 { + let mut vm = VM { + chunk, + ip: 0, + stack: vec![], + }; + + vm.run() +}