~starkingdoms/starkingdoms

048af52933dbe34e211c90d9d511c0d10bbbe19e — ghostly_zsh 1 year, 2 months ago 70e59fe
remove variables from stack, maybe other things pushed too
6 files changed, 223 insertions(+), 149 deletions(-)

M kabel/opcodes.txt
M kabel/src/codegen.rs
M kabel/src/debug.rs
M kabel/src/opcodes.rs
M kabel/src/vm.rs
M kabel/tmp.kab
M kabel/opcodes.txt => kabel/opcodes.txt +31 -26
@@ 1,32 1,37 @@
LOAD VAL        ; 0x00
VAR STACKPTR    ; 0x01
ASSIGN PTR      ; 0x02
ASN PTR         ; 0x02
ASNARR          ; 0x03
DECL            ; 0x04

ADD             ; 0x03
SUB             ; 0x04
MUL             ; 0x05
DIV             ; 0x06
MOD             ; 0x07
BITAND          ; 0x08
BITXOR          ; 0x09
BITOR           ; 0x0a
EQ              ; 0x0B
NE              ; 0x0C
GR              ; 0x0D
GE              ; 0x0E
LS              ; 0x0F
LE              ; 0x10
OR              ; 0x11
AND             ; 0x12
NOT             ; 0x13
NEG             ; 0x14
JMP LOC         ; 0x15
JMP_UP LOC      ; 0x16
JNE ELSE        ; 0x17
CALL ARITY      ; 0x18
RET             ; 0x19
LIST LEN        ; 0x1A
SCR             ; 0x1B
ADD             ; 0x05
SUB             ; 0x06
MUL             ; 0x07
DIV             ; 0x08
MOD             ; 0x09
BITAND          ; 0x0a
BITXOR          ; 0x0b
BITOR           ; 0x0c
EQ              ; 0x0D
NE              ; 0x0E
GR              ; 0x0F
GE              ; 0x10
LS              ; 0x11
LE              ; 0x12
OR              ; 0x13
AND             ; 0x14
NOT             ; 0x15
NEG             ; 0x16

JMP LOC         ; 0x17
JMP_UP LOC      ; 0x18
JNE ELSE        ; 0x19

CALL ARITY      ; 0x1A
RET             ; 0x1B

LIST LEN        ; 0x1C
SCR             ; 0x1D

POP COUNT       ; 0xFD
PRINT           ; 0xFE

M kabel/src/codegen.rs => kabel/src/codegen.rs +31 -15
@@ 1,4 1,4 @@
use crate::{ast::{ASTType, BinOp, LhsAssign, Lit, Name, UnOp, AST}, codegen_binary, codegen_unary, extension::Extension, opcodes::OpCode, vm::{Function, Unit, Value, VM}};
use crate::{ast::{ASTType, BinOp, LhsAssign, LhsAssignType, Lit, Name, UnOp, AST}, codegen_binary, codegen_unary, extension::Extension, opcodes::OpCode, vm::{Function, Unit, Value, VM}};

