aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/compiler.rs56
-rw-r--r--src/tokenizer.rs2
-rw-r--r--src/vm.rs2
-rw-r--r--tests/simple.tdy38
4 files changed, 62 insertions, 36 deletions
diff --git a/src/compiler.rs b/src/compiler.rs
index c542412..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;
@@ -380,12 +381,10 @@ impl Compiler {
block.add(Op::Pop, self.line());
}
- fn for(&mut self, block: &mut Block) {
+ fn for_loop(&mut self, block: &mut Block) {
expect!(self, Token::For, "Expected 'for' at start of for-loop.");
- self.level += 1;
- let h = self.stack.len();
-
+ // Definition
match self.peek_four() {
(Token::Identifier(name), Token::Identifier(typ), Token::ColonEqual, _) => {
self.eat();
@@ -403,21 +402,47 @@ impl Compiler {
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) {
self.clear_panic();
+ macro_rules! tokens {
+ ($( $token:pat ),*) => {
+ ($( $token , )* ..)
+ };
+ }
+
match self.peek_four() {
- (Token::Print, _, _, _) => {
+ tokens!(Token::Print) => {
self.eat();
self.expression(block);
block.add(Op::Print, self.line());
},
- (Token::Identifier(name), Token::Identifier(typ), Token::ColonEqual, _) => {
+ tokens!(Token::Identifier(name), Token::Identifier(typ), Token::ColonEqual) => {
self.eat();
self.eat();
self.eat();
@@ -428,43 +453,43 @@ impl Compiler {
}
}
- (Token::Identifier(name), Token::ColonEqual, _, _) => {
+ tokens!(Token::Identifier(name), Token::ColonEqual) => {
self.eat();
self.eat();
self.define_variable(&name, Type::UnkownType, block);
}
- (Token::Identifier(name), Token::Equal, _, _) => {
+ tokens!(Token::Identifier(name), Token::Equal) => {
self.eat();
self.eat();
self.assign(&name, block);
}
- (Token::If, _, _, _) => {
+ tokens!(Token::If) => {
self.if_statment(block);
}
- (Token::For, _, _, _) => {
- self.for(block);
+ tokens!(Token::For) => {
+ self.for_loop(block);
}
- (Token::Unreachable, _, _, _) => {
+ tokens!(Token::Unreachable) => {
self.eat();
block.add(Op::Unreachable, self.line());
}
- (Token::LeftBrace, _, _, _) => {
+ tokens!(Token::LeftBrace) => {
self.scope(block);
}
- (Token::Newline, _, _, _) => {}
+ tokens!(Token::Newline) => {}
_ => {
self.expression(block);
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>> {
@@ -472,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("->")]
diff --git a/src/vm.rs b/src/vm.rs
index d0b9190..2dadc5e 100644
--- a/src/vm.rs
+++ b/src/vm.rs
@@ -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 d07aad7..2f0f606 100644
--- a/tests/simple.tdy
+++ b/tests/simple.tdy
@@ -13,28 +13,26 @@
// print d
// print c
-
-for a := 0, a >= 0, a = a - 1 {
- if a == 2 {
- continue
- }
+for a := 0, a < 10, print a {
print a
+ a = a + 1
}
-for a := 0, a >= 0, a = a - 1 {
- if a == 2 {
- continue
- }
- print a
-}
-
-a = 0
-
-fiv a in something {
-}
-
-something.each((x) -> {
+// 1, 2, 3, 4
-}
-// 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