~starkingdoms/starkingdoms

c407349bf0c3102b6f292742db23f3e5be1aa696 — ghostly_zsh 1 year, 2 months ago 048af52
move variables to a separate list, assign to array subscript works
M kabel/opcodes.txt => kabel/opcodes.txt +29 -28
@@ 1,37 1,38 @@
LOAD VAL        ; 0x00
VAR STACKPTR    ; 0x01
ASN PTR         ; 0x02
ASNARR          ; 0x03
DECL            ; 0x04
REF PTR         ; 0x02
ASN PTR         ; 0x03
ASNARR          ; 0x04
DECL            ; 0x05

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
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 LOC         ; 0x17
JMP_UP LOC      ; 0x18
JNE ELSE        ; 0x19
JMP LOC         ; 0x18
JMP_UP LOC      ; 0x19
JNE ELSE        ; 0x1A

CALL ARITY      ; 0x1A
RET             ; 0x1B
CALL ARITY      ; 0x1B
RET             ; 0x1C

LIST LEN        ; 0x1C
SCR             ; 0x1D
LIST LEN        ; 0x1D
SCR             ; 0x1E

POP COUNT       ; 0xFD
PRINT           ; 0xFE

M kabel/src/codegen.rs => kabel/src/codegen.rs +14 -1
@@ 456,7 456,20 @@ impl Codegen {
            }
            LhsAssignType::Subscript(name, index) => {
                self.visit(*index);
                self.visit(*name);

                #[allow(irrefutable_let_patterns)]
                if let Extension::Resolution(_scope, ptr) = name.extensions[0] {
                    self.vm.units[self.vm.unit_ptr].code.push(OpCode::REF.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;
                    }
                } else {
                    panic!("Subscript assignment should always have a Resolution");
                }

                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 {

M kabel/src/debug.rs => kabel/src/debug.rs +9 -0
@@ 261,6 261,15 @@ pub fn debug_bytecode(vm: &VM) -> String {
                output += &vm.units[vm.unit_ptr].code[vm.ip].to_string();
                output += "\n";
            }
            REF => {
                output += &vm.ip.to_string();
                output += " ";
                output += &vm.find_line().to_string();
                output += " REF ";
                vm.ip += 1;
                output += &vm.units[vm.unit_ptr].code[vm.ip].to_string();
                output += "\n";
            }
            ASN => { 
                output += &vm.ip.to_string();
                output += " ";

M kabel/src/extension.rs => kabel/src/extension.rs +1 -1
@@ 1,4 1,4 @@
#[derive(Debug, Clone)]
pub enum Extension {
    Resolution(usize, usize), // scope, pointer to local table
    Resolution(usize, usize), // scope, pointer to variable
}

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


@@ 49,39 50,40 @@ impl From<OpCode> for u8 {
        match value {
            LOAD    => 0x00,
            VAR     => 0x01,
            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,
            REF     => 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     => 0x1E,

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


@@ 94,39 96,40 @@ impl From<u8> for OpCode {
        use OpCode::*; match value {
            0x00 => LOAD,
            0x01 => VAR,
            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,
            0x02 => REF,
            0x03 => ASN,
            0x04 => ASNARR,
            0x05 => DECL,

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

            0x16 => NOT,
            0x17 => NEG,

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

            0x1B => CALL,
            0x1c => RET,

            0x1D => LIST,
            0x1E => SCR,

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

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

use std::rc::Rc;

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



@@ 59,6 57,7 @@ impl VM {
            match self.read() {
                0x00 => { // LOAD
                    let byte = self.read() as usize;
                    println!("ip: {}", self.ip);
                    let value = self.units[self.unit_ptr].pool[byte].clone();
                    self.stack.push(value);
                }


@@ 67,15 66,19 @@ impl VM {
                    let value = self.variables[ptr+self.variables_offset].clone();
                    self.stack.push(value);
                }
                0x02 => { // ASN
                0x02 => { // REF
                    let ptr = self.read() as usize;
                    self.stack.push(Ref(ptr));
                }
                0x03 => { // ASN
                    let value = self.stack.pop().unwrap();
                    let ptr = self.read();
                    let offset = self.call_stack.last().expect("var call stack last").2;
                    self.variables[ptr as usize + offset] = value.clone();
                    self.stack.push(value);
                }
                0x03 => { // ASNARR
                    let mut list = self.stack.pop().unwrap();
                0x04 => { // ASNARR
                    let listref = self.stack.pop().unwrap();
                    let index = self.stack.pop().unwrap();
                    let value = self.stack.pop().unwrap();
                    if let Value::Num(index) = index {


@@ 83,26 86,32 @@ impl VM {
                            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))
                        if let Value::Ref(listref) = listref {
                            let list = &mut self.variables[listref];
                            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 {
                                let type_str = list.type_str();
                                return Err(vm_error!(self, RuntimeErrorKind::WrongType, "Tried to subscript non-list type {}", type_str))
                            }
                            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()))
                            panic!("Something went wrong in kabel, listref was not a Ref");
                        }
                    } else {
                        return Err(vm_error!(self, RuntimeErrorKind::WrongType, "Tried to use non-integer type {} to subscript list", index.type_str()))
                    }
                }
                0x04 => { // DECL
                0x05 => { // DECL
                    let value = self.stack.pop().unwrap();
                    self.variables.push(value);
                }
                0x05 => { // ADD
                0x06 => { // ADD
                    match (self.stack.pop().unwrap(), self.stack.pop().unwrap()) {
                        (Num(v1), Num(v2)) => self.stack.push(Num(v1 + v2)),
                        (Str(v1), Str(v2)) => {


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


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


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


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


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


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


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


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


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


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


@@ 303,9 312,12 @@ impl VM {
                    Fun(_v1) => {
                        return Err(vm_error!(self, RuntimeErrorKind::WrongType, "Tried to perform \"!\" on non-boolean function"))
                    }
                    Ref(_v1) => {
                        return Err(vm_error!(self, RuntimeErrorKind::WrongType, "Tried to perform \"!\" on non-boolean reference"))
                    }
                }
                // NEG
                0x16 => match self.stack.pop().unwrap() {
                0x17 => 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) => {


@@ 320,19 332,22 @@ impl VM {
                    Fun(_v1) => {
                        return Err(vm_error!(self, RuntimeErrorKind::WrongType, "Tried to perform \"-\" on non-number function"))
                    }
                    Ref(_v1) => {
                        return Err(vm_error!(self, RuntimeErrorKind::WrongType, "Tried to perform \"-\" on non-number reference"))
                    }
                }
                // JMP
                0x17 => {
                0x18 => {
                    let loc = self.read_u16();
                    self.ip += loc as usize;
                }
                // JMP_UP
                0x18 => {
                0x19 => {
                    let loc = self.read_u16();
                    self.ip -= loc as usize;
                }
                // JNE
                0x19 => {
                0x1A => {
                    let condition = self.stack.pop().unwrap();
                    if let Value::Bool(condition) = condition {
                        if !condition {


@@ 347,7 362,7 @@ impl VM {
                }

                // CALL
                0x1A => {
                0x1B => {
                    let num_args = self.read();
                    let function = self.stack.pop().expect("Stack was empty in call");
                    if let Value::Fun(function) = function {


@@ 364,7 379,7 @@ impl VM {
                    }
                }
                // RET
                0x1B => {
                0x1C => {
                    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[..variables_offset].to_vec();


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

                // LIST
                0x1C => {
                0x1D => {
                    let len = self.read();
                    let list = self.stack.drain(self.stack.len()-len as usize..).collect();
                    self.stack.push(Value::List(list));
                }
                // SCR
                0x1D => {
                0x1E => {
                    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 {


@@ 460,6 475,7 @@ impl VM {
#[derive(Debug, Clone)]
pub enum Value {
    Null, Num(f32), Str(String), Bool(bool), List(Vec<Value>), Fun(Function),
    Ref(usize),
}

impl Value {


@@ 471,6 487,7 @@ impl Value {
            Value::Bool(_) => "bool".to_string(),
            Value::List(_) => "list".to_string(),
            Value::Fun(_) => "function".to_string(),
            Value::Ref(_) => "reference".to_string(),
        }
    }
}


@@ 493,6 510,7 @@ impl ToString for Value {
                output
            }
            Fun(v) => format!("<function {}>", v.unit_ptr),
            Ref(v) => format!("<reference {}>", v)
        }
    }
}

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