#include "ast.h" #include "scope.h" #include static void expr_destroy(struct expr_node* node); static void stmt_destroy(struct stmt_node* node); static void var_ref_destroy(struct var_ref_node* node) { free(node->ident); } static void lval_destroy(struct lval_node* node) { switch (node->type) { case LVAL_VAR_DECL: break; case LVAL_VAR_REF: var_ref_destroy(&node->inner.var_ref); break; } } static void assign_destroy(struct assign_node* node) { lval_destroy(&node->lval); expr_destroy(node->rval); free(node->rval); } static void group_destroy(struct group_node* node) { struct stmt_node* body_node = node->head; while (body_node != NULL) { struct stmt_node* next = body_node->next; stmt_destroy(body_node); free(body_node); body_node = next; } scope_destroy(node->scope); free(node->scope); } static void args_decl_destroy(struct args_decl_node* node) { if (node != NULL) { free(node->decl); args_decl_destroy(node->next); } } static void fn_decl_destroy(struct fn_decl_node* node) { args_decl_destroy(node->args); free(node->args); group_destroy(&node->body); scope_destroy(node->scope); free(node->scope); } static void return_destroy(struct return_node* node) { if (node->ret_val != NULL) { expr_destroy(node->ret_val); free(node->ret_val); } } static void str_lit_destroy(struct str_lit_node* node) { free(node->val); } static void args_list_destroy(struct args_eval_node* node) { if (node != NULL) { expr_destroy(node->expr); free(node->expr); args_list_destroy(node->next); } } static void call_destroy(struct call_node* node) { args_list_destroy(node->args); free(node->args); } static void unary_destroy(struct unary_node* node) { expr_destroy(node->expr); free(node->expr); } static void binary_destroy(struct binary_node* node) { expr_destroy(node->lhs); free(node->lhs); expr_destroy(node->rhs); free(node->rhs); } static void expr_destroy(struct expr_node* node) { switch (node->type) { case EXPR_INT_LIT: case EXPR_FLOAT_LIT: case EXPR_CHAR_LIT: break; case EXPR_STR_LIT: str_lit_destroy(&node->inner.str_lit); break; case EXPR_VAR_REF: var_ref_destroy(&node->inner.var_ref); break; case EXPR_ASSIGN: assign_destroy(&node->inner.assign); break; case EXPR_CALL: call_destroy(&node->inner.call); break; case EXPR_UNARY: unary_destroy(&node->inner.unary); break; case EXPR_BINARY: binary_destroy(&node->inner.binary); break; } } static void if_destroy(struct if_node* node) { expr_destroy(node->cond); free(node->cond); stmt_destroy(node->true_branch); free(node->true_branch); if (node->false_branch != NULL) { stmt_destroy(node->false_branch); free(node->false_branch); } } static void stmt_destroy(struct stmt_node* node) { switch (node->type) { case STMT_EMPTY: break; case STMT_EXPR: expr_destroy(&node->inner.expr); break; case STMT_VAR_DECL: break; case STMT_RETURN: return_destroy(&node->inner.return_); break; case STMT_GROUP: group_destroy(&node->inner.group); break; case STMT_IF: if_destroy(&node->inner.if_); break; } } static void root_node_destroy(struct root_node* node) { switch (node->type) { case ROOT_FN_DECL: fn_decl_destroy(&node->inner.fn_decl); break; } } void ast_destroy(struct ast* ast) { struct root_node* node = ast->root_node; while (node != NULL) { struct root_node* next = node->next; root_node_destroy(node); free(node); node = next; } scope_destroy(ast->root_scope); free(ast->root_scope); }