diff --git a/src/vstc/function_compiler.rs b/src/vstc/function_compiler.rs index 04c8bd2..414717f 100644 --- a/src/vstc/function_compiler.rs +++ b/src/vstc/function_compiler.rs @@ -14,12 +14,18 @@ pub struct QueuedFunction { pub function: swc_ecma_ast::Function, } +pub struct LoopLabels { + pub continue_: String, + pub break_: String, +} + pub struct FunctionCompiler { pub definition: Vec, pub definition_allocator: Rc>, pub reg_allocator: NameAllocator, pub label_allocator: NameAllocator, pub queue: Queue, + pub loop_labels: Vec, } impl FunctionCompiler { @@ -34,6 +40,7 @@ impl FunctionCompiler { reg_allocator: reg_allocator, label_allocator: NameAllocator::default(), queue: Queue::new(), + loop_labels: vec![], }; } @@ -377,8 +384,33 @@ impl FunctionCompiler { }, Labeled(_) => std::panic!("Not implemented: Labeled statement"), - Break(_) => std::panic!("Not implemented: Break statement"), - Continue(_) => std::panic!("Not implemented: Continue statement"), + + Break(break_) => { + if break_.label.is_some() { + std::panic!("Not implemented: labeled break statement"); + } + + let loop_labels = self.loop_labels.last() + .expect("break statement outside loop") + ; + + self.definition.push( + format!(" jmp :{}", loop_labels.break_) + ); + }, + Continue(continue_) => { + if continue_.label.is_some() { + std::panic!("Not implemented: labeled continue statement"); + } + + let loop_labels = self.loop_labels.last() + .expect("continue statement outside loop") + ; + + self.definition.push( + format!(" jmp :{}", loop_labels.continue_) + ); + }, If(if_) => { let mut expression_compiler = ExpressionCompiler { fnc: self, @@ -433,6 +465,15 @@ impl FunctionCompiler { &"while".to_string() ); + let end_label = self.label_allocator.allocate_numbered( + &"while_end".to_string() + ); + + self.loop_labels.push(LoopLabels { + continue_: start_label.clone(), + break_: end_label.clone(), + }); + self.definition.push( std::format!("{}:", start_label) ); @@ -457,8 +498,6 @@ impl FunctionCompiler { cond_reg, )); - let end_label = self.label_allocator.allocate_numbered(&"while_end".to_string()); - let mut jmpif_instr = " jmpif %".to_string(); jmpif_instr += &cond_reg; jmpif_instr += " :"; @@ -471,12 +510,27 @@ impl FunctionCompiler { self.definition.push(std::format!(" jmp :{}", start_label)); self.definition.push(std::format!("{}:", end_label)); + + self.loop_labels.pop(); }, DoWhile(do_while) => { let start_label = self.label_allocator.allocate_numbered( &"do_while".to_string() ); + let continue_label = self.label_allocator.allocate_numbered( + &"do_while_continue".to_string() + ); + + let end_label = self.label_allocator.allocate_numbered( + &"do_while_end".to_string() + ); + + self.loop_labels.push(LoopLabels { + continue_: continue_label.clone(), + break_: end_label.clone(), + }); + self.definition.push( std::format!("{}:", start_label) ); @@ -494,11 +548,21 @@ impl FunctionCompiler { self.reg_allocator.release(®); } + self.definition.push( + format!("{}:", continue_label) + ); + let mut jmpif_instr = " jmpif ".to_string(); jmpif_instr += &condition.value_assembly; jmpif_instr += " :"; jmpif_instr += &start_label; self.definition.push(jmpif_instr); + + self.definition.push( + format!("{}:", end_label) + ); + + self.loop_labels.pop(); }, For(for_) => { let for_scope = scope.nest(); @@ -526,14 +590,23 @@ impl FunctionCompiler { &"for_test".to_string() ); - self.definition.push( - format!("{}:", &for_test_label) + let for_continue_label = self.label_allocator.allocate_numbered( + &"for_continue".to_string() ); let for_end_label = self.label_allocator.allocate_numbered( &"for_end".to_string() ); + self.definition.push( + format!("{}:", &for_test_label) + ); + + self.loop_labels.push(LoopLabels { + continue_: for_continue_label.clone(), + break_: for_end_label.clone(), + }); + match &for_.test { Some(cond) => { let mut ec = ExpressionCompiler { @@ -569,6 +642,10 @@ impl FunctionCompiler { self.statement(&for_.body, false, &for_scope); + self.definition.push( + format!("{}:", for_continue_label) + ); + match &for_.update { Some(update) => self.expression(update, &for_scope), None => {}, @@ -581,6 +658,8 @@ impl FunctionCompiler { self.definition.push( format!("{}:", for_end_label) ); + + self.loop_labels.pop(); }, ForIn(_) => std::panic!("Not implemented: ForIn statement"), ForOf(_) => std::panic!("Not implemented: ForOf statement"),