~starkingdoms/starkingdoms

0c7d4d3bcf29e877c99ba21a80128a192a4d26ac — ghostly_zsh 1 year, 3 months ago 731aaaa
one stack, but its somehow 2x slower
4 files changed, 76 insertions(+), 67 deletions(-)

M kabel/Cargo.toml
M kabel/src/codegen.rs
M kabel/src/macros.rs
M kabel/src/vm.rs
M kabel/Cargo.toml => kabel/Cargo.toml +3 -0
@@ 12,3 12,6 @@ timer = []
debug = ["debug_lexer", "debug_parser"]
debug_lexer = []
debug_parser = []

[profile.release]
debug = true

M kabel/src/codegen.rs => kabel/src/codegen.rs +4 -4
@@ 143,22 143,22 @@ impl Codegen {
        self.vm.ip = old_ip;
    }
    pub fn visit_return(&mut self, ast: &AST, expr: Option<AST>) {
        let mut scopes = self.scopes.clone();
        /*let mut scopes = self.scopes.clone();
        let mut pop_count = 0;
        /*loop {
        loop {
            let (scope_type, scope) = scopes.pop().expect("scopes empty in return");
            pop_count += scope;
            if scope_type == ScopeType::Function {
                break;
            }
        }*/
        }
        self.vm.units[self.vm.unit_ptr].code.push(OpCode::POP.into());
        self.vm.units[self.vm.unit_ptr].code.push(pop_count as u8);
        if self.vm.units[self.vm.unit_ptr].lines.last().unwrap().0 != ast.end_line {
            self.vm.units[self.vm.unit_ptr].lines.push((ast.end_line, 2));
        } else {
            self.vm.units[self.vm.unit_ptr].lines.last_mut().unwrap().1 += 2;
        }
        }*/

        if let Some(expr) = expr {
            self.visit(expr);

M kabel/src/macros.rs => kabel/src/macros.rs +13 -13
@@ 301,13 301,13 @@ macro_rules! push_codegen {
#[macro_export]
macro_rules! vm_boolean_equality {
    ($self:expr, $oper:tt) => {
        match ($self.stacks[$self.stack_ptr].pop().expect(&("Couldn't pop left side of ".to_owned() + stringify!($oper))),
                $self.stacks[$self.stack_ptr].pop().expect(&("Couldn't pop right side of ".to_owned() + stringify!($oper)))) {
            (Num(v1), Num(v2)) => $self.stacks[$self.stack_ptr].push(Bool(v1 $oper v2)),
            (Str(v1), Str(v2)) => $self.stacks[$self.stack_ptr].push(Bool(v1 $oper v2)),
            (Bool(v1), Bool(v2)) => $self.stacks[$self.stack_ptr].push(Bool(v1 $oper v2)),
            (Null, Null) => $self.stacks[$self.stack_ptr].push(Bool(true)),
            (_v1, _v2) => $self.stacks[$self.stack_ptr].push(Bool(false)),
        match ($self.stack.pop().expect(&("Couldn't pop left side of ".to_owned() + stringify!($oper))),
                $self.stack.pop().expect(&("Couldn't pop right side of ".to_owned() + stringify!($oper)))) {
            (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)),
            (Null, Null) => $self.stack.push(Bool(true)),
            (_v1, _v2) => $self.stack.push(Bool(false)),
        }
    };
}


@@ 315,14 315,14 @@ macro_rules! vm_boolean_equality {
#[macro_export]
macro_rules! vm_boolean_comparison {
    ($self:expr, $oper:tt) => {
        match ($self.stacks[$self.stack_ptr].pop().expect(&("Couldn't pop left side of ".to_owned() + stringify!($oper))),
                $self.stacks[$self.stack_ptr].pop().expect(&("Couldn't pop right side of ".to_owned() + stringify!($oper)))) {
            (Num(v1), Num(v2)) => $self.stacks[$self.stack_ptr].push(Bool(v1 $oper v2)),
            (Str(v1), Str(v2)) => $self.stacks[$self.stack_ptr].push(Bool(v1 $oper v2)),
            (Bool(v1), Bool(v2)) => $self.stacks[$self.stack_ptr].push(Bool(v1 $oper v2)),
        match ($self.stack.pop().expect(&("Couldn't pop left side of ".to_owned() + stringify!($oper))),
                $self.stack.pop().expect(&("Couldn't pop right side of ".to_owned() + stringify!($oper)))) {
            (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)),
            (Null, _) => return Err(vm_error!($self, RuntimeErrorKind::WrongType, "Tried to perform comparison \"{}\" on value null", stringify!($tt))),
            (_, Null) => return Err(vm_error!($self, RuntimeErrorKind::WrongType, "Tried to perform comparison \"{}\" on value null", stringify!($tt))),
            (_v1, _v2) => $self.stacks[$self.stack_ptr].push(Bool(false)),
            (_v1, _v2) => $self.stack.push(Bool(false)),
        }
    };
}

M kabel/src/vm.rs => kabel/src/vm.rs +56 -50
@@ 30,9 30,10 @@ pub struct VM {
    pub ip: usize,
    pub unit_ptr: usize,
    pub stack_ptr: usize,
    pub call_stack: Vec<(usize, usize)>, // (unit_ptr, ip)
    pub call_stack: Vec<(usize, usize, usize)>, // (unit_ptr, ip, stack_offset)
    pub units: Vec<Unit>,
    pub stacks: Vec<Vec<Value>>,
    pub stack: Vec<Value>,
    pub stack_offset: usize,
    text: Vec<String>
}



@@ 43,9 44,10 @@ impl VM {
            ip: 0,
            unit_ptr: 0,
            stack_ptr: 0,
            call_stack: Vec::new(),
            call_stack: vec![(0, 0, 0)],
            units: vec![Unit::new(bytecode, pool, lines)],
            stacks: vec![Vec::new()],
            stack: Vec::new(),
            stack_offset: 0,
            text: text.lines().map(|s| s.to_string()).collect::<Vec<String>>(),
        }
    }


@@ 56,25 58,28 @@ impl VM {
                0x00 => { // LOAD
                    let byte = self.read() as usize;
                    let value = self.units[self.unit_ptr].pool[byte].clone();
                    self.stacks[self.stack_ptr].push(value);
                    self.stack.push(value);
                }
                0x01 => { // VAR
                    let ptr = self.read() as usize;
                    let value = self.stacks[self.stack_ptr][ptr].clone();
                    self.stacks[self.stack_ptr].push(value);
                    let value = self.stack[ptr+self.stack_offset].clone();
                    //println!("offset {} ptr {}", offset, ptr);
                    //println!("stack {:?}", self.stack);
                    self.stack.push(value);
                }
                // ASSIGN
                0x02 => {
                    let value = self.stacks[self.stack_ptr].pop().unwrap();
                    let value = self.stack.pop().unwrap();
                    let ptr = self.read();
                    self.stacks[self.stack_ptr][ptr as usize] = value.clone();
                    self.stacks[self.stack_ptr].push(value);
                    let offset = self.call_stack.last().expect("var call stack last").2;
                    self.stack[ptr as usize + offset] = value.clone();
                    self.stack.push(value);
                }
                0x03 => { // ADD
                    match (self.stacks[self.stack_ptr].pop().unwrap(), self.stacks[self.stack_ptr].pop().unwrap()) {
                        (Num(v1), Num(v2)) => self.stacks[self.stack_ptr].push(Num(v1 + v2)),
                    match (self.stack.pop().unwrap(), self.stack.pop().unwrap()) {
                        (Num(v1), Num(v2)) => self.stack.push(Num(v1 + v2)),
                        (Str(v1), Str(v2)) => {
                            self.stacks[self.stack_ptr].push(Str(v1 + &v2));
                            self.stack.push(Str(v1 + &v2));
                        },
                        (Bool(_v1), Bool(_v2)) => {
                            return Err(vm_error!(self, RuntimeErrorKind::WrongType, "Cannot add booleans"))


@@ 85,8 90,8 @@ impl VM {
                    }
                }
                0x04 => { // SUB
                    match (self.stacks[self.stack_ptr].pop().unwrap(), self.stacks[self.stack_ptr].pop().unwrap()) {
                        (Num(v1), Num(v2)) => self.stacks[self.stack_ptr].push(Num(v1 - v2)),
                    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(vm_error!(self, RuntimeErrorKind::WrongType, "Cannot subtract strings"))
                        },


@@ 99,11 104,11 @@ impl VM {
                    }
                }
                0x05 => { // MUL
                    match (self.stacks[self.stack_ptr].pop().unwrap(), self.stacks[self.stack_ptr].pop().unwrap()) {
                        (Num(v1), Num(v2)) => self.stacks[self.stack_ptr].push(Num(v1 * v2)),
                    match (self.stack.pop().unwrap(), self.stack.pop().unwrap()) {
                        (Num(v1), Num(v2)) => self.stack.push(Num(v1 * v2)),
                        (Str(v1), Num(v2)) => {
                            if v2.fract() == 0.0 {
                                self.stacks[self.stack_ptr].push(Str(v1.repeat(v2 as usize)));
                                self.stack.push(Str(v1.repeat(v2 as usize)));
                            } else {
                                return Err(vm_error!(self, RuntimeErrorKind::WrongType, "Number must be an integer"))
                            }


@@ 120,8 125,8 @@ impl VM {
                    }
                }
                0x06 => { // DIV
                    match (self.stacks[self.stack_ptr].pop().unwrap(), self.stacks[self.stack_ptr].pop().unwrap()) {
                        (Num(v1), Num(v2)) => self.stacks[self.stack_ptr].push(Num(v1 / v2)),
                    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(vm_error!(self, RuntimeErrorKind::WrongType, "Cannot divide strings"))
                        },


@@ 134,8 139,8 @@ impl VM {
                    }
                }
                0x07 => { // MOD
                    match (self.stacks[self.stack_ptr].pop().unwrap(), self.stacks[self.stack_ptr].pop().unwrap()) {
                        (Num(v1), Num(v2)) => self.stacks[self.stack_ptr].push(Num(v1 % v2)),
                    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(vm_error!(self, RuntimeErrorKind::WrongType, "Cannot perform modulus on strings"))
                        },


@@ 148,7 153,7 @@ impl VM {
                    }
                }
                0x08 => { // BITAND
                    match (self.stacks[self.stack_ptr].pop().unwrap(), self.stacks[self.stack_ptr].pop().unwrap()) {
                    match (self.stack.pop().unwrap(), self.stack.pop().unwrap()) {
                        (Num(v1), Num(v2)) => {
                            if v1.fract() != 0.0 {
                                return Err(vm_error!(self, RuntimeErrorKind::WrongType, "Cannot perform bitwise AND on {}", v1))


@@ 156,7 161,7 @@ impl VM {
                            if v2.fract() != 0.0 {
                                return Err(vm_error!(self, RuntimeErrorKind::WrongType, "Cannot perform bitwise AND on {}", v2))
                            }
                            self.stacks[self.stack_ptr].push(Num((v1 as u32 & v2 as u32) as f32))
                            self.stack.push(Num((v1 as u32 & v2 as u32) as f32))
                        }
                        (Str(_v1), Str(_v2)) => {
                            return Err(vm_error!(self, RuntimeErrorKind::WrongType, "Cannot perform bitwise AND on strings"))


@@ 170,7 175,7 @@ impl VM {
                    }
                }
                0x09 => { // BITXOR
                    match (self.stacks[self.stack_ptr].pop().unwrap(), self.stacks[self.stack_ptr].pop().unwrap()) {
                    match (self.stack.pop().unwrap(), self.stack.pop().unwrap()) {
                        (Num(v1), Num(v2)) => {
                            if v1.fract() != 0.0 {
                                return Err(vm_error!(self, RuntimeErrorKind::WrongType, "Cannot perform bitwise XOR on {}", v1))


@@ 178,7 183,7 @@ impl VM {
                            if v2.fract() != 0.0 {
                                return Err(vm_error!(self, RuntimeErrorKind::WrongType, "Cannot perform bitwise XOR on {}", v2))
                            }
                            self.stacks[self.stack_ptr].push(Num((v1 as u32 ^ v2 as u32) as f32))
                            self.stack.push(Num((v1 as u32 ^ v2 as u32) as f32))
                        }
                        (Str(_v1), Str(_v2)) => {
                            return Err(vm_error!(self, RuntimeErrorKind::WrongType, "Cannot perform bitwise XOR on strings"))


@@ 192,7 197,7 @@ impl VM {
                    }
                }
                0x0A => { // BITOR
                    match (self.stacks[self.stack_ptr].pop().unwrap(), self.stacks[self.stack_ptr].pop().unwrap()) {
                    match (self.stack.pop().unwrap(), self.stack.pop().unwrap()) {
                        (Num(v1), Num(v2)) => {
                            if v1.fract() != 0.0 {
                                return Err(vm_error!(self, RuntimeErrorKind::WrongType, "Cannot perform bitwise OR on {}", v1))


@@ 200,7 205,7 @@ impl VM {
                            if v2.fract() != 0.0 {
                                return Err(vm_error!(self, RuntimeErrorKind::WrongType, "Cannot perform bitwise OR on {}", v2))
                            }
                            self.stacks[self.stack_ptr].push(Num((v1 as u32 | v2 as u32) as f32))
                            self.stack.push(Num((v1 as u32 | v2 as u32) as f32))
                        }
                        (Str(_v1), Str(_v2)) => {
                            return Err(vm_error!(self, RuntimeErrorKind::WrongType, "Cannot perform bitwise OR on strings"))


@@ 226,14 231,14 @@ impl VM {
                // LE
                0x10 => vm_boolean_comparison!(self, <=),
                // OR
                0x11 => match (self.stacks[self.stack_ptr].pop().unwrap(), self.stacks[self.stack_ptr].pop().unwrap()) {
                0x11 => match (self.stack.pop().unwrap(), self.stack.pop().unwrap()) {
                    (Num(_v1), Num(_v2)) => {
                        return Err(vm_error!(self, RuntimeErrorKind::WrongType, "Tried to perform \"||\" on non-boolean numbers"))
                    }
                    (Str(_v1), Str(_v2)) => {
                        return Err(vm_error!(self, RuntimeErrorKind::WrongType, "Tried to perform \"||\" on non-boolean strings"))
                    },
                    (Bool(v1), Bool(v2)) => self.stacks[self.stack_ptr].push(Bool(v1 || v2)),
                    (Bool(v1), Bool(v2)) => self.stack.push(Bool(v1 || v2)),
                    (Null, _) => return Err(vm_error!(self, RuntimeErrorKind::WrongType, "Tried to perform \"||\" on non-boolean value null")),
                    (_, Null) => return Err(vm_error!(self, RuntimeErrorKind::WrongType, "Tried to perform \"||\" on non-boolean value null")),
                    (v1, v2) => {


@@ 241,14 246,14 @@ impl VM {
                    }
                }
                // AND
                0x12 => match (self.stacks[self.stack_ptr].pop().unwrap(), self.stacks[self.stack_ptr].pop().unwrap()) {
                0x12 => match (self.stack.pop().unwrap(), self.stack.pop().unwrap()) {
                    (Num(_v1), Num(_v2)) => {
                        return Err(vm_error!(self, RuntimeErrorKind::WrongType, "Tried to perform \"&&\" on non-boolean numbers"))
                    }
                    (Str(_v1), Str(_v2)) => {
                        return Err(vm_error!(self, RuntimeErrorKind::WrongType, "Tried to perform \"&&\" on non-boolean strings"))
                    },
                    (Bool(v1), Bool(v2)) => self.stacks[self.stack_ptr].push(Bool(v1 && v2)),
                    (Bool(v1), Bool(v2)) => self.stack.push(Bool(v1 && v2)),
                    (Null, _) => return Err(vm_error!(self, RuntimeErrorKind::WrongType, "Tried to perform \"&&\" on non-boolean value null")),
                    (_, Null) => return Err(vm_error!(self, RuntimeErrorKind::WrongType, "Tried to perform \"&&\" on non-boolean value null")),
                    (v1, v2) => {


@@ 256,7 261,7 @@ impl VM {
                    }
                }
                // NOT
                0x13 => match self.stacks[self.stack_ptr].pop().unwrap() {
                0x13 => match self.stack.pop().unwrap() {
                    Null => { return Err(vm_error!(self, RuntimeErrorKind::WrongType, "Tried to perform \"!\" on non-boolean value null")) }
                    Num(_v1) => {
                        return Err(vm_error!(self, RuntimeErrorKind::WrongType, "Tried to perform \"!\" on non-boolean number"))


@@ 264,15 269,15 @@ impl VM {
                    Str(_v1) => {
                        return Err(vm_error!(self, RuntimeErrorKind::WrongType, "Tried to perform \"!\" on non-boolean string"))
                    }
                    Bool(v1) => self.stacks[self.stack_ptr].push(Bool(!v1)),
                    Bool(v1) => self.stack.push(Bool(!v1)),
                    Fun(_v1) => {
                        return Err(vm_error!(self, RuntimeErrorKind::WrongType, "Tried to perform \"!\" on non-boolean function"))
                    }
                }
                // NEG
                0x14 => match self.stacks[self.stack_ptr].pop().unwrap() {
                0x14 => match self.stack.pop().unwrap() {
                    Null => { return Err(vm_error!(self, RuntimeErrorKind::WrongType, "Tried to perform \"-\" on non-number value null")) }
                    Num(v1) => self.stacks[self.stack_ptr].push(Num(-v1)),
                    Num(v1) => self.stack.push(Num(-v1)),
                    Str(_v1) => {
                        return Err(vm_error!(self, RuntimeErrorKind::WrongType, "Tried to perform \"-\" on non-number string"))
                    }


@@ 295,7 300,7 @@ impl VM {
                }
                // JNE
                0x17 => {
                    let condition = self.stacks[self.stack_ptr].pop().unwrap();
                    let condition = self.stack.pop().unwrap();
                    if let Value::Bool(condition) = condition {
                        if !condition {
                            let loc = self.read_u16();


@@ 311,18 316,19 @@ impl VM {
                // CALL
                0x18 => {
                    let num_args = self.read();
                    let function = self.stacks[self.stack_ptr].pop().expect("Stack was empty in call");
                    let function = self.stack.pop().expect("Stack was empty in call");
                    if let Value::Fun(function) = function {
                        self.stacks.push(Vec::new());
                        if num_args as usize != function.arity {
                            return Err(vm_error!(self, RuntimeErrorKind::IncorrectArity, "Function has {} arguments, {} provided", function.arity, num_args))
                        }
                        self.call_stack.push((self.unit_ptr, self.ip));
                        self.stacks[self.stack_ptr+1].push(Value::Fun(function));
                        self.stack_offset = self.stack.len()-1;
                        self.call_stack.push((self.unit_ptr, self.ip, self.stack_offset));
                        for _ in 0..num_args {
                            let arg = self.stacks[self.stack_ptr].pop().expect("Missing arguments in call");
                            self.stacks[self.stack_ptr+1].push(arg);
                            let arg = self.stack.pop().expect("Missing arguments in call");
                            self.stack.push(arg);
                        }
                        self.stack.insert(self.stack.len()-num_args as usize, Value::Fun(function));
                        //println!("stack call {:?}", self.stack);
                        self.stack_ptr += 1;
                        self.ip = 0;
                        self.unit_ptr = function.unit_ptr as usize;


@@ 332,25 338,25 @@ impl VM {
                }
                // RET
                0x19 => {
                    let (unit_ptr, ip) = self.call_stack.pop().expect("Call stack empty on RET");
                    let ret = self.stacks[self.stack_ptr].pop().expect("Missing return value");
                    //self.stacks[self.stack_ptr].clear();
                    let (unit_ptr, ip, stack_offset) = self.call_stack.pop().expect("Call stack empty on RET");
                    let ret = self.stack.pop().expect("Missing return value");
                    self.stack = self.stack[..stack_offset].to_vec();
                    self.stack_offset = self.call_stack.last().expect("call stack empty").2;
                    self.unit_ptr = unit_ptr;
                    self.ip = ip;
                    // returned to code
                    self.stack_ptr -= 1;
                    self.stacks.pop().expect("RET pop stacks failed");
                    self.stacks[self.stack_ptr].push(ret);
                    self.stack.push(ret);
                }

                0xFD => { // POP
                    let times = self.read();
                    for _ in 0..times {
                        self.stacks[self.stack_ptr].pop().expect(&format!("{}: Unable to pop stack", self.ip));
                        self.stack.pop().expect(&format!("{}: Unable to pop stack", self.ip));
                    }
                }
                0xFE => { // PRINT
                    let value = self.stacks[self.stack_ptr].pop().unwrap();
                    let value = self.stack.pop().unwrap();
                    match value {
                        Null => *output += "null",
                        Num(v) => *output += &v.to_string(),