diff options
| -rw-r--r-- | ast.h | 1 | ||||
| -rw-r--r-- | codegen.c | 36 | ||||
| -rw-r--r-- | parser.c | 17 | ||||
| -rw-r--r-- | test/fibonacci.c | 2 | ||||
| -rw-r--r-- | type_checker.c | 31 |
5 files changed, 67 insertions, 20 deletions
@@ -136,6 +136,7 @@ struct if_node { struct expr_node* cond; struct stmt_node* true_branch; struct stmt_node* false_branch; + struct scope* scope; }; struct stmt_node { @@ -36,6 +36,21 @@ static struct scope* scope; static const struct fn_decl_node* active_fn; static unsigned long long branch_counter = 0; +static void enter_scope(struct scope* child_scope) { + if (child_scope == NULL || + child_scope->next_out != scope) + CGEN_PANIC("enter_scope: scopes are misaligned"); + + scope = child_scope; +} + +static void exit_scope(struct scope* child_scope) { + if (child_scope != scope || child_scope->next_out == NULL) + CGEN_PANIC("exit_scope: scopes are misaligned"); + + scope = child_scope->next_out; +} + static struct lval_def allocate_register(const struct type_def* type) { return (struct lval_def) { .loc = { @@ -547,20 +562,19 @@ static void emit_group_contents(FILE* outfile, const struct group_node* node) { } static void emit_group(FILE* outfile, const struct group_node* node) { - if (node->scope->next_out != scope) CGEN_PANIC("scopes are misaligned"); - - scope = node->scope; + enter_scope(node->scope); scope->bp_offset = scope->next_out->bp_offset; /* don't reset bp */ emit_group_contents(outfile, node); /* don't reset sp because alloca needs to work */ scope->next_out->bp_offset = scope->bp_offset; - scope = scope->next_out; + exit_scope(node->scope); } static void emit_if(FILE* outfile, const struct if_node* node) { - /* TODO: make type checking real so we aren't passing a null pointer here */ + enter_scope(node->scope); + struct lval_def cond_result = allocate_temporary(outfile, node->cond->resolved_type); emit_expr(outfile, node->cond, &cond_result); @@ -579,6 +593,8 @@ static void emit_if(FILE* outfile, const struct if_node* node) { emit_stmt(outfile, node->false_branch); fprintf(outfile, "branch%lld:\n", end_branch_num); } + + exit_scope(node->scope); } static void emit_stmt(FILE* outfile, const struct stmt_node* node) { @@ -604,6 +620,8 @@ static void emit_stmt(FILE* outfile, const struct stmt_node* node) { } static void emit_fn_decl(FILE* outfile, const struct fn_decl_node* node) { + enter_scope(node->scope); + if (active_fn != NULL) CGEN_PANIC( "can't define function %s inside function %s", @@ -615,8 +633,6 @@ static void emit_fn_decl(FILE* outfile, const struct fn_decl_node* node) { fprintf(outfile, "\tpush rbp\n"); fprintf(outfile, "\tmov rbp, rsp\n"); - if (node->scope->next_out != scope) CGEN_PANIC("scopes are misaligned"); - scope = node->scope; scope->bp_offset = 0; long long spilled_bp_ofs = -16; // return address + old bp @@ -644,15 +660,17 @@ static void emit_fn_decl(FILE* outfile, const struct fn_decl_node* node) { emit_mov(outfile, &arg_dst, &arg_src); } + enter_scope(node->body.scope); emit_group_contents(outfile, &node->body); - - scope = scope->next_out; + exit_scope(node->body.scope); fprintf(outfile, RETURN_LABEL_FMT ":\n", node->name); fprintf(outfile, "\tmov rsp, rbp\n"); fprintf(outfile, "\tpop rbp\n"); fprintf(outfile, "\tret\n"); + active_fn = NULL; + exit_scope(node->scope); } static void emit_root_node(FILE* outfile, const struct root_node* node) { @@ -324,6 +324,9 @@ static void parse_group(struct group_node* p_node) { static void parse_if(struct if_node* p_node) { expect_kw("if"); + scope_push(&scope); + p_node->scope = scope; + expect(TK_LPAREN); p_node->cond = protected_alloc(sizeof(struct expr_node)); parse_expr(p_node->cond); @@ -333,11 +336,14 @@ static void parse_if(struct if_node* p_node) { parse_stmt(p_node->true_branch); peek_or_panic(); - if (tok.type != TK_IDENT || strcmp(tok.data.ident, "else") != 0) return; - expect_kw("else"); + if (tok.type == TK_IDENT && strcmp(tok.data.ident, "else") == 0) { + expect_kw("else"); - p_node->false_branch = protected_alloc(sizeof(struct stmt_node)); - parse_stmt(p_node->false_branch); + p_node->false_branch = protected_alloc(sizeof(struct stmt_node)); + parse_stmt(p_node->false_branch); + } + + scope_pop(&scope); } static void parse_stmt_assign(struct stmt_node* p_node) { @@ -419,6 +425,9 @@ static void parse_args_decl(struct args_decl_node** pp_decl) { } static void parse_fn_decl(struct fn_decl_node* p_node) { + if (scope->next_out != NULL) + PARSER_PANIC("functions can only be define in the root scope"); + parse_type_ref(&p_node->return_type); expect(TK_IDENT); diff --git a/test/fibonacci.c b/test/fibonacci.c index 39a32be..a07c111 100644 --- a/test/fibonacci.c +++ b/test/fibonacci.c @@ -1,6 +1,6 @@ int fib (int n) { if (n) return n * fib(n-1); - return 1; + else return 1; } int main (int argc, char** argv) { diff --git a/type_checker.c b/type_checker.c index 2842ea2..aabd7c9 100644 --- a/type_checker.c +++ b/type_checker.c @@ -33,6 +33,21 @@ static void assert_cast_compatible( } } +static void enter_scope(struct scope* child_scope) { + if (child_scope == NULL || + child_scope->next_out != scope) + TYPE_PANIC("enter_scope: scopes are misaligned"); + + scope = child_scope; +} + +static void exit_scope(struct scope* child_scope) { + if (child_scope != scope || child_scope->next_out == NULL) + TYPE_PANIC("exit_scope: scopes are misaligned"); + + scope = child_scope->next_out; +} + static const struct type_def* resolve_type_ref(struct type_ref_node* node) { /* TODO: support pointers and such */ if (node->def_ref == NULL) TYPE_PANIC("use of unresolved type"); @@ -160,9 +175,13 @@ static void type_check_return(struct return_node* node) { } static void type_check_if(struct if_node* node) { + enter_scope(node->scope); + type_check_expr(node->cond); type_check_stmt(node->true_branch); if (node->false_branch != NULL) type_check_stmt(node->false_branch); + + exit_scope(node->scope); } static void type_check_stmt(struct stmt_node* node) { @@ -188,19 +207,19 @@ static void type_check_stmt(struct stmt_node* node) { } static void type_check_group(struct group_node* node) { - if (node->scope->next_out != scope) TYPE_PANIC("scopes are borked"); - scope = node->scope; + enter_scope(node->scope); + struct stmt_node* stmt = node->head; while (stmt != NULL) { type_check_stmt(stmt); stmt = stmt->next; } - scope = scope->next_out; + + exit_scope(node->scope); } static void type_check_fn_decl(struct fn_decl_node* node) { - if (node->scope->next_out != scope) TYPE_PANIC("scopes are borked"); - scope = node->scope; + enter_scope(node->scope); node->return_type.def_ref = resolve_type_ref(&node->return_type); @@ -211,7 +230,7 @@ static void type_check_fn_decl(struct fn_decl_node* node) { type_check_group(&node->body); - scope = scope->next_out; + exit_scope(node->scope); } static void type_check_root(struct root_node* node) { |
