diff options
| author | Carson Fleming <cflems@cflems.net> | 2026-07-26 19:20:30 -0700 |
|---|---|---|
| committer | Carson Fleming <cflems@cflems.net> | 2026-07-26 19:20:30 -0700 |
| commit | 4f9d0247549b06ddb25b76bb425541190105cb48 (patch) | |
| tree | 56f191c3611fc7509e6350138ce03c20956b656f /type_checker.c | |
| parent | 6a169de321b131e73b86967a1a8564365217275a (diff) | |
| download | ccc-4f9d0247549b06ddb25b76bb425541190105cb48.tar.gz | |
functioning type system perhaps?
Diffstat (limited to 'type_checker.c')
| -rw-r--r-- | type_checker.c | 110 |
1 files changed, 63 insertions, 47 deletions
diff --git a/type_checker.c b/type_checker.c index 5905c83..ccd816f 100644 --- a/type_checker.c +++ b/type_checker.c @@ -18,17 +18,28 @@ static void type_check_expr(struct expr_node* node); static void type_check_stmt(struct stmt_node* node); static void type_check_group(struct group_node* node); +static const char* get_type_name(const struct type* type) { + switch (type->type) { + case TP_DATA: + return type->data.data_type->name; + case TP_PTR: + /* TODO: this is a stub */ + return type->pointer.data_type->name; + } + TYPE_PANIC("unhandled type of type case"); +} + static void assert_cast_compatible( - const struct type_def* lval_type, - const struct type_def* rval_type + const struct type* lval_type, + const struct type* rval_type ) { /* TODO: impl */ /* TODO: we should also insert cast nodes eventually */ if (false) { TYPE_PANIC( "cannot assign value of type '%s' to '%s'", - lval_type->key.name, - rval_type->key.name); + get_type_name(lval_type), + get_type_name(rval_type)); } } @@ -47,45 +58,52 @@ static void exit_scope(struct scope* child_scope) { 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->type.raw_type == NULL) TYPE_PANIC("use of unresolved type"); - if (node->type.ptr_level > 0) return ast_ref->pointer_type; - return node->type.raw_type; -} - -static const struct type_def* resolve_int_lit(struct int_lit_node* node) { - return ast_ref->integral_type; -} - -static const struct type_def* resolve_float_lit(struct float_lit_node* node) { - return ast_ref->decimal_type; +static struct type* allocate_data_type( + const struct data_type* data_type, + bool is_unsigned +) { + if (is_unsigned && data_type->is_floating) + TYPE_PANIC("floating type '%s' cannot be unsigned", data_type->name); + + struct type* type = ccc_alloc(sizeof(struct type)); + type->type = TP_DATA; + type->data.data_type = data_type; + type->data.is_signed = !is_unsigned; + return type; } -static const struct type_def* resolve_char_lit(struct char_lit_node* node) { - return ast_ref->char_type; +static struct type* allocate_pointer_type( + const struct data_type* data_type, + integral_t ptr_level +) { + struct type* type = ccc_alloc(sizeof(struct type)); + type->type = TP_PTR; + type->pointer.data_type = data_type; + type->pointer.ptr_level = ptr_level; + return type; } -static const struct type_def* resolve_str_lit(struct str_lit_node* node) { - return ast_ref->pointer_type; +static struct type* copy_type(const struct type* source_type) { + struct type* type = ccc_alloc(sizeof(struct type)); + *type = *source_type; + return type; } -static const struct type_def* resolve_var_ref(struct var_ref_node* node) { - if (node->def_ref->resolved_type == NULL) - TYPE_PANIC("variable '%s' has unresolved type.", node->def_ref->name); - return node->def_ref->resolved_type; +static struct type* resolve_var_ref(struct var_ref_node* node) { + if (node->def_ref->type == NULL) + TYPE_PANIC("variable '%s' has undefined type.", node->def_ref->name); + return copy_type(node->def_ref->type); } static void type_check_var_decl(struct var_decl_node* node) { - const struct type_def* lval_type = resolve_type_ref(&node->type); - node->def_ref->resolved_type = lval_type; + node->def_ref->type = &node->type; if (node->initial_value != NULL) { type_check_expr(node->initial_value); - assert_cast_compatible(lval_type, node->initial_value->resolved_type); + assert_cast_compatible(&node->type, node->initial_value->resolved_type); } } -static const struct type_def* resolve_assign(struct assign_node* node) { +static struct type* resolve_assign(struct assign_node* node) { switch (node->lval->type) { case EXPR_VAR_REF: break; @@ -95,14 +113,14 @@ static const struct type_def* resolve_assign(struct assign_node* node) { type_check_expr(node->lval); type_check_expr(node->rval); - const struct type_def* lval_type = node->lval->resolved_type; - const struct type_def* rval_type = node->rval->resolved_type; + const struct type* lval_type = node->lval->resolved_type; + const struct type* rval_type = node->rval->resolved_type; assert_cast_compatible(lval_type, rval_type); - return lval_type; + return copy_type(lval_type); } -static const struct type_def* resolve_call(struct call_node* node) { +static struct type* resolve_call(struct call_node* node) { 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) { @@ -110,10 +128,10 @@ static const struct type_def* resolve_call(struct call_node* node) { 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; + const struct type* decl_type = + arg_decl->decl->def_ref->type; type_check_expr(arg_eval->expr); - const struct type_def* eval_type = arg_eval->expr->resolved_type; + const struct type* eval_type = arg_eval->expr->resolved_type; assert_cast_compatible(decl_type, eval_type); arg_decl = arg_decl->next; @@ -124,36 +142,36 @@ static const struct type_def* resolve_call(struct call_node* node) { "mismatched argument count in call to '%s'", node->called_fn_ref->name); - return resolve_type_ref(&node->called_fn_ref->return_type); + return copy_type(&node->called_fn_ref->return_type); } -static const struct type_def* resolve_unary(struct unary_node* node) { +static struct type* resolve_unary(struct unary_node* node) { type_check_expr(node->expr); /* TODO: delegate by individual operation to prohibit shit like -"yes" */ - return node->expr->resolved_type; + return copy_type(node->expr->resolved_type); } -static const struct type_def* resolve_binary(struct binary_node* node) { +static struct type* resolve_binary(struct binary_node* node) { /* TODO: math rules and such lol */ type_check_expr(node->lhs); type_check_expr(node->rhs); assert_cast_compatible(node->lhs->resolved_type, node->rhs->resolved_type); - return node->lhs->resolved_type; + return copy_type(node->lhs->resolved_type); } static void type_check_expr(struct expr_node* node) { switch (node->type) { case EXPR_INT_LIT: - node->resolved_type = resolve_int_lit(&node->inner.int_lit); + node->resolved_type = allocate_data_type(integral_type, false); break; case EXPR_FLOAT_LIT: - node->resolved_type = resolve_float_lit(&node->inner.float_lit); + node->resolved_type = allocate_data_type(floating_type, false); break; case EXPR_CHAR_LIT: - node->resolved_type = resolve_char_lit(&node->inner.char_lit); + node->resolved_type = allocate_data_type(character_type, false); break; case EXPR_STR_LIT: - node->resolved_type = resolve_str_lit(&node->inner.str_lit); + node->resolved_type = allocate_pointer_type(character_type, 1); break; case EXPR_VAR_REF: node->resolved_type = resolve_var_ref(&node->inner.var_ref); @@ -253,8 +271,6 @@ static void type_check_group(struct group_node* node) { static void type_check_fn_decl(struct fn_decl_node* node) { enter_scope(node->scope); - node->resolved_return_type = resolve_type_ref(&node->return_type); - for (struct decl_list_node* arg_decl = node->args; arg_decl != NULL; arg_decl = arg_decl->next) |
