~starkingdoms/starkingdoms

11293ac2bf60f33a9dfa9abe6cfbcaaa90d2de8b — ghostly_zsh 1 year, 4 months ago 337e611
run binary expressions
5 files changed, 109 insertions(+), 30 deletions(-)

M kabel/src/codegen.rs
M kabel/src/macros.rs
M kabel/src/opcodes.rs
M kabel/src/vm.rs
M kabel_test/src/main.rs
M kabel/src/codegen.rs => kabel/src/codegen.rs +4 -28
@@ 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 {

M kabel/src/macros.rs => kabel/src/macros.rs +27 -0
@@ 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)),
        }
    };
}

M kabel/src/opcodes.rs => kabel/src/opcodes.rs +24 -0
@@ 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<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,
            PRINT => 0xFE,
            ERR => 0xFF
        }


@@ 34,6 50,14 @@ 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,
            0xFE => PRINT,
            _ => ERR
        }

M kabel/src/vm.rs => kabel/src/vm.rs +53 -1
@@ 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();

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 4 / 5;".to_string();
    let program = "print 7%3;".to_string();

    let mut output = "".to_string();