summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKaz Kylheku <kaz@kylheku.com>2019-10-16 07:36:27 -0700
committerKaz Kylheku <kaz@kylheku.com>2019-10-16 07:36:27 -0700
commitbdc7277d09377f87319e0c27de40210b0212fabc (patch)
tree82f310bcb94d82c8db838d7dec41e380251bfa2f
parentafbca6b306ddd07e84c44f4d47bd04ddd3cada86 (diff)
downloadtxr-bdc7277d09377f87319e0c27de40210b0212fabc.tar.gz
txr-bdc7277d09377f87319e0c27de40210b0212fabc.tar.bz2
txr-bdc7277d09377f87319e0c27de40210b0212fabc.zip
tree: copy-search-tree function.
* lib.c (copy): Handle tree objects via copy_search_tree. * tree.c (deep_copy_tnode): New static function. (copy_search_tree): New function. (tree_init): copy-search-tree intrinsic registered. * tree.h (copy_search_tree): Declared. * txr.1: Documented copy-search-tree, and copy function's use thereof.
-rw-r--r--lib.c2
-rw-r--r--tree.c22
-rw-r--r--tree.h1
-rw-r--r--txr.124
4 files changed, 49 insertions, 0 deletions
diff --git a/lib.c b/lib.c
index 81f3d06d..b6f22971 100644
--- a/lib.c
+++ b/lib.c
@@ -10081,6 +10081,8 @@ val copy(val seq)
return make_random_state(seq, nil);
if (seq->co.cls == carray_s)
return copy_carray(seq);
+ if (seq->co.cls == tree_s)
+ return copy_search_tree(seq);
if (obj_struct_p(seq))
return copy_struct(seq);
/* fallthrough */
diff --git a/tree.c b/tree.c
index 70e43158..11cc612e 100644
--- a/tree.c
+++ b/tree.c
@@ -637,6 +637,27 @@ static val tree_construct(val opts, val keys)
return tree(keys, key_fn, less_fn, equal_fn);
}
+static val deep_copy_tnode(val node)
+{
+ if (node == nil)
+ return nil;
+ return tnode(node->tn.key,
+ deep_copy_tnode(node->tn.left),
+ deep_copy_tnode(node->tn.right));
+}
+
+val copy_search_tree(val tree)
+{
+ val self = lit("copy-search-tree");
+ struct tree *ntr = coerce(struct tree *, malloc(sizeof *ntr));
+ struct tree *otr = coerce(struct tree *, cobj_handle(self, tree, tree_s));
+ val nroot = deep_copy_tnode(otr->root);
+ val ntree = cobj(coerce(mem_t *, ntr), tree_s, &tree_ops);
+ *ntr = *otr;
+ ntr->root = nroot;
+ return ntree;
+}
+
val treep(val obj)
{
return tnil(type(obj) == COBJ && obj->co.cls == tree_s);
@@ -711,6 +732,7 @@ void tree_init(void)
reg_fun(intern(lit("copy-tnode"), user_package), func_n1(copy_tnode));
reg_fun(tree_s, func_n4o(tree, 0));
reg_fun(tree_construct_s, func_n2(tree_construct));
+ reg_fun(intern(lit("copy-search-tree"), user_package), func_n1(copy_search_tree));
reg_fun(intern(lit("treep"), user_package), func_n1(treep));
reg_fun(intern(lit("tree-insert-node"), user_package), func_n2(tree_insert_node));
reg_fun(intern(lit("tree-insert"), user_package), func_n2(tree_insert));
diff --git a/tree.h b/tree.h
index 528bae7b..7c7833bf 100644
--- a/tree.h
+++ b/tree.h
@@ -39,6 +39,7 @@ val set_right(val node, val nright);
val set_key(val node, val nkey);
val copy_tnode(val node);
val tree(val keys, val key_fn, val less_fn, val equal_fn);
+val copy_search_tree(val tree);
val treep(val obj);
val tree_insert_node(val tree, val node);
val tree_begin(val tree);
diff --git a/txr.1 b/txr.1
index 7f718700..5a536e50 100644
--- a/txr.1
+++ b/txr.1
@@ -28078,6 +28078,8 @@ the type of the argument, as follows:
.meti (make-random-state << object )
.coIP tnode
.meti (copy-tnode << object )
+.coIP tree
+.meti (copy-search-tree << object )
.RE
.IP
@@ -45638,6 +45640,28 @@ is already empty, then the function returns
otherwise it returns an integer which gives the count of the number
of deleted nodes.
+.coNP Function @ copy-search-tree
+.synb
+.mets (copy-search-tree << tree )
+.syne
+.desc
+The
+.code copy-search-tree
+returns a new tree object which is a copy of
+.metn tree .
+
+The
+.meta tree
+argument must be an object of type
+.codn tree .
+
+The returned object has the same key abstraction functions as
+.meta tree
+and contains the same elements.
+
+The nodes held inside the new tree are freshly allocated,
+but their key objects are shared with the original tree.
+
.coNP Function @ tree-begin
.synb
.mets (tree-begin < tree )