From 5d800d4baddb81e5d0e6f6a3eacc34377ee819a0 Mon Sep 17 00:00:00 2001 From: ghostly_zsh Date: Thu, 15 Aug 2024 21:04:50 -0500 Subject: [PATCH] break and continue added, but they dont clean up the stack --- kabel/opcodes.txt | 2 +- kabel/src/codegen.rs | 40 +++++++++++++++++++++------------------- kabel/src/debug.rs | 21 ++++++++++++++++++--- kabel/src/macros.rs | 3 ++- kabel/src/main.rs | 7 +++++-- kabel/src/vm.rs | 6 +++++- 6 files changed, 52 insertions(+), 27 deletions(-) diff --git a/kabel/opcodes.txt b/kabel/opcodes.txt index dfaaee713d652403f802cb97dfd46dac6fbfa262..d952fc063908521b0c723203c13ec7723613731e 100644 --- a/kabel/opcodes.txt +++ b/kabel/opcodes.txt @@ -26,5 +26,5 @@ JMP LOC ; 0x15 JMP_UP LOC ; 0x16 JNE ELSE ; 0x17 -POP ; 0xFD +POP COUNT ; 0xFD PRINT ; 0xFE diff --git a/kabel/src/codegen.rs b/kabel/src/codegen.rs index 222dc7bb633041e6601d5d2534ae1fba75d25618..72858baba94124d2ee0b8490370c15f78509b3b1 100644 --- a/kabel/src/codegen.rs +++ b/kabel/src/codegen.rs @@ -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) { @@ -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; diff --git a/kabel/src/debug.rs b/kabel/src/debug.rs index 481ef9bdb1117bcb3f84aa1e711f0fea611137bd..35da65dc7967b82a094a8469ed24962fdff73ede 100644 --- a/kabel/src/debug.rs +++ b/kabel/src/debug.rs @@ -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; diff --git a/kabel/src/macros.rs b/kabel/src/macros.rs index 16313977013cc14304e052bb7e9e3168ee11d381..6d8d0e859f4acae409879511bf22fe08d2d42cc7 100644 --- a/kabel/src/macros.rs +++ b/kabel/src/macros.rs @@ -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)), diff --git a/kabel/src/main.rs b/kabel/src/main.rs index ca5ecc15529cee374297d9d509a8942d959cd00b..91875e5fb693a87f88367d8a78c240fc682c0ca9 100644 --- a/kabel/src/main.rs +++ b/kabel/src/main.rs @@ -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); } diff --git a/kabel/src/vm.rs b/kabel/src/vm.rs index 6537a9c815e292e47094fb9e787b564e3ba84c93..5c4a03473cb295fac085beebb80c81d680589b1d 100644 --- a/kabel/src/vm.rs +++ b/kabel/src/vm.rs @@ -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();