~starkingdoms/starkingdoms

5d800d4baddb81e5d0e6f6a3eacc34377ee819a0 — ghostly_zsh 1 year, 4 months ago 426c4c0
break and continue added, but they dont clean up the stack
M kabel/opcodes.txt => kabel/opcodes.txt +1 -1
@@ 26,5 26,5 @@ JMP LOC         ; 0x15
JMP_UP LOC      ; 0x16
JNE ELSE        ; 0x17

POP             ; 0xFD
POP COUNT       ; 0xFD
PRINT           ; 0xFE

M kabel/src/codegen.rs => kabel/src/codegen.rs +21 -19
@@ 91,15 91,17 @@ impl Codegen {
        } else {
            self.vm.lines.last_mut().unwrap().1 += 3;
        }
        self.patch_jump(start_jmp_loc);
        self.patch_jump(start_jmp_loc, 0);

        let breaks = self.break_stack.pop().expect("break stack empty on pop");
        for loc in breaks {
            self.patch_jump(loc);
            println!("{:?}", self.scopes);
            self.patch_jump(loc, 0);
        }
        let continues = self.continue_stack.pop().expect("continue stack empty on pop");
        for loc in continues {
            let jump = loc - end_jmp - 2;
            println!("{:?}", self.scopes);
            let jump = loc - end_jmp + 2;
            self.vm.chunk[loc] = ((jump >> 8) & 0xFF) as u8;
            self.vm.chunk[loc + 1] = (jump & 0xFF) as u8;
        }


