lang: add user args to ast iterator; combine pre/post-order traversal modes

the caller can now provide a pointer arg to ivy_ast_node_iterate, which will
be forwarded to the specified callback function each time it is called.

the iterator now behaves similarly to fts, in that it visits each node
in both pre-order and post-order, and indicates to the callback whether
the current iteration is pre- or post-order.
This commit is contained in:
2025-04-14 12:24:42 +01:00
parent 7a9fc1b11c
commit 80e001cdc1
3 changed files with 63 additions and 15 deletions

View File

@@ -6,6 +6,7 @@ enum ivy_status iterate_regular(
struct ivy_ast_node *node, struct ivy_ast_node_iterator *it, struct ivy_ast_node *node, struct ivy_ast_node_iterator *it,
ivy_ast_node_iteration_callback callback) ivy_ast_node_iteration_callback callback)
{ {
#if 0
b_queue_push_back(&it->it_queue, &node->n_it.it_entry); b_queue_push_back(&it->it_queue, &node->n_it.it_entry);
node->n_it.it_depth = 0; node->n_it.it_depth = 0;
@@ -33,6 +34,7 @@ enum ivy_status iterate_regular(
b_queue_delete(&it->it_queue, entry); b_queue_delete(&it->it_queue, entry);
} }
#endif
return IVY_OK; return IVY_OK;
} }
@@ -96,7 +98,7 @@ enum ivy_status iterate_postorder(
return IVY_ERR_INTERNAL_FAILURE; return IVY_ERR_INTERNAL_FAILURE;
} }
callback(node, it); // callback(node, it);
} }
return IVY_OK; return IVY_OK;
@@ -104,18 +106,60 @@ enum ivy_status iterate_postorder(
enum ivy_status ivy_ast_node_iterate( enum ivy_status ivy_ast_node_iterate(
struct ivy_ast_node *node, struct ivy_ast_node_iterator *it, 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) { b_queue_iterator q_it;
case IVY_AST_ITERATE_REGULAR: b_queue_iterator_begin(&it->it_queue, &q_it);
return iterate_regular(node, it, callback);
case IVY_AST_ITERATE_POSTORDER: while (b_queue_iterator_is_valid(&q_it)) {
return iterate_postorder(node, it, callback); struct ivy_ast_node_iterator_entry *it_entry = b_unbox(
default: struct ivy_ast_node_iterator_entry, q_it.entry, it_entry);
return IVY_ERR_INVALID_VALUE; 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( void ast_node_iterator_enqueue_node(

View File

@@ -1,6 +1,9 @@
#ifndef _AST_ITERATE_H_ #ifndef _AST_ITERATE_H_
#define _AST_ITERATE_H_ #define _AST_ITERATE_H_
struct ivy_ast_node_iterator;
struct ivy_ast_node;
extern void ast_node_iterator_enqueue_node( extern void ast_node_iterator_enqueue_node(
struct ivy_ast_node_iterator *it, struct ivy_ast_node *parent, struct ivy_ast_node_iterator *it, struct ivy_ast_node *parent,
struct ivy_ast_node *node); struct ivy_ast_node *node);

View File

@@ -54,9 +54,9 @@ enum ivy_ast_node_type {
IVY_AST_TYPE_COUNT, IVY_AST_TYPE_COUNT,
}; };
enum ivy_ast_iterator_mode { enum ivy_ast_iteration_type {
IVY_AST_ITERATE_REGULAR, IVY_AST_ITERATION_PRE,
IVY_AST_ITERATE_POSTORDER, IVY_AST_ITERATION_POST,
}; };
struct ivy_ast_node_iterator { struct ivy_ast_node_iterator {
@@ -317,7 +317,8 @@ struct ivy_ast_block_node {
}; };
typedef enum ivy_status (*ivy_ast_node_iteration_callback)( 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 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);
@@ -332,7 +333,7 @@ IVY_API enum ivy_status ivy_parser_push_token(
IVY_API enum ivy_status ivy_ast_node_iterate( IVY_API enum ivy_status ivy_ast_node_iterate(
struct ivy_ast_node *node, struct ivy_ast_node_iterator *it, 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_to_string(struct ivy_ast_node *node, struct b_string *out);
IVY_API void ivy_ast_node_destroy(struct ivy_ast_node *node); IVY_API void ivy_ast_node_destroy(struct ivy_ast_node *node);