summaryrefslogtreecommitdiffstats
path: root/tree.c
diff options
context:
space:
mode:
authorKaz Kylheku <kaz@kylheku.com>2021-05-09 17:45:55 -0700
committerKaz Kylheku <kaz@kylheku.com>2021-05-09 17:45:55 -0700
commit96715da165569922e1efa584eb0ce4f4d272c46d (patch)
tree08e2b19c2c2a9637d2f70785c5a6a3a47de365d3 /tree.c
parent8a7a4963a6cdf0a0d8b7145aefb4a40f5f26c673 (diff)
downloadtxr-96715da165569922e1efa584eb0ce4f4d272c46d.tar.gz
txr-96715da165569922e1efa584eb0ce4f4d272c46d.tar.bz2
txr-96715da165569922e1efa584eb0ce4f4d272c46d.zip
tree: new tree-peek function.
* tree.c (tn_peek_next): New static function. (tree_peek): New function. (tree_init): Register tree-peek intrinsic. * tree.h (tree_peek): Declared. * txr.1: Documented. * tests/010/tree.c: Work tree-peek into existing test case. * share/txr/stdlib/doc-syms.tl: Updated.
Diffstat (limited to 'tree.c')
-rw-r--r--tree.c52
1 files changed, 52 insertions, 0 deletions
diff --git a/tree.c b/tree.c
index 47bbe8d6..2a5334a2 100644
--- a/tree.c
+++ b/tree.c
@@ -214,6 +214,43 @@ static val tn_find_next(val node, struct tree_iter *trit)
}
}
+static val tn_peek_next(val node, struct tree_iter *trit)
+{
+ enum tree_iter_state state = trit->state;
+ int depth = trit->depth;
+
+ for (;;) {
+ switch (state) {
+ case tr_visited_nothing:
+ if (!node)
+ return nil;
+ while (node->tn.left)
+ node = node->tn.left;
+ return node;
+ case tr_visited_left:
+ if (node->tn.right) {
+ state = tr_visited_nothing;
+ node = node->tn.right;
+ continue;
+ } else {
+ while (depth > 0) {
+ val parent = trit->path[--depth];
+ if (node == parent->tn.right) {
+ node = parent;
+ continue;
+ }
+ return parent;
+ }
+ return nil;
+ }
+ case tr_find_low_prepared:
+ return node;
+ default:
+ internal_error("invalid tree iterator state");
+ }
+ }
+}
+
static void tn_find_low(val node, struct tree_diter *tdi,
struct tree *tr, val key)
{
@@ -820,6 +857,20 @@ val tree_next(val iter)
return nil;
}
+val tree_peek(val iter)
+{
+ val self = lit("tree-peek");
+ struct tree_diter *tdi = coerce(struct tree_diter *,
+ cobj_handle(self, iter, tree_iter_s));
+
+ if (tdi->lastnode) {
+ val node = tn_peek_next(tdi->lastnode, &tdi->ti);
+ return node;
+ }
+
+ return nil;
+}
+
val tree_clear(val tree)
{
val self = lit("tree-clear");
@@ -860,6 +911,7 @@ void tree_init(void)
reg_fun(intern(lit("tree-reset"), user_package), func_n2(tree_reset));
reg_fun(intern(lit("tree-reset-at"), user_package), func_n3(tree_reset_at));
reg_fun(intern(lit("tree-next"), user_package), func_n1(tree_next));
+ reg_fun(intern(lit("tree-peek"), user_package), func_n1(tree_peek));
reg_fun(intern(lit("tree-clear"), user_package), func_n1(tree_clear));
reg_var(tree_fun_whitelist_s, list(identity_s, equal_s, less_s, nao));
}