aboutsummaryrefslogtreecommitdiff
path: root/crates/sloth_vm/src/lib.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/sloth_vm/src/lib.rs')
-rw-r--r--crates/sloth_vm/src/lib.rs111
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)
+ }
+}