summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKaz Kylheku <kaz@kylheku.com>2015-11-11 06:33:01 -0800
committerKaz Kylheku <kaz@kylheku.com>2015-11-11 06:33:01 -0800
commit82020af157ad104be3a62b57053d2420d17785f9 (patch)
treee2a54d56d981a7d6e2c657e154fa264b237546b4
parent73368784f2c3d69a0fbc227420550b4b1e05d4ea (diff)
downloadtxr-82020af157ad104be3a62b57053d2420d17785f9.tar.gz
txr-82020af157ad104be3a62b57053d2420d17785f9.tar.bz2
txr-82020af157ad104be3a62b57053d2420d17785f9.zip
Improve reverse and nreverse.
* lib.c (nreverse): Handle strings and vectors individually, and do strings and vectors in-place. (reverse): Handle strings and vectors individually, by duplicating and then in place. Handle lazy strings by forcing, then reversing a copy.
-rw-r--r--lib.c84
1 files changed, 68 insertions, 16 deletions
diff --git a/lib.c b/lib.c
index 4ce7cbac..a8f637dd 100644
--- a/lib.c
+++ b/lib.c
@@ -793,31 +793,83 @@ loc list_collect_append(loc ptail, val obj)
val nreverse(val in)
{
- val rev = nil;
+ switch (type(in)) {
+ case NIL:
+ return nil;
+ case CONS:
+ case LCONS:
+ {
+ val rev = nil;
- while (in) {
- val temp = cdr(in);
- set(cdr_l(in), rev);
- rev = in;
- in = temp;
- }
+ while (in) {
+ val temp = cdr(in);
+ set(cdr_l(in), rev);
+ rev = in;
+ in = temp;
+ }
- return rev;
+ return rev;
+ }
+ case VEC:
+ case STR:
+ {
+ cnum len = c_num(length(in));
+ cnum i;
+
+ for (i = 0; i < len / 2; i++) {
+ cnum j = len - i - 1;
+ val tmp = ref(in, num_fast(i));
+ refset(in, num_fast(i), ref(in, num_fast(j)));
+ refset(in, num_fast(j), tmp);
+ }
+
+ return in;
+ }
+ default:
+ uw_throwf(error_s, lit("nreverse: cannot reverse ~s"), in, nao);
+ }
}
val reverse(val in)
{
- val in_orig = in;
- val rev = nil;
+ switch (type(in)) {
+ case NIL:
+ return nil;
+ case CONS:
+ case LCONS:
+ {
+ val rev = nil;
- in = nullify(in);
+ while (in) {
+ rev = cons(car(in), rev);
+ in = cdr(in);
+ }
- while (in) {
- rev = cons(car(in), rev);
- in = cdr(in);
- }
+ return rev;
+ }
+ case LSTR:
+ in = lazy_str_force(in);
+ /* fallthrough */
+ case VEC:
+ case STR:
+ case LIT:
+ {
+ val obj = copy(in);
+ cnum len = c_num(length(in));
+ cnum i;
- return make_like(rev, in_orig);
+ for (i = 0; i < len / 2; i++) {
+ cnum j = len - i - 1;
+ val tmp = ref(obj, num_fast(i));
+ refset(obj, num_fast(i), ref(obj, num_fast(j)));
+ refset(obj, num_fast(j), tmp);
+ }
+
+ return obj;
+ }
+ default:
+ uw_throwf(error_s, lit("reverse: cannot reverse ~s"), in, nao);
+ }
}
val append2(val list1, val list2)