diff --git a/src/ast.c b/src/ast.c index da03a9a..f8b72fb 100644 --- a/src/ast.c +++ b/src/ast.c @@ -27,6 +27,13 @@ AST* ast_init(ASTType type, void* data) { ast->data = data; ast->scope = NULL; + if (ast->type > AST_TYPE_MAX) { + log_dbgf( + "Attempted to create invalid AST (%i > %i) to GC: ast:%p", + ast->type, AST_TYPE_MAX, ast + ); + } + return ast; } @@ -56,10 +63,7 @@ void ast_destroy(AST* ast) { } // If there're no more `AST`s linked to the scope, free. - if (ast->scope) { - ast->scope->uses--; - if (!ast->scope->uses) { scope_destroy_psv(ast->scope); } - } + if (ast->scope && !--ast->scope->uses) scope_destroy_psv(ast->scope); free(ast); } @@ -76,6 +80,7 @@ void ast_destroy_psv(AST* ast) { case AST_TYPE_FDEF: ast_fdef_data_destroy_psv(ast->data); break; case AST_TYPE_ARG: ast_arg_data_destroy(ast->data); break; case AST_TYPE_BIF: ast_bif_data_destroy(ast->data); break; + case AST_TYPE_EXC: ast_exc_data_destroy(ast->data); break; default: log_dbgf("Unknown ast type %d (max: %d)", ast->type, AST_TYPE_MAX); } @@ -127,13 +132,18 @@ void ast_num_print(ASTNumData* data, int i) { INDENT_END; } -ASTExcData* ast_exc_data_init(char* msg, AST* trace) { +ASTExcData* ast_exc_data_init(const char* msg, AST* trace) { ASTExcData* data = malloc(sizeof(ASTExcData)); data->msg = msg; data->trace = trace; return data; } +void ast_exc_data_destroy(ASTExcData* exc) { + // `msg` is static, and `trace` will get freed in GC. + free(exc); +} + void ast_exc_print(ASTExcData* data, int i) { INDENT_BEGIN(i); @@ -177,8 +187,8 @@ void ast_call_data_destroy(ASTCallData* call) { void ast_call_data_destroy_psv(ASTCallData* call) { if (!call) return; - free(call->to); - free(call->argv); + call->to = NULL; + call->argv = NULL; free(call); } diff --git a/src/gc.c b/src/gc.c index 4331486..6624e9b 100644 --- a/src/gc.c +++ b/src/gc.c @@ -10,6 +10,8 @@ GC* gclist = NULL; void gc_destroy(GC* gc) { free(gc); } +void f() {} + void* gc_alloc(size_t sz, GCType type) { void* mem = malloc(sz); GC* gc = malloc(sizeof(GC)); @@ -28,7 +30,17 @@ void gc_hack_free() { GC* gc = gclist; gclist = gclist->nxt; switch (gc->type) { - case GC_TYPE_AST: ast_destroy_psv(gc->p); break; + case GC_TYPE_AST: + f(); + if (((AST*)gc->p)->type > AST_TYPE_MAX) { + log_dbgf( + "Attempted to free invalid AST (%i > %i) to GC: gc:%p " + "ast:%p", + ((AST*)gc->p)->type, AST_TYPE_MAX, gc, gc->p + ); + } + ast_destroy_psv(gc->p); + break; case GC_TYPE_SCOPE: scope_destroy_psv(gc->p); break; } gc_destroy(gc); diff --git a/src/grammar.y b/src/grammar.y index 9854f38..1019d5a 100644 --- a/src/grammar.y +++ b/src/grammar.y @@ -124,7 +124,13 @@ block: exp: NUM { $$ = ast_init(AST_TYPE_NUM, ast_num_data_init($1)); } - //| BLOCKS exp BLOCKE { $$ = $2; } + // Function definitions. + | WORD GROUPS arg GROUPE EQ exp { + size_t argc = $3->ln; + AST** argv = $3->buf; + argarr_destroypsv($3); + $$ = ast_init(AST_TYPE_FDEF, ast_fdef_data_init($1, argc, argv, $6)); + } | BLOCKS block BLOCKE { $$ = ast_init(AST_TYPE_BLOCK, ast_block_data_init((AST**) $2->buf, $2->ln)); @@ -193,11 +199,4 @@ exp: strcpy(to, "div"); $$ = ast_init(AST_TYPE_CALL, ast_call_data_init(to, 2, argv)); } - - | WORD GROUPS arg GROUPE EQ exp { - size_t argc = $3->ln; - AST** argv = $3->buf; - argarr_destroypsv($3); - $$ = ast_init(AST_TYPE_FDEF, ast_fdef_data_init($1, argc, argv, $6)); - } %% diff --git a/src/include/ast.h b/src/include/ast.h index eaff6cc..b71ec39 100644 --- a/src/include/ast.h +++ b/src/include/ast.h @@ -25,7 +25,7 @@ typedef enum { AST_TYPE_BLOCK, // A block of code (scope). AST_TYPE_FDEF, // A function definition. AST_TYPE_ARG, // A definition argument. - AST_TYPE_MAX = AST_TYPE_FDEF, + AST_TYPE_MAX = AST_TYPE_ARG, } ASTType; // An Abstract Syntax Tree. @@ -60,11 +60,11 @@ void ast_num_print(ASTNumData*, int i); // An exception. typedef struct ASTEXCDATA { - char* msg; // The exception message. + const char* msg; // The exception message. AST* trace; // The previous exception. } ASTExcData; -// Create a new `ASTExecData. -ASTExcData* ast_exc_data_init(char* msg, AST* trace); +// Create a new `ASTExecData. `msg` should be static. +ASTExcData* ast_exc_data_init(const char* msg, AST* trace); // Destroy an `ASTExecData`. void ast_exc_data_destroy(ASTExcData* exc); // Print an `ASTExecData`.