diff options
| author | Cody <cody@codyq.dev> | 2023-04-11 17:34:11 -0500 |
|---|---|---|
| committer | Cody <cody@codyq.dev> | 2023-04-11 17:34:11 -0500 |
| commit | ee079d193b6644e65543c3fa02dbfcf7b4f2f9c6 (patch) | |
| tree | 80975f19a2fcbd909beee83f2000f3dcabac1d9a | |
| parent | 7451bdb02d54243eb299dde55f22d3b06ac5b2f2 (diff) | |
| download | sloth-ee079d193b6644e65543c3fa02dbfcf7b4f2f9c6.tar.gz | |
Hehehe
| -rw-r--r-- | crates/sloth_bytecode/macros/src/lib.rs | 2 | ||||
| -rw-r--r-- | crates/sloth_bytecode/src/lib.rs | 24 | ||||
| -rw-r--r-- | crates/sloth_vm/src/lib.rs | 230 | ||||
| -rw-r--r-- | crates/sloth_vm/src/native.rs | 0 | ||||
| -rw-r--r-- | crates/sloth_vm/src/obj.rs | 0 | ||||
| -rw-r--r-- | crates/sloth_vm/src/vm.rs | 140 |
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))); + } +} |
