From 11293ac2bf60f33a9dfa9abe6cfbcaaa90d2de8b Mon Sep 17 00:00:00 2001 From: ghostly_zsh Date: Thu, 8 Aug 2024 23:25:03 -0500 Subject: [PATCH] run binary expressions --- kabel/src/codegen.rs | 32 ++++--------------------- kabel/src/macros.rs | 27 +++++++++++++++++++++ kabel/src/opcodes.rs | 24 +++++++++++++++++++ kabel/src/vm.rs | 54 +++++++++++++++++++++++++++++++++++++++++- kabel_test/src/main.rs | 2 +- 5 files changed, 109 insertions(+), 30 deletions(-) diff --git a/kabel/src/codegen.rs b/kabel/src/codegen.rs index 7882222b098a375f98373fbe81f580bd7a5892ca..30298edada6722996d55c70da3be2b4265d15945 100644 --- a/kabel/src/codegen.rs +++ b/kabel/src/codegen.rs @@ -1,4 +1,4 @@ -use crate::{opcodes::OpCode, parser::{BinOp, Lit, AST}, vm::{Value, VM}}; +use crate::{codegen_binary, opcodes::OpCode, parser::{BinOp, Lit, AST}, vm::{Value, VM}}; pub struct Codegen { pub vm: VM @@ -44,33 +44,9 @@ impl Codegen { } pub fn visit_binary(&mut self, left: AST, oper: BinOp, right: AST) { use crate::parser::BinOp::*; - match oper { - Add => { - self.visit(right); - self.visit(left); - self.vm.chunk.push(OpCode::ADD.into()); - self.vm.lines.last_mut().unwrap().1 += 1; - } - Sub => { - self.visit(right); - self.visit(left); - self.vm.chunk.push(OpCode::SUB.into()); - self.vm.lines.last_mut().unwrap().1 += 1; - } - Mul => { - self.visit(right); - self.visit(left); - self.vm.chunk.push(OpCode::MUL.into()); - self.vm.lines.last_mut().unwrap().1 += 1; - } - Div => { - self.visit(right); - self.visit(left); - self.vm.chunk.push(OpCode::DIV.into()); - self.vm.lines.last_mut().unwrap().1 += 1; - } - _ => { panic!("not implemented") } - } + 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); } pub fn visit_lit(&mut self, ast: &AST, lit: Lit) { match lit { diff --git a/kabel/src/macros.rs b/kabel/src/macros.rs index b566fe5eadc6368c12f8c4ddad22fbcd6d910cd4..5c27c3f87f7d5353b805854a7933f427e9caeef5 100644 --- a/kabel/src/macros.rs +++ b/kabel/src/macros.rs @@ -175,3 +175,30 @@ macro_rules! collect_lines { $string.iter().fold("".to_string(), |acc, string| acc + string + "\n").trim_end().to_string() }; } + +#[macro_export] +macro_rules! codegen_binary { + ($self:expr, $left:expr, $right:expr, $match_to:expr, $( $oper:tt, $code:tt ),*) => { + match $match_to { + $( $oper => { + $self.visit($right); + $self.visit($left); + $self.vm.chunk.push(OpCode::$code.into()); + $self.vm.lines.last_mut().unwrap().1 += 1; + } )* + _ => { panic!("not implemented") } + } + }; +} + +#[macro_export] +macro_rules! vm_boolean_binary { + ($self:expr, $oper:tt) => { + match ($self.stack.pop().unwrap(), $self.stack.pop().unwrap()) { + (Num(v1), Num(v2)) => $self.stack.push(Bool(v1 $oper v2)), + (Str(v1), Str(v2)) => $self.stack.push(Bool(v1 $oper v2)), + (Bool(v1), Bool(v2)) => $self.stack.push(Bool(v1 $oper v2)), + (_v1, _v2) => $self.stack.push(Bool(false)), + } + }; +} diff --git a/kabel/src/opcodes.rs b/kabel/src/opcodes.rs index f62e1652c80ea217ee6351e97bc13061e6bc5cba..2d08893e8cb30988fd7d887596f548bcd6947ac1 100644 --- a/kabel/src/opcodes.rs +++ b/kabel/src/opcodes.rs @@ -5,6 +5,14 @@ pub enum OpCode { MUL, DIV, MOD, + EQ, + NE, + GR, + GE, + LS, + LE, + OR, + AND, PRINT, ERR, } @@ -19,6 +27,14 @@ 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, PRINT => 0xFE, ERR => 0xFF } @@ -34,6 +50,14 @@ 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, 0xFE => PRINT, _ => ERR } diff --git a/kabel/src/vm.rs b/kabel/src/vm.rs index e6395a7d3136559bb17199fb06c3276071acdaca..4c6d9131371db8d67269d2760a2144f9c96ec115 100644 --- a/kabel/src/vm.rs +++ b/kabel/src/vm.rs @@ -1,4 +1,4 @@ -use crate::{mismatched_types, runtime_error::KabelRuntimeError, wrong_type}; +use crate::{mismatched_types, runtime_error::KabelRuntimeError, vm_boolean_binary, wrong_type}; pub struct VM { ip: usize, @@ -91,6 +91,58 @@ impl VM { } } } + 0x05 => { // MOD + match (self.stack.pop().unwrap(), self.stack.pop().unwrap()) { + (Num(v1), Num(v2)) => self.stack.push(Num(v1 % v2)), + (Str(_v1), Str(_v2)) => { + return Err(wrong_type!(self, "Cannot perform modulus on strings")) + }, + (Bool(_v1), Bool(_v2)) => { + return Err(wrong_type!(self, "Cannot perform modulus on booleans")) + } + (v1, v2) => { + return Err(mismatched_types!(self, "Mismatched types: {} and {}", v1.type_str(), v2.type_str())) + } + } + } + // EQ + 0x06 => vm_boolean_binary!(self, ==), + // NE + 0x07 => vm_boolean_binary!(self, !=), + // GR + 0x08 => vm_boolean_binary!(self, >), + // GE + 0x09 => vm_boolean_binary!(self, >=), + // LS + 0x0A => vm_boolean_binary!(self, <), + // LE + 0x0B => vm_boolean_binary!(self, <=), + // OR + 0x0C => match (self.stack.pop().unwrap(), self.stack.pop().unwrap()) { + (Num(_v1), Num(_v2)) => { + return Err(wrong_type!(self, "Cannot perform logical OR on numbers")) + } + (Str(_v1), Str(_v2)) => { + return Err(wrong_type!(self, "Cannot perform logical OR on strings")) + }, + (Bool(v1), Bool(v2)) => self.stack.push(Bool(v1 || v2)), + (v1, v2) => { + return Err(mismatched_types!(self, "Mismatched types: {} and {}", v1.type_str(), v2.type_str())) + } + } + // AND + 0x0D => match (self.stack.pop().unwrap(), self.stack.pop().unwrap()) { + (Num(_v1), Num(_v2)) => { + return Err(wrong_type!(self, "Cannot perform logical AND on numbers")) + } + (Str(_v1), Str(_v2)) => { + return Err(wrong_type!(self, "Cannot perform logical AND on strings")) + }, + (Bool(v1), Bool(v2)) => self.stack.push(Bool(v1 && v2)), + (v1, v2) => { + return Err(mismatched_types!(self, "Mismatched types: {} and {}", v1.type_str(), v2.type_str())) + } + } 0xFE => { // PRINT let value = self.stack.pop().unwrap(); diff --git a/kabel_test/src/main.rs b/kabel_test/src/main.rs index 6af09de45c9508765aae3000f3ba12c200fe4809..ea7510e1b25c745d7115a85b86a94384d45b133e 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 4 / 5;".to_string(); + let program = "print 7%3;".to_string(); let mut output = "".to_string();