#include "node.h" #include 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; while (!b_queue_empty(&it->it_queue)) { b_queue_entry *entry = b_queue_first(&it->it_queue); struct ivy_ast_node_iterator_entry *it_entry = b_unbox( struct ivy_ast_node_iterator_entry, 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, it); 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 = entry; type->n_collect_children(node, it); } b_queue_delete(&it->it_queue, entry); } #endif return IVY_OK; } enum ivy_status iterate_postorder( struct ivy_ast_node *node, struct ivy_ast_node_iterator *it, ivy_ast_node_iteration_callback callback) { /* general iteration strategy: * 1. create a queue. * 2. push `node` to the end of the queue. * 3. for each node N in the queue: * 1. collect N's children. * 2. insert the children into the queue between N and the node * immediately following N. * 4. the loop in step 3 continues over all nodes added within the loop, * and stops when all nodes have been visited. * 5. iterate over the completed queue in reverse order, calling * `callback` on each one. * * NOTES: * - not sure how this will work for package definitions. * - should probably use this just for the executable parts of the AST, * not for nodes defining classes, function metadata, etc. */ b_queue_push_back(&it->it_queue, &node->n_it.it_entry); node->n_it.it_depth = 0; b_queue_entry *entry = b_queue_first(&it->it_queue); while (entry) { struct ivy_ast_node_iterator_entry *it_entry = b_unbox( struct ivy_ast_node_iterator_entry, 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; } const struct ast_node_type *type = get_ast_node_type(node->n_type); if (type->n_collect_children) { it->it_insert_after = entry; type->n_collect_children(node, it); } entry = b_queue_next(entry); } 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; } // callback(node, it); } return IVY_OK; } enum ivy_status ivy_ast_node_iterate( struct ivy_ast_node *node, struct ivy_ast_node_iterator *it, ivy_ast_node_iteration_callback callback, void *arg) { b_queue_push_back(&it->it_queue, &node->n_it.it_entry); node->n_it.it_depth = 0; b_queue_entry *entry = b_queue_first(&it->it_queue); while (entry) { struct ivy_ast_node_iterator_entry *it_entry = b_unbox( struct ivy_ast_node_iterator_entry, 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 = entry; type->n_collect_children(node, it); } entry = b_queue_next(entry); } 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( struct ivy_ast_node_iterator *it, struct ivy_ast_node *parent, struct ivy_ast_node *node) { if (it->it_insert_after) { b_queue_insert_after( &it->it_queue, &node->n_it.it_entry, it->it_insert_after); } else { b_queue_push_back(&it->it_queue, &node->n_it.it_entry); } node->n_it.it_depth = parent->n_it.it_depth + 1; it->it_insert_after = &node->n_it.it_entry; }