diff --git a/Cargo.lock b/Cargo.lock index d2c3234..e5acb2a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -37,6 +37,7 @@ name = "compiler" version = "0.1.0" dependencies = [ "insta", + "vm", ] [[package]] diff --git a/examples/snake/Game.jack b/examples/snake/Game.jack index 19b7043..f1a6921 100644 --- a/examples/snake/Game.jack +++ b/examples/snake/Game.jack @@ -1,6 +1,6 @@ class Game { static int FPS, FRAMES_PER_TICK; - static String msg_game_over; + static String msg_game_over, msg_game_paused; static int some_prime_num; field int key, tick, game_counter, GAME_STATE, apple_coords, score; @@ -11,6 +11,7 @@ class Game { let FPS = 60; let FRAMES_PER_TICK = FPS / 30; let msg_game_over = "=== Game Over! ==="; + let msg_game_paused = "=== Pause ==="; let GAME_STATE = 0; let score = 0; let ui = UI.new(); @@ -27,13 +28,11 @@ class Game { let GAME_STATE = 1; while (~(GAME_STATE = 0)) { - do Screen.clearScreen(); - do ui.init(); + do redraw(); let tick = 0; let score = 0; let snake = Snake.new(30, 20); let apple_coords = placeApple(snake); - do UI.drawIngameMenu(score); do run(); } return; @@ -47,6 +46,13 @@ class Game { return; } + method void redraw() { + do Screen.clearScreen(); + do ui.init(); + do UI.drawIngameMenu(score); + return; + } + method int run() { var char tempKey; // the key currently pressed by the user var boolean exit; @@ -58,10 +64,11 @@ class Game { while (~exit) { let tempKey = Keyboard.keyPressed(); - if (~(tempKey = 0)) { + if (~(tempKey = 0) & ~(tempKey = key)) { let key = tempKey; } if (key = 81) { let exit = true; let GAME_STATE = 0; return GAME_STATE; } // q key + if (key = 80) { do pauseLoop(tick); } // p key let is_over = tickGame(); do UI.updateIngameMenu(score); @@ -124,15 +131,38 @@ class Game { return; } + method void pauseLoop(int tick_initial) { + var char key; + let GAME_STATE = 3; + do UI.drawPanel(200, 100, msg_game_paused); + while (GAME_STATE = 3) { + let key = Keyboard.keyPressed(); + if ( + // p key + (key = 80) & + ((tick - tick_initial) > 10) + ) { + let GAME_STATE = 1; + let key = 0; + do Sys.wait(200); + do redraw(); + return; + } + do Sys.wait(1000 / FPS); + let tick = tick + 1; + } + return; + } + method int placeApple(Snake snake) { var int oldPlace; if (~(snake.getHead() = apple_coords)) { return apple_coords; } let oldPlace = apple_coords; - let oldPlace = Utils.modulo(oldPlace + some_prime_num, UI.getBoardIndexSize() - 1); + let oldPlace = Utils.modulo((oldPlace + some_prime_num) * tick, UI.getBoardIndexSize() - 1); while (snake.isCollided(oldPlace)) { - let oldPlace = Utils.modulo(oldPlace + some_prime_num, UI.getBoardIndexSize() - 1); + let oldPlace = Utils.modulo((oldPlace + some_prime_num) * tick, UI.getBoardIndexSize() - 1); } return oldPlace; } diff --git a/examples/snake/UI.jack b/examples/snake/UI.jack index fbd2623..ef4ed81 100644 --- a/examples/snake/UI.jack +++ b/examples/snake/UI.jack @@ -155,9 +155,6 @@ class UI { function void updateScore(int score) { var String s; - if (score = last_score) { - return; - } let s = "SCORE: "; do Output.moveCursor(0, 0); do Output.printString(s); @@ -168,6 +165,9 @@ class UI { } function void drawIngameMenu(int score) { + if (score = last_score) { + return; + } do UI.updateScore(score); return; } diff --git a/src/compiler/Cargo.toml b/src/compiler/Cargo.toml index efa8c96..b1c051a 100644 --- a/src/compiler/Cargo.toml +++ b/src/compiler/Cargo.toml @@ -17,5 +17,8 @@ name = "parser" [[bin]] name = "compiler" +[dependencies] +vm = { path = "../vm" } + [dev-dependencies] insta = { version = "^1.8.0", features = ["glob"] } diff --git a/src/compiler/src/codegen.rs b/src/compiler/src/codegen.rs index 8f87402..0ffe7c6 100644 --- a/src/compiler/src/codegen.rs +++ b/src/compiler/src/codegen.rs @@ -1,31 +1,114 @@ -pub fn write_pop(seg: &str, index: u16) -> String { - format!("pop {} {}", seg, index) +use vm::instruction::{PushPop, PushPopInstruction}; + +use crate::instruction::Instruction; + +#[derive(Clone, Debug)] +pub struct CompilerInstruction { + instruction: Instruction, +} + +#[derive(Clone, Debug)] +pub struct WriteInst { + instruction: CompilerInstruction, +} + +impl WriteInst { + pub fn new(instruction: CompilerInstruction) -> Self { + Self { instruction } + } + + pub fn code(&self) -> String { + self.instruction.code() + } + + pub fn instruction(&self) -> &Instruction { + &self.instruction.instruction + } +} + +impl CompilerInstruction { + pub fn new(instruction: Instruction) -> Self { + Self { instruction } + } + + #[allow(unreachable_patterns)] + pub fn code(&self) -> String { + match &self.instruction { + Instruction::Arithmetic(op) => op.into(), + Instruction::PushPop(PushPopInstruction { + segment, + addr: index, + inst_type, + }) => match inst_type { + PushPop::Push => format!("push {} {}", segment, index), + PushPop::Pop => format!("pop {} {}", segment, index), + }, + Instruction::Label(label, _) => format!("label {}", label), + Instruction::Goto(label, _) => format!("goto {}", label), + Instruction::IfGoto(label, _) => format!("if-goto {}", label), + Instruction::Function(name, n_locals) => format!("function {} {}", name, n_locals), + Instruction::Return() => "return".to_string(), + Instruction::Call(name, n_args) => format!("call {} {}", name, n_args), + _ => unreachable!("Unreachable instruction: {:?}", self.instruction), + } + } +} + +pub fn write_arith(op: &str) -> WriteInst { + WriteInst::new(CompilerInstruction::new(Instruction::Arithmetic(op.into()))) +} + +pub fn write_not() -> WriteInst { + write_arith("not") +} + +pub fn write_pop(seg: &str, index: u16) -> WriteInst { + WriteInst::new(CompilerInstruction::new(Instruction::PushPop( + PushPopInstruction::new(PushPop::Pop, seg.into(), index), + ))) } -pub fn write_push(seg: &str, index: u16) -> String { - format!("push {} {}", seg, index) +pub fn write_push(seg: &str, index: u16) -> WriteInst { + WriteInst::new(CompilerInstruction::new(Instruction::PushPop( + PushPopInstruction::new(PushPop::Push, seg.into(), index), + ))) } -pub fn write_function(name: String, n_locals: u16) -> String { - format!("function {} {}", name, n_locals) +pub fn write_function(name: String, n_locals: u16) -> WriteInst { + WriteInst::new(CompilerInstruction::new(Instruction::Function( + name, + n_locals.into(), + ))) } -pub fn write_call(name: S, n_args: usize) -> String { - format!("call {} {}", name, n_args) +pub fn write_call(name: S, n_args: usize) -> WriteInst { + WriteInst::new(CompilerInstruction::new(Instruction::Call( + name.to_string(), + n_args, + ))) } -pub fn write_return() -> String { - "return".to_string() +pub fn write_return() -> WriteInst { + WriteInst::new(CompilerInstruction::new(Instruction::Return())) } -pub fn write_label(label: S) -> String { - format!("label {}", label) +pub fn write_label(label: S) -> WriteInst { + WriteInst::new(CompilerInstruction::new(Instruction::Label( + label.to_string(), + None, + ))) } -pub fn write_if(label: S) -> String { - format!("if-goto {}", label) +pub fn write_if(label: S) -> WriteInst { + WriteInst::new(CompilerInstruction::new(Instruction::IfGoto( + label.to_string(), + None, + ))) } -pub fn write_goto(label: S) -> String { - format!("goto {}", label) +pub fn write_goto(label: S) -> WriteInst { + WriteInst::new(CompilerInstruction::new(Instruction::Goto( + label.to_string(), + None, + ))) } diff --git a/src/compiler/src/compiler.rs b/src/compiler/src/compiler.rs index 8bb92cc..1622452 100644 --- a/src/compiler/src/compiler.rs +++ b/src/compiler/src/compiler.rs @@ -1,6 +1,7 @@ use crate::{ codegen::*, node::*, + optimizer::{opimize_vm_instructions, optimize_syntax_tree_expression}, parser::ParseResult, symbol_table::{Entry, SubVarKind, SymbolTable}, token::Keyword, @@ -10,32 +11,52 @@ use std::{collections::HashSet, fmt::Write}; type CompilerError = Box; type Res = Result; -struct CompilerState<'a> { +pub struct CompilerState { class_name: String, label_id: usize, + instructions: Vec, methods: HashSet, sym_table: SymbolTable, - out: &'a mut (dyn Write), } -impl<'a> CompilerState<'a> { - fn new(class_name: String, sym_table: SymbolTable, out: &'a mut (dyn Write)) -> Self { +impl CompilerState { + pub fn sym_table(&mut self) -> &mut SymbolTable { + &mut self.sym_table + } +} + +impl CompilerState { + fn new(class_name: String, sym_table: SymbolTable) -> Self { Self { class_name, label_id: 0, + instructions: vec![], methods: Default::default(), sym_table, - out, } } - pub fn write(&mut self, s: S) { - writeln!(self.out, "{}", s).expect("Error writing"); + fn write_all(&mut self, out: &mut (dyn Write)) { + for inst in self.instructions.iter() { + self.write_inner(out, inst.code()) + } + } + + fn write_inner(&self, out: &mut (dyn Write), s: S) { + writeln!(out, "{}", s).expect("Error writing"); + } + + pub fn write_result(&mut self, res: WriteInst) { + self.save_result(res); } pub fn get_label(&mut self) -> String { self.label_id += 1; - format!("__VM_LABEL_{}", self.label_id) + Self::get_label_id(self.label_id) + } + + fn get_label_id(label_id: usize) -> String { + format!("__VM_LABEL_{}", label_id) } fn register_method(&mut self, sub_dec: &SubroutineDec) { @@ -47,11 +68,16 @@ impl<'a> CompilerState<'a> { fn has_method(&self, method: &str) -> bool { self.methods.contains(method) } + + fn save_result(&mut self, res: WriteInst) { + self.instructions.push(res); + } } #[derive(Debug, Default, Clone)] -struct CompilerContext { +pub struct CompilerContext { function_variant: Option, + lhs_context: LhsContext, return_type: Option, } @@ -59,6 +85,50 @@ impl CompilerContext { fn new() -> Self { Default::default() } + + pub fn lhs_context(&self) -> LhsContext { + self.lhs_context.clone() + } + + fn set_lhs_context_static(&mut self, name: String) { + if !self.is_in_constructor() { + return; + } + self.lhs_context = Some(LhsContextInner::new_for_class_static(name.as_str())) + } + + fn reset_lhs_context_static(&mut self) { + self.lhs_context = None + } + + fn is_in_constructor(&self) -> bool { + self.function_variant == Some(GrammarSubroutineVariant::Constructor) + } +} + +#[derive(Debug, Clone)] +pub struct LhsContextClassStatic { + name: String, +} +impl LhsContextClassStatic { + pub fn name(&self) -> &str { + self.name.as_str() + } + + fn new(name: &str) -> Self { + Self { name: name.into() } + } +} +#[derive(Debug, Clone)] +pub enum LhsContextInner { + ClassStatic(LhsContextClassStatic), +} +pub type LhsContext = Option; + +impl LhsContextInner { + pub fn new_for_class_static(name: &str) -> LhsContextInner { + LhsContextInner::ClassStatic(LhsContextClassStatic::new(name)) + } } fn lookup_var(state: &mut CompilerState, context: &CompilerContext, name: String) -> Res { @@ -78,12 +148,14 @@ fn lookup_var(state: &mut CompilerState, context: &CompilerContext, name: String pub fn compile_program(parse_result: ParseResult) -> Res { let mut out = String::new(); let sym_table = SymbolTable::new(); - let mut state = CompilerState::new(Default::default(), sym_table, &mut out); + let mut state = CompilerState::new(Default::default(), sym_table); let context = CompilerContext::new(); compile_class(&mut state, &context, parse_result.root).map_err(|e| { // dbg!(state.class_name, state.sym_table); e })?; + opimize_vm_instructions(&mut state.instructions); + state.write_all(&mut out); Ok(out) } @@ -116,7 +188,7 @@ fn compile_subroutine_dec( ) -> Res { state.sym_table.reset_subroutine_table(); let n_locals: u16 = sub.0.iter().map(|var_dec| var_dec.1.len() as u16).sum(); - state.write(write_function( + state.write_result(write_function( format!("{}.{}", state.class_name, ident), n_locals, )); @@ -126,13 +198,13 @@ fn compile_subroutine_dec( match variant { GrammarSubroutineVariant::Constructor => { let object_size = state.sym_table.count_instance_fields(); - state.write(write_push("constant", object_size)); - state.write(write_call("Memory.alloc", 1)); - state.write(write_pop("pointer", 0)); + state.write_result(write_push("constant", object_size)); + state.write_result(write_call("Memory.alloc", 1)); + state.write_result(write_pop("pointer", 0)); } GrammarSubroutineVariant::Method => { - state.write(write_push("argument", 0)); - state.write(write_pop("pointer", 0)); + state.write_result(write_push("argument", 0)); + state.write_result(write_pop("pointer", 0)); // Offset arguments in methods by setting fake value, since we also pass 'this' state.sym_table.define_subroutine_var( @@ -149,13 +221,13 @@ fn compile_subroutine_dec( .define_subroutine_var(¶m.ident, SubVarKind::Argument, ¶m.type_); } - compile_subroutine(state, &sub_context, sub, item_type)?; + compile_subroutine(state, &mut sub_context, sub, item_type)?; Ok(()) } fn compile_subroutine( state: &mut CompilerState, - context: &CompilerContext, + context: &mut CompilerContext, Subroutine(var_decs, stmts): Subroutine, _typ: GrammarSubroutineReturnType, ) -> Res { @@ -172,7 +244,7 @@ fn compile_subroutine( fn compile_statements( state: &mut CompilerState, - context: &CompilerContext, + context: &mut CompilerContext, statements: Vec, ) -> Res { for stmt in statements { @@ -181,7 +253,11 @@ fn compile_statements( Ok(()) } -fn compile_statement(state: &mut CompilerState, context: &CompilerContext, stmt: Statement) -> Res { +fn compile_statement( + state: &mut CompilerState, + context: &mut CompilerContext, + stmt: Statement, +) -> Res { match stmt { Statement::LetStatement(s) => compile_statement_let(state, context, s)?, Statement::IfStatement(s) => compile_statement_if(state, context, s)?, @@ -194,35 +270,41 @@ fn compile_statement(state: &mut CompilerState, context: &CompilerContext, stmt: fn compile_statement_let( state: &mut CompilerState, - context: &CompilerContext, + context: &mut CompilerContext, stmt: LetStatement, ) -> Res { let var = state .sym_table .lookup(&stmt.name) .ok_or(format!("Unknown var: {}", &stmt.name))?; + let is_static_var = var.kind == "static"; + if is_static_var { + context.set_lhs_context_static(stmt.name.clone()); + } + match stmt.index_expr { Some(expr) => { - state.write(write_push(var.kind.as_str(), var.index)); + state.write_result(write_push(var.kind.as_str(), var.index)); compile_expression(state, context, expr)?; - state.write("add"); + state.write_result(write_arith("add")); compile_expression(state, context, stmt.value_expr)?; - state.write(write_pop("temp", 0)); - state.write(write_pop("pointer", 1)); - state.write(write_push("temp", 0)); - state.write(write_pop("that", 0)); + state.write_result(write_pop("temp", 0)); + state.write_result(write_pop("pointer", 1)); + state.write_result(write_push("temp", 0)); + state.write_result(write_pop("that", 0)); } _ => { compile_expression(state, context, stmt.value_expr)?; - state.write(write_pop(var.kind.as_str(), var.index)); + state.write_result(write_pop(var.kind.as_str(), var.index)); } }; + context.reset_lhs_context_static(); Ok(()) } fn compile_statement_if( state: &mut CompilerState, - context: &CompilerContext, + context: &mut CompilerContext, stmt: IfStatement, ) -> Res { let end_label = state.get_label(); @@ -232,32 +314,32 @@ fn compile_statement_if( end_label.clone() }; compile_expression(state, context, stmt.if_expr)?; - state.write("not"); - state.write(write_if(&else_label)); + state.write_result(write_not()); + state.write_result(write_if(&else_label)); compile_statements(state, context, stmt.if_statements)?; - state.write(write_goto(&end_label)); if let Some(else_statements) = stmt.else_statements { - state.write(write_label(&else_label)); + state.write_result(write_goto(&end_label)); + state.write_result(write_label(&else_label)); compile_statements(state, context, else_statements)?; } - state.write(write_label(&end_label)); + state.write_result(write_label(&end_label)); Ok(()) } fn compile_statement_while( state: &mut CompilerState, - context: &CompilerContext, + context: &mut CompilerContext, stmt: WhileStatement, ) -> Res { let start_label = state.get_label(); let end_label = state.get_label(); - state.write(write_label(&start_label)); + state.write_result(write_label(&start_label)); compile_expression(state, context, stmt.cond_expr)?; - state.write("not"); - state.write(write_if(&end_label)); + state.write_result(write_not()); + state.write_result(write_if(&end_label)); compile_statements(state, context, stmt.statements)?; - state.write(write_goto(&start_label)); - state.write(write_label(&end_label)); + state.write_result(write_goto(&start_label)); + state.write_result(write_label(&end_label)); Ok(()) } @@ -268,7 +350,7 @@ fn compile_statement_do( ) -> Res { compile_call(state, context, stmt.call)?; // Pop return value, not used - state.write(write_pop("temp", 0)); + state.write_result(write_pop("temp", 0)); Ok(()) } @@ -292,10 +374,10 @@ fn compile_statement_return( compile_expression(state, context, expr)?; } None => { - state.write(write_push("constant", 0)); + state.write_result(write_push("constant", 0)); } } - state.write(write_return()); + state.write_result(write_return()); Ok(()) } @@ -322,7 +404,7 @@ fn compile_call(state: &mut CompilerState, context: &CompilerContext, call: Subr }; let n_args = args.len(); compile_expression_list(state, context, args)?; - state.write(write_call(func_name, n_args)); + state.write_result(write_call(func_name, n_args)); Ok(()) } @@ -356,11 +438,14 @@ fn compile_expression_list( Ok(()) } -fn compile_expression( - state: &mut CompilerState, - context: &CompilerContext, - Expr(term, extra_terms): Expr, -) -> Res { +fn compile_expression(state: &mut CompilerState, context: &CompilerContext, expr: Expr) -> Res { + if let Some(results) = optimize_syntax_tree_expression(&expr, state, context) { + for result in results { + state.write_result(result); + } + return Ok(()); + } + let Expr(term, extra_terms) = expr; compile_term(state, context, term)?; for (op, extra_term) in extra_terms { compile_term(state, context, extra_term)?; @@ -373,32 +458,32 @@ fn compile_term(state: &mut CompilerState, context: &CompilerContext, term: Term match term { Term::VarName(name) => { let var = lookup_var(state, context, name)?; - state.write(write_push(var.kind.as_str(), var.index)); + state.write_result(write_push(var.kind.as_str(), var.index)); } Term::KeywordConstant(kw) => { match kw { Keyword::True => { - state.write(write_push("constant", 0)); - state.write("not"); + state.write_result(write_push("constant", 0)); + state.write_result(write_not()); } Keyword::False | Keyword::Null => { - state.write(write_push("constant", 0)); + state.write_result(write_push("constant", 0)); } Keyword::This => { - state.write(write_push("pointer", 0)); + state.write_result(write_push("pointer", 0)); } _ => return Err(format!("Unexpected constant used as term: {:?}", kw).into()), }; } Term::IntegerConstant(i) => { - state.write(write_push("constant", i)); + state.write_result(write_push("constant", i)); } Term::StringConst(s) => { - state.write(write_push("constant", s.len() as u16)); - state.write(write_call("String.new", 1)); + state.write_result(write_push("constant", s.len() as u16)); + state.write_result(write_call("String.new", 1)); for c in s.chars() { - state.write(write_push("constant", (c as u8).into())); - state.write(write_call("String.appendChar", 2)); + state.write_result(write_push("constant", (c as u8).into())); + state.write_result(write_call("String.appendChar", 2)); } } Term::UnaryOp(op, term) => { @@ -410,11 +495,11 @@ fn compile_term(state: &mut CompilerState, context: &CompilerContext, term: Term } Term::IndexExpr(name, expr) => { let var = lookup_var(state, context, name)?; - state.write(write_push(var.kind.as_str(), var.index)); + state.write_result(write_push(var.kind.as_str(), var.index)); compile_expression(state, context, *expr)?; - state.write("add"); - state.write(write_pop("pointer", 1)); - state.write(write_push("that", 0)); + state.write_result(write_arith("add")); + state.write_result(write_pop("pointer", 1)); + state.write_result(write_push("that", 0)); } Term::SubroutineCall(call) => { compile_call(state, context, call)?; @@ -424,14 +509,14 @@ fn compile_term(state: &mut CompilerState, context: &CompilerContext, term: Term } fn compile_op(state: &mut CompilerState, _context: &CompilerContext, Op(op): Op) -> Res { - state.write(match op.as_str() { - "+" => "add".to_string(), - "-" => "sub".to_string(), - "=" => "eq".to_string(), - ">" => "gt".to_string(), - "<" => "lt".to_string(), - "&" => "and".to_string(), - "|" => "or".to_string(), + state.write_result(match op.as_str() { + "+" => write_arith("add"), + "-" => write_arith("sub"), + "=" => write_arith("eq"), + ">" => write_arith("gt"), + "<" => write_arith("lt"), + "&" => write_arith("and"), + "|" => write_arith("or"), "*" => write_call("Math.multiply", 2), "/" => write_call("Math.divide", 2), other => unreachable!("Unsupported op: {:?}", other), @@ -440,9 +525,9 @@ fn compile_op(state: &mut CompilerState, _context: &CompilerContext, Op(op): Op) } fn compile_unary_op(state: &mut CompilerState, _context: &CompilerContext, Op(op): Op) -> Res { - state.write(match op.as_str() { - "-" => "neg".to_string(), - "~" => "not".to_string(), + state.write_result(match op.as_str() { + "-" => write_arith("neg"), + "~" => write_not(), other => unreachable!("Unsupported unary op: {:?}", other), }); Ok(()) diff --git a/src/compiler/src/instruction.rs b/src/compiler/src/instruction.rs new file mode 100644 index 0000000..0219643 --- /dev/null +++ b/src/compiler/src/instruction.rs @@ -0,0 +1 @@ +pub use vm::instruction::{Instruction, PushPop}; diff --git a/src/compiler/src/lib.rs b/src/compiler/src/lib.rs index 305781e..e9601c8 100644 --- a/src/compiler/src/lib.rs +++ b/src/compiler/src/lib.rs @@ -3,11 +3,14 @@ pub mod compiler; pub mod compiler_cli; pub mod config; pub mod input; +pub mod instruction; pub mod line_chars; pub mod node; pub mod node_printer; +pub mod optimizer; pub mod parser; pub mod symbol_table; pub mod token; pub mod tokenizer; +pub mod utils; pub mod xml; diff --git a/src/compiler/src/optimizer/mod.rs b/src/compiler/src/optimizer/mod.rs new file mode 100644 index 0000000..4c3a904 --- /dev/null +++ b/src/compiler/src/optimizer/mod.rs @@ -0,0 +1,7 @@ +mod optimize_syntax_tree; +mod optimize_vm_instructions; + +pub use self::{ + optimize_syntax_tree::optimize_syntax_tree_expression, + optimize_vm_instructions::opimize_vm_instructions, +}; diff --git a/src/compiler/src/optimizer/optimize_syntax_tree.rs b/src/compiler/src/optimizer/optimize_syntax_tree.rs new file mode 100644 index 0000000..308eba2 --- /dev/null +++ b/src/compiler/src/optimizer/optimize_syntax_tree.rs @@ -0,0 +1,126 @@ +use crate::compiler::{CompilerContext, CompilerState, LhsContext, LhsContextInner}; + +use crate::codegen::{write_arith, write_push, WriteInst}; +use crate::node::{Expr, GrammarItemType, Op, Term}; +use crate::symbol_table::{type_as_string, SymbolTable}; +use crate::token::Keyword; + +pub fn optimize_syntax_tree_expression( + Expr(term1, ops): &Expr, + state: &mut CompilerState, + context: &CompilerContext, +) -> Option> { + let lhs_context = context.lhs_context(); + optimize_expr(term1, ops, &mut Some(state.sym_table()), &lhs_context) +} + +fn optimize_expr_int_inner( + term1: &Term, + ops: &[(Op, Term)], + sym_table: &mut Option<&mut SymbolTable>, + lhs_context: &LhsContext, +) -> Option { + // dbg!(term1, ops); + let term1_value = eval_term(term1, sym_table); + let mut full_expr_int_value = term1_value; + for (Op(op), term2) in ops { + if !is_simple_arith_op(op.as_str()) { + return None; + } + let term2_value = eval_term(term2, sym_table); + if let (Some(a), Some(b)) = (full_expr_int_value, term2_value) { + full_expr_int_value = eval_binop(op, a, b); + } else { + return None; + } + } + + if let (Some(term_value), Some(sym_table), Some(LhsContextInner::ClassStatic(class_static))) = + (full_expr_int_value, sym_table, lhs_context) + { + sym_table.add_constant_value_for_static(class_static.name(), term_value); + } + + full_expr_int_value +} + +fn is_simple_arith_op(op: &str) -> bool { + ["+", "-", "*", "/", "|", "&", "~"].contains(&op) +} + +fn optimize_expr( + term1: &Term, + ops: &[(Op, Term)], + sym_table: &mut Option<&mut SymbolTable>, + lhs_context: &LhsContext, +) -> Option> { + // dbg!(term1, ops); + optimize_expr_int_inner(term1, ops, sym_table, lhs_context) + .map(signed_constant_to_constant_insts) +} + +fn signed_constant_to_constant_insts(value: i16) -> Vec { + let mut insts = vec![write_push("constant", value.abs() as u16)]; + if value.is_negative() { + insts.push(write_arith("neg")); + } + insts +} + +fn eval_binop(op: &str, a: i16, b: i16) -> Option { + // dbg!(op, a, b); + match op { + "+" => Some(a + b), + "-" => Some(a - b), + "*" => Some(a * b), + "/" => Some(a / b), + "|" => Some(a | b), + "&" => Some(a & b), + _ => None, + } +} + +fn eval_unop(op: &str, a: i16) -> Option { + // dbg!(op, a, b); + match op { + "-" => eval_binop(op, 0, a), + "~" => Some(if a == 0 { -1 } else { 0 }), + _ => None, + } +} + +fn eval_term(term: &Term, sym_table: &mut Option<&mut SymbolTable>) -> Option { + // dbg!(term); + match term { + Term::IntegerConstant(value) => { + // dbg!(value); + Some((*value).try_into().unwrap()) + } + Term::UnaryOp(Op(op), term) => match eval_term(term, sym_table) { + Some(term_value) => eval_unop(op, term_value), + None => None, + }, + Term::ParenExpr(expr) => { + let Expr(termp1, ops) = &**expr; + optimize_expr_int_inner( + termp1, ops, sym_table, + // add_constant_value_for_static only for top level expression + &None, + ) + } + Term::KeywordConstant(Keyword::Null) => Some(0), + Term::KeywordConstant(Keyword::True) => Some(-1), + Term::KeywordConstant(Keyword::False) => Some(0), + #[allow(clippy::let_and_return)] + Term::VarName(ident) => { + let entry = sym_table.as_ref().and_then(|e| e.lookup(ident))?; + if entry.typ != type_as_string(&GrammarItemType::Int) { + return None; + } + let constant_value = entry.constant_value(); + // dbg!(constant_value, ident, entry); + constant_value + } + _ => None, + } +} diff --git a/src/compiler/src/optimizer/optimize_vm_instructions.rs b/src/compiler/src/optimizer/optimize_vm_instructions.rs new file mode 100644 index 0000000..879b8c0 --- /dev/null +++ b/src/compiler/src/optimizer/optimize_vm_instructions.rs @@ -0,0 +1,36 @@ +use crate::instruction::Instruction; + +use crate::codegen::WriteInst; + +pub fn opimize_vm_instructions(instructions: &mut Vec) { + let mut out = Vec::::with_capacity(instructions.len()); + let mut insts_iter = instructions.iter().peekable(); + + while let Some(wi) = insts_iter.next() { + let inst = wi.instruction(); + match inst { + Instruction::Arithmetic(op) => { + match (op.as_str(), insts_iter.peek().map(|i| i.instruction())) { + ("not", Some(Instruction::Arithmetic(op2))) if op2 == "not" => { + insts_iter.next(); + continue; + } + _ => {} + } + } + Instruction::Goto(goto_label, ..) => { + if let Some(Instruction::Label(label, ..)) = + insts_iter.peek().map(|i| i.instruction()) + { + if label == goto_label { + continue; + } + } + } + _ => {} + } + out.push(wi.to_owned()); + } + + *instructions = out; +} diff --git a/src/compiler/src/parser.rs b/src/compiler/src/parser.rs index 80235c5..9864cb4 100644 --- a/src/compiler/src/parser.rs +++ b/src/compiler/src/parser.rs @@ -18,7 +18,7 @@ pub struct Parser<'a> { } impl<'a> Parser<'a> { - pub fn new(tokens: &'a[Token]) -> Self { + pub fn new(tokens: &'a [Token]) -> Self { Self { tokens: tokens.iter().enumerate().peekable(), tokens_seq: tokens, diff --git a/src/compiler/src/symbol_table.rs b/src/compiler/src/symbol_table.rs index 717c455..8781156 100644 --- a/src/compiler/src/symbol_table.rs +++ b/src/compiler/src/symbol_table.rs @@ -23,6 +23,29 @@ struct EntryClass { typ: String, kind: ClassVarKind, index: u16, + + constant_value: Option, +} + +impl EntryClass { + fn new(typ: String, kind: ClassVarKind, index: u16) -> Self { + Self { + typ, + kind, + index, + constant_value: None, + } + } + + fn set_constant_value(&mut self, term_value: i16) { + assert!( + matches!(self.constant_value, None), + "Must be written only once. Entry: {:?}\nValue:{}", + self, + term_value + ); + self.constant_value = Some(term_value); + } } impl From<&EntryClass> for Entry { @@ -34,6 +57,8 @@ impl From<&EntryClass> for Entry { ClassVarKind::Field => "this".to_string(), ClassVarKind::Static => "static".to_string(), }, + + constant_value: other.constant_value, } } } @@ -60,6 +85,8 @@ impl From<&EntrySub> for Entry { SubVarKind::Argument => "argument".to_string(), SubVarKind::Var => "local".to_string(), }, + + constant_value: None, } } } @@ -86,6 +113,14 @@ pub struct Entry { // What kind of memory segment pub kind: String, pub index: u16, + + constant_value: Option, +} + +impl Entry { + pub fn constant_value(&self) -> Option { + self.constant_value + } } impl SymbolTable { @@ -119,21 +154,12 @@ impl SymbolTable { ) { let dict = &mut self.class; let index = dict.index_dict.entry(kind.into()).or_insert(0); - let entry = EntryClass { - typ: type_as_string(typ), - kind: kind.into(), - index: *index, - }; + let entry = EntryClass::new(type_as_string(typ), kind.into(), *index); *index += 1; dict.entry_dict.insert(name.into(), entry); } - pub fn define_subroutine_var( - &mut self, - name: &str, - kind: SubVarKind, - typ: &GrammarItemType, - ) { + pub fn define_subroutine_var(&mut self, name: &str, kind: SubVarKind, typ: &GrammarItemType) { let dict = &mut self.sub; let index = dict.index_dict.entry(kind.clone()).or_insert(0); let entry = EntrySub { @@ -148,6 +174,12 @@ impl SymbolTable { pub fn reset_subroutine_table(&mut self) { self.sub = Default::default(); } + + pub fn add_constant_value_for_static(&mut self, static_var: &str, term_value: i16) { + if let Some(entry) = self.class.entry_dict.get_mut(static_var) { + entry.set_constant_value(term_value); + } + } } pub fn type_as_string(typ: &GrammarItemType) -> String { diff --git a/src/compiler/src/utils.rs b/src/compiler/src/utils.rs new file mode 100644 index 0000000..1d8c314 --- /dev/null +++ b/src/compiler/src/utils.rs @@ -0,0 +1,23 @@ +use std::collections::VecDeque; + +#[derive(Debug)] +pub struct LimitedVecDeque { + capacity: usize, + deque: VecDeque, +} + +impl LimitedVecDeque { + pub fn new(capacity: usize) -> Self { + Self { + capacity, + deque: VecDeque::with_capacity(capacity), + } + } + + pub fn push(&mut self, value: T) { + if self.deque.len() == self.capacity { + self.deque.pop_front(); + } + self.deque.push_back(value) + } +} diff --git a/src/compiler/tests/snapshots/test_output__Compiler vm code example: snake__Game.jack@Game.jack.snap b/src/compiler/tests/snapshots/test_output__Compiler vm code example: snake__Game.jack@Game.jack.snap index 4f44dc3..78d4424 100644 --- a/src/compiler/tests/snapshots/test_output__Compiler vm code example: snake__Game.jack@Game.jack.snap +++ b/src/compiler/tests/snapshots/test_output__Compiler vm code example: snake__Game.jack@Game.jack.snap @@ -10,9 +10,7 @@ call Memory.alloc 1 pop pointer 0 push constant 60 pop static 0 -push static 0 -push constant 30 -call Math.divide 2 +push constant 2 pop static 1 push constant 18 call String.new 1 @@ -53,6 +51,35 @@ call String.appendChar 2 push constant 61 call String.appendChar 2 pop static 2 +push constant 13 +call String.new 1 +push constant 61 +call String.appendChar 2 +push constant 61 +call String.appendChar 2 +push constant 61 +call String.appendChar 2 +push constant 32 +call String.appendChar 2 +push constant 80 +call String.appendChar 2 +push constant 97 +call String.appendChar 2 +push constant 117 +call String.appendChar 2 +push constant 115 +call String.appendChar 2 +push constant 101 +call String.appendChar 2 +push constant 32 +call String.appendChar 2 +push constant 61 +call String.appendChar 2 +push constant 61 +call String.appendChar 2 +push constant 61 +call String.appendChar 2 +pop static 3 push constant 0 pop this 3 push constant 0 @@ -64,7 +91,7 @@ pop this 4 push constant 0 pop this 2 push constant 2341 -pop static 3 +pop static 4 push pointer 0 return function Game.start 0 @@ -73,13 +100,10 @@ pop pointer 0 push this 6 push constant 0 eq -not -not if-goto __VM_LABEL_1 push this 6 call Snake.dispose 1 pop temp 0 -goto __VM_LABEL_1 label __VM_LABEL_1 push constant 1 pop this 3 @@ -87,13 +111,9 @@ label __VM_LABEL_2 push this 3 push constant 0 eq -not -not if-goto __VM_LABEL_3 -call Screen.clearScreen 0 -pop temp 0 -push this 7 -call UI.init 1 +push pointer 0 +call Game.redraw 1 pop temp 0 push constant 0 pop this 1 @@ -107,9 +127,6 @@ push pointer 0 push this 6 call Game.placeApple 2 pop this 4 -push this 5 -call UI.drawIngameMenu 1 -pop temp 0 push pointer 0 call Game.run 1 pop temp 0 @@ -131,6 +148,19 @@ call Memory.deAlloc 1 pop temp 0 push constant 0 return +function Game.redraw 0 +push argument 0 +pop pointer 0 +call Screen.clearScreen 0 +pop temp 0 +push this 7 +call UI.init 1 +pop temp 0 +push this 5 +call UI.drawIngameMenu 1 +pop temp 0 +push constant 0 +return function Game.run 3 push argument 0 pop pointer 0 @@ -143,8 +173,6 @@ call Snake.drawFull 1 pop temp 0 label __VM_LABEL_4 push local 1 -not -not if-goto __VM_LABEL_5 call Keyboard.keyPressed 0 pop local 0 @@ -152,26 +180,39 @@ push local 0 push constant 0 eq not +push local 0 +push this 0 +eq +not +and not if-goto __VM_LABEL_6 push local 0 pop this 0 -goto __VM_LABEL_6 label __VM_LABEL_6 push this 0 push constant 81 eq not if-goto __VM_LABEL_7 -push constant 0 -not +push constant 1 +neg pop local 1 push constant 0 pop this 3 push this 3 return -goto __VM_LABEL_7 label __VM_LABEL_7 +push this 0 +push constant 80 +eq +not +if-goto __VM_LABEL_8 +push pointer 0 +push this 1 +call Game.pauseLoop 2 +pop temp 0 +label __VM_LABEL_8 push pointer 0 call Game.tickGame 1 pop local 2 @@ -184,12 +225,11 @@ or pop local 1 push local 2 not -if-goto __VM_LABEL_8 +if-goto __VM_LABEL_9 push pointer 0 call Game.endGameLoop 1 pop temp 0 -goto __VM_LABEL_8 -label __VM_LABEL_8 +label __VM_LABEL_9 goto __VM_LABEL_4 label __VM_LABEL_5 push this 3 @@ -202,12 +242,12 @@ push constant 1 add pop this 1 push this 1 -push static 1 +push constant 2 call Utils.modulo 2 push constant 0 eq not -if-goto __VM_LABEL_9 +if-goto __VM_LABEL_10 push this 2 push constant 1 add @@ -216,53 +256,49 @@ push this 0 push constant 131 eq not -if-goto __VM_LABEL_11 +if-goto __VM_LABEL_12 push constant 1 pop local 2 -goto __VM_LABEL_10 -label __VM_LABEL_11 +goto __VM_LABEL_11 +label __VM_LABEL_12 push this 0 push constant 133 eq not -if-goto __VM_LABEL_13 +if-goto __VM_LABEL_14 push constant 2 pop local 2 -goto __VM_LABEL_12 -label __VM_LABEL_13 +goto __VM_LABEL_13 +label __VM_LABEL_14 push this 0 push constant 130 eq not -if-goto __VM_LABEL_15 +if-goto __VM_LABEL_16 push constant 3 pop local 2 -goto __VM_LABEL_14 -label __VM_LABEL_15 +goto __VM_LABEL_15 +label __VM_LABEL_16 push this 0 push constant 132 eq not -if-goto __VM_LABEL_16 +if-goto __VM_LABEL_17 push constant 4 pop local 2 -goto __VM_LABEL_16 -label __VM_LABEL_16 -label __VM_LABEL_14 -label __VM_LABEL_12 -label __VM_LABEL_10 +label __VM_LABEL_17 +label __VM_LABEL_15 +label __VM_LABEL_13 +label __VM_LABEL_11 push local 2 push constant 0 eq -not -not -if-goto __VM_LABEL_17 +if-goto __VM_LABEL_18 push this 6 push local 2 call Snake.setDirection 2 pop temp 0 -goto __VM_LABEL_17 -label __VM_LABEL_17 +label __VM_LABEL_18 push this 6 push this 4 call Snake.advance 2 @@ -281,13 +317,12 @@ push that 0 pop local 1 push local 1 not -if-goto __VM_LABEL_18 +if-goto __VM_LABEL_19 push this 5 push constant 1 add pop this 5 -goto __VM_LABEL_18 -label __VM_LABEL_18 +label __VM_LABEL_19 push pointer 0 push this 6 call Game.placeApple 2 @@ -295,11 +330,8 @@ pop this 4 push pointer 0 call Game.drawApple 1 pop temp 0 -goto __VM_LABEL_9 -label __VM_LABEL_9 -push constant 1000 -push static 0 -call Math.divide 2 +label __VM_LABEL_10 +push constant 16 call Sys.wait 1 pop temp 0 call Keyboard.keyPressed 0 @@ -319,30 +351,80 @@ pop temp 0 push this 6 call Snake.dispose 1 pop temp 0 -label __VM_LABEL_19 +label __VM_LABEL_20 push this 3 push constant 2 eq not -if-goto __VM_LABEL_20 +if-goto __VM_LABEL_21 call Keyboard.keyPressed 0 pop local 0 push local 0 push constant 82 eq not -if-goto __VM_LABEL_21 +if-goto __VM_LABEL_22 push constant 1 pop this 3 -goto __VM_LABEL_21 +label __VM_LABEL_22 +push constant 16 +call Sys.wait 1 +pop temp 0 +goto __VM_LABEL_20 label __VM_LABEL_21 -push constant 1000 -push static 0 -call Math.divide 2 +push constant 0 +return +function Game.pauseLoop 1 +push argument 0 +pop pointer 0 +push constant 3 +pop this 3 +push constant 200 +push constant 100 +push static 3 +call UI.drawPanel 3 +pop temp 0 +label __VM_LABEL_23 +push this 3 +push constant 3 +eq +not +if-goto __VM_LABEL_24 +call Keyboard.keyPressed 0 +pop local 0 +push local 0 +push constant 80 +eq +push this 1 +push argument 1 +sub +push constant 10 +gt +and +not +if-goto __VM_LABEL_25 +push constant 1 +pop this 3 +push constant 0 +pop local 0 +push constant 200 call Sys.wait 1 pop temp 0 -goto __VM_LABEL_19 -label __VM_LABEL_20 +push pointer 0 +call Game.redraw 1 +pop temp 0 +push constant 0 +return +label __VM_LABEL_25 +push constant 16 +call Sys.wait 1 +pop temp 0 +push this 1 +push constant 1 +add +pop this 1 +goto __VM_LABEL_23 +label __VM_LABEL_24 push constant 0 return function Game.placeApple 1 @@ -352,46 +434,47 @@ push argument 1 call Snake.getHead 1 push this 4 eq -not -not -if-goto __VM_LABEL_22 +if-goto __VM_LABEL_26 push this 4 return -goto __VM_LABEL_22 -label __VM_LABEL_22 +label __VM_LABEL_26 push this 4 pop local 0 push local 0 -push static 3 +push static 4 add +push this 1 +call Math.multiply 2 call UI.getBoardIndexSize 0 push constant 1 sub call Utils.modulo 2 pop local 0 -label __VM_LABEL_23 +label __VM_LABEL_27 push argument 1 push local 0 call Snake.isCollided 2 not -if-goto __VM_LABEL_24 +if-goto __VM_LABEL_28 push local 0 -push static 3 +push static 4 add +push this 1 +call Math.multiply 2 call UI.getBoardIndexSize 0 push constant 1 sub call Utils.modulo 2 pop local 0 -goto __VM_LABEL_23 -label __VM_LABEL_24 +goto __VM_LABEL_27 +label __VM_LABEL_28 push local 0 return function Game.drawApple 0 push argument 0 pop pointer 0 -push constant 0 -not +push constant 1 +neg push this 4 call UI.drawBlockIndex 2 pop temp 0 diff --git a/src/compiler/tests/snapshots/test_output__Compiler vm code example: snake__List.jack@List.jack.snap b/src/compiler/tests/snapshots/test_output__Compiler vm code example: snake__List.jack@List.jack.snap index ffd669c..c3ef307 100644 --- a/src/compiler/tests/snapshots/test_output__Compiler vm code example: snake__List.jack@List.jack.snap +++ b/src/compiler/tests/snapshots/test_output__Compiler vm code example: snake__List.jack@List.jack.snap @@ -47,8 +47,6 @@ label __VM_LABEL_1 push local 0 push constant 0 eq -not -not if-goto __VM_LABEL_2 push local 0 call List.getData 1 @@ -70,13 +68,10 @@ pop pointer 0 push this 1 push constant 0 eq -not -not if-goto __VM_LABEL_3 push this 1 call List.dispose 1 pop temp 0 -goto __VM_LABEL_3 label __VM_LABEL_3 push pointer 0 call Memory.deAlloc 1 @@ -107,7 +102,6 @@ not if-goto __VM_LABEL_4 push constant 0 return -goto __VM_LABEL_4 label __VM_LABEL_4 push local 0 pop local 1 @@ -119,8 +113,6 @@ push local 2 call List.getNext 1 push constant 0 eq -not -not if-goto __VM_LABEL_6 push local 1 call List.getNext 1 @@ -152,8 +144,6 @@ push local 0 call List.getNext 1 push constant 0 eq -not -not if-goto __VM_LABEL_8 push local 0 call List.getNext 1 diff --git a/src/compiler/tests/snapshots/test_output__Compiler vm code example: snake__Snake.jack@Snake.jack.snap b/src/compiler/tests/snapshots/test_output__Compiler vm code example: snake__Snake.jack@Snake.jack.snap index 25098af..6a77585 100644 --- a/src/compiler/tests/snapshots/test_output__Compiler vm code example: snake__Snake.jack@Snake.jack.snap +++ b/src/compiler/tests/snapshots/test_output__Compiler vm code example: snake__Snake.jack@Snake.jack.snap @@ -89,12 +89,9 @@ pop local 1 push local 1 push local 0 eq -not -not if-goto __VM_LABEL_3 push argument 1 pop this 1 -goto __VM_LABEL_3 label __VM_LABEL_3 push constant 0 return @@ -163,7 +160,6 @@ not if-goto __VM_LABEL_10 push constant 1 pop local 2 -goto __VM_LABEL_10 label __VM_LABEL_10 label __VM_LABEL_8 label __VM_LABEL_6 @@ -198,15 +194,14 @@ if-goto __VM_LABEL_11 push this 3 push constant 0 add -push constant 0 -not +push constant 1 +neg pop temp 0 pop pointer 1 push temp 0 pop that 0 push this 3 return -goto __VM_LABEL_11 label __VM_LABEL_11 push argument 1 push local 1 @@ -226,7 +221,6 @@ if-goto __VM_LABEL_12 push pointer 0 call Snake.grow 1 pop temp 0 -goto __VM_LABEL_12 label __VM_LABEL_12 push this 0 push local 1 @@ -264,8 +258,6 @@ label __VM_LABEL_13 push local 0 push constant 0 eq -not -not if-goto __VM_LABEL_14 push pointer 0 push local 0 @@ -287,15 +279,12 @@ pop local 0 push local 0 push constant 0 eq -not -not if-goto __VM_LABEL_15 push local 0 call List.getData 1 push this 1 call UI.drawSnakeHead 2 pop temp 0 -goto __VM_LABEL_15 label __VM_LABEL_15 push local 0 call List.getNext 1 @@ -333,8 +322,6 @@ label __VM_LABEL_16 push local 0 push constant 0 eq -not -not if-goto __VM_LABEL_17 push local 0 call List.getData 1 @@ -342,10 +329,9 @@ push argument 1 eq not if-goto __VM_LABEL_18 -push constant 0 -not +push constant 1 +neg return -goto __VM_LABEL_18 label __VM_LABEL_18 push local 0 call List.getNext 1 diff --git a/src/compiler/tests/snapshots/test_output__Compiler vm code example: snake__UI.jack@UI.jack.snap b/src/compiler/tests/snapshots/test_output__Compiler vm code example: snake__UI.jack@UI.jack.snap index 4497062..a9e7869 100644 --- a/src/compiler/tests/snapshots/test_output__Compiler vm code example: snake__UI.jack@UI.jack.snap +++ b/src/compiler/tests/snapshots/test_output__Compiler vm code example: snake__UI.jack@UI.jack.snap @@ -12,21 +12,9 @@ push constant 8 pop static 0 push constant 4 pop static 1 -push constant 512 -push static 0 -call Math.divide 2 -push constant 2 -push static 1 -call Math.multiply 2 -sub +push constant 56 pop static 2 -push constant 256 -push static 0 -call Math.divide 2 -push constant 2 -push static 1 -call Math.multiply 2 -sub +push constant 24 pop static 3 push constant 1 neg @@ -36,12 +24,10 @@ return function UI.init 1 push argument 0 pop pointer 0 -push static 1 -push static 0 -call Math.multiply 2 +push constant 32 pop local 0 -push constant 0 -not +push constant 1 +neg call Screen.setColor 1 pop temp 0 push local 0 @@ -96,11 +82,9 @@ label __VM_LABEL_1 push local 1 push constant 0 lt -not -not if-goto __VM_LABEL_2 -push constant 0 -not +push constant 1 +neg call Screen.setColor 1 pop temp 0 push local 2 @@ -171,15 +155,13 @@ pop temp 0 push constant 0 return function UI.getFieldWidth 0 -push static 2 +push constant 56 return function UI.getFieldHeight 0 -push static 3 +push constant 24 return function UI.getBoardIndexSize 0 -push static 2 -push static 3 -call Math.multiply 2 +push constant 1344 return function UI.drawBlock 0 push argument 0 @@ -217,7 +199,6 @@ push constant 6 pop local 3 push constant 2 pop local 4 -goto __VM_LABEL_3 label __VM_LABEL_3 push argument 1 push constant 2 @@ -232,7 +213,6 @@ push constant 2 pop local 3 push constant 6 pop local 4 -goto __VM_LABEL_4 label __VM_LABEL_4 push argument 1 push constant 3 @@ -247,7 +227,6 @@ push constant 2 pop local 3 push constant 2 pop local 4 -goto __VM_LABEL_5 label __VM_LABEL_5 push argument 1 push constant 4 @@ -262,7 +241,6 @@ push constant 6 pop local 3 push constant 6 pop local 4 -goto __VM_LABEL_6 label __VM_LABEL_6 push local 0 push constant 0 @@ -302,8 +280,8 @@ pop temp 0 push constant 0 return function UI.drawSnakePartBase 2 -push constant 0 -not +push constant 1 +neg push argument 0 call UI.drawBlockIndex 2 pop temp 0 @@ -313,7 +291,7 @@ pop temp 0 push argument 0 call UI.fromGameToScreen 1 pop local 1 -push static 0 +push constant 8 pop local 0 push local 1 push constant 0 @@ -460,7 +438,7 @@ push local 0 push constant 0 add push argument 0 -push static 2 +push constant 56 call Utils.modulo 2 pop temp 0 pop pointer 1 @@ -488,7 +466,7 @@ pop local 1 push local 1 push constant 0 add -push static 0 +push constant 8 push static 1 push local 0 push constant 0 @@ -504,7 +482,7 @@ pop that 0 push local 1 push constant 1 add -push static 0 +push constant 8 push static 1 push local 0 push constant 1 @@ -523,15 +501,6 @@ pop temp 0 push local 1 return function UI.updateScore 1 -push argument 0 -push static 4 -eq -not -if-goto __VM_LABEL_7 -push constant 0 -return -goto __VM_LABEL_7 -label __VM_LABEL_7 push constant 7 call String.new 1 push constant 83 @@ -568,6 +537,14 @@ push constant 0 return function UI.drawIngameMenu 0 push argument 0 +push static 4 +eq +not +if-goto __VM_LABEL_7 +push constant 0 +return +label __VM_LABEL_7 +push argument 0 call UI.updateScore 1 pop temp 0 push constant 0 diff --git a/src/compiler/tests/snapshots/test_output__Compiler vm code example: snake__Utils.jack@Utils.jack.snap b/src/compiler/tests/snapshots/test_output__Compiler vm code example: snake__Utils.jack@Utils.jack.snap index cd64827..2a44857 100644 --- a/src/compiler/tests/snapshots/test_output__Compiler vm code example: snake__Utils.jack@Utils.jack.snap +++ b/src/compiler/tests/snapshots/test_output__Compiler vm code example: snake__Utils.jack@Utils.jack.snap @@ -22,7 +22,6 @@ push local 0 push argument 1 add pop local 0 -goto __VM_LABEL_1 label __VM_LABEL_1 push local 0 return diff --git a/src/compiler/tests/snapshots/test_output__Compiler vm code: src__compiler__tests__inputs__10__ExpressionLessSquare__Square.jack@Square.jack.snap b/src/compiler/tests/snapshots/test_output__Compiler vm code: src__compiler__tests__inputs__10__ExpressionLessSquare__Square.jack@Square.jack.snap index 2b6ede2..ced16f4 100644 --- a/src/compiler/tests/snapshots/test_output__Compiler vm code: src__compiler__tests__inputs__10__ExpressionLessSquare__Square.jack@Square.jack.snap +++ b/src/compiler/tests/snapshots/test_output__Compiler vm code: src__compiler__tests__inputs__10__ExpressionLessSquare__Square.jack@Square.jack.snap @@ -69,7 +69,6 @@ pop this 2 push pointer 0 call Square.draw 1 pop temp 0 -goto __VM_LABEL_1 label __VM_LABEL_1 push constant 0 return @@ -87,7 +86,6 @@ pop this 2 push pointer 0 call Square.draw 1 pop temp 0 -goto __VM_LABEL_2 label __VM_LABEL_2 push constant 0 return @@ -117,7 +115,6 @@ push this 0 push this 1 call Screen.drawRectangle 4 pop temp 0 -goto __VM_LABEL_3 label __VM_LABEL_3 push constant 0 return @@ -147,7 +144,6 @@ push this 0 push this 1 call Screen.drawRectangle 4 pop temp 0 -goto __VM_LABEL_4 label __VM_LABEL_4 push constant 0 return @@ -177,7 +173,6 @@ push this 0 push this 1 call Screen.drawRectangle 4 pop temp 0 -goto __VM_LABEL_5 label __VM_LABEL_5 push constant 0 return @@ -207,7 +202,6 @@ push this 0 push this 1 call Screen.drawRectangle 4 pop temp 0 -goto __VM_LABEL_6 label __VM_LABEL_6 push constant 0 return diff --git a/src/compiler/tests/snapshots/test_output__Compiler vm code: src__compiler__tests__inputs__10__ExpressionLessSquare__SquareGame.jack@SquareGame.jack.snap b/src/compiler/tests/snapshots/test_output__Compiler vm code: src__compiler__tests__inputs__10__ExpressionLessSquare__SquareGame.jack@SquareGame.jack.snap index b67b5cc..86b2dbb 100644 --- a/src/compiler/tests/snapshots/test_output__Compiler vm code: src__compiler__tests__inputs__10__ExpressionLessSquare__SquareGame.jack@SquareGame.jack.snap +++ b/src/compiler/tests/snapshots/test_output__Compiler vm code: src__compiler__tests__inputs__10__ExpressionLessSquare__SquareGame.jack@SquareGame.jack.snap @@ -34,7 +34,6 @@ if-goto __VM_LABEL_1 push this 0 call Square.moveUp 1 pop temp 0 -goto __VM_LABEL_1 label __VM_LABEL_1 push this 1 not @@ -42,7 +41,6 @@ if-goto __VM_LABEL_2 push this 0 call Square.moveDown 1 pop temp 0 -goto __VM_LABEL_2 label __VM_LABEL_2 push this 1 not @@ -50,7 +48,6 @@ if-goto __VM_LABEL_3 push this 0 call Square.moveLeft 1 pop temp 0 -goto __VM_LABEL_3 label __VM_LABEL_3 push this 1 not @@ -58,7 +55,6 @@ if-goto __VM_LABEL_4 push this 0 call Square.moveRight 1 pop temp 0 -goto __VM_LABEL_4 label __VM_LABEL_4 push this 1 call Sys.wait 1 @@ -90,7 +86,6 @@ not if-goto __VM_LABEL_9 push local 1 pop local 1 -goto __VM_LABEL_9 label __VM_LABEL_9 push local 0 not @@ -98,7 +93,6 @@ if-goto __VM_LABEL_10 push this 0 call Square.decSize 1 pop temp 0 -goto __VM_LABEL_10 label __VM_LABEL_10 push local 0 not @@ -106,35 +100,30 @@ if-goto __VM_LABEL_11 push this 0 call Square.incSize 1 pop temp 0 -goto __VM_LABEL_11 label __VM_LABEL_11 push local 0 not if-goto __VM_LABEL_12 push local 1 pop this 1 -goto __VM_LABEL_12 label __VM_LABEL_12 push local 0 not if-goto __VM_LABEL_13 push local 0 pop this 1 -goto __VM_LABEL_13 label __VM_LABEL_13 push local 0 not if-goto __VM_LABEL_14 push this 0 pop this 1 -goto __VM_LABEL_14 label __VM_LABEL_14 push local 0 not if-goto __VM_LABEL_15 push this 1 pop this 1 -goto __VM_LABEL_15 label __VM_LABEL_15 label __VM_LABEL_16 push local 0 diff --git a/src/compiler/tests/snapshots/test_output__Compiler vm code: src__compiler__tests__inputs__10__Square__Square.jack@Square.jack.snap b/src/compiler/tests/snapshots/test_output__Compiler vm code: src__compiler__tests__inputs__10__Square__Square.jack@Square.jack.snap index 8ade166..4a36fe6 100644 --- a/src/compiler/tests/snapshots/test_output__Compiler vm code: src__compiler__tests__inputs__10__Square__Square.jack@Square.jack.snap +++ b/src/compiler/tests/snapshots/test_output__Compiler vm code: src__compiler__tests__inputs__10__Square__Square.jack@Square.jack.snap @@ -30,8 +30,8 @@ return function Square.draw 0 push argument 0 pop pointer 0 -push constant 0 -not +push constant 1 +neg call Screen.setColor 1 pop temp 0 push this 0 @@ -90,7 +90,6 @@ pop this 2 push pointer 0 call Square.draw 1 pop temp 0 -goto __VM_LABEL_1 label __VM_LABEL_1 push constant 0 return @@ -112,7 +111,6 @@ pop this 2 push pointer 0 call Square.draw 1 pop temp 0 -goto __VM_LABEL_2 label __VM_LABEL_2 push constant 0 return @@ -145,8 +143,8 @@ push this 1 push constant 2 sub pop this 1 -push constant 0 -not +push constant 1 +neg call Screen.setColor 1 pop temp 0 push this 0 @@ -159,7 +157,6 @@ push constant 1 add call Screen.drawRectangle 4 pop temp 0 -goto __VM_LABEL_3 label __VM_LABEL_3 push constant 0 return @@ -190,8 +187,8 @@ push this 1 push constant 2 add pop this 1 -push constant 0 -not +push constant 1 +neg call Screen.setColor 1 pop temp 0 push this 0 @@ -208,7 +205,6 @@ push this 2 add call Screen.drawRectangle 4 pop temp 0 -goto __VM_LABEL_4 label __VM_LABEL_4 push constant 0 return @@ -241,8 +237,8 @@ push this 0 push constant 2 sub pop this 0 -push constant 0 -not +push constant 1 +neg call Screen.setColor 1 pop temp 0 push this 0 @@ -255,7 +251,6 @@ push this 2 add call Screen.drawRectangle 4 pop temp 0 -goto __VM_LABEL_5 label __VM_LABEL_5 push constant 0 return @@ -286,8 +281,8 @@ push this 0 push constant 2 add pop this 0 -push constant 0 -not +push constant 1 +neg call Screen.setColor 1 pop temp 0 push this 0 @@ -304,7 +299,6 @@ push this 2 add call Screen.drawRectangle 4 pop temp 0 -goto __VM_LABEL_6 label __VM_LABEL_6 push constant 0 return diff --git a/src/compiler/tests/snapshots/test_output__Compiler vm code: src__compiler__tests__inputs__10__Square__SquareGame.jack@SquareGame.jack.snap b/src/compiler/tests/snapshots/test_output__Compiler vm code: src__compiler__tests__inputs__10__Square__SquareGame.jack@SquareGame.jack.snap index 72abfe4..65ae248 100644 --- a/src/compiler/tests/snapshots/test_output__Compiler vm code: src__compiler__tests__inputs__10__Square__SquareGame.jack@SquareGame.jack.snap +++ b/src/compiler/tests/snapshots/test_output__Compiler vm code: src__compiler__tests__inputs__10__Square__SquareGame.jack@SquareGame.jack.snap @@ -39,7 +39,6 @@ if-goto __VM_LABEL_1 push this 0 call Square.moveUp 1 pop temp 0 -goto __VM_LABEL_1 label __VM_LABEL_1 push this 1 push constant 2 @@ -49,7 +48,6 @@ if-goto __VM_LABEL_2 push this 0 call Square.moveDown 1 pop temp 0 -goto __VM_LABEL_2 label __VM_LABEL_2 push this 1 push constant 3 @@ -59,7 +57,6 @@ if-goto __VM_LABEL_3 push this 0 call Square.moveLeft 1 pop temp 0 -goto __VM_LABEL_3 label __VM_LABEL_3 push this 1 push constant 4 @@ -69,7 +66,6 @@ if-goto __VM_LABEL_4 push this 0 call Square.moveRight 1 pop temp 0 -goto __VM_LABEL_4 label __VM_LABEL_4 push constant 5 call Sys.wait 1 @@ -83,8 +79,6 @@ push constant 0 pop local 1 label __VM_LABEL_5 push local 1 -not -not if-goto __VM_LABEL_6 label __VM_LABEL_7 push local 0 @@ -104,10 +98,9 @@ push constant 81 eq not if-goto __VM_LABEL_9 -push constant 0 -not +push constant 1 +neg pop local 1 -goto __VM_LABEL_9 label __VM_LABEL_9 push local 0 push constant 90 @@ -117,7 +110,6 @@ if-goto __VM_LABEL_10 push this 0 call Square.decSize 1 pop temp 0 -goto __VM_LABEL_10 label __VM_LABEL_10 push local 0 push constant 88 @@ -127,7 +119,6 @@ if-goto __VM_LABEL_11 push this 0 call Square.incSize 1 pop temp 0 -goto __VM_LABEL_11 label __VM_LABEL_11 push local 0 push constant 131 @@ -136,7 +127,6 @@ not if-goto __VM_LABEL_12 push constant 1 pop this 1 -goto __VM_LABEL_12 label __VM_LABEL_12 push local 0 push constant 133 @@ -145,7 +135,6 @@ not if-goto __VM_LABEL_13 push constant 2 pop this 1 -goto __VM_LABEL_13 label __VM_LABEL_13 push local 0 push constant 130 @@ -154,7 +143,6 @@ not if-goto __VM_LABEL_14 push constant 3 pop this 1 -goto __VM_LABEL_14 label __VM_LABEL_14 push local 0 push constant 132 @@ -163,14 +151,11 @@ not if-goto __VM_LABEL_15 push constant 4 pop this 1 -goto __VM_LABEL_15 label __VM_LABEL_15 label __VM_LABEL_16 push local 0 push constant 0 eq -not -not if-goto __VM_LABEL_17 call Keyboard.keyPressed 0 pop local 0 diff --git a/src/compiler/tests/snapshots/test_output__Compiler vm code: src__compiler__tests__inputs__11__ComplexArrays__Main.jack@Main.jack.snap b/src/compiler/tests/snapshots/test_output__Compiler vm code: src__compiler__tests__inputs__11__ComplexArrays__Main.jack@Main.jack.snap index 483483e..2c82b89 100644 --- a/src/compiler/tests/snapshots/test_output__Compiler vm code: src__compiler__tests__inputs__11__ComplexArrays__Main.jack@Main.jack.snap +++ b/src/compiler/tests/snapshots/test_output__Compiler vm code: src__compiler__tests__inputs__11__ComplexArrays__Main.jack@Main.jack.snap @@ -469,7 +469,6 @@ pop temp 0 pop pointer 1 push temp 0 pop that 0 -goto __VM_LABEL_1 label __VM_LABEL_1 push constant 44 call String.new 1 diff --git a/src/compiler/tests/snapshots/test_output__Compiler vm code: src__compiler__tests__inputs__11__ConvertToBin__Main.jack@Main.jack.snap b/src/compiler/tests/snapshots/test_output__Compiler vm code: src__compiler__tests__inputs__11__ConvertToBin__Main.jack@Main.jack.snap index 290861f..f55636f 100644 --- a/src/compiler/tests/snapshots/test_output__Compiler vm code: src__compiler__tests__inputs__11__ConvertToBin__Main.jack@Main.jack.snap +++ b/src/compiler/tests/snapshots/test_output__Compiler vm code: src__compiler__tests__inputs__11__ConvertToBin__Main.jack@Main.jack.snap @@ -20,8 +20,8 @@ pop temp 0 push constant 0 return function Main.convert 3 -push constant 0 -not +push constant 1 +neg pop local 2 label __VM_LABEL_1 push local 2 @@ -37,16 +37,12 @@ pop local 0 push local 1 push constant 16 gt -not -not if-goto __VM_LABEL_4 push argument 0 push local 0 and push constant 0 eq -not -not if-goto __VM_LABEL_6 push constant 8000 push local 1 diff --git a/src/compiler/tests/snapshots/test_output__Compiler vm code: src__compiler__tests__inputs__11__Pong__Ball.jack@Ball.jack.snap b/src/compiler/tests/snapshots/test_output__Compiler vm code: src__compiler__tests__inputs__11__Pong__Ball.jack@Ball.jack.snap index 8048bb0..7b9b743 100644 --- a/src/compiler/tests/snapshots/test_output__Compiler vm code: src__compiler__tests__inputs__11__Pong__Ball.jack@Ball.jack.snap +++ b/src/compiler/tests/snapshots/test_output__Compiler vm code: src__compiler__tests__inputs__11__Pong__Ball.jack@Ball.jack.snap @@ -42,8 +42,8 @@ return function Ball.show 0 push argument 0 pop pointer 0 -push constant 0 -not +push constant 1 +neg call Screen.setColor 1 pop temp 0 push pointer 0 @@ -249,50 +249,38 @@ label __VM_LABEL_11 push this 0 push this 10 gt -not -not if-goto __VM_LABEL_17 push constant 1 pop this 14 push this 10 pop this 0 -goto __VM_LABEL_17 label __VM_LABEL_17 push this 0 push this 11 lt -not -not if-goto __VM_LABEL_18 push constant 2 pop this 14 push this 11 pop this 0 -goto __VM_LABEL_18 label __VM_LABEL_18 push this 1 push this 12 gt -not -not if-goto __VM_LABEL_19 push constant 3 pop this 14 push this 12 pop this 1 -goto __VM_LABEL_19 label __VM_LABEL_19 push this 1 push this 13 lt -not -not if-goto __VM_LABEL_20 push constant 4 pop this 14 push this 13 pop this 1 -goto __VM_LABEL_20 label __VM_LABEL_20 push pointer 0 call Ball.show 1 diff --git a/src/compiler/tests/snapshots/test_output__Compiler vm code: src__compiler__tests__inputs__11__Pong__Bat.jack@Bat.jack.snap b/src/compiler/tests/snapshots/test_output__Compiler vm code: src__compiler__tests__inputs__11__Pong__Bat.jack@Bat.jack.snap index d85d438..63fb025 100644 --- a/src/compiler/tests/snapshots/test_output__Compiler vm code: src__compiler__tests__inputs__11__Pong__Bat.jack@Bat.jack.snap +++ b/src/compiler/tests/snapshots/test_output__Compiler vm code: src__compiler__tests__inputs__11__Pong__Bat.jack@Bat.jack.snap @@ -34,8 +34,8 @@ return function Bat.show 0 push argument 0 pop pointer 0 -push constant 0 -not +push constant 1 +neg call Screen.setColor 1 pop temp 0 push pointer 0 @@ -120,7 +120,6 @@ not if-goto __VM_LABEL_3 push constant 0 pop this 0 -goto __VM_LABEL_3 label __VM_LABEL_3 push constant 0 call Screen.setColor 1 @@ -141,8 +140,8 @@ push this 3 add call Screen.drawRectangle 4 pop temp 0 -push constant 0 -not +push constant 1 +neg call Screen.setColor 1 pop temp 0 push this 0 @@ -172,7 +171,6 @@ push constant 511 push this 2 sub pop this 0 -goto __VM_LABEL_4 label __VM_LABEL_4 push constant 0 call Screen.setColor 1 @@ -189,8 +187,8 @@ push this 3 add call Screen.drawRectangle 4 pop temp 0 -push constant 0 -not +push constant 1 +neg call Screen.setColor 1 pop temp 0 push this 0 diff --git a/src/compiler/tests/snapshots/test_output__Compiler vm code: src__compiler__tests__inputs__11__Pong__PongGame.jack@PongGame.jack.snap b/src/compiler/tests/snapshots/test_output__Compiler vm code: src__compiler__tests__inputs__11__Pong__PongGame.jack@PongGame.jack.snap index bf993c3..fa42ac5 100644 --- a/src/compiler/tests/snapshots/test_output__Compiler vm code: src__compiler__tests__inputs__11__Pong__PongGame.jack@PongGame.jack.snap +++ b/src/compiler/tests/snapshots/test_output__Compiler vm code: src__compiler__tests__inputs__11__Pong__PongGame.jack@PongGame.jack.snap @@ -98,8 +98,6 @@ push argument 0 pop pointer 0 label __VM_LABEL_1 push this 3 -not -not if-goto __VM_LABEL_2 label __VM_LABEL_3 push local 0 @@ -150,10 +148,9 @@ push constant 140 eq not if-goto __VM_LABEL_9 -push constant 0 -not +push constant 1 +neg pop this 3 -goto __VM_LABEL_9 label __VM_LABEL_9 label __VM_LABEL_7 label __VM_LABEL_5 @@ -211,7 +208,6 @@ push constant 114 call String.appendChar 2 call Output.printString 1 pop temp 0 -goto __VM_LABEL_12 label __VM_LABEL_12 push constant 0 return @@ -261,8 +257,6 @@ lt or pop this 3 push this 3 -not -not if-goto __VM_LABEL_15 push local 4 push local 1 @@ -285,7 +279,6 @@ not if-goto __VM_LABEL_18 push constant 1 pop local 0 -goto __VM_LABEL_18 label __VM_LABEL_18 label __VM_LABEL_16 push this 6 @@ -307,15 +300,12 @@ pop temp 0 push this 4 call Output.printInt 1 pop temp 0 -goto __VM_LABEL_15 label __VM_LABEL_15 -goto __VM_LABEL_14 label __VM_LABEL_14 push this 1 push local 0 call Ball.bounce 2 pop temp 0 -goto __VM_LABEL_13 label __VM_LABEL_13 push constant 0 return diff --git a/src/compiler/tests/snapshots/test_output__Compiler vm code: src__compiler__tests__inputs__11__Seven__Main.jack@Main.jack.snap b/src/compiler/tests/snapshots/test_output__Compiler vm code: src__compiler__tests__inputs__11__Seven__Main.jack@Main.jack.snap index 55c30a0..43ed84f 100644 --- a/src/compiler/tests/snapshots/test_output__Compiler vm code: src__compiler__tests__inputs__11__Seven__Main.jack@Main.jack.snap +++ b/src/compiler/tests/snapshots/test_output__Compiler vm code: src__compiler__tests__inputs__11__Seven__Main.jack@Main.jack.snap @@ -5,11 +5,7 @@ input_file: src/compiler/tests/inputs/11/Seven/Main.jack --- function Main.main 0 -push constant 1 -push constant 2 -push constant 3 -call Math.multiply 2 -add +push constant 7 call Output.printInt 1 pop temp 0 push constant 0 diff --git a/src/compiler/tests/snapshots/test_output__Compiler vm code: src__compiler__tests__inputs__11__Square__Square.jack@Square.jack.snap b/src/compiler/tests/snapshots/test_output__Compiler vm code: src__compiler__tests__inputs__11__Square__Square.jack@Square.jack.snap index 806337d..499a94a 100644 --- a/src/compiler/tests/snapshots/test_output__Compiler vm code: src__compiler__tests__inputs__11__Square__Square.jack@Square.jack.snap +++ b/src/compiler/tests/snapshots/test_output__Compiler vm code: src__compiler__tests__inputs__11__Square__Square.jack@Square.jack.snap @@ -30,8 +30,8 @@ return function Square.draw 0 push argument 0 pop pointer 0 -push constant 0 -not +push constant 1 +neg call Screen.setColor 1 pop temp 0 push this 0 @@ -90,7 +90,6 @@ pop this 2 push pointer 0 call Square.draw 1 pop temp 0 -goto __VM_LABEL_1 label __VM_LABEL_1 push constant 0 return @@ -112,7 +111,6 @@ pop this 2 push pointer 0 call Square.draw 1 pop temp 0 -goto __VM_LABEL_2 label __VM_LABEL_2 push constant 0 return @@ -145,8 +143,8 @@ push this 1 push constant 2 sub pop this 1 -push constant 0 -not +push constant 1 +neg call Screen.setColor 1 pop temp 0 push this 0 @@ -159,7 +157,6 @@ push constant 1 add call Screen.drawRectangle 4 pop temp 0 -goto __VM_LABEL_3 label __VM_LABEL_3 push constant 0 return @@ -190,8 +187,8 @@ push this 1 push constant 2 add pop this 1 -push constant 0 -not +push constant 1 +neg call Screen.setColor 1 pop temp 0 push this 0 @@ -208,7 +205,6 @@ push this 2 add call Screen.drawRectangle 4 pop temp 0 -goto __VM_LABEL_4 label __VM_LABEL_4 push constant 0 return @@ -241,8 +237,8 @@ push this 0 push constant 2 sub pop this 0 -push constant 0 -not +push constant 1 +neg call Screen.setColor 1 pop temp 0 push this 0 @@ -255,7 +251,6 @@ push this 2 add call Screen.drawRectangle 4 pop temp 0 -goto __VM_LABEL_5 label __VM_LABEL_5 push constant 0 return @@ -286,8 +281,8 @@ push this 0 push constant 2 add pop this 0 -push constant 0 -not +push constant 1 +neg call Screen.setColor 1 pop temp 0 push this 0 @@ -304,7 +299,6 @@ push this 2 add call Screen.drawRectangle 4 pop temp 0 -goto __VM_LABEL_6 label __VM_LABEL_6 push constant 0 return diff --git a/src/compiler/tests/snapshots/test_output__Compiler vm code: src__compiler__tests__inputs__11__Square__SquareGame.jack@SquareGame.jack.snap b/src/compiler/tests/snapshots/test_output__Compiler vm code: src__compiler__tests__inputs__11__Square__SquareGame.jack@SquareGame.jack.snap index 92bc6e4..92d097d 100644 --- a/src/compiler/tests/snapshots/test_output__Compiler vm code: src__compiler__tests__inputs__11__Square__SquareGame.jack@SquareGame.jack.snap +++ b/src/compiler/tests/snapshots/test_output__Compiler vm code: src__compiler__tests__inputs__11__Square__SquareGame.jack@SquareGame.jack.snap @@ -39,7 +39,6 @@ if-goto __VM_LABEL_1 push this 0 call Square.moveUp 1 pop temp 0 -goto __VM_LABEL_1 label __VM_LABEL_1 push this 1 push constant 2 @@ -49,7 +48,6 @@ if-goto __VM_LABEL_2 push this 0 call Square.moveDown 1 pop temp 0 -goto __VM_LABEL_2 label __VM_LABEL_2 push this 1 push constant 3 @@ -59,7 +57,6 @@ if-goto __VM_LABEL_3 push this 0 call Square.moveLeft 1 pop temp 0 -goto __VM_LABEL_3 label __VM_LABEL_3 push this 1 push constant 4 @@ -69,7 +66,6 @@ if-goto __VM_LABEL_4 push this 0 call Square.moveRight 1 pop temp 0 -goto __VM_LABEL_4 label __VM_LABEL_4 push constant 5 call Sys.wait 1 @@ -83,8 +79,6 @@ push constant 0 pop local 1 label __VM_LABEL_5 push local 1 -not -not if-goto __VM_LABEL_6 label __VM_LABEL_7 push local 0 @@ -104,10 +98,9 @@ push constant 81 eq not if-goto __VM_LABEL_9 -push constant 0 -not +push constant 1 +neg pop local 1 -goto __VM_LABEL_9 label __VM_LABEL_9 push local 0 push constant 90 @@ -117,7 +110,6 @@ if-goto __VM_LABEL_10 push this 0 call Square.decSize 1 pop temp 0 -goto __VM_LABEL_10 label __VM_LABEL_10 push local 0 push constant 88 @@ -127,7 +119,6 @@ if-goto __VM_LABEL_11 push this 0 call Square.incSize 1 pop temp 0 -goto __VM_LABEL_11 label __VM_LABEL_11 push local 0 push constant 131 @@ -136,7 +127,6 @@ not if-goto __VM_LABEL_12 push constant 1 pop this 1 -goto __VM_LABEL_12 label __VM_LABEL_12 push local 0 push constant 133 @@ -145,7 +135,6 @@ not if-goto __VM_LABEL_13 push constant 2 pop this 1 -goto __VM_LABEL_13 label __VM_LABEL_13 push local 0 push constant 130 @@ -154,7 +143,6 @@ not if-goto __VM_LABEL_14 push constant 3 pop this 1 -goto __VM_LABEL_14 label __VM_LABEL_14 push local 0 push constant 132 @@ -163,14 +151,11 @@ not if-goto __VM_LABEL_15 push constant 4 pop this 1 -goto __VM_LABEL_15 label __VM_LABEL_15 label __VM_LABEL_16 push local 0 push constant 0 eq -not -not if-goto __VM_LABEL_17 call Keyboard.keyPressed 0 pop local 0 diff --git a/src/vm/src/instruction.rs b/src/vm/src/instruction.rs index e36b294..dd3be2d 100644 --- a/src/vm/src/instruction.rs +++ b/src/vm/src/instruction.rs @@ -11,6 +11,16 @@ pub struct PushPopInstruction { pub inst_type: PushPop, } +impl PushPopInstruction { + pub fn new(inst_type: PushPop, segment: String, addr: u16) -> Self { + Self { + segment, + addr, + inst_type, + } + } +} + #[derive(Debug, Clone)] pub enum Instruction { PushPop(PushPopInstruction), diff --git a/src/vm/src/lib.rs b/src/vm/src/lib.rs index 7aa6f3c..679f060 100644 --- a/src/vm/src/lib.rs +++ b/src/vm/src/lib.rs @@ -1,6 +1,6 @@ mod code; pub mod config; -mod instruction; +pub mod instruction; mod parser; use std::error::Error;