about summary refs log tree commit diff
diff options
context:
space:
mode:
authorVincent Ambo <mail@tazj.in>2022-08-07T20·42+0300
committertazjin <tazjin@tvl.su>2022-08-12T13·05+0000
commitd59968649e843371db7d83ac1e2b327c08e70093 (patch)
treed49f4547db6e1ffd349fb8bbcace6f1d5f7ddf45
parent34df2c8473e681335351f95d5e07d56d24262a81 (diff)
feat(tvix/eval): add initial stack-based VM r/4407
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>
-rw-r--r--tvix/eval/src/main.rs1
-rw-r--r--tvix/eval/src/vm.rs55
2 files changed, 56 insertions, 0 deletions
diff --git a/tvix/eval/src/main.rs b/tvix/eval/src/main.rs
index bdb5818a3c2a..55365efabd1b 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 000000000000..e35cd99b1e3d
--- /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<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()
+}