diff options
| author | Carson Fleming <cflems@cflems.net> | 2026-07-17 00:38:51 -0400 |
|---|---|---|
| committer | Carson Fleming <cflems@cflems.net> | 2026-07-17 00:38:51 -0400 |
| commit | a5c12fd6f4438fc172f28b722e54908b575c6ce1 (patch) | |
| tree | 5f9b2d48681e02d392567eb8798ba614cb96bfbd /type_checker.c | |
| parent | 1dfa2971999b4adf36a33866b0b07af07188da08 (diff) | |
| download | ccc-a5c12fd6f4438fc172f28b722e54908b575c6ce1.tar.gz | |
before I do something crazy
Diffstat (limited to 'type_checker.c')
| -rw-r--r-- | type_checker.c | 74 |
1 files changed, 74 insertions, 0 deletions
diff --git a/type_checker.c b/type_checker.c new file mode 100644 index 0000000..f914c34 --- /dev/null +++ b/type_checker.c @@ -0,0 +1,74 @@ +#include "ast.h" +#include "scope.h" +#include <stdio.h> +#include <stdlib.h> + +#define TYPE_PANIC(format, ...) {\ + fprintf(\ + stderr,\ + "ccc: type error: " format "\n" __VA_OPT__(,)\ + __VA_ARGS__);\ + exit(1);\ +} + +static struct scope* scope; + +static void type_check_group(struct group_node* node); + +static void type_check_expr(struct expr_node* node) {} + +static void type_check_var_decl(struct var_decl_node* node) {} + +static void type_check_return(struct return_node* node) {} + +static void type_check_stmt(struct stmt_node* node) { + switch (node->type) { + case STMT_EMPTY: + break; + case STMT_EXPR: + type_check_expr(&node->inner.expr); + break; + case STMT_VAR_DECL: + type_check_var_decl(&node->inner.var_decl); + break; + case STMT_RETURN: + type_check_return(&node->inner.return_); + break; + case STMT_GROUP: + type_check_group(&node->inner.group); + break; + } +} + +static void type_check_group(struct group_node* node) { + if (node->scope->next_out != scope) TYPE_PANIC("scopes are borked"); + scope = node->scope; + struct stmt_node* stmt = node->head; + while (stmt != NULL) { + type_check_stmt(stmt); + stmt = stmt->next; + } +} + +static void type_check_fn_decl(struct fn_decl_node* node) { + scope = node->scope; + type_check_group(&node->body); +} + +static void type_check_root(struct root_node* node) { + switch (node->type) { + case ROOT_FN_DECL: + type_check_fn_decl(&node->inner.fn_decl); + break; + } +} + +void type_check(struct ast* ast) { + scope = ast->root_scope; + + struct root_node* node = ast->root_node; + while (node != NULL) { + type_check_root(node); + node = node->next; + } +} |
