about summary refs log tree commit diff
path: root/tvix/eval
diff options
context:
space:
mode:
Diffstat (limited to 'tvix/eval')
-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()
+}