diff options
author | Kaz Kylheku <kaz@kylheku.com> | 2024-02-27 08:18:42 -0800 |
---|---|---|
committer | Kaz Kylheku <kaz@kylheku.com> | 2024-02-27 08:18:42 -0800 |
commit | 585b970c097bf1522d596a81e3528cc75cc12960 (patch) | |
tree | f8ce27efe529ba3e0fa9e6b5d219f1ce2b299b08 | |
parent | 338d0803cd5fcd89cd5ed908b6d3ca75f0dd35ed (diff) | |
download | txr-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.
-rw-r--r-- | lib.c | 21 |
1 files changed, 19 insertions, 2 deletions
@@ -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) |