diff --git a/examples/test.lua b/examples/test.lua index 8a11c15..ffe5b49 100644 --- a/examples/test.lua +++ b/examples/test.lua @@ -1,59 +1,8 @@ -global b = 5 -function add(x) - return function (y) - x = x + 1 - b = b + 1 - return x + y, 1, 2, b - end +local i = 0 +print("before") +while i < 10 do + i = i + 1 + print(i) end - -function min(x, y) - local m = x - if y < x then - m = y - end - return m -end - - -function f(x, ...) - local b = {10, ..., add(10)(15)} - return x + 5, b -end - -global sometable = {} -sometable["hello"] = { 100, 150, add(10)(15) } -print(#sometable["hello"]) -sometable["hello"].there = "my dude" -print(sometable.hello.there) - -print(max(11.12345, 9)) -print(add(10)(15)) -print(add(10)(15)) -print(b) -print(min(11, 9)) -print(10 - 15) -print("hello there!") -print(true or 0) - -global value, table = f(10, 11, 12) - -print("hello") -for i=1,#table do - print(table[i]) - if i > 2 then - goto test - end -end -::test:: - -local test = table[1] -if test == 10 then - print("first") -elseif test == 11 then - print("second") -else - print("third") -end -print("after") +print("after") \ No newline at end of file diff --git a/src/ast.rs b/src/ast.rs index c5a9ca9..6a9dabc 100644 --- a/src/ast.rs +++ b/src/ast.rs @@ -271,6 +271,8 @@ pub enum Statement { Node, Block, ), + While(Node, Block), + Repeat(Block, Node), Break, Label(Node), GoTo(Node), @@ -400,6 +402,19 @@ impl Parse for Statement { step, block, )) + } else if let Some(Token::Keyword(Keyword::While)) = stream.peek() { + stream.next(); + let expr = stream.parse()?; + stream.expect(Token::Keyword(Keyword::Do))?; + let block = stream.parse()?; + stream.expect(Token::Keyword(Keyword::End))?; + Ok(Statement::While(expr, block)) + } else if let Some(Token::Keyword(Keyword::Repeat)) = stream.peek() { + stream.next(); + let block = stream.parse()?; + stream.expect(Token::Keyword(Keyword::Until))?; + let expr = stream.parse()?; + Ok(Statement::Repeat(block, expr)) } else if let Ok(expr) = stream.parse() { Ok(Self::Expression(expr)) } else if let Some(Token::Keyword(Keyword::Break)) = stream.peek() { diff --git a/src/compile.rs b/src/compile.rs index c54efe1..702302b 100644 --- a/src/compile.rs +++ b/src/compile.rs @@ -207,6 +207,18 @@ impl Statement { constants.extend(block.find_constants(scope, Vec::new())); constants } + Statement::While(node, block) => { + let mut constants = HashSet::new(); + constants.extend(node.kind.find_constants(scope)); + constants.extend(block.find_constants(scope, Vec::new())); + constants + } + Statement::Repeat(block, node) => { + let mut constants = HashSet::new(); + constants.extend(node.kind.find_constants(scope)); + constants.extend(block.find_constants(scope, Vec::new())); + constants + } Statement::Break => HashSet::new(), Statement::Label(_) => HashSet::new(), Statement::GoTo(_) => HashSet::new(), @@ -469,6 +481,27 @@ impl Statement { ))); instructions.push(PreInstr::Instr(Instruction::Jmp(-(instr_len + 4)))); } + Statement::While(expr, block) => { + 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, + ))); + + let block_instructions = block.compile(state, scope); + let block_instr_len = block_instructions.len() as i32; + + instructions.push(PreInstr::Instr(Instruction::Jmp(block_instr_len + 1))); + instructions.extend(block_instructions); + + instructions.push(PreInstr::Instr(Instruction::Jmp( + -(block_instr_len + expr_instr_len + 2), + ))); + } + Statement::Repeat(block, expr) => todo!(), 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())), diff --git a/src/token_stream/lexer.rs b/src/token_stream/lexer.rs index 746a5e9..db05c28 100644 --- a/src/token_stream/lexer.rs +++ b/src/token_stream/lexer.rs @@ -23,6 +23,9 @@ pub enum Keyword { Nil, Not, For, + While, + Repeat, + Until, Do, Break, GoTo, @@ -48,6 +51,9 @@ impl Keyword { "do" => Keyword::Do, "break" => Keyword::Break, "goto" => Keyword::GoTo, + "while" => Keyword::While, + "repeat" => Keyword::Repeat, + "until" => Keyword::Until, _ => None?, }) } @@ -70,6 +76,9 @@ impl ToString for Keyword { Keyword::Nil => "nil", Keyword::Not => "not", Keyword::For => "for", + Keyword::While => "while", + Keyword::Repeat => "repeat", + Keyword::Until => "until", Keyword::Do => "do", Keyword::Break => "break", Keyword::GoTo => "goto",