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();