summaryrefslogtreecommitdiff
path: root/type_checker.c
diff options
context:
space:
mode:
authorCarson Fleming <cflems@cflems.net>2026-07-17 00:38:51 -0400
committerCarson Fleming <cflems@cflems.net>2026-07-17 00:38:51 -0400
commita5c12fd6f4438fc172f28b722e54908b575c6ce1 (patch)
tree5f9b2d48681e02d392567eb8798ba614cb96bfbd /type_checker.c
parent1dfa2971999b4adf36a33866b0b07af07188da08 (diff)
downloadccc-a5c12fd6f4438fc172f28b722e54908b575c6ce1.tar.gz
before I do something crazy
Diffstat (limited to 'type_checker.c')
-rw-r--r--type_checker.c74
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;
+ }
+}