From f9039c39c19642c713556245576794ab028da0e7 Mon Sep 17 00:00:00 2001 From: ghostly_zsh Date: Thu, 8 Aug 2024 23:55:01 -0500 Subject: [PATCH] bitwise operations --- kabel/src/codegen.rs | 4 +- kabel/src/macros.rs | 5 +-- kabel/src/opcodes.rs | 51 ++++++++++++++----------- kabel/src/vm.rs | 86 +++++++++++++++++++++++++++++++++++++----- kabel_test/src/main.rs | 2 +- 5 files changed, 111 insertions(+), 37 deletions(-) diff --git a/kabel/src/codegen.rs b/kabel/src/codegen.rs index c2e64cfd49cc4753d8008c7091f4b001303d9640..7027e6ae754da260dcc0d4f87c20ae888dbdc2ae 100644 --- a/kabel/src/codegen.rs +++ b/kabel/src/codegen.rs @@ -48,8 +48,8 @@ impl Codegen { pub fn visit_binary(&mut self, left: AST, oper: BinOp, right: AST) { use crate::parser::BinOp::*; codegen_binary!(self, left, right, oper, Add, ADD, Sub, SUB, Mul, MUL, - Div, DIV, Mod, MOD, Eq, EQ, Ne, NE, Gr, GR, Ge, GE, Ls, LS, - Le, LE, Or, OR, And, AND); + Div, DIV, Mod, MOD, BitAnd, BITAND, BitXor, BITXOR, BitOr, BITOR, + Eq, EQ, Ne, NE, Gr, GR, Ge, GE, Ls, LS, Le, LE, Or, OR, And, AND); } pub fn visit_unary(&mut self, oper: UnOp, right: AST) { use crate::parser::UnOp::*; diff --git a/kabel/src/macros.rs b/kabel/src/macros.rs index 4aa7c2f4380bd5b2128e4ba5bc4d017202bb7654..0c6c72aa3244390549d1ce9344e04cbb057fcce3 100644 --- a/kabel/src/macros.rs +++ b/kabel/src/macros.rs @@ -156,12 +156,12 @@ macro_rules! mismatched_types { } #[macro_export] macro_rules! wrong_type { - ($self:expr, $message:expr) => { + ($self:expr, $message:expr $(, $args:expr )*) => { { let line = $self.find_line(); $crate::runtime_error::KabelRuntimeError::new( $crate::runtime_error::RuntimeErrorKind::WrongType, - $message.to_string(), + format!($message, $( $args ),*), line, $self.text[line].to_string(), ) @@ -186,7 +186,6 @@ macro_rules! codegen_binary { $self.vm.chunk.push(OpCode::$code.into()); $self.vm.lines.last_mut().unwrap().1 += 1; } )* - _ => { panic!("not implemented") } } }; } diff --git a/kabel/src/opcodes.rs b/kabel/src/opcodes.rs index 7d6e6f6ee2345390d34d21c649ada22f1ed337c3..b8d0c55f1e6ee78c66f2bc6d870b3e189f6f4ab7 100644 --- a/kabel/src/opcodes.rs +++ b/kabel/src/opcodes.rs @@ -6,6 +6,9 @@ pub enum OpCode { MUL, DIV, MOD, + BITAND, + BITXOR, + BITOR, EQ, NE, GR, @@ -32,17 +35,20 @@ impl From for u8 { MUL => 0x03, DIV => 0x04, MOD => 0x05, - EQ => 0x06, - NE => 0x07, - GR => 0x08, - GE => 0x09, - LS => 0x0A, - LE => 0x0B, - OR => 0x0C, - AND => 0x0D, + BITAND => 0x06, + BITXOR => 0x07, + BITOR => 0x08, + EQ => 0x09, + NE => 0x0A, + GR => 0x0B, + GE => 0x0C, + LS => 0x0D, + LE => 0x0E, + OR => 0x0F, + AND => 0x10, - NOT => 0x0E, - NEG => 0x0F, + NOT => 0x11, + NEG => 0x12, PRINT => 0xFE, ERR => 0xFF } @@ -59,18 +65,21 @@ impl From for OpCode { 0x03 => MUL, 0x04 => DIV, 0x05 => MOD, - 0x06 => EQ, - 0x07 => NE, - 0x08 => GR, - 0x09 => GE, - 0x0A => LS, - 0x0B => LE, - 0x0C => OR, - 0x0D => AND, + 0x06 => BITAND, + 0x07 => BITXOR, + 0x08 => BITOR, + 0x09 => EQ, + 0x0A => NE, + 0x0B => GR, + 0x0C => GE, + 0x0D => LS, + 0x0E => LE, + 0x0F => OR, + 0x10 => AND, - 0x0E => NOT, - 0x0F => NEG, - 0xFE => PRINT, + 0x11 => NOT, + 0x12 => NEG, + 0x13 => PRINT, _ => ERR } } diff --git a/kabel/src/vm.rs b/kabel/src/vm.rs index 45bf07396b278b6273c6d788fe0c2d6d763ee42c..db5c1ec60a18e7cf39bcb7790c67795359b9f60a 100644 --- a/kabel/src/vm.rs +++ b/kabel/src/vm.rs @@ -105,20 +105,86 @@ impl VM { } } } + 0x06 => { // BITAND + match (self.stack.pop().unwrap(), self.stack.pop().unwrap()) { + (Num(v1), Num(v2)) => { + if v1.fract() != 0.0 { + return Err(wrong_type!(self, "Cannot perform bitwise AND on {}", v1)) + } + if v2.fract() != 0.0 { + return Err(wrong_type!(self, "Cannot perform bitwise AND on {}", v2)) + } + self.stack.push(Num((v1 as u32 & v2 as u32) as f32)) + } + (Str(_v1), Str(_v2)) => { + return Err(wrong_type!(self, "Cannot perform bitwise AND on strings")) + }, + (Bool(_v1), Bool(_v2)) => { + return Err(wrong_type!(self, "Cannot perform bitwise AND on booleans")) + } + (v1, v2) => { + return Err(mismatched_types!(self, "Mismatched types: {} and {}", v1.type_str(), v2.type_str())) + } + } + } + 0x07 => { // BITXOR + match (self.stack.pop().unwrap(), self.stack.pop().unwrap()) { + (Num(v1), Num(v2)) => { + if v1.fract() != 0.0 { + return Err(wrong_type!(self, "Cannot perform bitwise XOR on {}", v1)) + } + if v2.fract() != 0.0 { + return Err(wrong_type!(self, "Cannot perform bitwise XOR on {}", v2)) + } + self.stack.push(Num((v1 as u32 ^ v2 as u32) as f32)) + } + (Str(_v1), Str(_v2)) => { + return Err(wrong_type!(self, "Cannot perform bitwise XOR on strings")) + }, + (Bool(_v1), Bool(_v2)) => { + return Err(wrong_type!(self, "Cannot perform bitwise XOR on booleans")) + } + (v1, v2) => { + return Err(mismatched_types!(self, "Mismatched types: {} and {}", v1.type_str(), v2.type_str())) + } + } + } + 0x08 => { // BITOR + match (self.stack.pop().unwrap(), self.stack.pop().unwrap()) { + (Num(v1), Num(v2)) => { + if v1.fract() != 0.0 { + return Err(wrong_type!(self, "Cannot perform bitwise OR on {}", v1)) + } + if v2.fract() != 0.0 { + return Err(wrong_type!(self, "Cannot perform bitwise OR on {}", v2)) + } + self.stack.push(Num((v1 as u32 | v2 as u32) as f32)) + } + (Str(_v1), Str(_v2)) => { + return Err(wrong_type!(self, "Cannot perform bitwise OR on strings")) + }, + (Bool(_v1), Bool(_v2)) => { + return Err(wrong_type!(self, "Cannot perform bitwise OR on booleans")) + } + (v1, v2) => { + return Err(mismatched_types!(self, "Mismatched types: {} and {}", v1.type_str(), v2.type_str())) + } + } + } // EQ - 0x06 => vm_boolean_binary!(self, ==), + 0x09 => vm_boolean_binary!(self, ==), // NE - 0x07 => vm_boolean_binary!(self, !=), + 0x0A => vm_boolean_binary!(self, !=), // GR - 0x08 => vm_boolean_binary!(self, >), + 0x0B => vm_boolean_binary!(self, >), // GE - 0x09 => vm_boolean_binary!(self, >=), + 0x0C => vm_boolean_binary!(self, >=), // LS - 0x0A => vm_boolean_binary!(self, <), + 0x0D => vm_boolean_binary!(self, <), // LE - 0x0B => vm_boolean_binary!(self, <=), + 0x0E => vm_boolean_binary!(self, <=), // OR - 0x0C => match (self.stack.pop().unwrap(), self.stack.pop().unwrap()) { + 0x0F => match (self.stack.pop().unwrap(), self.stack.pop().unwrap()) { (Num(_v1), Num(_v2)) => { return Err(wrong_type!(self, "Cannot perform logical OR on numbers")) } @@ -131,7 +197,7 @@ impl VM { } } // AND - 0x0D => match (self.stack.pop().unwrap(), self.stack.pop().unwrap()) { + 0x10 => match (self.stack.pop().unwrap(), self.stack.pop().unwrap()) { (Num(_v1), Num(_v2)) => { return Err(wrong_type!(self, "Cannot perform logical AND on numbers")) } @@ -144,7 +210,7 @@ impl VM { } } // NOT - 0x0E => match self.stack.pop().unwrap() { + 0x11 => match self.stack.pop().unwrap() { Num(_v1) => { return Err(wrong_type!(self, "Cannot perform logical NOT on numbers")) } @@ -154,7 +220,7 @@ impl VM { Bool(v1) => self.stack.push(Bool(!v1)), } // NEG - 0x0F => match self.stack.pop().unwrap() { + 0x12 => match self.stack.pop().unwrap() { Num(v1) => self.stack.push(Num(-v1)), Str(_v1) => { return Err(wrong_type!(self, "Cannot negate strings")) diff --git a/kabel_test/src/main.rs b/kabel_test/src/main.rs index 6f2f8b37d29b92bb5b865f2d97d05030814483ea..7dc017f0569012a2a49dd5928c67d7b0ae191155 100644 --- a/kabel_test/src/main.rs +++ b/kabel_test/src/main.rs @@ -9,7 +9,7 @@ fn main() { let program = fs::read_to_string(args[1].clone()).unwrap();*/ - let program = "print !(false == true || 4 > 5);".to_string(); + let program = "print 4|5;".to_string(); let mut output = "".to_string();