M kabel/src/codegen.rs => kabel/src/codegen.rs +8 -1
@@ 1,4 1,4 @@
-use crate::{codegen_binary, opcodes::OpCode, parser::{BinOp, Lit, AST}, vm::{Value, VM}};
+use crate::{codegen_binary, codegen_unary, opcodes::OpCode, parser::{BinOp, Lit, UnOp, AST}, vm::{Value, VM}};
pub struct Codegen {
pub vm: VM
@@ 26,6 26,9 @@ impl Codegen {
Binary(left, oper, right) => {
self.visit_binary(*left, oper, *right);
}
+ Unary(oper, right) => {
+ self.visit_unary(oper, *right);
+ }
Lit(ref lit) => {
self.visit_lit(&ast, lit.clone());
}
@@ 48,6 51,10 @@ impl Codegen {
Div, DIV, Mod, MOD, 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::*;
+ codegen_unary!(self, right, oper, Not, NOT, Neg, NEG);
+ }
pub fn visit_lit(&mut self, ast: &AST, lit: Lit) {
match lit {
Lit::Num(value) => {
M kabel/src/macros.rs => kabel/src/macros.rs +12 -0
@@ 190,6 190,18 @@ macro_rules! codegen_binary {
}
};
}
+#[macro_export]
+macro_rules! codegen_unary {
+ ($self:expr, $right:expr, $match_to:expr, $( $oper:tt, $code:tt ),*) => {
+ match $match_to {
+ $( $oper => {
+ $self.visit($right);
+ $self.vm.chunk.push(OpCode::$code.into());
+ $self.vm.lines.last_mut().unwrap().1 += 1;
+ } )*
+ }
+ };
+}
#[macro_export]
macro_rules! vm_boolean_binary {
M kabel/src/opcodes.rs => kabel/src/opcodes.rs +12 -0
@@ 1,5 1,6 @@
pub enum OpCode {
CONSTANT,
+
ADD,
SUB,
MUL,
@@ 13,6 14,9 @@ pub enum OpCode {
LE,
OR,
AND,
+
+ NOT,
+ NEG,
PRINT,
ERR,
}
@@ 22,6 26,7 @@ impl From<OpCode> for u8 {
use OpCode::*;
match value {
CONSTANT => 0x00,
+
ADD => 0x01,
SUB => 0x02,
MUL => 0x03,
@@ 35,6 40,9 @@ impl From<OpCode> for u8 {
LE => 0x0B,
OR => 0x0C,
AND => 0x0D,
+
+ NOT => 0x0E,
+ NEG => 0x0F,
PRINT => 0xFE,
ERR => 0xFF
}
@@ 45,6 53,7 @@ impl From<u8> for OpCode {
use OpCode::*;
match value {
0x00 => CONSTANT,
+
0x01 => ADD,
0x02 => SUB,
0x03 => MUL,
@@ 58,6 67,9 @@ impl From<u8> for OpCode {
0x0B => LE,
0x0C => OR,
0x0D => AND,
+
+ 0x0E => NOT,
+ 0x0F => NEG,
0xFE => PRINT,
_ => ERR
}
M kabel/src/vm.rs => kabel/src/vm.rs +20 -0
@@ 143,6 143,26 @@ impl VM {
return Err(mismatched_types!(self, "Mismatched types: {} and {}", v1.type_str(), v2.type_str()))
}
}
+ // NOT
+ 0x0E => match self.stack.pop().unwrap() {
+ Num(_v1) => {
+ return Err(wrong_type!(self, "Cannot perform logical NOT on numbers"))
+ }
+ Str(_v1) => {
+ return Err(wrong_type!(self, "Cannot perform logical NOT on strings"))
+ }
+ Bool(v1) => self.stack.push(Bool(!v1)),
+ }
+ // NEG
+ 0x0F => match self.stack.pop().unwrap() {
+ Num(v1) => self.stack.push(Num(-v1)),
+ Str(_v1) => {
+ return Err(wrong_type!(self, "Cannot negate strings"))
+ }
+ Bool(_v1) => {
+ return Err(wrong_type!(self, "Cannot negate bools"))
+ }
+ }
0xFE => { // PRINT
let value = self.stack.pop().unwrap();
M kabel_test/src/main.rs => kabel_test/src/main.rs +2 -2
@@ 2,14 2,14 @@
//use kabel::{debug::{debug_ast, debug_token_array}, run_lexer, run_parser, run_semantic_analysis};
-use kabel::{run_codegen, run_lexer, run_parser, run_semantic_analysis, vm::{Value, VM}};
+use kabel::{run_codegen, run_lexer, run_parser, run_semantic_analysis};
fn main() {
/*let args: Vec<String> = env::args().collect();
let program =
fs::read_to_string(args[1].clone()).unwrap();*/
- let program = "print 7%3;".to_string();
+ let program = "print !(false == true || 4 > 5);".to_string();
let mut output = "".to_string();