aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--compiler/codegen.cup26
-rw-r--r--compiler/parser.cup53
2 files changed, 77 insertions, 2 deletions
diff --git a/compiler/codegen.cup b/compiler/codegen.cup
index 975844d..ffe7c1f 100644
--- a/compiler/codegen.cup
+++ b/compiler/codegen.cup
@@ -290,6 +290,32 @@ fn generate_statement(node: Node*) {
generate_block(node.d.conditional.els);
emit_asm(".if"); emit_num(label); emit_asm(":\n");
+ } else if (node.typ == AST_WHILE) {
+ let label = ++gen_label_counter;
+ emit_asm(".loop_s"); emit_num(label); emit_asm(":\n");
+ generate_expr_into_rax(node.d.looop.cond);
+ emit_asm(" cmp rax, 0\n");
+ emit_asm(" je .loop_e"); emit_num(label); emit_asm("\n");
+ generate_statement(node.d.looop.body);
+ emit_asm(" jmp .loop_s"); emit_num(label); emit_asm("\n");
+ emit_asm(".loop_e"); emit_num(label); emit_asm(":\n");
+
+ } else if (node.typ == AST_FOR) {
+ let label = ++gen_label_counter;
+ if (node.d.looop.init)
+ generate_statement(node.d.looop.init);
+ emit_asm(".loop_s"); emit_num(label); emit_asm(":\n");
+ if (node.d.looop.cond) {
+ generate_expr_into_rax(node.d.looop.cond);
+ emit_asm(" cmp rax, 0\n");
+ emit_asm(" je .loop_e"); emit_num(label); emit_asm("\n");
+ }
+ generate_statement(node.d.looop.body);
+ if (node.d.looop.step)
+ generate_statement(node.d.looop.step);
+ emit_asm(" jmp .loop_s"); emit_num(label); emit_asm("\n");
+ emit_asm(".loop_e"); emit_num(label); emit_asm(":\n");
+
} else {
// Default to a simple expression statement
generate_expr_into_rax(node);
diff --git a/compiler/parser.cup b/compiler/parser.cup
index 1335fba..914c4e6 100644
--- a/compiler/parser.cup
+++ b/compiler/parser.cup
@@ -413,6 +413,7 @@ fn add_variable_to_current_block(var: Variable*) {
}
fn parse_var_declaration(lexer: Lexer*): Node* {
+
let token: Token;
lexer_next_assert(lexer, &token, TOKEN_LET);
lexer_next_assert(lexer, &token, TOKEN_IDENTIFIER);
@@ -486,7 +487,48 @@ fn parse_function_params(lexer: Lexer*, func: Node*) {
}
fn parse_block(lexer: Lexer*): Node*;
+fn parse_statement(lexer: Lexer*): Node*;
+
+fn parse_for_loop(lexer: Lexer*): Node* {
+ let token: Token;
+ lexer_next_assert(lexer, &token, TOKEN_FOR);
+
+ let looop = node_new(AST_FOR);
+ lexer_next_assert(lexer, &token, TOKEN_OPEN_PAREN);
+
+ // NOTE: We're going to put the for loop in it's own block
+ // so that any declarations in the init of the loop
+ // can only be referenced within the loop.
+ let node = node_new(AST_BLOCK);
+ node.d.block.children = vector_new_sized(1);
+ node.d.block.locals = vector_new_sized(1);
+ block_add_child(node, looop);
+ block_stack_push(node);
+ // All of the expressions in the for loop are optional
+
+ lexer_peek(lexer, &token);
+ if (token.typ == TOKEN_LET)
+ looop.d.looop.init = parse_var_declaration(lexer);
+ else if (token.typ != TOKEN_SEMICOLON)
+ looop.d.looop.init = parse_expression(lexer);
+ lexer_next_assert(lexer, &token, TOKEN_SEMICOLON);
+
+ lexer_peek(lexer, &token);
+ if (token.typ != TOKEN_SEMICOLON)
+ looop.d.looop.cond = parse_expression(lexer);
+ lexer_next_assert(lexer, &token, TOKEN_SEMICOLON);
+
+ lexer_peek(lexer, &token);
+ if (token.typ != TOKEN_CLOSE_PAREN)
+ looop.d.looop.step = parse_expression(lexer);
+ lexer_next_assert(lexer, &token, TOKEN_CLOSE_PAREN);
+
+ looop.d.looop.body = parse_statement(lexer);
+ block_stack_pop();
+
+ return node;
+}
fn parse_statement(lexer: Lexer*): Node* {
let node: Node*;
@@ -524,9 +566,16 @@ fn parse_statement(lexer: Lexer*): Node* {
node.d.conditional.els = parse_statement(lexer);
}
} else if (token.typ == TOKEN_WHILE) {
- die("while is not implemented yet");
+ lexer_next(lexer, &token);
+ node = node_new(AST_WHILE);
+ lexer_next_assert(lexer, &token, TOKEN_OPEN_PAREN);
+ node.d.looop.cond = parse_expression(lexer);
+ lexer_next_assert(lexer, &token, TOKEN_CLOSE_PAREN);
+ node.d.looop.body = parse_statement(lexer);
+
} else if (token.typ == TOKEN_FOR) {
- die("for is not implemented yet");
+ node = parse_for_loop(lexer);
+
} else if (token.typ == TOKEN_DEFER) {
die("defer is not implemented yet");
} else if (token.typ == TOKEN_LET) {