aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCody <cody@codyq.dev>2023-04-11 17:34:11 -0500
committerCody <cody@codyq.dev>2023-04-11 17:34:11 -0500
commitee079d193b6644e65543c3fa02dbfcf7b4f2f9c6 (patch)
tree80975f19a2fcbd909beee83f2000f3dcabac1d9a
parent7451bdb02d54243eb299dde55f22d3b06ac5b2f2 (diff)
downloadsloth-ee079d193b6644e65543c3fa02dbfcf7b4f2f9c6.tar.gz
Hehehe
-rw-r--r--crates/sloth_bytecode/macros/src/lib.rs2
-rw-r--r--crates/sloth_bytecode/src/lib.rs24
-rw-r--r--crates/sloth_vm/src/lib.rs230
-rw-r--r--crates/sloth_vm/src/native.rs0
-rw-r--r--crates/sloth_vm/src/obj.rs0
-rw-r--r--crates/sloth_vm/src/vm.rs140
6 files changed, 166 insertions, 230 deletions
diff --git a/crates/sloth_bytecode/macros/src/lib.rs b/crates/sloth_bytecode/macros/src/lib.rs
index 31f462f..1690c17 100644
--- a/crates/sloth_bytecode/macros/src/lib.rs
+++ b/crates/sloth_bytecode/macros/src/lib.rs
@@ -97,7 +97,7 @@ fn into_bytecode_parser(instruction: &DslInstructionInput) -> TokenStream {
let mut chunks = Vec::new();
for byte in 0..bytes {
- let shift_amount = size - (byte + 1) * bytes;
+ let shift_amount = size - (byte + 1) * 8;
chunks.push(quote! {
((chunk[*offset + #byte] as #arg) << #shift_amount)
});
diff --git a/crates/sloth_bytecode/src/lib.rs b/crates/sloth_bytecode/src/lib.rs
index e499597..bf20068 100644
--- a/crates/sloth_bytecode/src/lib.rs
+++ b/crates/sloth_bytecode/src/lib.rs
@@ -18,12 +18,12 @@ pub enum Error {
instructions! {
Instruction;
- 0x00 Constant [u64] "Push a constant value onto the stack",
- 0x01 Load [u64] "Load a value from a variable",
- 0x02 Push [u64] "Push a value to a variable",
+ 0x00 Constant [u32] "Push a constant value onto the stack",
+ 0x01 Load [u32] "Load a value from a variable",
+ 0x02 Push [u32] "Push a value to a variable",
0x10 Dup [] "Duplicate a value on the stack",
- 0x11 Pop [] "Pop a value from the stack",
+ 0x11 Del [] "Delete a value from the stack",
0x20 Add [] "Add the last 2 values on the stack",
0x21 Sub [] "Subtract the last 2 values on the stack",
@@ -31,8 +31,16 @@ instructions! {
0x23 Div [] "Divide the last 2 values on the stack",
0x24 Mod [] "Modulo the last 2 values on the stack",
+ 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 [u32] "Jump to a specific point in the program",
+ 0x41 JmpIf [u32] "Jump to a specific point in the program if true is on the stack",
+
+ 0xE0 Hlt [] "Halt the program",
+ 0xE1 Exit [] "Exit the program",
+
0xF0 VMReturn [] "[DEBUG] Pop value from stack and return it from the program",
- 0xF1 VMExit [] "[DEBUG] Exit from the VM",
}
#[cfg(test)]
@@ -44,8 +52,8 @@ mod tests {
fn decompile_basic_instructions() {
let code = [
// Load constant 0
- 0x00, 0, 0, 0, 0, 0, 0, 0, 0,
- // Pop, Dup, Add, Sub, Mul, Div, Mod
+ 0x00, 0, 0, 0, 0,
+ // Pop, Del, Add, Sub, Mul, Div, Mod
0x10, 0x11, 0x20, 0x21, 0x22, 0x23, 0x24,
];
@@ -53,7 +61,7 @@ mod tests {
assert_eq!(Instruction::disassemble(&code, &mut offset), Instruction::Constant(0));
assert_eq!(Instruction::disassemble(&code, &mut offset), Instruction::Dup);
- assert_eq!(Instruction::disassemble(&code, &mut offset), Instruction::Pop);
+ assert_eq!(Instruction::disassemble(&code, &mut offset), Instruction::Del);
assert_eq!(Instruction::disassemble(&code, &mut offset), Instruction::Add);
assert_eq!(Instruction::disassemble(&code, &mut offset), Instruction::Sub);
assert_eq!(Instruction::disassemble(&code, &mut offset), Instruction::Mul);
diff --git a/crates/sloth_vm/src/lib.rs b/crates/sloth_vm/src/lib.rs
index 68f0406..77f7a25 100644
--- a/crates/sloth_vm/src/lib.rs
+++ b/crates/sloth_vm/src/lib.rs
@@ -7,111 +7,19 @@
unused_lifetimes
)]
-use sloth_bytecode::Instruction;
+pub mod native;
+pub mod obj;
+pub mod vm;
+
+pub use crate::vm::VM;
pub struct Chunk {
- code: Vec<u8>,
constants: Vec<Data>,
+ code: Vec<u8>,
}
-pub struct VM {
- vm_return: Option<Data>,
- stack: Stack,
-}
-
-impl VM {
- fn new() -> Self {
- Self {
- vm_return: None,
- stack: Stack::default(),
- }
- }
-
- fn execute(&mut self) {
- loop {
- self.execute_once();
- }
- }
-
- fn execute_once(&mut self) {
- //
- }
-
- fn run(&mut self, chunk: &Chunk) {
- let mut pointer = 0;
-
- loop {
- let instruction = Instruction::disassemble(&chunk.code, &mut pointer);
-
- match instruction {
- Instruction::Constant(idx) => {
- let value = chunk.constants[idx as usize];
- self.stack.push(value);
- }
- Instruction::Load(_) => todo!(),
- Instruction::Push(_) => todo!(),
- Instruction::Dup => {
- let value = self.stack.pop();
- self.stack.push(value);
- self.stack.push(value);
- }
- Instruction::Pop => {
- self.stack.pop();
- }
- Instruction::Add => {
- let value = match self.stack.pop2() {
- (Data::Integer(lhs), Data::Integer(rhs)) => Data::Integer(lhs + rhs),
- (Data::Float(lhs), Data::Float(rhs)) => Data::Float(lhs + rhs),
- _ => panic!(),
- };
-
- self.stack.push(value);
- }
- Instruction::Sub => {
- let value = match self.stack.pop2() {
- (Data::Integer(lhs), Data::Integer(rhs)) => Data::Integer(lhs - rhs),
- (Data::Float(lhs), Data::Float(rhs)) => Data::Float(lhs - rhs),
- _ => panic!(),
- };
-
- self.stack.push(value);
- }
- Instruction::Mul => {
- let value = match self.stack.pop2() {
- (Data::Integer(lhs), Data::Integer(rhs)) => Data::Integer(lhs * rhs),
- (Data::Float(lhs), Data::Float(rhs)) => Data::Float(lhs * rhs),
- _ => panic!(),
- };
-
- self.stack.push(value);
- }
- Instruction::Div => {
- let value = match self.stack.pop2() {
- (Data::Integer(lhs), Data::Integer(rhs)) => Data::Integer(lhs / rhs),
- (Data::Float(lhs), Data::Float(rhs)) => Data::Float(lhs / rhs),
- _ => panic!(),
- };
-
- self.stack.push(value);
- }
- Instruction::Mod => {
- let value = match self.stack.pop2() {
- (Data::Integer(lhs), Data::Integer(rhs)) => Data::Integer(lhs % rhs),
- (Data::Float(lhs), Data::Float(rhs)) => Data::Float(lhs % rhs),
- _ => panic!(),
- };
-
- self.stack.push(value);
- }
- Instruction::VMReturn => {
- let value = self.stack.pop();
- self.vm_return = Some(value);
- break;
- }
- Instruction::VMExit => break,
- }
- }
- }
+pub struct Function {
+ chunk: Chunk,
}
#[derive(Debug, Clone, Copy, PartialEq)]
@@ -166,124 +74,4 @@ impl Stack {
}
}
-#[cfg(test)]
-mod tests {
- use crate::{Chunk, Data, VM};
-
- #[test]
- fn arithmetic_ops() {
- let mut vm = VM::new();
-
- // Addition
- vm.run(&Chunk {
- code: vec![
- 0x00, 0, 0, 0, 0, 0, 0, 0, 0, // Load constant from 0
- 0x10, // Duplicate
- 0x20, // Add
- 0xF0, // Return VM
- ],
- constants: vec![Data::Integer(7)],
- });
-
- let add1 = vm.vm_return;
-
- vm.run(&Chunk {
- code: vec![
- 0x00, 0, 0, 0, 0, 0, 0, 0, 0, // Load constant from 0
- 0x00, 0, 0, 0, 0, 0, 0, 0, 1, // Load constant from 1
- 0x20, // Add
- 0xF0, // Return VM
- ],
- constants: vec![Data::Integer(2), Data::Integer(11)],
- });
-
- let add2 = vm.vm_return;
-
- // Subtraction
- vm.run(&Chunk {
- code: vec![
- 0x00, 0, 0, 0, 0, 0, 0, 0, 0, // Load constant from 0
- 0x10, // Duplicate
- 0x21, // Subtraction
- 0xF0, // Return VM
- ],
- constants: vec![Data::Integer(7)],
- });
-
- let sub1 = vm.vm_return;
-
- vm.run(&Chunk {
- code: vec![
- 0x00, 0, 0, 0, 0, 0, 0, 0, 0, // Load constant from 0
- 0x00, 0, 0, 0, 0, 0, 0, 0, 1, // Load constant from 1
- 0x21, // Subtraction
- 0xF0, // Return VM
- ],
- constants: vec![Data::Integer(2), Data::Integer(11)],
- });
-
- let sub2 = vm.vm_return;
-
- // Multiplication
- vm.run(&Chunk {
- code: vec![
- 0x00, 0, 0, 0, 0, 0, 0, 0, 0, // Load constant from 0
- 0x10, // Duplicate
- 0x22, // Multiplication
- 0xF0, // Return VM
- ],
- constants: vec![Data::Integer(7)],
- });
-
- let mul1 = vm.vm_return;
-
- vm.run(&Chunk {
- code: vec![
- 0x00, 0, 0, 0, 0, 0, 0, 0, 0, // Load constant from 0
- 0x00, 0, 0, 0, 0, 0, 0, 0, 1, // Load constant from 1
- 0x22, // Multiplication
- 0xF0, // Return VM
- ],
- constants: vec![Data::Integer(2), Data::Integer(11)],
- });
-
- let mul2 = vm.vm_return;
-
- // Division
- vm.run(&Chunk {
- code: vec![
- 0x00, 0, 0, 0, 0, 0, 0, 0, 0, // Load constant from 0
- 0x10, // Duplicate
- 0x23, // Division
- 0xF0, // Return VM
- ],
- constants: vec![Data::Integer(7)],
- });
-
- let div1 = vm.vm_return;
-
- vm.run(&Chunk {
- code: vec![
- 0x00, 0, 0, 0, 0, 0, 0, 0, 0, // Load constant from 0
- 0x00, 0, 0, 0, 0, 0, 0, 0, 1, // Load constant from 1
- 0x23, // Division
- 0xF0, // Return VM
- ],
- constants: vec![Data::Integer(2), Data::Integer(11)],
- });
-
- let div2 = vm.vm_return;
-
- assert_eq!(add1, Some(Data::Integer(14)));
- assert_eq!(add2, Some(Data::Integer(13)));
-
- assert_eq!(sub1, Some(Data::Integer(0)));
- assert_eq!(sub2, Some(Data::Integer(9)));
-
- assert_eq!(mul1, Some(Data::Integer(49)));
- assert_eq!(mul2, Some(Data::Integer(22)));
-
- assert_eq!(div1, Some(Data::Integer(1)));
- assert_eq!(div2, Some(Data::Integer(5)));
- }
-}
+pub struct ObjectMap {}
diff --git a/crates/sloth_vm/src/native.rs b/crates/sloth_vm/src/native.rs
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/crates/sloth_vm/src/native.rs
diff --git a/crates/sloth_vm/src/obj.rs b/crates/sloth_vm/src/obj.rs
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/crates/sloth_vm/src/obj.rs
diff --git a/crates/sloth_vm/src/vm.rs b/crates/sloth_vm/src/vm.rs
new file mode 100644
index 0000000..22b769b
--- /dev/null
+++ b/crates/sloth_vm/src/vm.rs
@@ -0,0 +1,140 @@
+use sloth_bytecode::Instruction;
+
+use crate::{Chunk, Data, Stack};
+
+pub struct VM {
+ vm_return: Option<Data>,
+ stack: Stack,
+}
+
+impl VM {
+ fn new() -> Self {
+ Self {
+ vm_return: None,
+ stack: Stack::default(),
+ }
+ }
+
+ fn execute(&mut self) {
+ loop {
+ self.execute_once();
+ }
+ }
+
+ fn execute_once(&mut self) {
+ //
+ }
+
+ fn run(&mut self, chunk: &Chunk) {
+ let mut pointer = 0;
+
+ loop {
+ let instruction = Instruction::disassemble(&chunk.code, &mut pointer);
+
+ match instruction {
+ Instruction::Constant(idx) => {
+ let value = chunk.constants[idx as usize];
+ self.stack.push(value);
+ }
+ Instruction::Load(_) => todo!(),
+ Instruction::Push(_) => todo!(),
+ Instruction::Dup => {
+ let value = self.stack.pop();
+ self.stack.push(value);
+ self.stack.push(value);
+ }
+ Instruction::Del => {
+ self.stack.pop();
+ }
+ Instruction::Add => {
+ let value = match self.stack.pop2() {
+ (Data::Integer(lhs), Data::Integer(rhs)) => Data::Integer(lhs + rhs),
+ (Data::Float(lhs), Data::Float(rhs)) => Data::Float(lhs + rhs),
+ _ => panic!(),
+ };
+
+ self.stack.push(value);
+ }
+ Instruction::Sub => {
+ let value = match self.stack.pop2() {
+ (Data::Integer(lhs), Data::Integer(rhs)) => Data::Integer(lhs - rhs),
+ (Data::Float(lhs), Data::Float(rhs)) => Data::Float(lhs - rhs),
+ _ => panic!(),
+ };
+
+ self.stack.push(value);
+ }
+ Instruction::Mul => {
+ let value = match self.stack.pop2() {
+ (Data::Integer(lhs), Data::Integer(rhs)) => Data::Integer(lhs * rhs),
+ (Data::Float(lhs), Data::Float(rhs)) => Data::Float(lhs * rhs),
+ _ => panic!(),
+ };
+
+ self.stack.push(value);
+ }
+ Instruction::Div => {
+ let value = match self.stack.pop2() {
+ (Data::Integer(lhs), Data::Integer(rhs)) => Data::Integer(lhs / rhs),
+ (Data::Float(lhs), Data::Float(rhs)) => Data::Float(lhs / rhs),
+ _ => panic!(),
+ };
+
+ self.stack.push(value);
+ }
+ Instruction::Mod => {
+ let value = match self.stack.pop2() {
+ (Data::Integer(lhs), Data::Integer(rhs)) => Data::Integer(lhs % rhs),
+ (Data::Float(lhs), Data::Float(rhs)) => Data::Float(lhs % rhs),
+ _ => panic!(),
+ };
+
+ self.stack.push(value);
+ }
+ Instruction::Hlt => break,
+ Instruction::Exit => break,
+ Instruction::VMReturn => {
+ let value = self.stack.pop();
+ self.vm_return = Some(value);
+ break;
+ }
+ _ => unimplemented!(),
+ }
+ }
+ }
+}
+
+#[cfg(test)]
+mod tests {
+ use crate::{Chunk, Data, VM};
+
+ #[test]
+ fn arithmetic_ops() {
+ let mut vm = VM::new();
+
+ // Addition
+ vm.run(&Chunk {
+ constants: vec![Data::Integer(7)],
+ code: vec![
+ 0x00, 0, 0, 0, 0, // Load constant from 0
+ 0x10, // Duplicate
+ 0x20, // Add
+ 0xF0, // Return VM
+ ],
+ });
+
+ assert_eq!(vm.vm_return, Some(Data::Integer(14)));
+
+ vm.run(&Chunk {
+ constants: vec![Data::Integer(2), Data::Integer(11)],
+ code: vec![
+ 0x00, 0, 0, 0, 0, // Load constant from 0
+ 0x00, 0, 0, 0, 1, // Load constant from 1
+ 0x20, // Add
+ 0xF0, // Return VM
+ ],
+ });
+
+ assert_eq!(vm.vm_return, Some(Data::Integer(13)));
+ }
+}