lang: ast: implement ast iteration
iteration is implementing without recursion, instead using type-specific callbacks to construct a queue of nodes to iterate through. ast priting is implemented using this functionality.
This commit is contained in:
48
lang/ast/iterate.c
Normal file
48
lang/ast/iterate.c
Normal file
@@ -0,0 +1,48 @@
|
||||
#include <ivy/lang/ast.h>
|
||||
#include "node.h"
|
||||
|
||||
enum ivy_status ivy_ast_node_iterate(
|
||||
struct ivy_ast_node *node,
|
||||
struct ivy_ast_node_iterator *it,
|
||||
ivy_ast_node_iteration_callback callback)
|
||||
{
|
||||
memset(it, 0x0, sizeof *it);
|
||||
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);
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
Reference in New Issue
Block a user