diff options
| author | Carson Fleming <cflems@cflems.net> | 2026-07-29 23:58:55 -0400 |
|---|---|---|
| committer | Carson Fleming <cflems@cflems.net> | 2026-07-29 23:58:55 -0400 |
| commit | 3445947c072a4cd533f5f3a53178f77361859123 (patch) | |
| tree | 9ba7d330b1091fdad76bbb190579491e022dc3d3 | |
| parent | 29510d33cab6e86b28b12c6246bca58acdab26e2 (diff) | |
| download | ccc-3445947c072a4cd533f5f3a53178f77361859123.tar.gz | |
improve type system
| -rw-r--r-- | ast.c | 4 | ||||
| -rw-r--r-- | ast.h | 4 | ||||
| -rw-r--r-- | parser.c | 21 | ||||
| -rw-r--r-- | type.c | 24 | ||||
| -rw-r--r-- | type.h | 9 | ||||
| -rw-r--r-- | type_checker.c | 67 |
6 files changed, 65 insertions, 64 deletions
@@ -25,8 +25,6 @@ static void expr_list_destroy(struct expr_list_node* node) { expr_list_destroy(node->next); free(node->next); } - - if (node->resolved_type != NULL) free(node->resolved_type); } static void assign_destroy(struct assign_node* node) { @@ -136,8 +134,6 @@ static void expr_destroy(struct expr_node* node) { paren_destroy(&node->inner.paren); break; } - - if (node->resolved_type != NULL) free(node->resolved_type); } static void if_destroy(struct if_node* node) { @@ -11,7 +11,7 @@ struct expr_list_node { struct expr_node* expr; struct expr_list_node* next; - struct type* resolved_type; + const struct type* resolved_type; }; struct int_lit_node { @@ -104,7 +104,7 @@ struct expr_node { struct paren_node paren; } inner; - struct type* resolved_type; + const struct type* resolved_type; }; struct group_node { @@ -121,13 +121,32 @@ static void parse_literal(struct expr_node* p_node) { case TK_INT_LIT: expect(TK_INT_LIT); p_node->type = EXPR_INT_LIT; - p_node->inner.int_lit.val = tok.data.int_lit; + p_node->inner.int_lit = (struct int_lit_node) { + .val = tok.data.int_lit, + }; break; case TK_CHAR_LIT: expect(TK_CHAR_LIT); p_node->type = EXPR_CHAR_LIT; + p_node->inner.char_lit = (struct char_lit_node) { + .val = tok.data.char_lit, + }; p_node->inner.char_lit.val = tok.data.char_lit; break; + case TK_FLOAT_LIT: + expect(TK_FLOAT_LIT); + p_node->type = EXPR_FLOAT_LIT; + p_node->inner.float_lit = (struct float_lit_node) { + .val = tok.data.float_lit, + }; + break; + case TK_STR_LIT: + expect(TK_STR_LIT); + p_node->type = EXPR_STR_LIT; + p_node->inner.str_lit = (struct str_lit_node) { + .val = tok.data.str_lit, + }; + break; default: PARSER_PANIC("invalid literal type"); } @@ -42,11 +42,29 @@ const struct data_type double_type = { .is_floating = true, }; -const struct data_type* integral_type = &long_type; -const struct data_type* floating_type = &double_type; -const struct data_type* character_type = &char_type; const struct data_type* primitive_types[] = { &void_type, &char_type, &short_type, &int_type, &long_type, &long_long_type, &float_type, &double_type, NULL }; + +const struct type integral_type = { + .type = TP_DATA, + .data.data_type = &long_type, + .data.is_signed = true, +}; +const struct type floating_type = { + .type = TP_DATA, + .data.data_type = &double_type, + .data.is_signed = true, +}; +const struct type character_type = { + .type = TP_DATA, + .data.data_type = &char_type, + .data.is_signed = true, /* impl defined */ +}; +const struct type string_type = { + .type = TP_PTR, + .pointer.data_type = &char_type, + .pointer.ptr_level = 1, +}; @@ -34,10 +34,11 @@ extern const struct data_type long_type; extern const struct data_type long_long_type; extern const struct data_type float_type; extern const struct data_type double_type; - -extern const struct data_type* integral_type; -extern const struct data_type* floating_type; -extern const struct data_type* character_type; extern const struct data_type* primitive_types[]; +extern const struct type integral_type; +extern const struct type floating_type; +extern const struct type character_type; +extern const struct type string_type; + #endif diff --git a/type_checker.c b/type_checker.c index 8b4763c..86fe63a 100644 --- a/type_checker.c +++ b/type_checker.c @@ -58,41 +58,10 @@ static void exit_scope(struct scope* child_scope) { scope = child_scope->next_out; } -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 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 struct type* copy_type(const struct type* source_type) { - struct type* type = ccc_alloc(sizeof(struct type)); - *type = *source_type; - return type; -} - -static struct type* resolve_var_ref(struct var_ref_node* node) { +static const 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); + return node->def_ref->type; } static void type_check_decl( @@ -112,7 +81,7 @@ static void type_check_decl_list(struct decl_list_node* node) { type_check_decl(&node->type, cur); } -static struct type* resolve_assign(struct assign_node* node) { +static const struct type* resolve_assign(struct assign_node* node) { switch (node->lval->type) { case EXPR_VAR_REF: break; @@ -126,19 +95,17 @@ static struct type* resolve_assign(struct assign_node* node) { const struct type* rval_type = node->rval->resolved_type; assert_cast_compatible(lval_type, rval_type); - return copy_type(lval_type); + return lval_type; } static void type_check_expr_list(struct expr_list_node* node) { - const struct type* last_item_type; for (; node != NULL; node = node->next) { type_check_expr(node->expr); - last_item_type = node->expr->resolved_type; + node->resolved_type = node->expr->resolved_type; } - node->resolved_type = copy_type(last_item_type); } -static struct type* resolve_call(struct call_node* node) { +static const struct type* resolve_call(struct call_node* node) { type_check_expr_list(node->args); /* TODO: enforce that the function has been type checked prior to this */ struct arg_decl_node* arg_decl = node->fn_ref->args; @@ -157,41 +124,41 @@ static struct type* resolve_call(struct call_node* node) { if (arg_eval != NULL) TYPE_PANIC("too many arguments to function '%s'", node->fn_ref->name); - return copy_type(&node->fn_ref->return_type); + return &node->fn_ref->return_type; } -static struct type* resolve_unary(struct unary_node* node) { +static const struct type* resolve_unary(struct unary_node* node) { type_check_expr(node->expr); /* TODO: delegate by individual operation to prohibit shit like -"yes" */ - return copy_type(node->expr->resolved_type); + return node->expr->resolved_type; } -static struct type* resolve_binary(struct binary_node* node) { +static const 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 copy_type(node->lhs->resolved_type); + return node->lhs->resolved_type; } -static struct type* resolve_paren(struct paren_node* node) { +static const struct type* resolve_paren(struct paren_node* node) { type_check_expr_list(node->expr_list); - return copy_type(node->expr_list->resolved_type); + return node->expr_list->resolved_type; } static void type_check_expr(struct expr_node* node) { switch (node->type) { case EXPR_INT_LIT: - node->resolved_type = allocate_data_type(integral_type, false); + node->resolved_type = &integral_type; break; case EXPR_FLOAT_LIT: - node->resolved_type = allocate_data_type(floating_type, false); + node->resolved_type = &floating_type; break; case EXPR_CHAR_LIT: - node->resolved_type = allocate_data_type(character_type, false); + node->resolved_type = &character_type; break; case EXPR_STR_LIT: - node->resolved_type = allocate_pointer_type(character_type, 1); + node->resolved_type = &string_type; break; case EXPR_VAR_REF: node->resolved_type = resolve_var_ref(&node->inner.var_ref); |
