diff --git a/examples/test.lua b/examples/test.lua index ffe5b49..2a4110e 100644 --- a/examples/test.lua +++ b/examples/test.lua @@ -1,8 +1,8 @@ local i = 0 print("before") -while i < 10 do +repeat i = i + 1 print(i) -end +until i >= 10 print("after") \ No newline at end of file diff --git a/src/ast.rs b/src/ast.rs index 6a9dabc..451486a 100644 --- a/src/ast.rs +++ b/src/ast.rs @@ -238,6 +238,7 @@ impl Parse for Block { Token::Keyword(Keyword::End) | Token::Keyword(Keyword::ElseIf) | Token::Keyword(Keyword::Else) + | Token::Keyword(Keyword::Until) | Token::Eof ) ) { diff --git a/src/compile.rs b/src/compile.rs index 702302b..5b1cab9 100644 --- a/src/compile.rs +++ b/src/compile.rs @@ -491,7 +491,9 @@ impl Statement { 0, ))); - let block_instructions = block.compile(state, scope); + let mut inner_scope = scope.clone(); + + let block_instructions = block.compile(state, &mut inner_scope); let block_instr_len = block_instructions.len() as i32; instructions.push(PreInstr::Instr(Instruction::Jmp(block_instr_len + 1))); @@ -501,7 +503,27 @@ impl Statement { -(block_instr_len + expr_instr_len + 2), ))); } - Statement::Repeat(block, expr) => todo!(), + Statement::Repeat(block, expr) => { + let mut inner_scope = scope.clone(); + + let block_instructions = block.compile(state, &mut inner_scope); + let block_instr_len = block_instructions.len() as i32; + instructions.extend(block_instructions); + + let (instr, expr_regs) = expr.kind.compile(state, scope, Some(1)); + let expr_instr_len = instr.len() as i32; + instructions.extend(instr); + + instructions.push(PreInstr::Instr(Instruction::Test( + scope.register_counter.next(), + *expr_regs.first().unwrap(), + 0, + ))); + + instructions.push(PreInstr::Instr(Instruction::Jmp( + -(block_instr_len + expr_instr_len + 2), + ))); + } Statement::Break => instructions.push(PreInstr::Break), Statement::Label(node) => instructions.push(PreInstr::Label(node.kind.clone())), Statement::GoTo(node) => instructions.push(PreInstr::GoTo(node.kind.clone())),