aboutsummaryrefslogtreecommitdiff
path: root/crates
diff options
context:
space:
mode:
Diffstat (limited to 'crates')
-rw-r--r--crates/sloth_bytecode/src/lib.rs17
-rw-r--r--crates/sloth_vm/src/lib.rs23
-rw-r--r--crates/sloth_vm/src/vm.rs55
3 files changed, 69 insertions, 26 deletions
diff --git a/crates/sloth_bytecode/src/lib.rs b/crates/sloth_bytecode/src/lib.rs
index df91c41..992c24f 100644
--- a/crates/sloth_bytecode/src/lib.rs
+++ b/crates/sloth_bytecode/src/lib.rs
@@ -45,7 +45,12 @@ opcodes! {
0x02 Push "Push a value to a variable",
0x10 Dup "Duplicate a value on the stack",
- 0x11 Del "Delete a value from the stack",
+ 0x11 Pop "Pop a value from the stack",
+
+ 0x12 GetGlobal "Get a global value",
+ 0x13 SetGlobal "Set a global value",
+ 0x14 GetLocal "Get a local value",
+ 0x15 SetLocal "Set a local value",
0x20 Add "Add the last 2 values on the stack",
0x21 Sub "Subtract the last 2 values on the stack",
@@ -56,14 +61,14 @@ opcodes! {
0x30 Eq "Check if the last 2 values on the stack are equal",
0x31 Ne "Check if the last 2 values on the stack are not equal",
- 0x40 Jmp "Jump to a specific point in the program",
- 0x41 JmpIf "Jump to a specific point in the program if true is on the stack",
+ 0x40 Jump "Jump to a specific point in the program",
+ 0x41 JumpIf "Jump to a specific point in the program if true is on the stack",
0x50 Call "Call function on stack",
- 0x51 Return "Return from function on stack",
+ 0x51 CallNative "Call native function",
+ 0x52 Return "Return from function on stack",
- 0xE0 Hlt "Halt the program",
- 0xE1 Exit "Exit the program",
+ 0xE0 Halt "Halt the program",
0xF0 VMReturn "[DEBUG] Pop value from stack and return it fromthe program",
0xF1 VMPrint "[DEBUG] Print value to console"
diff --git a/crates/sloth_vm/src/lib.rs b/crates/sloth_vm/src/lib.rs
index be134d8..121ea6a 100644
--- a/crates/sloth_vm/src/lib.rs
+++ b/crates/sloth_vm/src/lib.rs
@@ -11,6 +11,8 @@ pub mod native;
pub mod value;
pub mod vm;
+use std::ops::{Index, IndexMut};
+
use value::{Object, ObjectType};
use crate::value::Primitive;
@@ -25,8 +27,8 @@ const STACK_SIZE: usize = 1024;
#[derive(Debug)]
pub struct Stack {
- top: usize,
stack: [Primitive; STACK_SIZE],
+ top: usize,
}
impl Default for Stack {
@@ -68,6 +70,25 @@ impl Stack {
pub fn peek(&self) -> Primitive {
self.stack[self.top - 1]
}
+
+ #[inline(always)]
+ pub fn peek_nth(&self, nth: usize) -> Primitive {
+ self.stack[self.top - 1 - nth]
+ }
+}
+
+impl Index<usize> for Stack {
+ type Output = Primitive;
+
+ fn index(&self, index: usize) -> &Self::Output {
+ &self.stack[index]
+ }
+}
+
+impl IndexMut<usize> for Stack {
+ fn index_mut(&mut self, index: usize) -> &mut Self::Output {
+ &mut self.stack[index]
+ }
}
pub struct ObjectMap {
diff --git a/crates/sloth_vm/src/vm.rs b/crates/sloth_vm/src/vm.rs
index ded7aa6..cab797e 100644
--- a/crates/sloth_vm/src/vm.rs
+++ b/crates/sloth_vm/src/vm.rs
@@ -13,20 +13,18 @@ pub struct CallFrame {
}
impl CallFrame {
- #[inline]
- fn function(&self) -> &Function {
- unsafe { &*self.function }
- }
-}
-
-impl From<&Function> for CallFrame {
- fn from(value: &Function) -> Self {
+ fn new(stack_offset: usize, function: &Function) -> Self {
Self {
pointer: 0,
- stack_offset: 0,
- function: value as *const _,
+ stack_offset,
+ function: function as *const _,
}
}
+
+ #[inline]
+ fn function(&self) -> &Function {
+ unsafe { &*self.function }
+ }
}
const CALL_STACK_SIZE: usize = 1024;
@@ -89,8 +87,8 @@ impl VM {
let mut this = Self::init(objects);
// Allocating the root function
- root.chunk.code.push(Opcode::Hlt as u8);
- this.call_stack.push(CallFrame::from(&root));
+ root.chunk.code.push(Opcode::Halt as u8);
+ this.call_stack.push(CallFrame::new(0, &root));
this.objects
.allocate(Object::new(ObjectType::Function(root)));
@@ -104,8 +102,8 @@ impl VM {
match Opcode::from_u8(opcode) {
Opcode::Constant => {
- let idx = self.read_u16();
- let value = self.call_stack.peek().function().chunk.constants[idx as usize];
+ let idx = self.read_u16() as usize;
+ let value = self.call_stack.peek().function().chunk.constants[idx];
self.stack.push(value);
}
@@ -114,9 +112,21 @@ impl VM {
self.stack.push(value);
self.stack.push(value);
}
- Opcode::Del => {
+ Opcode::Pop => {
self.stack.pop();
}
+ Opcode::GetLocal => {
+ let idx = self.read_u16() as usize;
+ let value = self.stack[self.call_stack.peek().stack_offset + idx];
+
+ self.stack.push(value);
+ }
+ Opcode::SetLocal => {
+ let idx = self.read_u16() as usize;
+ let value = self.stack.pop();
+
+ self.stack[self.call_stack.peek().stack_offset + idx] = value;
+ }
Opcode::Add => {
let value = match self.stack.pop2() {
@@ -179,7 +189,7 @@ impl VM {
};
// Push the function onto the call stack
- self.call_stack.push(CallFrame::from(function));
+ self.call_stack.push(CallFrame::new(0, function));
}
Opcode::Return => {
@@ -188,8 +198,7 @@ impl VM {
self.call_stack.pop();
}
- Opcode::Hlt => return false,
- Opcode::Exit => return false,
+ Opcode::Halt => return false,
_ => unimplemented!(),
}
@@ -201,6 +210,14 @@ impl VM {
while self.step() {}
}
+ fn call(&mut self, function: &Function) {
+ self.call_stack.push(CallFrame {
+ pointer: 0,
+ stack_offset: self.stack.top - 1 - (function.arity as usize),
+ function,
+ });
+ }
+
#[inline(always)]
fn read_u8(&mut self) -> u8 {
let frame = self.call_stack.peek_mut();
@@ -274,7 +291,7 @@ mod tests {
name: Some("foo".to_string()),
chunk: Chunk {
constants: vec![Primitive::Integer(7)],
- code: vec![0x00, 0, 0, 0x10, 0x20, 0x51],
+ code: vec![0x00, 0, 0, 0x10, 0x20, 0x52],
},
arity: 0,
})),