From 719300aa0298afb2f83fd1532d3bfcaaa5f09a72 Mon Sep 17 00:00:00 2001 From: ghostly_zsh Date: Thu, 8 Aug 2024 23:38:38 -0500 Subject: [PATCH] run unary expressions --- kabel/src/codegen.rs | 9 ++++++++- kabel/src/macros.rs | 12 ++++++++++++ kabel/src/opcodes.rs | 12 ++++++++++++ kabel/src/vm.rs | 20 ++++++++++++++++++++ kabel_test/src/main.rs | 4 ++-- 5 files changed, 54 insertions(+), 3 deletions(-) diff --git a/kabel/src/codegen.rs b/kabel/src/codegen.rs index 30298edada6722996d55c70da3be2b4265d15945..c2e64cfd49cc4753d8008c7091f4b001303d9640 100644 --- a/kabel/src/codegen.rs +++ b/kabel/src/codegen.rs @@ -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) => { diff --git a/kabel/src/macros.rs b/kabel/src/macros.rs index 5c27c3f87f7d5353b805854a7933f427e9caeef5..4aa7c2f4380bd5b2128e4ba5bc4d017202bb7654 100644 --- a/kabel/src/macros.rs +++ b/kabel/src/macros.rs @@ -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 { diff --git a/kabel/src/opcodes.rs b/kabel/src/opcodes.rs index 2d08893e8cb30988fd7d887596f548bcd6947ac1..7d6e6f6ee2345390d34d21c649ada22f1ed337c3 100644 --- a/kabel/src/opcodes.rs +++ b/kabel/src/opcodes.rs @@ -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 for u8 { use OpCode::*; match value { CONSTANT => 0x00, + ADD => 0x01, SUB => 0x02, MUL => 0x03, @@ -35,6 +40,9 @@ impl From for u8 { LE => 0x0B, OR => 0x0C, AND => 0x0D, + + NOT => 0x0E, + NEG => 0x0F, PRINT => 0xFE, ERR => 0xFF } @@ -45,6 +53,7 @@ impl From for OpCode { use OpCode::*; match value { 0x00 => CONSTANT, + 0x01 => ADD, 0x02 => SUB, 0x03 => MUL, @@ -58,6 +67,9 @@ impl From for OpCode { 0x0B => LE, 0x0C => OR, 0x0D => AND, + + 0x0E => NOT, + 0x0F => NEG, 0xFE => PRINT, _ => ERR } diff --git a/kabel/src/vm.rs b/kabel/src/vm.rs index 4c6d9131371db8d67269d2760a2144f9c96ec115..45bf07396b278b6273c6d788fe0c2d6d763ee42c 100644 --- a/kabel/src/vm.rs +++ b/kabel/src/vm.rs @@ -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(); diff --git a/kabel_test/src/main.rs b/kabel_test/src/main.rs index ea7510e1b25c745d7115a85b86a94384d45b133e..6f2f8b37d29b92bb5b865f2d97d05030814483ea 100644 --- a/kabel_test/src/main.rs +++ b/kabel_test/src/main.rs @@ -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 = 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();