From 6d7ae0d677f9c507d15af86cf51f365d6248401d Mon Sep 17 00:00:00 2001
From: Kaz Kylheku <kaz@kylheku.com>
Date: Sun, 22 Sep 2019 16:11:33 -0700
Subject: New data type: tnode.

Binary search tree nodes are being added as a basic heap data
type. The C type tag is TNOD, and the Lisp type is tnode.

Binary search tree nodes have three elements: a key, a left
child and a right child.

The printed notation is #N(key left right). Quasiquoting
is supported: ^#N(,foo ,bar) but not splicing.

Because tnodes have three elements, they they fit into TXR's
four-word heap cell, not requiring any additional memory
allocation.

These nodes are going to be the basis for a binary search tree
container, which will use the scapegoat tree algorithm for
maintaining balance.

* tree.c, tree.h: New files.

* Makefile (OBJS): Adding tree.o.

* eval.c (expand_qquote_rec): Recurse through tnode cells,
so unquotes work inside #N syntax.

* gc.c (finalize): Add TNOD to no-op case in switch; tnodes
don't require finalization.
(mark_obj): Traverse tnode cell.

* hash.c (equal_hash): Add TNOD case.

* lib.c (tnode_s): New symbol variable.
(seq_kind_tab): New entry for TNOD, mapping to SEQ_NOTSEQ.
(code2type, equal): Handle TNOD.
(obj_init): Initialize tnode_s variable.
(obj_print_impl, populate_obj_hash): Handle TNOD.
(init): Call tree_init function in tree.c.

* lib.h (enum type, type_t): New enumeration TNOD.
(struct tnod): New struct type.
(union obj, obj_t): New union member tn of type struct tnod.
(tnode_s): Declard.

* parserc.c (circ_backpatch): Handle TNOD, so circular
notation works through tnode cells.

* parser.l (grammar): Recognize #N prefix, mapping to
HASH_N token.

* parser.y (HASH_N): New grammar terminal symbol.
(tnode): New nonterminal symbol.
(i_expr, n_expr): Add tnode cases to productions.
(yybadtoken): Map HASH_N to "#N" string.
---
 tree.c | 91 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 91 insertions(+)
 create mode 100644 tree.c

(limited to 'tree.c')

diff --git a/tree.c b/tree.c
new file mode 100644
index 00000000..205d5b84
--- /dev/null
+++ b/tree.c
@@ -0,0 +1,91 @@
+/* Copyright 2019
+ * Kaz Kylheku <kaz@kylheku.com>
+ * Vancouver, Canada
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ *    list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ *    this list of conditions and the following disclaimer in the documentation
+ *    and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+#include <stddef.h>
+#include <stdio.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <limits.h>
+#include <signal.h>
+#include "config.h"
+#include "alloca.h"
+#if HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#include "lib.h"
+#include "gc.h"
+#include "args.h"
+#include "txr.h"
+#include "signal.h"
+#include "unwind.h"
+#include "stream.h"
+#include "eval.h"
+#include "itypes.h"
+#include "arith.h"
+#include "tree.h"
+
+val tnode(val key, val left, val right)
+{
+  val obj = make_obj();
+  obj->tn.type = TNOD;
+  obj->tn.left = left;
+  obj->tn.right = right;
+  obj->tn.key = key;
+  return obj;
+}
+
+val tnodep(val obj)
+{
+  return tnil(type(obj) == TNOD);
+}
+
+val left(val node)
+{
+  type_check(lit("left"), node, TNOD);
+  return node->tn.left;
+}
+
+val right(val node)
+{
+  type_check(lit("right"), node, TNOD);
+  return node->tn.right;
+}
+
+val key(val node)
+{
+  type_check(lit("key"), node, TNOD);
+  return node->tn.key;
+}
+
+void tree_init(void)
+{
+  reg_fun(tnode_s, func_n3(tnode));
+  reg_fun(intern(lit("left"), user_package), func_n1(left));
+  reg_fun(intern(lit("right"), user_package), func_n1(right));
+  reg_fun(intern(lit("key"), user_package), func_n1(key));
+}
-- 
cgit v1.2.3