From 364d4a85a2f9f86d7c719da1b2ee51ca7244e1df Mon Sep 17 00:00:00 2001 From: ghostly_zsh Date: Wed, 21 Aug 2024 10:09:34 -0500 Subject: [PATCH] repo synchronization between computers --- kabel/opcodes.txt | 3 + kabel/src/codegen.rs | 333 +++++++++++++++++++++-------------- kabel/src/debug.rs | 39 ++-- kabel/src/macros.rs | 20 +-- kabel/src/main.rs | 13 +- kabel/src/name_resolution.rs | 39 ++-- kabel/src/opcodes.rs | 9 + kabel/src/parser.rs | 2 +- kabel/src/vm.rs | 137 ++++++++------ kabel/tmp.kab | 6 +- 10 files changed, 377 insertions(+), 224 deletions(-) diff --git a/kabel/opcodes.txt b/kabel/opcodes.txt index d952fc063908521b0c723203c13ec7723613731e..c92a88ba9bd6dbdea1afc2c51fd423938c1a9ca2 100644 --- a/kabel/opcodes.txt +++ b/kabel/opcodes.txt @@ -26,5 +26,8 @@ JMP LOC ; 0x15 JMP_UP LOC ; 0x16 JNE ELSE ; 0x17 +CALL NUMARGS UNIT_PTR ; 0x18 +RET ; 0x19 + POP COUNT ; 0xFD PRINT ; 0xFE diff --git a/kabel/src/codegen.rs b/kabel/src/codegen.rs index 2efdbf6b0a67a58f774c1bdc15d4e5574e55b668..c93294ab343349c63c68b6bed417391184a62c90 100644 --- a/kabel/src/codegen.rs +++ b/kabel/src/codegen.rs @@ -1,4 +1,4 @@ -use crate::{ast::{ASTType, BinOp, Lit, Name, UnOp, AST}, codegen_binary, codegen_unary, extension::Extension, opcodes::OpCode, vm::{Value, VM}}; +use crate::{ast::{ASTType, BinOp, Lit, Name, UnOp, AST}, codegen_binary, codegen_unary, extension::Extension, opcodes::OpCode, vm::{Unit, Value, VM}}; pub struct Codegen { pub vm: VM, @@ -25,6 +25,9 @@ impl Codegen { self.visit(ast); } } + Function(name, args, block) => { + self.visit_function(name, args, *block); + } While(condition, block) => { self.visit_while(*condition, *block); } @@ -65,36 +68,74 @@ impl Codegen { Lit(ref lit) => { self.visit_lit(&ast, lit.clone()); } + Call(ref name, ref args) => { + self.visit_call(&ast, name.clone(), args.clone()); + } _ => {} } } + pub fn visit_function(&mut self, _name: Name, _args: Vec, block: AST) { + let old_unit_ptr = self.vm.unit_ptr; + let old_ip = self.vm.ip; + // create new compilation unit + self.vm.units.push(Unit::new_empty()); + // set unit to write to + self.vm.unit_ptr = self.vm.units.len()-1; + self.vm.ip = 0; + + if let ASTType::Block(ref stmts) = block.ast_type { + self.visit_block(&block, stmts.clone(), ScopeType::Function); + } + match self.vm.units[self.vm.unit_ptr].code.last() { + Some(instr) => { + if *instr != OpCode::RET.into() { + self.vm.units[self.vm.unit_ptr].code.push(OpCode::RET.into()); + if self.vm.units[self.vm.unit_ptr].lines.last().unwrap().0 != block.end_line { + self.vm.units[self.vm.unit_ptr].lines.push((block.end_line, 1)); + } else { + self.vm.units[self.vm.unit_ptr].lines.last_mut().unwrap().1 += 1; + } + } + } + None => { + self.vm.units[self.vm.unit_ptr].code.push(OpCode::RET.into()); + if self.vm.units[self.vm.unit_ptr].lines.last().unwrap().0 != block.end_line { + self.vm.units[self.vm.unit_ptr].lines.push((block.end_line, 1)); + } else { + self.vm.units[self.vm.unit_ptr].lines.last_mut().unwrap().1 += 1; + } + } + }; + self.vm.unit_ptr = old_unit_ptr; + self.vm.ip = old_ip; + } 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(); + let end_jmp = self.vm.units[self.vm.unit_ptr].code.len(); self.visit(condition.clone()); - self.vm.chunk.push(OpCode::JNE.into()); - self.vm.chunk.push(0xFF); // placeholder - self.vm.chunk.push(0xFF); // placeholder - let start_jmp_loc = self.vm.chunk.len()-2; - if self.vm.lines.last().unwrap().0 != condition.end_line { - self.vm.lines.push((condition.end_line, 3)); + self.vm.units[self.vm.unit_ptr].code.push(OpCode::JNE.into()); + self.vm.units[self.vm.unit_ptr].code.push(0xFF); // placeholder + self.vm.units[self.vm.unit_ptr].code.push(0xFF); // placeholder + let start_jmp_loc = self.vm.units[self.vm.unit_ptr].code.len()-2; + if self.vm.units[self.vm.unit_ptr].lines.last().unwrap().0 != condition.end_line { + self.vm.units[self.vm.unit_ptr].lines.push((condition.end_line, 3)); } else { - self.vm.lines.last_mut().unwrap().1 += 3; + self.vm.units[self.vm.unit_ptr].lines.last_mut().unwrap().1 += 3; } if let ASTType::Block(ref stmts) = block.ast_type { self.visit_block(&block, stmts.clone(), ScopeType::Loop); } - self.vm.chunk.push(OpCode::JMP_UP.into()); - let current = self.vm.chunk.len()+2; + self.vm.units[self.vm.unit_ptr].code.push(OpCode::JMP_UP.into()); + let current = self.vm.units[self.vm.unit_ptr].code.len()+2; let current_to_start = current - end_jmp; - self.vm.chunk.push(((current_to_start >> 8) & 0xFF) as u8); - self.vm.chunk.push((current_to_start & 0xFF) as u8); - if self.vm.lines.last().unwrap().0 != block.end_line { - self.vm.lines.push((block.end_line, 3)); + self.vm.units[self.vm.unit_ptr].code.push(((current_to_start >> 8) & 0xFF) as u8); + self.vm.units[self.vm.unit_ptr].code.push((current_to_start & 0xFF) as u8); + if self.vm.units[self.vm.unit_ptr].lines.last().unwrap().0 != block.end_line { + self.vm.units[self.vm.unit_ptr].lines.push((block.end_line, 3)); } else { - self.vm.lines.last_mut().unwrap().1 += 3; + self.vm.units[self.vm.unit_ptr].lines.last_mut().unwrap().1 += 3; } self.patch_jump(start_jmp_loc, 0); @@ -105,8 +146,8 @@ impl Codegen { 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; + self.vm.units[self.vm.unit_ptr].code[loc] = ((jump >> 8) & 0xFF) as u8; + self.vm.units[self.vm.unit_ptr].code[loc + 1] = (jump & 0xFF) as u8; } } pub fn visit_for(&mut self, expr1: Option, expr2: Option, @@ -119,18 +160,18 @@ impl Codegen { if let Some(expr1) = expr1 { self.visit(expr1); } - let end_jmp = self.vm.chunk.len(); + let end_jmp = self.vm.units[self.vm.unit_ptr].code.len(); let mut start_jmp_loc = None; if let Some(expr2) = expr2 { self.visit(expr2.clone()); - self.vm.chunk.push(OpCode::JNE.into()); - self.vm.chunk.push(0xFF); // placeholder - self.vm.chunk.push(0xFF); // placeholder - start_jmp_loc = Some(self.vm.chunk.len()-2); - if self.vm.lines.last().unwrap().0 != expr2.end_line { - self.vm.lines.push((expr2.end_line, 3)); + self.vm.units[self.vm.unit_ptr].code.push(OpCode::JNE.into()); + self.vm.units[self.vm.unit_ptr].code.push(0xFF); // placeholder + self.vm.units[self.vm.unit_ptr].code.push(0xFF); // placeholder + start_jmp_loc = Some(self.vm.units[self.vm.unit_ptr].code.len()-2); + if self.vm.units[self.vm.unit_ptr].lines.last().unwrap().0 != expr2.end_line { + self.vm.units[self.vm.unit_ptr].lines.push((expr2.end_line, 3)); } else { - self.vm.lines.last_mut().unwrap().1 += 3; + self.vm.units[self.vm.unit_ptr].lines.last_mut().unwrap().1 += 3; } } if let ASTType::Block(ref stmts) = block.ast_type { @@ -139,31 +180,31 @@ impl Codegen { 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;*/ + self.vm.units[self.vm.unit_ptr].code[loc] = ((jump >> 8) & 0xFF) as u8; + self.vm.units[self.vm.unit_ptr].code[loc + 1] = (jump & 0xFF) as u8;*/ self.patch_jump(loc, 0); } if let Some(expr3) = expr3 { self.visit(expr3); - self.vm.chunk.push(OpCode::POP.into()); - self.vm.chunk.push(0x01); - if self.vm.lines.last().unwrap().0 != block.end_line { - self.vm.lines.push((block.end_line, 2)); + self.vm.units[self.vm.unit_ptr].code.push(OpCode::POP.into()); + self.vm.units[self.vm.unit_ptr].code.push(0x01); + if self.vm.units[self.vm.unit_ptr].lines.last().unwrap().0 != block.end_line { + self.vm.units[self.vm.unit_ptr].lines.push((block.end_line, 2)); } else { - self.vm.lines.last_mut().unwrap().1 += 2; + self.vm.units[self.vm.unit_ptr].lines.last_mut().unwrap().1 += 2; } } // write instruction to loop - self.vm.chunk.push(OpCode::JMP_UP.into()); - let current = self.vm.chunk.len()+2; + self.vm.units[self.vm.unit_ptr].code.push(OpCode::JMP_UP.into()); + let current = self.vm.units[self.vm.unit_ptr].code.len()+2; let current_to_start = current - end_jmp; - self.vm.chunk.push(((current_to_start >> 8) & 0xFF) as u8); - self.vm.chunk.push((current_to_start & 0xFF) as u8); - if self.vm.lines.last().unwrap().0 != block.end_line { - self.vm.lines.push((block.end_line, 3)); + self.vm.units[self.vm.unit_ptr].code.push(((current_to_start >> 8) & 0xFF) as u8); + self.vm.units[self.vm.unit_ptr].code.push((current_to_start & 0xFF) as u8); + if self.vm.units[self.vm.unit_ptr].lines.last().unwrap().0 != block.end_line { + self.vm.units[self.vm.unit_ptr].lines.push((block.end_line, 3)); } else { - self.vm.lines.last_mut().unwrap().1 += 3; + self.vm.units[self.vm.unit_ptr].lines.last_mut().unwrap().1 += 3; } let breaks = self.break_stack.pop().expect("break stack empty on pop"); @@ -177,12 +218,12 @@ impl Codegen { } let (_scope_type, variables) = self.scopes.pop().expect("popped scope in block"); - self.vm.chunk.push(OpCode::POP.into()); - self.vm.chunk.push(variables as u8); - if self.vm.lines.last().unwrap().0 != block.end_line { - self.vm.lines.push((block.end_line, 2)); + self.vm.units[self.vm.unit_ptr].code.push(OpCode::POP.into()); + self.vm.units[self.vm.unit_ptr].code.push(variables as u8); + if self.vm.units[self.vm.unit_ptr].lines.last().unwrap().0 != block.end_line { + self.vm.units[self.vm.unit_ptr].lines.push((block.end_line, 2)); } else { - self.vm.lines.last_mut().unwrap().1 += 2; + self.vm.units[self.vm.unit_ptr].lines.last_mut().unwrap().1 += 2; } } @@ -196,18 +237,18 @@ impl Codegen { break; } } - self.vm.chunk.push(OpCode::POP.into()); - self.vm.chunk.push(pop_count as u8); + 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); - 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, 5)); + self.vm.units[self.vm.unit_ptr].code.push(OpCode::JMP.into()); + self.vm.units[self.vm.unit_ptr].code.push(0xFF); + self.vm.units[self.vm.unit_ptr].code.push(0xFF); + 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, 5)); } else { - self.vm.lines.last_mut().unwrap().1 += 5; + self.vm.units[self.vm.unit_ptr].lines.last_mut().unwrap().1 += 5; } - self.break_stack.last_mut().expect("break not in a loop").push(self.vm.chunk.len()-2); + self.break_stack.last_mut().expect("break not in a loop").push(self.vm.units[self.vm.unit_ptr].code.len()-2); } // ====================================================================== // CONTINUE IS BROKEN AND HANGS IN FOR LOOPS, FIX LATER @@ -222,29 +263,29 @@ impl Codegen { break; } } - self.vm.chunk.push(OpCode::POP.into()); - self.vm.chunk.push(pop_count as u8); + 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); - 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, 5)); + self.vm.units[self.vm.unit_ptr].code.push(OpCode::JMP.into()); + self.vm.units[self.vm.unit_ptr].code.push(0xFF); + self.vm.units[self.vm.unit_ptr].code.push(0xFF); + 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, 5)); } else { - self.vm.lines.last_mut().unwrap().1 += 5; + self.vm.units[self.vm.unit_ptr].lines.last_mut().unwrap().1 += 5; } - self.continue_stack.last_mut().expect("continue not in a loop").push(self.vm.chunk.len()-2); + self.continue_stack.last_mut().expect("continue not in a loop").push(self.vm.units[self.vm.unit_ptr].code.len()-2); } pub fn visit_if(&mut self, condition: AST, block: AST, else_expr: Option) { self.visit(condition.clone()); - self.vm.chunk.push(OpCode::JNE.into()); - self.vm.chunk.push(0xFF); // placeholder - self.vm.chunk.push(0xFF); // placeholder - let start_jmp_loc = self.vm.chunk.len()-2; - if self.vm.lines.last().unwrap().0 != condition.end_line { - self.vm.lines.push((condition.end_line, 5)); + self.vm.units[self.vm.unit_ptr].code.push(OpCode::JNE.into()); + self.vm.units[self.vm.unit_ptr].code.push(0xFF); // placeholder + self.vm.units[self.vm.unit_ptr].code.push(0xFF); // placeholder + let start_jmp_loc = self.vm.units[self.vm.unit_ptr].code.len()-2; + if self.vm.units[self.vm.unit_ptr].lines.last().unwrap().0 != condition.end_line { + self.vm.units[self.vm.unit_ptr].lines.push((condition.end_line, 5)); } else { - self.vm.lines.last_mut().unwrap().1 += 5; + self.vm.units[self.vm.unit_ptr].lines.last_mut().unwrap().1 += 5; } if let ASTType::Block(ref stmts) = block.ast_type { self.visit_block(&block, stmts.clone(), ScopeType::If); @@ -252,14 +293,14 @@ impl Codegen { if let Some(ast) = else_expr { match ast.ast_type { ASTType::If(_, _, _) => { - self.vm.chunk.push(OpCode::JMP.into()); - self.vm.chunk.push(0xFF); // placeholder - self.vm.chunk.push(0xFF); // placeholder - let end_jmp_loc = self.vm.chunk.len()-2; - if self.vm.lines.last().unwrap().0 != ast.end_line { - self.vm.lines.push((ast.end_line, 3)); + self.vm.units[self.vm.unit_ptr].code.push(OpCode::JMP.into()); + self.vm.units[self.vm.unit_ptr].code.push(0xFF); // placeholder + self.vm.units[self.vm.unit_ptr].code.push(0xFF); // placeholder + let end_jmp_loc = self.vm.units[self.vm.unit_ptr].code.len()-2; + 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, 3)); } else { - self.vm.lines.last_mut().unwrap().1 += 3; + self.vm.units[self.vm.unit_ptr].lines.last_mut().unwrap().1 += 3; } self.patch_jump(start_jmp_loc, 0); @@ -268,16 +309,16 @@ impl Codegen { } ASTType::Block(_) => { - self.vm.chunk.push(OpCode::JMP.into()); - self.vm.chunk.push(0xFF); // placeholder - self.vm.chunk.push(0xFF); // placeholder - if self.vm.lines.last().unwrap().0 != ast.end_line { - self.vm.lines.push((ast.end_line, 3)); + self.vm.units[self.vm.unit_ptr].code.push(OpCode::JMP.into()); + self.vm.units[self.vm.unit_ptr].code.push(0xFF); // placeholder + self.vm.units[self.vm.unit_ptr].code.push(0xFF); // placeholder + 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, 3)); } else { - self.vm.lines.last_mut().unwrap().1 += 3; + self.vm.units[self.vm.unit_ptr].lines.last_mut().unwrap().1 += 3; } - let end_jmp_loc = self.vm.chunk.len()-2; + let end_jmp_loc = self.vm.units[self.vm.unit_ptr].code.len()-2; self.patch_jump(start_jmp_loc, 0); // jmp to else if let ASTType::Block(ref stmts) = ast.ast_type { self.visit_block(&ast, stmts.clone(), ScopeType::If); @@ -296,12 +337,15 @@ impl Codegen { self.visit(stmt); } let (_scope_type, variables) = self.scopes.pop().expect("popped scope in block"); - 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; + self.vm.units[self.vm.unit_ptr].code.push(OpCode::POP.into()); + self.vm.units[self.vm.unit_ptr].code.push(variables as u8); + match self.vm.units[self.vm.unit_ptr].lines.last() { + Some(last) => if last.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; + } + None => self.vm.units[self.vm.unit_ptr].lines.push((ast.end_line, 2)) } } pub fn visit_decl(&mut self, ast: &AST, _name: Name, expr: AST) { @@ -313,41 +357,41 @@ 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, 2)); + self.vm.units[self.vm.unit_ptr].code.push(OpCode::POP.into()); + self.vm.units[self.vm.unit_ptr].code.push(0x01); + 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.lines.last_mut().unwrap().1 += 2; + self.vm.units[self.vm.unit_ptr].lines.last_mut().unwrap().1 += 2; } } // REMOVE LATER pub fn visit_print(&mut self, ast: &AST, expr: AST) { self.visit(expr); - self.vm.chunk.push(OpCode::PRINT.into()); - if self.vm.lines.last().unwrap().0 != ast.end_line { - self.vm.lines.push((ast.end_line, 1)); + self.vm.units[self.vm.unit_ptr].code.push(OpCode::PRINT.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.lines.last_mut().unwrap().1 += 1; + self.vm.units[self.vm.unit_ptr].lines.last_mut().unwrap().1 += 1; } } pub fn visit_assign(&mut self, ast: &AST, _name: Name, expr: AST) { self.visit(expr); // pop stack to get value. then find variable in stack. set variable to value. - self.vm.chunk.push(OpCode::ASSIGN.into()); + self.vm.units[self.vm.unit_ptr].code.push(OpCode::ASSIGN.into()); #[allow(irrefutable_let_patterns)] if let Extension::Resolution(_scope, ptr) = ast.extensions[0] { - self.vm.chunk.push(ptr as u8); - if self.vm.lines.last().unwrap().0 != ast.end_line { - self.vm.lines.push((ast.end_line, 1)); + self.vm.units[self.vm.unit_ptr].code.push(ptr 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, 1)); } else { - self.vm.lines.last_mut().unwrap().1 += 1; + self.vm.units[self.vm.unit_ptr].lines.last_mut().unwrap().1 += 1; } } - if self.vm.lines.last().unwrap().0 != ast.end_line { - self.vm.lines.push((ast.end_line, 1)); + 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.lines.last_mut().unwrap().1 += 1; + 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) { @@ -363,63 +407,82 @@ impl Codegen { pub fn visit_lit(&mut self, ast: &AST, lit: Lit) { match lit { Lit::Num(value) => { - self.vm.pool.push(Value::Num(value)); - self.vm.chunk.push(OpCode::LOAD.into()); - self.vm.chunk.push((self.vm.pool.len()-1) as u8); - if self.vm.lines.len() == 0 || self.vm.lines.last().unwrap().0 != ast.end_line { - self.vm.lines.push((ast.end_line, 2)); + self.vm.units[self.vm.unit_ptr].pool.push(Value::Num(value)); + self.vm.units[self.vm.unit_ptr].code.push(OpCode::LOAD.into()); + let loc = (self.vm.units[self.vm.unit_ptr].pool.len()-1) as u8; + self.vm.units[self.vm.unit_ptr].code.push(loc); + 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.lines.last_mut().unwrap().1 += 2; + self.vm.units[self.vm.unit_ptr].lines.last_mut().unwrap().1 += 2; } } Lit::Str(value) => { - self.vm.pool.push(Value::Str(value.into())); - self.vm.chunk.push(OpCode::LOAD.into()); - self.vm.chunk.push((self.vm.pool.len()-1) as u8); - if self.vm.lines.len() == 0 || self.vm.lines.last().unwrap().0 != ast.end_line { - self.vm.lines.push((ast.end_line, 2)); + self.vm.units[self.vm.unit_ptr].pool.push(Value::Str(value.into())); + self.vm.units[self.vm.unit_ptr].code.push(OpCode::LOAD.into()); + let loc = (self.vm.units[self.vm.unit_ptr].pool.len()-1) as u8; + self.vm.units[self.vm.unit_ptr].code.push(loc); + 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.lines.last_mut().unwrap().1 += 2; + self.vm.units[self.vm.unit_ptr].lines.last_mut().unwrap().1 += 2; } } Lit::Bool(value) => { - self.vm.pool.push(Value::Bool(value)); - self.vm.chunk.push(OpCode::LOAD.into()); - self.vm.chunk.push((self.vm.pool.len()-1) as u8); - if self.vm.lines.len() == 0 || self.vm.lines.last().unwrap().0 != ast.end_line { - self.vm.lines.push((ast.end_line, 2)); + self.vm.units[self.vm.unit_ptr].pool.push(Value::Bool(value)); + self.vm.units[self.vm.unit_ptr].code.push(OpCode::LOAD.into()); + let loc = (self.vm.units[self.vm.unit_ptr].pool.len()-1) as u8; + self.vm.units[self.vm.unit_ptr].code.push(loc); + 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.lines.last_mut().unwrap().1 += 2; + self.vm.units[self.vm.unit_ptr].lines.last_mut().unwrap().1 += 2; } } Lit::Ident(_name) => { - self.vm.chunk.push(OpCode::VAR.into()); + self.vm.units[self.vm.unit_ptr].code.push(OpCode::VAR.into()); #[allow(irrefutable_let_patterns)] if let Extension::Resolution(_scope, ptr) = ast.extensions[0] { /*println!("line: {} ptr: {} locals: {:?}", ast.end_line, ptr, self.locals); let (_scope, slot) = self.locals.get(ptr).unwrap(); println!("slot: {}", *slot); - self.vm.chunk.push(*slot);*/ - self.vm.chunk.push(ptr as u8); - if self.vm.lines.len() == 0 || self.vm.lines.last().unwrap().0 != ast.end_line { - self.vm.lines.push((ast.end_line, 2)); + self.vm.units[self.vm.unit_ptr].code.push(*slot);*/ + self.vm.units[self.vm.unit_ptr].code.push(ptr 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.lines.last_mut().unwrap().1 += 2; + self.vm.units[self.vm.unit_ptr].lines.last_mut().unwrap().1 += 2; } } } _ => {} } } + pub fn visit_call(&mut self, ast: &AST, _name: Name, args: Vec) { + for arg in args.clone() { + self.visit(arg); + } + self.vm.units[self.vm.unit_ptr].code.push(OpCode::CALL.into()); + self.vm.units[self.vm.unit_ptr].code.push(args.len() as u8); + #[allow(irrefutable_let_patterns)] + if let Extension::Resolution(_scope, ptr) = ast.extensions[0] { + self.vm.units[self.vm.unit_ptr].code.push(ptr 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, 3)); + } else { + self.vm.units[self.vm.unit_ptr].lines.last_mut().unwrap().1 += 3; + } + } + } pub fn patch_jump(&mut self, loc: usize, offset: i32) { - let jump = ((self.vm.chunk.len() - loc - 2) as i32) + offset; + let jump = ((self.vm.units[self.vm.unit_ptr].code.len() - loc - 2) as i32) + offset; - self.vm.chunk[loc] = ((jump >> 8) & 0xFF) as u8; - self.vm.chunk[loc + 1] = (jump & 0xFF) as u8; + self.vm.units[self.vm.unit_ptr].code[loc] = ((jump >> 8) & 0xFF) as u8; + self.vm.units[self.vm.unit_ptr].code[loc + 1] = (jump & 0xFF) as u8; } } #[derive(Debug, Clone, PartialEq, Eq)] pub enum ScopeType { - Main, Loop, If, Other, + Main, Function, Loop, If, Other, } diff --git a/kabel/src/debug.rs b/kabel/src/debug.rs index 35da65dc7967b82a094a8469ed24962fdff73ede..a8acb49c098019d3ac152ecae69287843eef3450 100644 --- a/kabel/src/debug.rs +++ b/kabel/src/debug.rs @@ -1,4 +1,4 @@ -use crate::{ast::AST, lexer::Token, push_codegen, push_output, vm::{Value, VM}}; +use crate::{ast::AST, extension::Extension, lexer::Token, push_codegen, push_output, vm::{Value, VM}}; pub fn debug_token_array(tokens: Vec) -> String { let mut output = "".to_string(); @@ -30,6 +30,7 @@ pub fn debug_ast(ast: AST, level: usize) -> String { for arg in args { output += &(" ".to_string() + &arg.name); } + output += &format!(" {:?}", ast.extensions); output += "\n"; output += &debug_ast(*block, level+1); } @@ -118,6 +119,7 @@ pub fn debug_ast(ast: AST, level: usize) -> String { output += &"| ".repeat(level); output += "Decl "; output += &name.name; + output += &format!(" {:?}", ast.extensions); output += "\n"; output += &debug_ast(*expr, level+1); } @@ -125,6 +127,7 @@ pub fn debug_ast(ast: AST, level: usize) -> String { output += &"| ".repeat(level); output += "Assign "; output += &name.name; + output += &format!(" {:?}", ast.extensions); output += "\n"; output += &debug_ast(*expr, level+1); } @@ -169,6 +172,7 @@ pub fn debug_ast(ast: AST, level: usize) -> String { match lit { Ident(name) => { output += &name; + output += &format!(" {:?}", ast.extensions); } Str(value) => { output += &value; @@ -212,19 +216,19 @@ pub fn debug_bytecode(vm: &VM) -> String { //let mut ip = 0; let mut output = "".to_string(); let mut vm = vm.clone(); - while vm.ip < vm.chunk.len() { + while vm.ip < vm.units[vm.unit_ptr].code.len() { // remove PRINT later - push_codegen!(vm.chunk[vm.ip].into(), vm, output, ADD, SUB, MUL, DIV, MOD, BITAND, + push_codegen!(vm.units[vm.unit_ptr].code[vm.ip].into(), vm, output, ADD, SUB, MUL, DIV, MOD, BITAND, BITXOR, BITOR, EQ, NE, GR, GE, LS, LE, OR, AND, NOT, NEG, PRINT, ERR); - match vm.chunk[vm.ip].into() { + match vm.units[vm.unit_ptr].code[vm.ip].into() { LOAD => { output += &vm.ip.to_string(); output += " "; output += &vm.find_line().to_string(); output += " CONSTANT "; vm.ip += 1; - output += &vm.chunk[vm.ip].to_string(); + output += &vm.units[vm.unit_ptr].code[vm.ip].to_string(); output += "\n"; } VAR => { @@ -233,7 +237,7 @@ pub fn debug_bytecode(vm: &VM) -> String { output += &vm.find_line().to_string(); output += " VAR "; vm.ip += 1; - output += &vm.chunk[vm.ip].to_string(); + output += &vm.units[vm.unit_ptr].code[vm.ip].to_string(); output += "\n"; } ASSIGN => { @@ -242,7 +246,7 @@ pub fn debug_bytecode(vm: &VM) -> String { output += &vm.find_line().to_string(); output += " ASSIGN "; vm.ip += 1; - output += &vm.chunk[vm.ip].to_string(); + output += &vm.units[vm.unit_ptr].code[vm.ip].to_string(); output += "\n"; } @@ -252,9 +256,9 @@ pub fn debug_bytecode(vm: &VM) -> String { output += &vm.find_line().to_string(); output += " JMP "; vm.ip += 1; - let byte_one = (vm.chunk[vm.ip] as u16) << 8; + let byte_one = (vm.units[vm.unit_ptr].code[vm.ip] as u16) << 8; vm.ip += 1; - let byte_two = vm.chunk[vm.ip] as u16; + let byte_two = vm.units[vm.unit_ptr].code[vm.ip] as u16; output += &(byte_one | byte_two).to_string(); output += "\n"; } @@ -264,9 +268,9 @@ pub fn debug_bytecode(vm: &VM) -> String { output += &vm.find_line().to_string(); output += " JMP_UP "; vm.ip += 1; - let byte_one = (vm.chunk[vm.ip] as u16) << 8; + let byte_one = (vm.units[vm.unit_ptr].code[vm.ip] as u16) << 8; vm.ip += 1; - let byte_two = vm.chunk[vm.ip] as u16; + let byte_two = vm.units[vm.unit_ptr].code[vm.ip] as u16; output += &(byte_one | byte_two).to_string(); output += "\n"; } @@ -276,19 +280,26 @@ pub fn debug_bytecode(vm: &VM) -> String { output += &vm.find_line().to_string(); output += " JNE "; vm.ip += 1; - let byte_one = (vm.chunk[vm.ip] as u16) << 8; + let byte_one = (vm.units[vm.unit_ptr].code[vm.ip] as u16) << 8; vm.ip += 1; - let byte_two = vm.chunk[vm.ip] as u16; + let byte_two = vm.units[vm.unit_ptr].code[vm.ip] as u16; output += &(byte_one | byte_two).to_string(); output += "\n"; } + RET => { + output += &vm.ip.to_string(); + output += " "; + output += &vm.find_line().to_string(); + output += " RET "; + 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 += &vm.units[vm.unit_ptr].code[vm.ip].to_string(); output += "\n"; } _ => {} diff --git a/kabel/src/macros.rs b/kabel/src/macros.rs index 7b74d2828342d2f668fb364a874a15fcb4b6cace..f115d3630209e7c69fe102a0a987b5ebac1b7707 100644 --- a/kabel/src/macros.rs +++ b/kabel/src/macros.rs @@ -264,8 +264,8 @@ macro_rules! codegen_binary { $( $oper => { $self.visit($right); $self.visit($left); - $self.vm.chunk.push(OpCode::$code.into()); - $self.vm.lines.last_mut().unwrap().1 += 1; + $self.vm.units[$self.vm.unit_ptr].code.push(OpCode::$code.into()); + $self.vm.units[$self.vm.unit_ptr].lines.last_mut().unwrap().1 += 1; } )* } }; @@ -276,8 +276,8 @@ macro_rules! codegen_unary { match $match_to { $( $oper => { $self.visit($right); - $self.vm.chunk.push(OpCode::$code.into()); - $self.vm.lines.last_mut().unwrap().1 += 1; + $self.vm.units[0].code.push(OpCode::$code.into()); + $self.vm.units[0].lines.last_mut().unwrap().1 += 1; } )* } }; @@ -302,12 +302,12 @@ macro_rules! push_codegen { #[macro_export] macro_rules! vm_boolean_binary { ($self:expr, $oper:tt) => { - 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)), - (_v1, _v2) => $self.stack.push(Bool(false)), + match ($self.units[0].stack.pop().expect(&("Couldn't pop left side of ".to_owned() + stringify!($oper))), + $self.units[0].stack.pop().expect(&("Couldn't pop right side of ".to_owned() + stringify!($oper)))) { + (Num(v1), Num(v2)) => $self.units[0].stack.push(Bool(v1 $oper v2)), + (Str(v1), Str(v2)) => $self.units[0].stack.push(Bool(v1 $oper v2)), + (Bool(v1), Bool(v2)) => $self.units[0].stack.push(Bool(v1 $oper v2)), + (_v1, _v2) => $self.units[0].stack.push(Bool(false)), } }; } diff --git a/kabel/src/main.rs b/kabel/src/main.rs index a5c6d11ba4b10df61be4dd0dc62a1dc92a984740..72d7cc3af504855b138c496d30ad8208abcc4efe 100644 --- a/kabel/src/main.rs +++ b/kabel/src/main.rs @@ -52,15 +52,22 @@ fn main() { let codegen = run_codegen(program.to_string(), ast); let mut vm = codegen.vm; - output += &debug_bytecode(&vm); - output += "\n"; + for (index, _) in vm.units.iter().enumerate() { + vm.unit_ptr = index; + output += "unit ptr: "; + output += &vm.unit_ptr.to_string(); + output += "\n"; + output += &debug_bytecode(&vm); + output += "\n"; + } + vm.unit_ptr = 0; output += "\n"; match vm.run(&mut output) { Ok(()) => {} Err(e) => output += &e.to_string(), } - output += &debug_stack(&vm.stack); + output += &debug_stack(&vm.units[0].stack); println!("{}", output); } diff --git a/kabel/src/name_resolution.rs b/kabel/src/name_resolution.rs index 4dc2eb4458cc996810e63e6e1eec337e5114b091..49a31a2b6bab91fc7860b46cdec4de4f6e2e8d3c 100644 --- a/kabel/src/name_resolution.rs +++ b/kabel/src/name_resolution.rs @@ -61,14 +61,23 @@ impl Resolver { } else {} } } - self.symbol_table.last_mut().unwrap().insert(name.name.clone(), (Symbol::Function(args.len()),0)); self.symbol_table.push(HashMap::new()); for arg in args.clone() { self.symbol_table.last_mut().unwrap().insert(arg.name, (Symbol::Var,0)); } let block = self.visit(*block); self.symbol_table.pop(); - ast_from_ast!(Function(name, args, Box::new(block)), ast, ast) + self.locals.push(self.scope); + self.symbol_table.last_mut().unwrap().insert(name.name.clone(), + (Symbol::Function(args.len()), self.locals.len()-1)); + AST { + ast_type: Function(name, args, Box::new(block)), + extensions: vec![Extension::Resolution(self.scope, self.locals.len()-1)], + start_line: ast.start_line, + end_line: ast.end_line, + start_column: ast.start_column, + end_column: ast.end_column, + } } Return(expr) => { if let Some(expr) = *expr { @@ -251,9 +260,11 @@ impl Resolver { ast_from_ast!(Lit(lit), ast, ast) } Call(ident, args) => { - if let Err(e) = self.resolve_function(&ident.name, args.len()) { - match e { - (ErrorKind::OutOfScope, _, _) => self.errors.push(ast_error!(self, ErrorKind::OutOfScope, ast, "Function \"{}\" not in scope", ident.name)), + let resolution = self.resolve_function(&ident.name, args.len()); + let place = match resolution { + Ok(place) => place, + Err(e) => match e { + (ErrorKind::OutOfScope, _, _) => { self.errors.push(ast_error!(self, ErrorKind::OutOfScope, ast, "Function \"{}\" not in scope", ident.name)); 0 }, (ErrorKind::IncorrectArity, Some(f_arity), Some(arity)) => { self.errors.push( KabelError::new( @@ -265,15 +276,23 @@ impl Resolver { collect_lines!(self.text[ast.start_line-1..ast.end_line-1]), ) ); + 0 } _ => { panic!("Returned invalid ErrorKind from resolve_function") }, } - } + }; let mut n_args = Vec::new(); for arg in args { n_args.push(self.visit(arg)); } - ast_from_ast!(Call(ident, n_args), ast, ast) + return AST { + ast_type: Call(ident, n_args), + extensions: vec![Extension::Resolution(self.scope, place)], + start_line: ast.start_line, + end_line: ast.end_line, + start_column: ast.start_column, + end_column: ast.end_column, + }; } /*Member(left, right) => { self.visit_member(*left, *right); @@ -294,11 +313,11 @@ impl Resolver { } (false, 0) } - fn resolve_function(&mut self, name: &String, arity: usize) -> Result<(), (ErrorKind, Option, Option)>{ + fn resolve_function(&mut self, name: &String, arity: usize) -> Result, Option)>{ for scope in self.symbol_table.iter().rev() { - if let Some((Symbol::Function(f_arity), _place)) = scope.get(name) { + if let Some((Symbol::Function(f_arity), place)) = scope.get(name) { if *f_arity == arity { - return Ok(()); + return Ok(*place); } else { return Err((ErrorKind::IncorrectArity, Some(*f_arity), Some(arity))); } diff --git a/kabel/src/opcodes.rs b/kabel/src/opcodes.rs index e4b74c37eec30db26e467bc9a1b6cda5ee8aa5be..eee4999a6823d32da9895acbfa661f8654dc04a1 100644 --- a/kabel/src/opcodes.rs +++ b/kabel/src/opcodes.rs @@ -30,6 +30,9 @@ pub enum OpCode { JMP_UP, JNE, + CALL, + RET, + POP, PRINT, ERR, @@ -67,6 +70,9 @@ impl From for u8 { JMP_UP => 0x16, JNE => 0x17, + CALL => 0x18, + RET => 0x19, + POP => 0xFD, PRINT => 0xFE, ERR => 0xFF @@ -104,6 +110,9 @@ impl From for OpCode { 0x16 => JMP_UP, 0x17 => JNE, + 0x18 => CALL, + 0x19 => RET, + 0xFD => POP, 0xFE => PRINT, _ => ERR diff --git a/kabel/src/parser.rs b/kabel/src/parser.rs index 50b28a81bd11254cd2a256f6388e08ced78d8a54..a4ef97e21287a667e1c9a886b8d209cc8b2b5ea9 100644 --- a/kabel/src/parser.rs +++ b/kabel/src/parser.rs @@ -1,5 +1,5 @@ use crate::{ - ast_from_ast, ast_from_ast_token, ast_from_token, ast_from_token_ast, collect_lines, error::{ErrorKind, KabelError}, extension::Extension, lexer::{Token, TokenType}, lit, name, unexpected_token + ast_from_ast, ast_from_ast_token, ast_from_token, ast_from_token_ast, collect_lines, error::{ErrorKind, KabelError}, lexer::{Token, TokenType}, lit, name, unexpected_token }; use crate::ast::{AST, ASTType, BinOp, UnOp, Lit}; diff --git a/kabel/src/vm.rs b/kabel/src/vm.rs index bbd8cd05ed62074dfa24d882e5bba5a7276e2b9e..34d69fd3e4834916e55edfa15635db3ed76c13df 100644 --- a/kabel/src/vm.rs +++ b/kabel/src/vm.rs @@ -1,15 +1,39 @@ -use std::collections::HashMap; -use crate::{opcodes::OpCode, runtime_error::{KabelRuntimeError, RuntimeErrorKind}, vm, vm_boolean_binary}; +use crate::{runtime_error::{KabelRuntimeError, RuntimeErrorKind}, vm_boolean_binary}; use crate::vm_error; -#[derive(Clone)] -pub struct VM { - pub ip: usize, - pub chunk: Vec, +#[derive(Debug, Clone)] +pub struct Unit { + pub code: Vec, pub stack: Vec, pub pool: Vec, pub lines: Vec<(usize, usize)>, // line #, repeats number of instructions +} +impl Unit { + pub fn new(code: Vec, stack: Vec, pool: Vec, lines: Vec<(usize, usize)>) -> Self { + Self { + code, + stack, + pool, + lines, + } + } + pub fn new_empty() -> Self { + Self { + code: Vec::new(), + stack: Vec::new(), + pool: Vec::new(), + lines: Vec::new(), + } + } +} + +#[derive(Clone)] +pub struct VM { + pub ip: usize, + pub unit_ptr: usize, + pub call_stack: Vec<(usize, usize)>, // (unit_ptr, ip) + pub units: Vec, text: Vec } @@ -18,37 +42,38 @@ impl VM { text: String) -> Self { Self { ip: 0, - chunk: bytecode, - stack: Vec::new(), - pool, - lines, + unit_ptr: 0, + call_stack: Vec::new(), + units: vec![Unit::new(bytecode, Vec::new(), pool, lines)], text: text.lines().map(|s| s.to_string()).collect::>(), } } pub fn run(&mut self, output: &mut String) -> Result<(), KabelRuntimeError> { use Value::*; - while self.ip < self.chunk.len() { + while self.ip < self.units[self.unit_ptr].code.len() { match self.read() { 0x00 => { // LOAD let byte = self.read() as usize; - self.stack.push(self.pool[byte].clone()); + let value = self.units[self.unit_ptr].pool[byte].clone(); + self.units[self.unit_ptr].stack.push(value); } 0x01 => { // VAR let ptr = self.read() as usize; - self.stack.push(self.stack[ptr].clone()); + let value = self.units[self.unit_ptr].stack[ptr].clone(); + self.units[self.unit_ptr].stack.push(value); } // ASSIGN 0x02 => { - let value = self.stack.pop().unwrap(); + let value = self.units[self.unit_ptr].stack.pop().unwrap(); let ptr = self.read(); - self.stack[ptr as usize] = value.clone(); - self.stack.push(value); + self.units[self.unit_ptr].stack[ptr as usize] = value.clone(); + self.units[self.unit_ptr].stack.push(value); } 0x03 => { // ADD - match (self.stack.pop().unwrap(), self.stack.pop().unwrap()) { - (Num(v1), Num(v2)) => self.stack.push(Num(v1 + v2)), + match (self.units[self.unit_ptr].stack.pop().unwrap(), self.units[self.unit_ptr].stack.pop().unwrap()) { + (Num(v1), Num(v2)) => self.units[self.unit_ptr].stack.push(Num(v1 + v2)), (Str(v1), Str(v2)) => { - self.stack.push(Str(v1 + &v2)); + self.units[self.unit_ptr].stack.push(Str(v1 + &v2)); }, (Bool(_v1), Bool(_v2)) => { return Err(vm_error!(self, RuntimeErrorKind::WrongType, "Cannot add booleans")) @@ -59,8 +84,8 @@ impl VM { } } 0x04 => { // SUB - match (self.stack.pop().unwrap(), self.stack.pop().unwrap()) { - (Num(v1), Num(v2)) => self.stack.push(Num(v1 - v2)), + match (self.units[self.unit_ptr].stack.pop().unwrap(), self.units[self.unit_ptr].stack.pop().unwrap()) { + (Num(v1), Num(v2)) => self.units[self.unit_ptr].stack.push(Num(v1 - v2)), (Str(_v1), Str(_v2)) => { return Err(vm_error!(self, RuntimeErrorKind::WrongType, "Cannot subtract strings")) }, @@ -73,11 +98,11 @@ impl VM { } } 0x05 => { // MUL - match (self.stack.pop().unwrap(), self.stack.pop().unwrap()) { - (Num(v1), Num(v2)) => self.stack.push(Num(v1 * v2)), + match (self.units[self.unit_ptr].stack.pop().unwrap(), self.units[self.unit_ptr].stack.pop().unwrap()) { + (Num(v1), Num(v2)) => self.units[self.unit_ptr].stack.push(Num(v1 * v2)), (Str(v1), Num(v2)) => { if v2.fract() == 0.0 { - self.stack.push(Str(v1.repeat(v2 as usize))); + self.units[self.unit_ptr].stack.push(Str(v1.repeat(v2 as usize))); } else { return Err(vm_error!(self, RuntimeErrorKind::WrongType, "Number must be an integer")) } @@ -94,8 +119,8 @@ impl VM { } } 0x06 => { // DIV - match (self.stack.pop().unwrap(), self.stack.pop().unwrap()) { - (Num(v1), Num(v2)) => self.stack.push(Num(v1 / v2)), + match (self.units[self.unit_ptr].stack.pop().unwrap(), self.units[self.unit_ptr].stack.pop().unwrap()) { + (Num(v1), Num(v2)) => self.units[self.unit_ptr].stack.push(Num(v1 / v2)), (Str(_v1), Str(_v2)) => { return Err(vm_error!(self, RuntimeErrorKind::WrongType, "Cannot divide strings")) }, @@ -108,8 +133,8 @@ impl VM { } } 0x07 => { // MOD - match (self.stack.pop().unwrap(), self.stack.pop().unwrap()) { - (Num(v1), Num(v2)) => self.stack.push(Num(v1 % v2)), + match (self.units[self.unit_ptr].stack.pop().unwrap(), self.units[self.unit_ptr].stack.pop().unwrap()) { + (Num(v1), Num(v2)) => self.units[self.unit_ptr].stack.push(Num(v1 % v2)), (Str(_v1), Str(_v2)) => { return Err(vm_error!(self, RuntimeErrorKind::WrongType, "Cannot perform modulus on strings")) }, @@ -122,7 +147,7 @@ impl VM { } } 0x08 => { // BITAND - match (self.stack.pop().unwrap(), self.stack.pop().unwrap()) { + match (self.units[self.unit_ptr].stack.pop().unwrap(), self.units[self.unit_ptr].stack.pop().unwrap()) { (Num(v1), Num(v2)) => { if v1.fract() != 0.0 { return Err(vm_error!(self, RuntimeErrorKind::WrongType, "Cannot perform bitwise AND on {}", v1)) @@ -130,7 +155,7 @@ impl VM { if v2.fract() != 0.0 { return Err(vm_error!(self, RuntimeErrorKind::WrongType, "Cannot perform bitwise AND on {}", v2)) } - self.stack.push(Num((v1 as u32 & v2 as u32) as f32)) + self.units[self.unit_ptr].stack.push(Num((v1 as u32 & v2 as u32) as f32)) } (Str(_v1), Str(_v2)) => { return Err(vm_error!(self, RuntimeErrorKind::WrongType, "Cannot perform bitwise AND on strings")) @@ -144,7 +169,7 @@ impl VM { } } 0x09 => { // BITXOR - match (self.stack.pop().unwrap(), self.stack.pop().unwrap()) { + match (self.units[self.unit_ptr].stack.pop().unwrap(), self.units[self.unit_ptr].stack.pop().unwrap()) { (Num(v1), Num(v2)) => { if v1.fract() != 0.0 { return Err(vm_error!(self, RuntimeErrorKind::WrongType, "Cannot perform bitwise XOR on {}", v1)) @@ -152,7 +177,7 @@ impl VM { if v2.fract() != 0.0 { return Err(vm_error!(self, RuntimeErrorKind::WrongType, "Cannot perform bitwise XOR on {}", v2)) } - self.stack.push(Num((v1 as u32 ^ v2 as u32) as f32)) + self.units[self.unit_ptr].stack.push(Num((v1 as u32 ^ v2 as u32) as f32)) } (Str(_v1), Str(_v2)) => { return Err(vm_error!(self, RuntimeErrorKind::WrongType, "Cannot perform bitwise XOR on strings")) @@ -166,7 +191,7 @@ impl VM { } } 0x0A => { // BITOR - match (self.stack.pop().unwrap(), self.stack.pop().unwrap()) { + match (self.units[self.unit_ptr].stack.pop().unwrap(), self.units[self.unit_ptr].stack.pop().unwrap()) { (Num(v1), Num(v2)) => { if v1.fract() != 0.0 { return Err(vm_error!(self, RuntimeErrorKind::WrongType, "Cannot perform bitwise OR on {}", v1)) @@ -174,7 +199,7 @@ impl VM { if v2.fract() != 0.0 { return Err(vm_error!(self, RuntimeErrorKind::WrongType, "Cannot perform bitwise OR on {}", v2)) } - self.stack.push(Num((v1 as u32 | v2 as u32) as f32)) + self.units[self.unit_ptr].stack.push(Num((v1 as u32 | v2 as u32) as f32)) } (Str(_v1), Str(_v2)) => { return Err(vm_error!(self, RuntimeErrorKind::WrongType, "Cannot perform bitwise OR on strings")) @@ -200,44 +225,44 @@ impl VM { // LE 0x10 => vm_boolean_binary!(self, <=), // OR - 0x11 => match (self.stack.pop().unwrap(), self.stack.pop().unwrap()) { + 0x11 => match (self.units[self.unit_ptr].stack.pop().unwrap(), self.units[self.unit_ptr].stack.pop().unwrap()) { (Num(_v1), Num(_v2)) => { return Err(vm_error!(self, RuntimeErrorKind::WrongType, "Cannot perform logical OR on numbers")) } (Str(_v1), Str(_v2)) => { return Err(vm_error!(self, RuntimeErrorKind::WrongType, "Cannot perform logical OR on strings")) }, - (Bool(v1), Bool(v2)) => self.stack.push(Bool(v1 || v2)), + (Bool(v1), Bool(v2)) => self.units[self.unit_ptr].stack.push(Bool(v1 || v2)), (v1, v2) => { return Err(vm_error!(self, RuntimeErrorKind::MismatchedTypes, "Mismatched types: {} and {}", v1.type_str(), v2.type_str())) } } // AND - 0x12 => match (self.stack.pop().unwrap(), self.stack.pop().unwrap()) { + 0x12 => match (self.units[self.unit_ptr].stack.pop().unwrap(), self.units[self.unit_ptr].stack.pop().unwrap()) { (Num(_v1), Num(_v2)) => { return Err(vm_error!(self, RuntimeErrorKind::WrongType, "Cannot perform logical AND on numbers")) } (Str(_v1), Str(_v2)) => { return Err(vm_error!(self, RuntimeErrorKind::WrongType, "Cannot perform logical AND on strings")) }, - (Bool(v1), Bool(v2)) => self.stack.push(Bool(v1 && v2)), + (Bool(v1), Bool(v2)) => self.units[self.unit_ptr].stack.push(Bool(v1 && v2)), (v1, v2) => { return Err(vm_error!(self, RuntimeErrorKind::MismatchedTypes, "Mismatched types: {} and {}", v1.type_str(), v2.type_str())) } } // NOT - 0x13 => match self.stack.pop().unwrap() { + 0x13 => match self.units[self.unit_ptr].stack.pop().unwrap() { Num(_v1) => { return Err(vm_error!(self, RuntimeErrorKind::WrongType, "Cannot perform logical NOT on numbers")) } Str(_v1) => { return Err(vm_error!(self, RuntimeErrorKind::WrongType, "Cannot perform logical NOT on strings")) } - Bool(v1) => self.stack.push(Bool(!v1)), + Bool(v1) => self.units[self.unit_ptr].stack.push(Bool(!v1)), } // NEG - 0x14 => match self.stack.pop().unwrap() { - Num(v1) => self.stack.push(Num(-v1)), + 0x14 => match self.units[self.unit_ptr].stack.pop().unwrap() { + Num(v1) => self.units[self.unit_ptr].stack.push(Num(-v1)), Str(_v1) => { return Err(vm_error!(self, RuntimeErrorKind::WrongType, "Cannot negate strings")) } @@ -257,7 +282,7 @@ impl VM { } // JNE 0x17 => { - let condition = self.stack.pop().unwrap(); + let condition = self.units[self.unit_ptr].stack.pop().unwrap(); if let Value::Bool(condition) = condition { if !condition { let loc = self.read_u16(); @@ -270,14 +295,28 @@ impl VM { } } + // CALL + 0x18 => { + let num_args = self.read(); + let unit_ptr = self.read(); + self.call_stack.push((self.unit_ptr, self.ip)); + for i in 0..num_args { + + } + } + // RET + 0x19 => { + + } + 0xFD => { // POP let times = self.read(); for _ in 0..times { - self.stack.pop().expect(&format!("{}: Unable to pop stack", self.ip)); + self.units[self.unit_ptr].stack.pop().expect(&format!("{}: Unable to pop stack", self.ip)); } } 0xFE => { // PRINT - let value = self.stack.pop().unwrap(); + let value = self.units[self.unit_ptr].stack.pop().unwrap(); match value { Num(v) => *output += &v.to_string(), Str(v) => *output += &v, @@ -291,20 +330,20 @@ impl VM { Ok(()) } pub fn read(&mut self) -> u8 { - let byte = self.chunk[self.ip]; + let byte = self.units[self.unit_ptr].code[self.ip]; self.ip += 1; byte } pub fn read_u16(&mut self) -> u16 { - let byte_one = (self.chunk[self.ip] as u16) << 0x08; + let byte_one = (self.units[self.unit_ptr].code[self.ip] as u16) << 0x08; self.ip += 1; - let byte_two = self.chunk[self.ip] as u16; + let byte_two = self.units[self.unit_ptr].code[self.ip] as u16; self.ip += 1; byte_one | byte_two } pub fn find_line(&self) -> usize { // returns line # at ip let mut line_ip = 0; - for (line, rep) in self.lines.clone() { + for (line, rep) in self.units[self.unit_ptr].lines.clone() { if line_ip + rep > self.ip { return line; } diff --git a/kabel/tmp.kab b/kabel/tmp.kab index 1276cf98e64db8682a7e37c047a08aec564cc160..7ba20beb3ff8eb37734611fce8938ccd29d34f1e 100644 --- a/kabel/tmp.kab +++ b/kabel/tmp.kab @@ -1,2 +1,4 @@ -var i = 0; -function i() {} +function i(j) { + j+1; +} +print i(2);