~starkingdoms/starkingdoms

3cad7d73f8ce1baf291a334628fb96a93c5fafe6 — ghostly_zsh 1 year, 3 months ago 0c7d4d3
list initialization and subscripting
M kabel/opcodes.txt => kabel/opcodes.txt +3 -0
@@ 29,5 29,8 @@ JNE ELSE        ; 0x17
CALL NUMARGS    ; 0x18
RET             ; 0x19

LIST LEN        ; 0x1A
SCR             ; 0x1B

POP COUNT       ; 0xFD
PRINT           ; 0xFE

M kabel/src/codegen.rs => kabel/src/codegen.rs +25 -17
@@ 62,6 62,9 @@ impl Codegen {
            Assign(ref name, ref expr) => {
                self.visit_assign(&ast, name.clone(), *expr.clone());
            }
            Subscript(ref left, ref right) => {
                self.visit_subscript(&ast, *left.clone(), *right.clone());
            }
            Binary(left, oper, right) => {
                self.visit_binary(*left, oper, *right);
            }


@@ 143,23 146,6 @@ 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 pop_count = 0;
        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);
        } else {


@@ 462,6 448,16 @@ impl Codegen {
            self.vm.units[self.vm.unit_ptr].lines.last_mut().unwrap().1 += 1;
        }
    }
    pub fn visit_subscript(&mut self, ast: &AST, left: AST, right: AST) {
        self.visit(left);
        self.visit(right);
        self.vm.units[self.vm.unit_ptr].code.push(OpCode::SCR.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;
        }
    }
    pub fn visit_binary(&mut self, left: AST, oper: BinOp, right: AST) {
        use crate::ast::BinOp::*;
        codegen_binary!(self, left, right, oper, Add, ADD, Sub, SUB, Mul, MUL,


@@ 507,6 503,18 @@ impl Codegen {
                    self.vm.units[self.vm.unit_ptr].lines.last_mut().unwrap().1 += 2;
                }
            }
            Lit::Array(exprs) => {
                for expr in &exprs {
                    self.visit(expr.clone());
                }
                self.vm.units[self.vm.unit_ptr].code.push(OpCode::LIST.into());
                self.vm.units[self.vm.unit_ptr].code.push(exprs.len() as u8);
                if self.vm.units[self.vm.unit_ptr].lines.len() == 0 || 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;
                }
            }
            Lit::Ident(_name) => {
                self.vm.units[self.vm.unit_ptr].code.push(OpCode::VAR.into());
                #[allow(irrefutable_let_patterns)]

M kabel/src/debug.rs => kabel/src/debug.rs +17 -1
@@ 299,7 299,23 @@ pub fn debug_bytecode(vm: &VM) -> String {
                output += &vm.ip.to_string();
                output += " ";
                output += &vm.find_line().to_string();
                output += " RET ";
                output += " RET";
                output += "\n";
            }
            LIST => {
                output += &vm.ip.to_string();
                output += " ";
                output += &vm.find_line().to_string();
                output += " LIST ";
                vm.ip += 1;
                output += &(vm.units[vm.unit_ptr].code[vm.ip]).to_string();
                output += "\n";
            }
            SCR => {
                output += &vm.ip.to_string();
                output += " ";
                output += &vm.find_line().to_string();
                output += " SCR";
                output += "\n";
            }
            POP => {

M kabel/src/opcodes.rs => kabel/src/opcodes.rs +9 -0
@@ 33,6 33,9 @@ pub enum OpCode {
    CALL,
    RET,

    LIST,
    SCR,

    POP,
    PRINT,
    ERR,


@@ 73,6 76,9 @@ impl From<OpCode> for u8 {
            CALL    => 0x18,
            RET     => 0x19,

            LIST    => 0x1A,
            SCR     => 0x1B,

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


@@ 113,6 119,9 @@ impl From<u8> for OpCode {
            0x18 => CALL,
            0x19 => RET,

            0x1A => LIST,
            0x1B => SCR,

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

M kabel/src/runtime_error.rs => kabel/src/runtime_error.rs +3 -0
@@ 43,6 43,7 @@ pub enum RuntimeErrorKind {
    MismatchedTypes,
    WrongType,
    IncorrectArity,
    ArrayOutOfBounds,
}

impl std::fmt::Display for RuntimeErrorKind {


@@ 52,6 53,7 @@ impl std::fmt::Display for RuntimeErrorKind {
            MismatchedTypes => f.write_str("Mismatched types"),
            WrongType => f.write_str("Wrong type"),
            IncorrectArity => f.write_str("Incorrect arity"),
            ArrayOutOfBounds => f.write_str("Array out of bounds"),
        }
    }
}


@@ 63,6 65,7 @@ impl From<RuntimeErrorKind> for usize {
            MismatchedTypes => 0x00,
            WrongType => 0x01,
            IncorrectArity => 0x02,
            ArrayOutOfBounds => 0x03,
        }
    }
}

M kabel/src/vm.rs => kabel/src/vm.rs +67 -3
@@ 270,6 270,9 @@ impl VM {
                        return Err(vm_error!(self, RuntimeErrorKind::WrongType, "Tried to perform \"!\" on non-boolean string"))
                    }
                    Bool(v1) => self.stack.push(Bool(!v1)),
                    List(_v1) => {
                        return Err(vm_error!(self, RuntimeErrorKind::WrongType, "Tried to perform \"!\" on non-boolean list"))
                    }
                    Fun(_v1) => {
                        return Err(vm_error!(self, RuntimeErrorKind::WrongType, "Tried to perform \"!\" on non-boolean function"))
                    }


@@ 284,6 287,9 @@ impl VM {
                    Bool(_v1) => {
                        return Err(vm_error!(self, RuntimeErrorKind::WrongType, "Tried to perform \"-\" on non-number boolean"))
                    }
                    List(_v1) => {
                        return Err(vm_error!(self, RuntimeErrorKind::WrongType, "Tried to perform \"!\" on non-number list"))
                    }
                    Fun(_v1) => {
                        return Err(vm_error!(self, RuntimeErrorKind::WrongType, "Tried to perform \"-\" on non-number function"))
                    }


@@ 348,6 354,33 @@ impl VM {
                    self.stack_ptr -= 1;
                    self.stack.push(ret);
                }
                // LIST
                0x1A => {
                    let len = self.read();
                    let list = self.stack.drain(self.stack.len()-len as usize..).collect();
                    self.stack.push(Value::List(list));
                }
                // SCR
                0x1B => {
                    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 {
                        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(list) = list {
                            if index > list.len() {
                                return Err(vm_error!(self, RuntimeErrorKind::ArrayOutOfBounds, "List length is {} but found index {}", list.len(), index))
                            }
                            self.stack.push(list[index].clone());
                        } 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()))
                    }
                }

                0xFD => { // POP
                    let times = self.read();


@@ 357,13 390,21 @@ impl VM {
                }
                0xFE => { // PRINT
                    let value = self.stack.pop().unwrap();
                    match value {
                    /*match value {
                        Null => *output += "null",
                        Num(v) => *output += &v.to_string(),
                        Str(v) => *output += &v,
                        Bool(v) => *output += &v.to_string(),
                        List(v) => {
                            *output += "[";
                            for value in v {
                                *output += &format!("", value);
                            }
                            *output += "[";
                        }
                        Fun(v) => *output += &format!("<function {}>", v.unit_ptr),
                    }
                    }*/
                    *output += &value.to_string();
                    *output += "\n";
                }
                _ => {}


@@ 398,7 439,7 @@ impl VM {

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

impl Value {


@@ 408,10 449,33 @@ impl Value {
            Value::Num(_) => "number".to_string(),
            Value::Str(_) => "string".to_string(),
            Value::Bool(_) => "bool".to_string(),
            Value::List(_) => "list".to_string(),
            Value::Fun(_) => "function".to_string(),
        }
    }
}
impl ToString for Value {
    fn to_string(&self) -> String {
        use Value::*;
        match self {
            Null => "null".to_string(),
            Num(v) => v.to_string(),
            Str(v) => v.to_string(),
            Bool(v) => v.to_string(),
            List(v) => {
                let mut output = "".to_string();
                output += "[";
                for value in v {
                    output += &value.to_string();
                    output += ",";
                }
                output += "]";
                output
            }
            Fun(v) => format!("<function {}>", v.unit_ptr),
        }
    }
}

#[derive(Debug, Clone, Copy)]
pub struct Function {

M kabel/tmp.kab => kabel/tmp.kab +7 -9
@@ 1,10 1,8 @@
function fib(x) {
    if(x == 0) {
        return 0;
    }
    if(x == 1 || x == 2) {
        return 1;
    }
    return fib(x-1) + fib(x-2);
function foo(bar) {
    bar();
}
print fib(35);
function bar() {
    print 3;
}

foo(bar);