@@ 151,9 153,9 @@ impl Codegen {
                        self.vm.lines.last_mut().unwrap().1 += 3;
                    }
                    
                    self.patch_jump(start_jmp_loc);
                    self.patch_jump(start_jmp_loc, 0);
                    self.visit(ast);
                    self.patch_jump(end_jmp_loc);
                    self.patch_jump(end_jmp_loc, 0);
                }
                ASTType::Block(_) => {



@@ 167,14 169,14 @@ impl Codegen {
                    }
                    
                    let end_jmp_loc = self.vm.chunk.len()-2;
                    self.patch_jump(start_jmp_loc); // jmp to else
                    self.patch_jump(start_jmp_loc, 0); // jmp to else
                    self.visit(ast);
                    self.patch_jump(end_jmp_loc); // jmp to after else
                    self.patch_jump(end_jmp_loc, 0); // jmp to after else
                }
                _ => { println!("unimplemented"); }
            }
        } else {
            self.patch_jump(start_jmp_loc);
            self.patch_jump(start_jmp_loc, 0);
        }
    }
    pub fn visit_block(&mut self, ast: &AST, stmts: Vec<AST>) {


@@ 183,13 185,12 @@ impl Codegen {
            self.visit(stmt);
        }
        let variables = self.scopes.pop().expect("popped scope in block");
        for _ in 0..variables {
            self.vm.chunk.push(OpCode::POP.into());
            if self.vm.lines.last().unwrap().0 != ast.end_line {
                self.vm.lines.push((ast.end_line, 1));
            } else {
                self.vm.lines.last_mut().unwrap().1 += 1;
            }
        self.vm.chunk.push(OpCode::POP.into());
        self.vm.chunk.push(variables as u8);
        if self.vm.lines.last().unwrap().0 != ast.end_line {
            self.vm.lines.push((ast.end_line, 2));
        } else {
            self.vm.lines.last_mut().unwrap().1 += 2;
        }
    }
    pub fn visit_decl(&mut self, ast: &AST, _name: Name, expr: AST) {


@@ 202,10 203,11 @@ impl Codegen {
    pub fn visit_expr_stmt(&mut self, ast: &AST, expr: AST) {
        self.visit(expr);
        self.vm.chunk.push(OpCode::POP.into());
        self.vm.chunk.push(0x01);
        if self.vm.lines.last().unwrap().0 != ast.end_line {
            self.vm.lines.push((ast.end_line, 1));
            self.vm.lines.push((ast.end_line, 2));
        } else {
            self.vm.lines.last_mut().unwrap().1 += 1;
            self.vm.lines.last_mut().unwrap().1 += 2;
        }
    }
    // REMOVE LATER


@@ 298,8 300,8 @@ impl Codegen {
            _ => {}
        }
    }
    pub fn patch_jump(&mut self, loc: usize) {
        let jump = self.vm.chunk.len() - loc - 2;
    pub fn patch_jump(&mut self, loc: usize, offset: i32) {
        let jump = ((self.vm.chunk.len() - loc - 2) as i32) + offset;

        self.vm.chunk[loc] = ((jump >> 8) & 0xFF) as u8;
        self.vm.chunk[loc + 1] = (jump & 0xFF) as u8;

M kabel/src/debug.rs => kabel/src/debug.rs +18 -3
@@ 73,8 73,14 @@ pub fn debug_ast(ast: AST, level: usize) -> String {
            output += "\n";
            output += &debug_ast(*block, level+1);
        }
        Break => { output += "Break\n"; }
        Continue => { output += "Continue\n"; }
        Break => {
            output += &"| ".repeat(level);
            output += "Break";
        }
        Continue => {
            output += &"| ".repeat(level);
            output += "Continue";
        }
        If(condition, block, else_expr) => {
            output += &"| ".repeat(level);
            output += "If\n";


@@ 209,7 215,7 @@ pub fn debug_bytecode(vm: &VM) -> String {
    while vm.ip < vm.chunk.len() {
        // remove PRINT later
        push_codegen!(vm.chunk[vm.ip].into(), vm, output, ADD, SUB, MUL, DIV, MOD, BITAND,
            BITXOR, BITOR, EQ, NE, GR, GE, LS, LE, OR, AND, NOT, NEG, POP,
            BITXOR, BITOR, EQ, NE, GR, GE, LS, LE, OR, AND, NOT, NEG,
            PRINT, ERR);
        match vm.chunk[vm.ip].into() {
            LOAD => {


@@ 276,6 282,15 @@ pub fn debug_bytecode(vm: &VM) -> String {
                output += &(byte_one | byte_two).to_string();
                output += "\n";
            }
            POP => {
                output += &vm.ip.to_string();
                output += " ";
                output += &vm.find_line().to_string();
                output += " POP ";
                vm.ip += 1;
                output += &vm.chunk[vm.ip].to_string();
                output += "\n";
            }
            _ => {}
        }
        vm.ip += 1;

M kabel/src/macros.rs => kabel/src/macros.rs +2 -1
@@ 226,7 226,8 @@ macro_rules! push_codegen {
#[macro_export]
macro_rules! vm_boolean_binary {
    ($self:expr, $oper:tt) => {
        match ($self.stack.pop().unwrap(), $self.stack.pop().unwrap()) {
        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)),

M kabel/src/main.rs => kabel/src/main.rs +5 -2
@@ 11,10 11,11 @@ fn main() {

    let program =
"
for(var i = 0; i < 5; i++) {
var i = 0;
while(i < 5) {
    print i;
    i += 1;
    continue;
    print i;
}
".to_string();



@@ 63,12 64,14 @@ for(var i = 0; i < 5; i++) {
    let mut vm = codegen.vm;
    output += &debug_bytecode(&vm);
    output += "\n";
    println!("{}", output);

    output += "\n";
    match vm.run(&mut output) {
        Ok(()) => {}
        Err(e) => output += &e.to_string(),
    }
    output += &debug_stack(&vm.stack);

    println!("{}", output);
}

M kabel/src/vm.rs => kabel/src/vm.rs +5 -1
@@ 270,7 270,11 @@ impl VM {
                }

                0xFD => { // POP
                    self.stack.pop().unwrap();
                    let times = self.read();
                    for _ in 0..times {
                        println!("{:?}", self.stack);
                        self.stack.pop().expect(&format!("{}: Unable to pop stack", self.ip));
                    }
                }
                0xFE => { // PRINT
                    let value = self.stack.pop().unwrap();