summaryrefslogtreecommitdiff
path: root/type_checker.c
diff options
context:
space:
mode:
authorCarson Fleming <cflems@cflems.net>2026-07-21 14:36:02 -0700
committerCarson Fleming <cflems@cflems.net>2026-07-21 14:36:02 -0700
commit0cabbd2a0853c332c82af621b8716643741d758a (patch)
tree4d1772e07ff1b81e00b563f877c6f1ead3305a8d /type_checker.c
parentf87e953223b7d498fc5401247952c08ab1e08f93 (diff)
downloadccc-0cabbd2a0853c332c82af621b8716643741d758a.tar.gz
more faithful grammar
Diffstat (limited to 'type_checker.c')
-rw-r--r--type_checker.c57
1 files changed, 37 insertions, 20 deletions
diff --git a/type_checker.c b/type_checker.c
index 8a07f2a..5905c83 100644
--- a/type_checker.c
+++ b/type_checker.c
@@ -15,7 +15,6 @@ static struct ast* ast_ref;
static struct scope* scope;
static void type_check_expr(struct expr_node* node);
-static void type_check_lval(struct lval_node* node);
static void type_check_stmt(struct stmt_node* node);
static void type_check_group(struct group_node* node);
@@ -78,13 +77,25 @@ static const struct type_def* resolve_var_ref(struct var_ref_node* node) {
}
static void type_check_var_decl(struct var_decl_node* node) {
- node->def_ref->resolved_type = resolve_type_ref(&node->type);
+ const struct type_def* lval_type = resolve_type_ref(&node->type);
+ node->def_ref->resolved_type = lval_type;
+ if (node->initial_value != NULL) {
+ type_check_expr(node->initial_value);
+ assert_cast_compatible(lval_type, node->initial_value->resolved_type);
+ }
}
static const struct type_def* resolve_assign(struct assign_node* node) {
- type_check_lval(&node->lval);
+ switch (node->lval->type) {
+ case EXPR_VAR_REF:
+ break;
+ default:
+ TYPE_PANIC("expression is not assignable");
+ }
+
+ type_check_expr(node->lval);
type_check_expr(node->rval);
- const struct type_def* lval_type = node->lval.resolved_type;
+ const struct type_def* lval_type = node->lval->resolved_type;
const struct type_def* rval_type = node->rval->resolved_type;
assert_cast_compatible(lval_type, rval_type);
@@ -92,9 +103,12 @@ static const struct type_def* resolve_assign(struct assign_node* node) {
}
static const struct type_def* resolve_call(struct call_node* node) {
- struct args_decl_node* arg_decl = node->called_fn_ref->args;
- struct args_eval_node* arg_eval = node->args;
+ struct decl_list_node* arg_decl = node->called_fn_ref->args;
+ struct expr_list_node* arg_eval = node->args;
while (arg_decl != NULL && arg_eval != NULL) {
+ if (arg_decl->decl->initial_value != NULL)
+ TYPE_PANIC("C does not support default arguments");
+
type_check_var_decl(arg_decl->decl);
const struct type_def* decl_type =
arg_decl->decl->def_ref->resolved_type;
@@ -127,18 +141,6 @@ static const struct type_def* resolve_binary(struct binary_node* node) {
return node->lhs->resolved_type;
}
-static void type_check_lval(struct lval_node* node) {
- switch (node->type) {
- case LVAL_VAR_DECL:
- type_check_var_decl(&node->inner.var_decl);
- node->resolved_type = node->inner.var_decl.def_ref->resolved_type;
- break;
- case LVAL_VAR_REF:
- node->resolved_type = resolve_var_ref(&node->inner.var_ref);
- break;
- }
-}
-
static void type_check_expr(struct expr_node* node) {
switch (node->type) {
case EXPR_INT_LIT:
@@ -185,10 +187,25 @@ static void type_check_if(struct if_node* node) {
exit_scope(node->scope);
}
+static void type_check_expr_list(struct expr_list_node* node) {
+ for (; node != NULL; node = node->next) type_check_expr(node->expr);
+}
+
+static void type_check_loop_init(struct loop_init_node* node) {
+ switch (node->type) {
+ case INIT_EXPR_LIST:
+ type_check_expr_list(node->expr_list);
+ break;
+ case INIT_DECL:
+ type_check_var_decl(node->decl);
+ break;
+ }
+}
+
static void type_check_loop(struct loop_node* node) {
enter_scope(node->scope);
- if (node->init != NULL) type_check_expr(node->init);
+ if (node->init != NULL) type_check_loop_init(node->init);
if (node->cond != NULL) type_check_expr(node->cond);
if (node->incr != NULL) type_check_expr(node->incr);
type_check_stmt(node->body);
@@ -238,7 +255,7 @@ static void type_check_fn_decl(struct fn_decl_node* node) {
node->resolved_return_type = resolve_type_ref(&node->return_type);
- for (struct args_decl_node* arg_decl = node->args;
+ for (struct decl_list_node* arg_decl = node->args;
arg_decl != NULL;
arg_decl = arg_decl->next)
type_check_var_decl(arg_decl->decl);