#include "ast.h" #include static void expr_destroy(struct expr_node* node); static void stmt_destroy(struct stmt_node* node); static void var_decl_destroy(struct var_decl_node* node) { free(node->ident); } 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: var_decl_destroy(&node->as._var_decl); break; case LVAL_VAR_REF: var_ref_destroy(&node->as._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->body_head; while (body_node != NULL) { struct stmt_node* next = body_node->next; stmt_destroy(body_node); free(body_node); body_node = next; } } static void fn_decl_destroy(struct fn_decl_node* node) { free(node->name); struct var_decl_node* args_node = node->args_head; while (args_node != NULL) { struct var_decl_node* next = args_node->next; var_decl_destroy(args_node); free(args_node); args_node = next; } group_destroy(&node->body); } 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 call_destroy(struct call_node* node) { /* don't destroy node->called_fn, this is owned by its declaration */ struct expr_node* args_node = node->args_head; while (args_node != NULL) { struct expr_node* next = args_node->next; expr_destroy(args_node); free(args_node); args_node = next; } } 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->as._str_lit); break; case EXPR_VAR_REF: var_ref_destroy(&node->as._var_ref); break; case EXPR_ASSIGN: assign_destroy(&node->as._assign); break; case EXPR_CALL: call_destroy(&node->as._call); break; } } static void stmt_destroy(struct stmt_node* node) { switch (node->type) { case STMT_EMPTY: break; case STMT_EXPR: expr_destroy(&node->as._expr); break; case STMT_VAR_DECL: var_decl_destroy(&node->as._var_decl); break; case STMT_RETURN: return_destroy(&node->as._return); break; case STMT_GROUP: group_destroy(&node->as._group); } } static void root_node_destroy(struct root_node* node) { switch (node->type) { case ROOT_FN_DECL: fn_decl_destroy(&node->as._fn_decl); break; } } void ast_destroy(struct root_node* head) { struct root_node* node = head; while (node != NULL) { struct root_node* next = node->next; root_node_destroy(node); free(node); node = next; } }