about summary refs log tree commit diff
path: root/users/tazjin/rlox/src/bytecode/vm.rs
diff options
context:
space:
mode:
Diffstat (limited to 'users/tazjin/rlox/src/bytecode/vm.rs')
-rw-r--r--users/tazjin/rlox/src/bytecode/vm.rs59
1 files changed, 59 insertions, 0 deletions
diff --git a/users/tazjin/rlox/src/bytecode/vm.rs b/users/tazjin/rlox/src/bytecode/vm.rs
new file mode 100644
index 000000000000..1b9c4a235940
--- /dev/null
+++ b/users/tazjin/rlox/src/bytecode/vm.rs
@@ -0,0 +1,59 @@
+use super::chunk;
+use super::errors::*;
+use super::opcode::OpCode;
+use super::value::Value;
+
+pub struct VM {
+    chunk: chunk::Chunk,
+
+    // TODO(tazjin): Accessing array elements constantly is not ideal,
+    // lets see if something clever can be done with iterators.
+    ip: usize,
+
+    stack: Vec<Value>,
+}
+
+impl VM {
+    fn push(&mut self, value: Value) {
+        self.stack.push(value)
+    }
+
+    fn pop(&mut self) -> Value {
+        self.stack.pop().expect("fatal error: stack empty!")
+    }
+}
+
+impl VM {
+    fn run(&mut self) -> LoxResult<()> {
+        loop {
+            let op = &self.chunk.code[self.ip];
+
+            #[cfg(feature = "disassemble")]
+            chunk::disassemble_instruction(&self.chunk, self.ip);
+
+            self.ip += 1;
+
+            match op {
+                OpCode::OpReturn => {
+                    println!("{:?}", self.pop());
+                    return Ok(());
+                }
+
+                OpCode::OpConstant(idx) => {
+                    let c = *self.chunk.constant(*idx);
+                    self.push(c);
+                }
+            }
+        }
+    }
+}
+
+pub fn interpret(chunk: chunk::Chunk) -> LoxResult<()> {
+    let mut vm = VM {
+        chunk,
+        ip: 0,
+        stack: vec![],
+    };
+
+    vm.run()
+}