diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/compiler.rs | 58 | ||||
| -rw-r--r-- | src/tokenizer.rs | 2 | ||||
| -rw-r--r-- | src/vm.rs | 2 |
3 files changed, 60 insertions, 2 deletions
diff --git a/src/compiler.rs b/src/compiler.rs index 50e8ee4..4bb2469 100644 --- a/src/compiler.rs +++ b/src/compiler.rs @@ -338,6 +338,7 @@ impl Compiler { while !matches!(self.peek(), Token::RightBrace | Token::EOF) { self.statement(block); + expect!(self, Token::Newline, "Expect newline after expression."); } self.level -= 1; @@ -373,6 +374,56 @@ impl Compiler { block.patch(Op::JmpFalse(block.curr()), jump); } + self.expression(block); + self.scope(block); + + // Loop variable + block.add(Op::Pop, self.line()); + } + + fn for_loop(&mut self, block: &mut Block) { + expect!(self, Token::For, "Expected 'for' at start of for-loop."); + + // Definition + match self.peek_four() { + (Token::Identifier(name), Token::Identifier(typ), Token::ColonEqual, _) => { + self.eat(); + self.eat(); + self.eat(); + if let Ok(typ) = Type::try_from(typ.as_ref()) { + self.define_variable(&name, typ, block); + } else { + error!(self, format!("Failed to parse type '{}'.", typ)); + } + } + + (Token::Identifier(name), Token::ColonEqual, _, _) => { + self.eat(); + self.eat(); + self.define_variable(&name, Type::UnkownType, block); + } + + _ => { error!(self, "Expected definition at start of for-loop."); } + } + + expect!(self, Token::Comma, "Expect ',' between initalizer and loop expression."); + + let cond = block.curr(); + self.expression(block); + let cond_out = block.add(Op::Illegal, self.line()); + let cond_cont = block.add(Op::Illegal, self.line()); + expect!(self, Token::Comma, "Expect ',' between initalizer and loop expression."); + + let inc = block.curr(); + self.statement(block); + block.add(Op::Jmp(cond), self.line()); + + // patch_jmp!(Op::Jmp, cond_cont => block.curr()); + block.patch(Op::Jmp(block.curr()), cond_cont); + self.scope(block); + block.add(Op::Jmp(inc), self.line()); + + block.patch(Op::JmpFalse(block.curr()), cond_out); } fn statement(&mut self, block: &mut Block) { @@ -418,6 +469,10 @@ impl Compiler { self.if_statment(block); } + tokens!(Token::For) => { + self.for_loop(block); + } + tokens!(Token::Unreachable) => { self.eat(); block.add(Op::Unreachable, self.line()); @@ -434,7 +489,7 @@ impl Compiler { block.add(Op::Pop, self.line()); } } - expect!(self, Token::Newline, "Expect newline after expression."); + } pub fn compile(&mut self, name: &str, file: &Path) -> Result<Block, Vec<Error>> { @@ -442,6 +497,7 @@ impl Compiler { while self.peek() != Token::EOF { self.statement(&mut block); + expect!(self, Token::Newline, "Expect newline after expression."); } block.add(Op::Return, self.line()); diff --git a/src/tokenizer.rs b/src/tokenizer.rs index e52410c..62397c5 100644 --- a/src/tokenizer.rs +++ b/src/tokenizer.rs @@ -103,6 +103,8 @@ pub enum Token { #[token("!")] Not, + #[token(",")] + Comma, #[token(".")] Dot, #[token("->")] @@ -153,7 +153,7 @@ impl VM { } pub fn run(&mut self) -> Result<(), Error>{ - const PRINT_WHILE_RUNNING: bool = false; + const PRINT_WHILE_RUNNING: bool = true; const PRINT_BLOCK: bool = true; if PRINT_BLOCK { |
