~starkingdoms/starkingdoms

426c4c005ea227b6953945c8bacb92575f5e392d — ghostly_zsh 1 year, 4 months ago dda08ce
basic break and continue but it doesn't quite work
3 files changed, 50 insertions(+), 3 deletions(-)

M kabel/src/codegen.rs
M kabel/src/main.rs
M kabel/src/name_resolution.rs
M kabel/src/codegen.rs => kabel/src/codegen.rs +46 -0
@@ 3,6 3,8 @@ use crate::{ast::{ASTType, BinOp, Lit, Name, UnOp, AST}, codegen_binary, codegen
pub struct Codegen {
    pub vm: VM,
    pub scopes: Vec<usize>, // number of variables declared in the scope
    break_stack: Vec<Vec<usize>>,
    continue_stack: Vec<Vec<usize>>,
}

impl Codegen {


@@ 11,6 13,8 @@ impl Codegen {
            vm: VM::new(Vec::new(), Vec::new(),
                Vec::new(), text),
            scopes: vec![0],
            break_stack: Vec::new(),
            continue_stack: Vec::new(),
        }
    }
    pub fn visit(&mut self, ast: AST) {


@@ 24,6 28,12 @@ impl Codegen {
            While(condition, block) => {
                self.visit_while(*condition, *block);
            }
            Break => {
                self.visit_break(&ast);
            }
            Continue => {
                self.visit_continue(&ast);
            }
            If(condition, block, else_expr) => {
                self.visit_if(*condition, *block, *else_expr);
            }


@@ 56,6 66,9 @@ impl Codegen {
        }
    }
    pub fn visit_while(&mut self, condition: AST, block: AST) {
        self.break_stack.push(Vec::new());
        self.continue_stack.push(Vec::new());

        let end_jmp = self.vm.chunk.len();
        self.visit(condition.clone());
        self.vm.chunk.push(OpCode::JNE.into());


@@ 79,6 92,39 @@ impl Codegen {
            self.vm.lines.last_mut().unwrap().1 += 3;
        }
        self.patch_jump(start_jmp_loc);

        let breaks = self.break_stack.pop().expect("break stack empty on pop");
        for loc in breaks {
            self.patch_jump(loc);
        }
        let continues = self.continue_stack.pop().expect("continue stack empty on pop");
        for loc in continues {
            let jump = loc - end_jmp - 2;
            self.vm.chunk[loc] = ((jump >> 8) & 0xFF) as u8;
            self.vm.chunk[loc + 1] = (jump & 0xFF) as u8;
        }
    }
    pub fn visit_break(&mut self, ast: &AST) {
        self.vm.chunk.push(OpCode::JMP.into());
        self.vm.chunk.push(0xFF);
        self.vm.chunk.push(0xFF);
        if self.vm.lines.last().unwrap().0 != ast.end_line {
            self.vm.lines.push((ast.end_line, 3));
        } else {
            self.vm.lines.last_mut().unwrap().1 += 3;
        }
        self.break_stack.last_mut().expect("break not in a loop").push(self.vm.chunk.len()-2);
    }
    pub fn visit_continue(&mut self, ast: &AST) {
        self.vm.chunk.push(OpCode::JMP_UP.into());
        self.vm.chunk.push(0xFF);
        self.vm.chunk.push(0xFF);
        if self.vm.lines.last().unwrap().0 != ast.end_line {
            self.vm.lines.push((ast.end_line, 3));
        } else {
            self.vm.lines.last_mut().unwrap().1 += 3;
        }
        self.continue_stack.last_mut().expect("continue not in a loop").push(self.vm.chunk.len()-2);
    }
    pub fn visit_if(&mut self, condition: AST, block: AST, else_expr: Option<AST>) {
        self.visit(condition.clone());

M kabel/src/main.rs => kabel/src/main.rs +2 -3
@@ 12,10 12,9 @@ fn main() {
    let program =
"
for(var i = 0; i < 5; i++) {
    var j = 0;
    print i;
    print j;
    j++;
    continue;
    print i;
}
".to_string();


M kabel/src/name_resolution.rs => kabel/src/name_resolution.rs +2 -0
@@ 64,6 64,8 @@ impl Resolver {
                let block = self.visit(*block);
                ast_from_ast!(While(Box::new(condition), Box::new(block)), ast, ast)
            }
            Break => { ast_from_ast!(Break, ast, ast) }
            Continue => { ast_from_ast!(Continue, ast, ast) }
            For(expr1, expr2, expr3, block) => {
                let mut n_expr1 = None;
                let mut n_expr2 = None;