pub struct Codegen {
    pub vm: VM,


@@ 407,6 407,12 @@ impl Codegen {
    }
    pub fn visit_decl(&mut self, ast: &AST, _name: Name, expr: AST) {
        self.visit(expr);
        self.vm.units[self.vm.unit_ptr].code.push(OpCode::DECL.into());
        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, 1));
        } else {
            self.vm.units[self.vm.unit_ptr].lines.last_mut().unwrap().1 += 1;
        }
        #[allow(irrefutable_let_patterns)]
        if let Extension::Resolution(_scope, _ptr) = ast.extensions[0] {
            self.scopes.last_mut().expect("codegen scopes vec was empty").1 += 1;


@@ 432,23 438,33 @@ impl Codegen {
            self.vm.units[self.vm.unit_ptr].lines.last_mut().unwrap().1 += 1;
        }
    }
    pub fn visit_assign(&mut self, ast: &AST, _name: LhsAssign, expr: AST) {
    pub fn visit_assign(&mut self, ast: &AST, name: LhsAssign, expr: AST) {
        self.visit(expr);
        // pop stack to get value. then find variable in stack. set variable to value.
        self.vm.units[self.vm.unit_ptr].code.push(OpCode::ASSIGN.into());
        #[allow(irrefutable_let_patterns)]
        if let Extension::Resolution(_scope, ptr) = ast.extensions[0] {
            self.vm.units[self.vm.unit_ptr].code.push(ptr 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, 1));
            } else {
                self.vm.units[self.vm.unit_ptr].lines.last_mut().unwrap().1 += 1;
        match name.kind {
            LhsAssignType::Ident(_) => {
                #[allow(irrefutable_let_patterns)]
                if let Extension::Resolution(_scope, ptr) = ast.extensions[0] {
                    self.vm.units[self.vm.unit_ptr].code.push(OpCode::ASN.into());
                    self.vm.units[self.vm.unit_ptr].code.push(ptr 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;
                    }
                }
            }
            LhsAssignType::Subscript(name, index) => {
                self.visit(*index);
                self.visit(*name);
                self.vm.units[self.vm.unit_ptr].code.push(OpCode::ASNARR.into());

                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, 1));
                } else {
                    self.vm.units[self.vm.unit_ptr].lines.last_mut().unwrap().1 += 1;
                }
            }
        }
        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, 1));
        } else {
            self.vm.units[self.vm.unit_ptr].lines.last_mut().unwrap().1 += 1;
        }
    }
    pub fn visit_anonymous(&mut self, params: Vec<Name>, block: AST) {

M kabel/src/debug.rs => kabel/src/debug.rs +17 -3
@@ 247,7 247,7 @@ pub fn debug_bytecode(vm: &VM) -> String {
                output += &vm.ip.to_string();
                output += " ";
                output += &vm.find_line().to_string();
                output += " CONSTANT ";
                output += " LOAD ";
                vm.ip += 1;
                output += &vm.units[vm.unit_ptr].code[vm.ip].to_string();
                output += "\n";


@@ 261,15 261,29 @@ pub fn debug_bytecode(vm: &VM) -> String {
                output += &vm.units[vm.unit_ptr].code[vm.ip].to_string();
                output += "\n";
            }
            ASSIGN => { 
            ASN => { 
                output += &vm.ip.to_string();
                output += " ";
                output += &vm.find_line().to_string();
                output += " ASSIGN ";
                output += " ASN ";
                vm.ip += 1;
                output += &vm.units[vm.unit_ptr].code[vm.ip].to_string();
                output += "\n";
            }
            ASNARR => {
                output += &vm.ip.to_string();
                output += " ";
                output += &vm.find_line().to_string();
                output += " ASNARR";
                output += "\n";
            }
            DECL => {
                output += &vm.ip.to_string();
                output += " ";
                output += &vm.find_line().to_string();
                output += " DECL";
                output += "\n";
            }

            JMP => {
                output += &vm.ip.to_string();

M kabel/src/opcodes.rs => kabel/src/opcodes.rs +69 -63
@@ 4,7 4,9 @@
pub enum OpCode {
    LOAD,
    VAR,
    ASSIGN,
    ASN,
    ASNARR,
    DECL,

    ADD,
    SUB,


@@ 47,37 49,39 @@ impl From<OpCode> for u8 {
        match value {
            LOAD    => 0x00,
            VAR     => 0x01,
            ASSIGN  => 0x02,

            ADD     => 0x03,
            SUB     => 0x04,
            MUL     => 0x05,
            DIV     => 0x06,
            MOD     => 0x07,
            BITAND  => 0x08,
            BITXOR  => 0x09,
            BITOR   => 0x0a,
            EQ      => 0x0B,
            NE      => 0x0C,
            GR      => 0x0D,
            GE      => 0x0E,
            LS      => 0x0F,
            LE      => 0x10,
            OR      => 0x11,
            AND     => 0x12,

            NOT     => 0x13,
            NEG     => 0x14,

            JMP     => 0x15,
            JMP_UP  => 0x16,
            JNE     => 0x17,

            CALL    => 0x18,
            RET     => 0x19,

            LIST    => 0x1A,
            SCR     => 0x1B,
            ASN     => 0x02,
            ASNARR  => 0x03,
            DECL    => 0x04,

            ADD     => 0x05,
            SUB     => 0x06,
            MUL     => 0x07,
            DIV     => 0x08,
            MOD     => 0x09,
            BITAND  => 0x0a,
            BITXOR  => 0x0b,
            BITOR   => 0x0c,
            EQ      => 0x0D,
            NE      => 0x0E,
            GR      => 0x0F,
            GE      => 0x10,
            LS      => 0x11,
            LE      => 0x12,
            OR      => 0x13,
            AND     => 0x14,

            NOT     => 0x15,
            NEG     => 0x16,

            JMP     => 0x17,
            JMP_UP  => 0x18,
            JNE     => 0x19,

            CALL    => 0x1A,
            RET     => 0x1B,

            LIST    => 0x1C,
            SCR     => 0x1D,

            POP     => 0xFD,
            PRINT   => 0xFE,


@@ 90,37 94,39 @@ impl From<u8> for OpCode {
        use OpCode::*; match value {
            0x00 => LOAD,
            0x01 => VAR,
            0x02 => ASSIGN,

            0x03 => ADD,
            0x04 => SUB,
            0x05 => MUL,
            0x06 => DIV,
            0x07 => MOD,
            0x08 => BITAND,
            0x09 => BITXOR,
            0x0a => BITOR,
            0x0B => EQ,
            0x0C => NE,
            0x0D => GR,
            0x0E => GE,
            0x0F => LS,
            0x10 => LE,
            0x11 => OR,
            0x12 => AND,

            0x13 => NOT,
            0x14 => NEG,

            0x15 => JMP,
            0x16 => JMP_UP,
            0x17 => JNE,

            0x18 => CALL,
            0x19 => RET,

            0x1A => LIST,
            0x1B => SCR,
            0x02 => ASN,
            0x03 => ASNARR,
            0x04 => DECL,

            0x05 => ADD,
            0x06 => SUB,
            0x07 => MUL,
            0x08 => DIV,
            0x09 => MOD,
            0x0A => BITAND,
            0x0b => BITXOR,
            0x0c => BITOR,
            0x0D => EQ,
            0x0E => NE,
            0x0F => GR,
            0x10 => GE,
            0x11 => LS,
            0x12 => LE,
            0x13 => OR,
            0x14 => AND,

            0x15 => NOT,
            0x16 => NEG,

            0x17 => JMP,
            0x18 => JMP_UP,
            0x19 => JNE,

            0x1A => CALL,
            0x1b => RET,

            0x1C => LIST,
            0x1D => SCR,

            0xFD => POP,
            0xFE => PRINT,

M kabel/src/vm.rs => kabel/src/vm.rs +70 -41
@@ 1,4 1,6 @@

use std::rc::Rc;

use crate::{runtime_error::{KabelRuntimeError, RuntimeErrorKind}, vm_boolean_comparison, vm_boolean_equality};
use crate::vm_error;



@@ 32,7 34,8 @@ pub struct VM {
    pub call_stack: Vec<(usize, usize, usize)>, // (unit_ptr, ip, stack_offset)
    pub units: Vec<Unit>,
    pub stack: Vec<Value>,
    pub stack_offset: usize,
    pub variables: Vec<Value>,
    pub variables_offset: usize,
    text: Vec<String>
}



@@ 45,7 48,8 @@ impl VM {
            call_stack: vec![(0, 0, 0)],
            units: vec![Unit::new(bytecode, pool, lines)],
            stack: Vec::new(),
            stack_offset: 0,
            variables: Vec::new(),
            variables_offset: 0,
            text: text.lines().map(|s| s.to_string()).collect::<Vec<String>>(),
        }
    }


@@ 60,24 64,49 @@ impl VM {
                }
                0x01 => { // VAR
                    let ptr = self.read() as usize;
                    let value = self.stack[ptr+self.stack_offset].clone();
                    //println!("offset {} ptr {}", offset, ptr);
                    //println!("stack {:?}", self.stack);
                    let value = self.variables[ptr+self.variables_offset].clone();
                    self.stack.push(value);
                }
                // ASSIGN
                0x02 => {
                0x02 => { // ASN
                    let value = self.stack.pop().unwrap();
                    let ptr = self.read();
                    let offset = self.call_stack.last().expect("var call stack last").2;
                    self.stack[ptr as usize + offset] = value.clone();
                    self.variables[ptr as usize + offset] = value.clone();
                    self.stack.push(value);
                }
                0x03 => { // ADD
                0x03 => { // ASNARR
                    let mut list = self.stack.pop().unwrap();
                    let index = self.stack.pop().unwrap();
                    let value = self.stack.pop().unwrap();
                    if let Value::Num(index) = index {
                        if index.fract() != 0.0 {
                            return Err(vm_error!(self, RuntimeErrorKind::WrongType, "Subscript index must be an integer but found {}", index))
                        }
                        let index = index as usize;
                        if let Value::List(ref mut list) = list {
                            let len = list.len();
                            if index > len {
                                return Err(vm_error!(self, RuntimeErrorKind::ArrayOutOfBounds, "List length is {} but found index {}", len, index))
                            }
                            println!("index: {}", index);
                            list[index] = value.clone();
                            self.stack.push(value);
                        } else {
                            return Err(vm_error!(self, RuntimeErrorKind::WrongType, "Tried to subscript non-list type {}", list.type_str()))
                        }
                    } else {
                        return Err(vm_error!(self, RuntimeErrorKind::WrongType, "Tried to use non-integer type {} to subscript list", index.type_str()))
                    }
                }
                0x04 => { // DECL
                    let value = self.stack.pop().unwrap();
                    self.variables.push(value);
                }
                0x05 => { // ADD
                    match (self.stack.pop().unwrap(), self.stack.pop().unwrap()) {
                        (Num(v1), Num(v2)) => self.stack.push(Num(v1 + v2)),
                        (Str(v1), Str(v2)) => {
                            self.stack.push(Str(v1 + &v2));
                            self.stack.push(Str(v1.clone() + &v2));
                        },
                        (Bool(_v1), Bool(_v2)) => {
                            return Err(vm_error!(self, RuntimeErrorKind::WrongType, "Cannot add booleans"))


@@ 87,7 116,7 @@ impl VM {
                        }
                    }
                }
                0x04 => { // SUB
                0x06 => { // SUB
                    match (self.stack.pop().unwrap(), self.stack.pop().unwrap()) {
                        (Num(v1), Num(v2)) => self.stack.push(Num(v1 - v2)),
                        (Str(_v1), Str(_v2)) => {


@@ 101,7 130,7 @@ impl VM {
                        }
                    }
                }
                0x05 => { // MUL
                0x07 => { // MUL
                    match (self.stack.pop().unwrap(), self.stack.pop().unwrap()) {
                        (Num(v1), Num(v2)) => self.stack.push(Num(v1 * v2)),
                        (Str(v1), Num(v2)) => {


@@ 122,7 151,7 @@ impl VM {
                        }
                    }
                }
                0x06 => { // DIV
                0x08 => { // DIV
                    match (self.stack.pop().unwrap(), self.stack.pop().unwrap()) {
                        (Num(v1), Num(v2)) => self.stack.push(Num(v1 / v2)),
                        (Str(_v1), Str(_v2)) => {


@@ 136,7 165,7 @@ impl VM {
                        }
                    }
                }
                0x07 => { // MOD
                0x09 => { // MOD
                    match (self.stack.pop().unwrap(), self.stack.pop().unwrap()) {
                        (Num(v1), Num(v2)) => self.stack.push(Num(v1 % v2)),
                        (Str(_v1), Str(_v2)) => {


@@ 150,7 179,7 @@ impl VM {
                        }
                    }
                }
                0x08 => { // BITAND
                0x0A => { // BITAND
                    match (self.stack.pop().unwrap(), self.stack.pop().unwrap()) {
                        (Num(v1), Num(v2)) => {
                            if v1.fract() != 0.0 {


@@ 172,7 201,7 @@ impl VM {
                        }
                    }
                }
                0x09 => { // BITXOR
                0x0B => { // BITXOR
                    match (self.stack.pop().unwrap(), self.stack.pop().unwrap()) {
                        (Num(v1), Num(v2)) => {
                            if v1.fract() != 0.0 {


@@ 194,7 223,7 @@ impl VM {
                        }
                    }
                }
                0x0A => { // BITOR
                0x0C => { // BITOR
                    match (self.stack.pop().unwrap(), self.stack.pop().unwrap()) {
                        (Num(v1), Num(v2)) => {
                            if v1.fract() != 0.0 {


@@ 217,19 246,19 @@ impl VM {
                    }
                }
                // EQ
                0x0b => vm_boolean_equality!(self, ==),
                0x0D => vm_boolean_equality!(self, ==),
                // NE
                0x0C => vm_boolean_equality!(self, !=),
                0x0E => vm_boolean_equality!(self, !=),
                // GR
                0x0D => vm_boolean_comparison!(self, >),
                0x0F => vm_boolean_comparison!(self, >),
                // GE
                0x0E => vm_boolean_comparison!(self, >=),
                0x10 => vm_boolean_comparison!(self, >=),
                // LS
                0x0F => vm_boolean_comparison!(self, <),
                0x11 => vm_boolean_comparison!(self, <),
                // LE
                0x10 => vm_boolean_comparison!(self, <=),
                0x12 => vm_boolean_comparison!(self, <=),
                // OR
                0x11 => match (self.stack.pop().unwrap(), self.stack.pop().unwrap()) {
                0x13 => 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"))
                    }


@@ 244,7 273,7 @@ impl VM {
                    }
                }
                // AND
                0x12 => match (self.stack.pop().unwrap(), self.stack.pop().unwrap()) {
                0x14 => 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"))
                    }


@@ 259,7 288,7 @@ impl VM {
                    }
                }
                // NOT
                0x13 => match self.stack.pop().unwrap() {
                0x15 => 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"))


@@ 276,7 305,7 @@ impl VM {
                    }
                }
                // NEG
                0x14 => match self.stack.pop().unwrap() {
                0x16 => match self.stack.pop().unwrap() {
                    Null => { return Err(vm_error!(self, RuntimeErrorKind::WrongType, "Tried to perform \"-\" on non-number value null")) }
                    Num(v1) => self.stack.push(Num(-v1)),
                    Str(_v1) => {


@@ 293,17 322,17 @@ impl VM {
                    }
                }
                // JMP
                0x15 => {
                0x17 => {
                    let loc = self.read_u16();
                    self.ip += loc as usize;
                }
                // JMP_UP
                0x16 => {
                0x18 => {
                    let loc = self.read_u16();
                    self.ip -= loc as usize;
                }
                // JNE
                0x17 => {
                0x19 => {
                    let condition = self.stack.pop().unwrap();
                    if let Value::Bool(condition) = condition {
                        if !condition {


@@ 318,15 347,15 @@ impl VM {
                }

                // CALL
                0x18 => {
                0x1A => {
                    let num_args = self.read();
                    let function = self.stack.pop().expect("Stack was empty in call");
                    if let Value::Fun(function) = function {
                        if num_args as usize != function.arity {
                            return Err(vm_error!(self, RuntimeErrorKind::IncorrectArity, "Function has {} arguments, {} provided", function.arity, num_args))
                        }
                        self.stack_offset = self.stack.len() - num_args as usize;
                        self.call_stack.push((self.unit_ptr, self.ip, self.stack_offset));
                        self.variables_offset = self.stack.len() - num_args as usize;
                        self.call_stack.push((self.unit_ptr, self.ip, self.variables_offset));
                        self.stack.insert(self.stack.len()-num_args as usize, Value::Fun(function));
                        self.ip = 0;
                        self.unit_ptr = function.unit_ptr as usize;


@@ 335,11 364,11 @@ impl VM {
                    }
                }
                // RET
                0x19 => {
                    let (unit_ptr, ip, stack_offset) = self.call_stack.pop().expect("Call stack empty on RET");
                0x1B => {
                    let (unit_ptr, ip, variables_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.stack = self.stack[..variables_offset].to_vec();
                    self.variables_offset = self.call_stack.last().expect("call stack empty").2;
                    self.unit_ptr = unit_ptr;
                    self.ip = ip;
                    // returned to code


@@ 347,13 376,13 @@ impl VM {
                }

                // LIST
                0x1A => {
                0x1C => {
                    let len = self.read();
                    let list = self.stack.drain(self.stack.len()-len as usize..).collect();
                    self.stack.push(Value::List(list));
                }
                // SCR
                0x1B => {
                0x1D => {
                    let index = self.stack.pop().expect("stack empty on subscript index");
                    let list = self.stack.pop().expect("stack empty on subscript list");
                    if let Value::Num(index) = index {


@@ 430,7 459,7 @@ impl VM {

#[derive(Debug, Clone)]
pub enum Value {
    Null, Num(f32), Str(String), Bool(bool), List(Vec<Value>), Fun(Function)
    Null, Num(f32), Str(String), Bool(bool), List(Vec<Value>), Fun(Function),
}

impl Value {


@@ 456,7 485,7 @@ impl ToString for Value {
            List(v) => {
                let mut output = "".to_string();
                output += "[";
                for value in v {
                for value in <Vec<Value>>::clone(&v).into_iter() {
                    output += &value.to_string();
                    output += ",";
                }

M kabel/tmp.kab => kabel/tmp.kab +5 -1
@@ 1,2 1,6 @@
// put [3, 2] on stack
var i = [3, 2];
i[0] = 3;
// get reference to i
// set index 0 from i to 3
i[0] = 1;
print i;