summaryrefslogtreecommitdiff
path: root/type_checker.c
diff options
context:
space:
mode:
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;
+ }
+}