summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKaz Kylheku <kaz@kylheku.com>2024-02-27 08:18:42 -0800
committerKaz Kylheku <kaz@kylheku.com>2024-02-27 08:18:42 -0800
commitef524fdf234fe51a37021b8c1a3bb700d5501132 (patch)
treef8ce27efe529ba3e0fa9e6b5d219f1ce2b299b08
parent5ddea59ed9e1a3686c352059bad2ddab2dda19a4 (diff)
downloadtxr-ef524fdf234fe51a37021b8c1a3bb700d5501132.tar.gz
txr-ef524fdf234fe51a37021b8c1a3bb700d5501132.tar.bz2
txr-ef524fdf234fe51a37021b8c1a3bb700d5501132.zip
seq_build: build lists in order using tail pointer.
* lib.c (seq_build_list_add, seq_build_list_finish): We use the trick that bu->obj (if not nil) points to the tail cons cell of the list being built, and the cdr of that tail always points back to the head. To finish the list, all we do is nil out that head pointer, so the list is properly terminated, and then plan the head as bu->obj.
-rw-r--r--lib.c21
1 files changed, 19 insertions, 2 deletions
diff --git a/lib.c b/lib.c
index b8aed8d6..c83afa4d 100644
--- a/lib.c
+++ b/lib.c
@@ -1472,12 +1472,29 @@ static void seq_build_buf_finish(seq_build_t *bu)
static void seq_build_list_add(seq_build_t *bu, val item)
{
- bu->obj = cons(item, bu->obj);
+ val obj = bu->obj;
+
+ if (obj) {
+ val head = us_cdr(obj);
+ val nobj = cons(item, head);
+ us_rplacd(obj, nobj);
+ bu->obj = nobj;
+ } else {
+ val nobj = cons(item, nil);
+ us_rplacd(nobj, nobj);
+ bu->obj = nobj;
+ }
}
static void seq_build_list_finish(seq_build_t *bu)
{
- bu->obj = nreverse(bu->obj);
+ val obj = bu->obj;
+
+ if (obj) {
+ val head = us_cdr(obj);
+ us_rplacd(obj, nil);
+ bu->obj = head;
+ }
}
static void seq_build_struct_finish(seq_build_t *bu)