#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 decl_destroy(struct decl_node* node) { if (node->initial_value != NULL) { expr_destroy(node->initial_value); free(node->initial_value); } if (node->next != NULL) { decl_destroy(node->next); free(node->next); } } static void expr_list_destroy(struct expr_list_node* node) { expr_destroy(node->expr); free(node->expr); if (node->next != NULL) { expr_list_destroy(node->next); free(node->next); } } static void assign_destroy(struct assign_node* node) { expr_destroy(node->lval); free(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 decl_list_destroy(struct decl_list_node* node) { decl_destroy(node->head); free(node->head); } static void fn_arg_destroy(struct arg_decl_node* node) { if (node->next != NULL) { fn_arg_destroy(node->next); free(node->next); } } static void fn_decl_destroy(struct fn_decl_node* node) { if (node->args != NULL) { fn_arg_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_list_destroy(node->ret_val); free(node->ret_val); } } static void str_lit_destroy(struct str_lit_node* node) { free(node->val); } static void call_destroy(struct call_node* node) { if (node->args != NULL) { expr_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 paren_destroy(struct paren_node* node) { expr_list_destroy(node->expr_list); free(node->expr_list); } static void cast_destroy(struct cast_node* node) { expr_destroy(node->expr); free(node->expr); } 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: 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; case EXPR_PAREN: paren_destroy(&node->inner.paren); break; case EXPR_CAST: cast_destroy(&node->inner.cast); break; } } static void if_destroy(struct if_node* node) { expr_list_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); } scope_destroy(node->scope); free(node->scope); } static void loop_init_destroy(struct loop_init_node* node) { switch (node->type) { case INIT_EXPR_LIST: expr_list_destroy(node->expr_list); free(node->expr_list); break; case INIT_DECL_LIST: decl_list_destroy(node->decl_list); free(node->decl_list); break; } } static void loop_destroy(struct loop_node* node) { if (node->init != NULL) { loop_init_destroy(node->init); free(node->init); } if (node->cond != NULL) { expr_list_destroy(node->cond); free(node->cond); } if (node->incr != NULL) { expr_list_destroy(node->incr); free(node->incr); } stmt_destroy(node->body); free(node->body); scope_destroy(node->scope); free(node->scope); } static void stmt_destroy(struct stmt_node* node) { switch (node->type) { case STMT_EMPTY: break; case STMT_EXPR_LIST: expr_list_destroy(&node->inner.expr_list); break; case STMT_DECL_LIST: decl_list_destroy(&node->inner.decl_list); 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; case STMT_LOOP: loop_destroy(&node->inner.loop); 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); }