diff options
| author | Edvard Thörnros <edvard.thornros@gmail.com> | 2021-01-12 19:33:19 +0100 |
|---|---|---|
| committer | Edvard Thörnros <edvard.thornros@gmail.com> | 2021-01-12 19:33:19 +0100 |
| commit | f34d41db5b8f72d3b82fa1c4e9fe3ad71f509d52 (patch) | |
| tree | d1490f4f54811c4b3b5213032ca8ec436f918ff3 | |
| parent | 840d820d0951dc38e266bd4d184be2cf8bf142e3 (diff) | |
| parent | 32fa47b52b03f4ae84bc773bad785cf77334ae78 (diff) | |
| download | sylt-f34d41db5b8f72d3b82fa1c4e9fe3ad71f509d52.tar.gz | |
For-loops
| -rw-r--r-- | src/compiler.rs | 58 | ||||
| -rw-r--r-- | src/tokenizer.rs | 2 | ||||
| -rw-r--r-- | src/vm.rs | 2 | ||||
| -rw-r--r-- | tests/simple.tdy | 28 |
4 files changed, 81 insertions, 9 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 { diff --git a/tests/simple.tdy b/tests/simple.tdy index 3fe05a4..2f0f606 100644 --- a/tests/simple.tdy +++ b/tests/simple.tdy @@ -13,12 +13,26 @@ // print d // print c -a int := 2 -if a == 0 { - print "123" -} else if a == 1 { - print "BCD" -} else { - print "ABC" +for a := 0, a < 10, print a { + print a + a = a + 1 } + // 1, 2, 3, 4 + + +// +// === main === +// | Constant(Int(0)) +// | ReadLocal(0) +// | Constant(Int(10)) +// | Less +// | JmpFalse(12) +// | Jmp(11) +// | Jmp(1) +// | ReadLocal(0) +// | Constant(Int(1)) +// | Add +// | Assign(0) +// | Jmp(7) +// | Return |
