M kabel/src/codegen.rs => kabel/src/codegen.rs +2 -2
@@ 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::*;
M kabel/src/macros.rs => kabel/src/macros.rs +2 -3
@@ 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") }
}
};
}
M kabel/src/opcodes.rs => kabel/src/opcodes.rs +30 -21
@@ 6,6 6,9 @@ pub enum OpCode {
MUL,
DIV,
MOD,
+ BITAND,
+ BITXOR,
+ BITOR,
EQ,
NE,
GR,
@@ 32,17 35,20 @@ impl From<OpCode> 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<u8> 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
}
}
M kabel/src/vm.rs => kabel/src/vm.rs +76 -10
@@ 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"))
M kabel_test/src/main.rs => kabel_test/src/main.rs +1 -1
@@ 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();