diff options
Diffstat (limited to 'crates/sloth_vm/src/lib.rs')
| -rw-r--r-- | crates/sloth_vm/src/lib.rs | 111 |
1 files changed, 83 insertions, 28 deletions
diff --git a/crates/sloth_vm/src/lib.rs b/crates/sloth_vm/src/lib.rs index 77f7a25..be134d8 100644 --- a/crates/sloth_vm/src/lib.rs +++ b/crates/sloth_vm/src/lib.rs @@ -8,70 +8,125 @@ )] pub mod native; -pub mod obj; +pub mod value; pub mod vm; +use value::{Object, ObjectType}; + +use crate::value::Primitive; pub use crate::vm::VM; pub struct Chunk { - constants: Vec<Data>, + constants: Vec<Primitive>, code: Vec<u8>, } -pub struct Function { - chunk: Chunk, -} - -#[derive(Debug, Clone, Copy, PartialEq)] -pub enum Data { - Integer(i128), - Float(f64), - Bool(bool), - Empty, -} - const STACK_SIZE: usize = 1024; #[derive(Debug)] pub struct Stack { - pointer: usize, - stack: [Data; STACK_SIZE], + top: usize, + stack: [Primitive; STACK_SIZE], } impl Default for Stack { fn default() -> Self { Self { - pointer: Default::default(), - stack: [Data::Empty; STACK_SIZE], + top: Default::default(), + stack: [Primitive::Empty; STACK_SIZE], } } } impl Stack { #[inline(always)] - pub fn push(&mut self, value: Data) { - if self.pointer >= STACK_SIZE { + pub fn push(&mut self, value: Primitive) { + if self.top >= STACK_SIZE { panic!("Stack overflow"); } - self.stack[self.pointer] = value; - self.pointer += 1; + self.stack[self.top] = value; + self.top += 1; } #[inline(always)] - pub fn pop(&mut self) -> Data { - if self.pointer == 0 { + pub fn pop(&mut self) -> Primitive { + if self.top == 0 { panic!("Stack underflow"); } - self.pointer -= 1; - self.stack[self.pointer] + self.top -= 1; + self.stack[self.top] } #[inline(always)] - pub fn pop2(&mut self) -> (Data, Data) { + pub fn pop2(&mut self) -> (Primitive, Primitive) { (self.pop(), self.pop()) } + + #[inline(always)] + pub fn peek(&self) -> Primitive { + self.stack[self.top - 1] + } } -pub struct ObjectMap {} +pub struct ObjectMap { + free: usize, + heap: Vec<Object>, +} + +impl Default for ObjectMap { + fn default() -> Self { + Self::with_capacity(32) + } +} + +impl From<Vec<Object>> for ObjectMap { + fn from(heap: Vec<Object>) -> Self { + let mut free = heap.len(); + for (idx, obj) in heap.iter().enumerate() { + if let ObjectType::Free { .. } = obj.typ { + free = idx; + break; + } + } + + Self { free, heap } + } +} + +impl ObjectMap { + pub fn with_capacity(capacity: usize) -> Self { + let mut heap = Vec::with_capacity(capacity); + for i in 0..capacity { + heap.push(Object::new(ObjectType::Free { next: i + 1 })); + } + + Self { free: 0, heap } + } + + pub fn allocate(&mut self, object: Object) -> usize { + let current = self.free; + if current >= self.heap.len() { + self.heap + .push(Object::new(ObjectType::Free { next: current + 1 })) + } + + let ObjectType::Free { next } = self.heap[current].typ else { + panic!("Allocation failed: Expected free location wasn't free"); + }; + + self.heap[current] = object; + self.free = next; + + current + } + + pub fn get(&self, idx: usize) -> Option<&Object> { + self.heap.get(idx) + } + + pub fn get_mut(&mut self, idx: usize) -> Option<&mut Object> { + self.heap.get_mut(idx) + } +} |
