From 25c1fbd44b6513fb625a617a5995964d4552e7b7 Mon Sep 17 00:00:00 2001 From: Max Wash Date: Thu, 17 Apr 2025 23:15:48 +0100 Subject: [PATCH] lang: fix a bunch of memory leaks --- lang/ast/ctx.c | 25 +++++++++++++++++++++- lang/ast/node.c | 41 +++++++++++++++++++++++++++++++++++++ lang/ast/node.h | 1 + lang/include/ivy/lang/ast.h | 3 ++- 4 files changed, 68 insertions(+), 2 deletions(-) diff --git a/lang/ast/ctx.c b/lang/ast/ctx.c index 18ad892..f1c53a0 100644 --- a/lang/ast/ctx.c +++ b/lang/ast/ctx.c @@ -39,8 +39,31 @@ enum ivy_status ivy_parser_create(struct ivy_parser **parser) return IVY_OK; } -void ivy_parser_destroy(struct ivy_parser *parser) +void ivy_parser_destroy(struct ivy_parser *parser, struct ivy_ast_node **result) { + struct ivy_ast_node *root = NULL; + + b_queue_iterator it; + b_queue_iterator_begin(&parser->p_state, &it); + while (b_queue_iterator_is_valid(&it)) { + struct parser_state *state + = b_unbox(struct parser_state, it.entry, s_entry); + b_queue_iterator_erase(&it); + + if (root) { + ivy_ast_node_destroy(root); + } + + root = state->s_node; + free(state); + } + + if (result) { + *result = root; + } else if (root) { + ivy_ast_node_destroy(root); + } + free(parser); } diff --git a/lang/ast/node.c b/lang/ast/node.c index e97efa4..9b59c61 100644 --- a/lang/ast/node.c +++ b/lang/ast/node.c @@ -252,6 +252,47 @@ void ivy_ast_node_to_string(struct ivy_ast_node *node, struct b_string *out) void ivy_ast_node_destroy(struct ivy_ast_node *node) { + struct ivy_ast_node_iterator it = {}; + b_queue_push_back(&it.it_queue, &node->n_it.it_entry); + node->n_it.it_depth = 0; + + b_queue_iterator q_it; + b_queue_iterator_begin(&it.it_queue, &q_it); + + while (b_queue_iterator_is_valid(&q_it)) { + struct ivy_ast_node_iterator_entry *it_entry = b_unbox( + struct ivy_ast_node_iterator_entry, q_it.entry, it_entry); + node = b_unbox(struct ivy_ast_node, it_entry, n_it); + + if (!node) { + /* this should never happen. */ + return; + } + + const struct ast_node_type *type = get_ast_node_type(node->n_type); + if (type->n_collect_children) { + it.it_insert_after = q_it.entry; + type->n_collect_children(node, &it); + } + + b_queue_iterator_next(&q_it); + } + + while (!b_queue_empty(&it.it_queue)) { + b_queue_entry *entry = b_queue_pop_back(&it.it_queue); + if (!entry) { + break; + } + + node = b_unbox(struct ivy_ast_node, entry, n_it); + + const struct ast_node_type *type = get_ast_node_type(node->n_type); + if (type && type->n_destroy) { + type->n_destroy(node); + } + + free(node); + } } #define ENUM_STR(x) \ diff --git a/lang/ast/node.h b/lang/ast/node.h index 6edcb83..7b1a5d2 100644 --- a/lang/ast/node.h +++ b/lang/ast/node.h @@ -50,6 +50,7 @@ struct ast_node_type { void (*n_init_state)(struct ivy_parser *, struct parser_state *, uintptr_t); void (*n_collect_children)( struct ivy_ast_node *, struct ivy_ast_node_iterator *); + void (*n_destroy)(struct ivy_ast_node *); size_t n_state_size; size_t n_node_size; diff --git a/lang/include/ivy/lang/ast.h b/lang/include/ivy/lang/ast.h index 43d1678..cabe5d5 100644 --- a/lang/include/ivy/lang/ast.h +++ b/lang/include/ivy/lang/ast.h @@ -329,7 +329,8 @@ typedef enum ivy_status (*ivy_ast_node_iteration_callback)( struct ivy_ast_node_iterator *, void *); IVY_API enum ivy_status ivy_parser_create(struct ivy_parser **parser); -IVY_API void ivy_parser_destroy(struct ivy_parser *parser); +IVY_API void ivy_parser_destroy( + struct ivy_parser *parser, struct ivy_ast_node **result); IVY_API enum ivy_status ivy_parser_get_status(struct ivy_parser *parser); IVY_API bool ivy_parser_is_node_complete(struct ivy_parser *parser);