From b48e27f5cc31af65d8bb92d4b81cd03a60c5bcdb Mon Sep 17 00:00:00 2001 From: Carson Fleming Date: Thu, 6 Aug 2026 00:24:49 -0400 Subject: clean up yesterday's hacks + functions in type system --- ast.c | 41 +++++++++++++++++++++++++-- ast.h | 11 ++++---- ccc.c | 22 +++++++++++++++ ccc.h | 1 + codegen.c | 87 ++++++++++++++++++++++++++++------------------------------ dseg.c | 6 +--- main.c | 10 ++----- parser.c | 56 ++++++++++++++++++------------------- scope.h | 19 +++++++------ type.h | 12 ++++++++ type_checker.c | 87 ++++++++++++++++++++++++++++++++++++++++++---------------- 11 files changed, 224 insertions(+), 128 deletions(-) diff --git a/ast.c b/ast.c index c491c42..fe65f4e 100644 --- a/ast.c +++ b/ast.c @@ -47,21 +47,52 @@ static void group_destroy(struct group_node* node) { free(node->scope); } +static void type_list_destroy(struct type_list* node) { + if (node->next != NULL) { + type_list_destroy(node->next); + free(node->next); + } +} + +static void type_destroy(struct type* node) { + switch (node->type) { + case TP_FN: + type_destroy(node->fn.return_type); + free(node->fn.return_type); + + if (node->fn.arg_types != NULL) { + type_list_destroy(node->fn.arg_types); + free(node->fn.arg_types); + } + break; + case TP_DATA: + case TP_PTR: + break; + } +} + static void decl_list_destroy(struct decl_list_node* node) { + type_destroy(&node->type); decl_destroy(node->head); free(node->head); } -static void fn_arg_destroy(struct arg_decl_node* node) { +static void arg_decl_destroy(struct arg_decl_node* node) { + type_destroy(&node->type); + if (node->next != NULL) { - fn_arg_destroy(node->next); + arg_decl_destroy(node->next); free(node->next); } } static void fn_decl_destroy(struct fn_decl_node* node) { + type_destroy(&node->type); + + free(node->name); + if (node->args != NULL) { - fn_arg_destroy(node->args); + arg_decl_destroy(node->args); free(node->args); } @@ -86,6 +117,9 @@ static void str_lit_destroy(struct str_lit_node* node) { } static void call_destroy(struct call_node* node) { + expr_destroy(node->expr); + free(node->expr); + if (node->args != NULL) { expr_list_destroy(node->args); free(node->args); @@ -111,6 +145,7 @@ static void paren_destroy(struct paren_node* node) { } static void cast_destroy(struct cast_node* node) { + type_destroy(&node->type); expr_destroy(node->expr); free(node->expr); } diff --git a/ast.h b/ast.h index af35d45..0c5c741 100644 --- a/ast.h +++ b/ast.h @@ -31,7 +31,7 @@ struct str_lit_node { }; struct var_ref_node { - struct var_def* def_ref; + const struct var_def* def_ref; }; struct decl_node { @@ -51,8 +51,7 @@ struct assign_node { }; struct call_node { - /* TODO: function pointers */ - struct fn_decl_node* fn_ref; /* borrowed */ + struct expr_node* expr; struct expr_list_node* args; }; @@ -126,15 +125,15 @@ struct arg_decl_node { }; struct fn_decl_node { - struct type return_type; - const char* name; + struct type type; + char* name; /* TODO: why is this borrowed? who owns it? */ struct arg_decl_node* args; struct group_node* body; struct scope* scope; }; struct return_node { - struct fn_decl_node* fn_ref; + struct var_def* fn_def; struct expr_list_node* ret_val; /* null to return void */ }; diff --git a/ccc.c b/ccc.c index ca4eba1..c1b1540 100644 --- a/ccc.c +++ b/ccc.c @@ -1,6 +1,7 @@ #include "ccc.h" #include #include +#include void* ccc_alloc(integral_t sz) { void* ptr = calloc(1, sz); @@ -10,3 +11,24 @@ void* ccc_alloc(integral_t sz) { } return ptr; } + +char* ccc_sprintf(const char* format, ...) { + va_list args; + + va_start(args, format); + int req_sz = vsnprintf(NULL, 0, format, args); + va_end(args); + + if (req_sz < 0) { + fprintf(stderr, "ccc: formatting error\n"); + exit(1); + } + req_sz += 1; /* null terminated */ + char* buffer = ccc_alloc(req_sz); + + va_start(args, format); + vsnprintf(buffer, req_sz, format, args); + va_end(args); + + return buffer; +} diff --git a/ccc.h b/ccc.h index 37bcbf1..d9bbc2b 100644 --- a/ccc.h +++ b/ccc.h @@ -9,5 +9,6 @@ typedef long long sintegral_t; typedef double floating_t; void* ccc_alloc(integral_t sz); +char* ccc_sprintf(const char* format, ...); #endif diff --git a/codegen.c b/codegen.c index 71350e4..3950912 100644 --- a/codegen.c +++ b/codegen.c @@ -7,6 +7,7 @@ #include #include #include +#include #define CGEN_PANIC(format, ...) {\ fprintf(\ @@ -32,7 +33,7 @@ static struct reg* MULDIV_OVERFLOW_REG = &RDX; static struct hash_map dseg; static struct scope* scope; -static const struct fn_decl_node* active_fn; +struct var_def* active_fn; static integral_t branch_counter = 0; static integral_t loop_counter = 0; @@ -90,8 +91,11 @@ static const struct data_type* get_effective_data_type( return type->data.data_type; case TP_PTR: return &long_long_type; + case TP_FN: + /* functions have size 1 I guess */ + return &char_type; } - CGEN_PANIC("unhandled type of type case"); + unreachable(); } static struct lval_def allocate_stack( @@ -132,11 +136,8 @@ static void release_temporary(FILE* outfile, const struct lval_def* tmp) { break; case STO_STACK: case STO_IMM: - case STO_FN: case STO_LABEL: break; - case STO_UNRESOLVED: - CGEN_PANIC("can't release unresolved storage"); } } @@ -149,9 +150,6 @@ static void emit_storage_loc( case STO_LABEL: fprintf(outfile, "%s", loc->label); break; - case STO_FN: - fprintf(outfile, "%s", loc->decl->name); - break; case STO_REG: if (sz > 4) fprintf(outfile, "%s", loc->reg->qword); else if (sz > 2) fprintf(outfile, "%s", loc->reg->dword); @@ -169,8 +167,6 @@ static void emit_storage_loc( case STO_IMM: fprintf(outfile, "0x%llx", loc->value); break; - case STO_UNRESOLVED: - CGEN_PANIC("can't emit unresolved storage location"); } } @@ -189,12 +185,8 @@ static bool locs_equal( return a->bp_offset == b->bp_offset; case STO_LABEL: return strcmp(a->label, b->label) == 0; - case STO_FN: - return a->decl == b->decl; - case STO_UNRESOLVED: - return false; } - CGEN_PANIC("unhandled storage type case"); + unreachable(); } static void emit_size_const(FILE* outfile, integral_t sz) { @@ -253,10 +245,8 @@ static void emit_label_lea( if (spill_reg) unspill_register(outfile, tmp_reg); else release_register(tmp_reg); return; - case STO_FN: case STO_IMM: case STO_LABEL: - case STO_UNRESOLVED: CGEN_PANIC("can't load label address into non-value storage"); } } @@ -331,9 +321,7 @@ static void emit_mov( break; case STO_LABEL: case STO_IMM: - case STO_FN: - case STO_UNRESOLVED: - CGEN_PANIC("can't move value into storage type"); + CGEN_PANIC("can't move value into non-storage type"); } fprintf(outfile, "\n"); } @@ -351,9 +339,7 @@ static void emit_cmp_zero(FILE* outfile, const struct lval_def* lval) { break; case STO_LABEL: case STO_IMM: - case STO_FN: - case STO_UNRESOLVED: - CGEN_PANIC("can't compare this storage type") + CGEN_PANIC("can't compare this non-storage type") } fprintf(outfile, ", 0\n"); } @@ -427,7 +413,7 @@ static void emit_var_ref( const struct lval_def* dst ) { if (dst != NULL) { - emit_mov(outfile, dst, &node->def_ref->loc); + emit_mov(outfile, dst, &node->def_ref->storage); } } @@ -439,7 +425,7 @@ static void emit_decl( ) { struct lval_def var_dst = allocate_stack(outfile, node->def_ref->type); - node->def_ref->loc = var_dst.loc; + node->def_ref->storage = var_dst.loc; fprintf(outfile, "\t; %s\n", node->def_ref->name); @@ -468,7 +454,7 @@ static void emit_assignment( struct var_ref_node* var_ref = &node->lval->inner.var_ref; lval_def = (struct lval_def) { .type = var_ref->def_ref->type, - .loc = var_ref->def_ref->loc, + .loc = var_ref->def_ref->storage, }; break; default: @@ -532,10 +518,14 @@ static void emit_call( } /* 3. `call