diff --git a/lang/ast/iterate.c b/lang/ast/iterate.c index e3895c7..6036a95 100644 --- a/lang/ast/iterate.c +++ b/lang/ast/iterate.c @@ -6,6 +6,7 @@ enum ivy_status iterate_regular( struct ivy_ast_node *node, struct ivy_ast_node_iterator *it, ivy_ast_node_iteration_callback callback) { +#if 0 b_queue_push_back(&it->it_queue, &node->n_it.it_entry); node->n_it.it_depth = 0; @@ -33,6 +34,7 @@ enum ivy_status iterate_regular( b_queue_delete(&it->it_queue, entry); } +#endif return IVY_OK; } @@ -96,7 +98,7 @@ enum ivy_status iterate_postorder( return IVY_ERR_INTERNAL_FAILURE; } - callback(node, it); + // callback(node, it); } return IVY_OK; @@ -104,18 +106,60 @@ enum ivy_status iterate_postorder( enum ivy_status ivy_ast_node_iterate( struct ivy_ast_node *node, struct ivy_ast_node_iterator *it, - enum ivy_ast_iterator_mode mode, ivy_ast_node_iteration_callback callback) + ivy_ast_node_iteration_callback callback, void *arg) { - memset(it, 0x0, sizeof *it); + b_queue_push_back(&it->it_queue, &node->n_it.it_entry); + node->n_it.it_depth = 0; - switch (mode) { - case IVY_AST_ITERATE_REGULAR: - return iterate_regular(node, it, callback); - case IVY_AST_ITERATE_POSTORDER: - return iterate_postorder(node, it, callback); - default: - return IVY_ERR_INVALID_VALUE; + 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 IVY_ERR_INTERNAL_FAILURE; + } + + enum ivy_status status + = callback(node, IVY_AST_ITERATION_PRE, it, arg); + if (status != IVY_OK) { + return status; + } + + 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); + + if (!node) { + /* this should never happen. */ + return IVY_ERR_INTERNAL_FAILURE; + } + + enum ivy_status status + = callback(node, IVY_AST_ITERATION_POST, it, arg); + if (status != IVY_OK) { + return status; + } + } + + return IVY_OK; } void ast_node_iterator_enqueue_node( diff --git a/lang/ast/iterate.h b/lang/ast/iterate.h index 5d5f70f..d098493 100644 --- a/lang/ast/iterate.h +++ b/lang/ast/iterate.h @@ -1,6 +1,9 @@ #ifndef _AST_ITERATE_H_ #define _AST_ITERATE_H_ +struct ivy_ast_node_iterator; +struct ivy_ast_node; + extern void ast_node_iterator_enqueue_node( struct ivy_ast_node_iterator *it, struct ivy_ast_node *parent, struct ivy_ast_node *node); diff --git a/lang/include/ivy/lang/ast.h b/lang/include/ivy/lang/ast.h index e273c27..de68c2b 100644 --- a/lang/include/ivy/lang/ast.h +++ b/lang/include/ivy/lang/ast.h @@ -54,9 +54,9 @@ enum ivy_ast_node_type { IVY_AST_TYPE_COUNT, }; -enum ivy_ast_iterator_mode { - IVY_AST_ITERATE_REGULAR, - IVY_AST_ITERATE_POSTORDER, +enum ivy_ast_iteration_type { + IVY_AST_ITERATION_PRE, + IVY_AST_ITERATION_POST, }; struct ivy_ast_node_iterator { @@ -317,7 +317,8 @@ struct ivy_ast_block_node { }; typedef enum ivy_status (*ivy_ast_node_iteration_callback)( - struct ivy_ast_node *, struct ivy_ast_node_iterator *); + struct ivy_ast_node *, enum ivy_ast_iteration_type, + 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); @@ -332,7 +333,7 @@ IVY_API enum ivy_status ivy_parser_push_token( IVY_API enum ivy_status ivy_ast_node_iterate( struct ivy_ast_node *node, struct ivy_ast_node_iterator *it, - enum ivy_ast_iterator_mode mode, ivy_ast_node_iteration_callback callback); + ivy_ast_node_iteration_callback callback, void *arg); IVY_API void ivy_ast_node_to_string(struct ivy_ast_node *node, struct b_string *out); IVY_API void ivy_ast_node_destroy(struct ivy_ast_node *node);