scl/src/ast.c
Jacob 482f2b4877 Big refactor to unclutter ast.h.
Moves all print functions to own file for sanity.

Also, just hit 2,000 lines; nice.
2025-06-28 12:25:10 -04:00

248 lines
5.9 KiB
C

#include <inttypes.h>
#include <stdio.h>
#include "include/ast.h"
#include "include/gc.h"
#include "include/scope.h"
#include "include/util.h"
extern AST* root;
AST* ast_init(ASTType type, void* data) {
AST* ast = gc_alloc(sizeof(AST), GC_TYPE_AST);
ast->type = type;
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;
}
AST* ast_init_scope(ASTType type, void* data, Scope* scope) {
AST* ast = malloc(sizeof(AST));
ast->type = type;
ast->data = data;
ast->scope = scope;
return ast;
}
void ast_destroy(AST* ast) {
if (!ast) return;
switch (ast->type) {
case AST_TYPE_NUM: ast_num_data_destroy(ast->data); break;
case AST_TYPE_CALL: ast_call_data_destroy(ast->data); break;
case AST_TYPE_VREF: ast_vref_data_destroy(ast->data); break;
case AST_TYPE_VDEF: ast_vdef_data_destroy(ast->data); break;
case AST_TYPE_BLOCK: ast_block_data_destroy(ast->data); break;
case AST_TYPE_FDEF: ast_fdef_data_destroy(ast->data); break;
case AST_TYPE_ARG: ast_arg_data_destroy(ast->data); break;
case AST_TYPE_LAMBDA: ast_lambda_data_destroy(ast->data); break;
default:
log_dbgf("Unknown ast type %d (max: %d)", ast->type, AST_TYPE_MAX);
}
// If there're no more `AST`s linked to the scope, free.
if (ast->scope && !--ast->scope->uses) scope_destroy_psv(ast->scope);
free(ast);
}
void ast_destroy_psv(AST* ast) {
if (!ast) return;
switch (ast->type) {
case AST_TYPE_NUM: ast_num_data_destroy(ast->data); break;
case AST_TYPE_CALL: ast_call_data_destroy_psv(ast->data); break;
case AST_TYPE_VREF: ast_vref_data_destroy(ast->data); break;
case AST_TYPE_VDEF: ast_vdef_data_destroy_psv(ast->data); break;
case AST_TYPE_BLOCK: ast_block_data_destroy_psv(ast->data); break;
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;
case AST_TYPE_LAMBDA: ast_lambda_data_destroy(ast->data); break;
default:
log_dbgf("Unknown ast type %d (max: %d)", ast->type, AST_TYPE_MAX);
}
free(ast);
}
ASTNumData* ast_num_data_init(double val) {
talloc(ASTNumData, num);
*num = val;
return num;
}
void ast_num_data_destroy(ASTNumData* num) { free(num); }
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);
}
ASTBIFData* ast_bif_data_init(AST* fn(size_t, AST**, Scope*)) {
return (ASTBIFData*)fn;
}
void ast_bif_data_destroy(ASTBIFData* bif) { return; }
ASTCallData* ast_call_data_init(char* to, size_t argc, AST** argv) {
talloc(ASTCallData, call);
log_dbgf("to: %s", to);
call->to = to;
call->argc = argc;
call->argv = argv;
return call;
}
void ast_call_data_destroy(ASTCallData* call) {
if (!call) return;
free(call->to);
for (size_t i = 0; i < call->argc; i++) ast_destroy(call->argv[i]);
free(call->argv);
free(call);
}
void ast_call_data_destroy_psv(ASTCallData* call) {
if (!call) return;
free(call->to);
call->to = NULL;
free(call->argv);
call->argv = NULL;
free(call);
}
ASTVDefData* ast_vdef_data_init(char* name, AST* val) {
talloc(ASTVDefData, vdef);
vdef->name = name;
vdef->val = val;
return vdef;
}
void ast_vdef_data_destroy(ASTVDefData* vdef) {
ast_destroy(vdef->val);
free(vdef->name);
free(vdef);
}
void ast_vdef_data_destroy_psv(ASTVDefData* vdef) {
free(vdef->name);
free(vdef);
}
ASTVrefData* ast_vref_data_init(char* to) {
talloc(ASTVrefData, vref);
vref->to = to;
return vref;
}
void ast_vref_data_destroy(ASTVrefData* vref) {
free(vref->to);
free(vref);
}
ASTBlockData* ast_block_data_init(AST** inside, size_t ln) {
ASTBlockData* block = malloc(sizeof(ASTBlockData));
block->inside = inside;
block->ln = ln;
return block;
}
void ast_block_data_destroy(ASTBlockData* block) {
for (size_t i = 0; i < block->ln; i++) { ast_destroy(block->inside[i]); }
free(block->inside);
free(block);
}
void ast_block_data_destroy_psv(ASTBlockData* block) {
free(block->inside);
free(block);
}
ASTFDefData*
ast_fdef_data_init(char* name, size_t argc, AST** argv, AST* body) {
ASTFDefData* fdef = malloc(sizeof(ASTFDefData));
fdef->name = name;
fdef->argc = argc;
fdef->argv = argv;
fdef->body = body;
return fdef;
}
void ast_fdef_data_destroy(ASTFDefData* fdef) {
free(fdef->name);
for (int i = 0; i < fdef->argc; ast_destroy(fdef->argv[i++]));
ast_destroy(fdef->body);
}
void ast_fdef_data_destroy_psv(ASTFDefData* fdef) {
free(fdef->name);
free(fdef->argv);
free(fdef);
}
ASTArgData* ast_arg_data_init(char* name) {
ASTArgData* arg = malloc(sizeof(ASTArgData));
arg->name = name;
return arg;
}
void ast_arg_data_destroy(ASTArgData* arg) { free(arg->name); }
ASTLambdaData* ast_lambda_data_init(size_t argc, AST** argv, AST* body) {
talloc(ASTLambdaData, lambda);
lambda->argc = argc;
lambda->argv = argv;
lambda->body = body;
return lambda;
}
void ast_lambda_data_destroy(ASTLambdaData* lambda) {
free(lambda->argv);
free(lambda);
}
AST* ast_find(Scope* scope, char* name) {
while (scope) {
AST* gotten = htab_get(scope->here, name);
if (gotten) return gotten;
else scope = scope->inherit;
}
return NULL;
}