lang: fix a bunch of memory leaks
This commit is contained in:
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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) \
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user