summaryrefslogtreecommitdiffstats
path: root/lib.c
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
commit585b970c097bf1522d596a81e3528cc75cc12960 (patch)
treef8ce27efe529ba3e0fa9e6b5d219f1ce2b299b08 /lib.c
parent338d0803cd5fcd89cd5ed908b6d3ca75f0dd35ed (diff)
downloadtxr-585b970c097bf1522d596a81e3528cc75cc12960.tar.gz
txr-585b970c097bf1522d596a81e3528cc75cc12960.tar.bz2
txr-585b970c097bf1522d596a81e3528cc75cc12960.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.
Diffstat (limited to 'lib.c')
-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)