summaryrefslogtreecommitdiffstats
path: root/lib.c
diff options
context:
space:
mode:
authorKaz Kylheku <kaz@kylheku.com>2017-09-29 21:57:03 -0700
committerKaz Kylheku <kaz@kylheku.com>2017-09-29 21:57:03 -0700
commit389df91392be85e2b30150e20c5c2a98ec6fd05b (patch)
tree05253cbde059ec0bcfb04a774e300f3aa3b8b551 /lib.c
parentf021a78368b5ba841d8d88fec74d75f9f398d647 (diff)
downloadtxr-389df91392be85e2b30150e20c5c2a98ec6fd05b.tar.gz
txr-389df91392be85e2b30150e20c5c2a98ec6fd05b.tar.bz2
txr-389df91392be85e2b30150e20c5c2a98ec6fd05b.zip
Fixes in partition, partition*, split and split*.
Bunch of issues here: broken pre-171 compatibility, non-termination on lazy infinite lists of indices, doc issues. * lib.c (partition_func, split_func, split_star_func): Do the check for negative index values here, with the compat handling for 170 or older. (partition_split_common): Remove code that tries to adjust negative indices, and delete zeros or indices that are still negative after adjustment. The code consumes the entire list of prefixes, so chokes on lazy lists. Also in the compat case, there is complete breakage: the loop doesn't execute, and so out is just nil, and it is taken as the index list. (partition_star_func): Similar change like in partition_func. (partition_star): Similarly to partition_split_common, take out the bogus loop. Also take out loop that tries to remove leading negatives: we cannot do that because we haven't normalized them. * txr.1: Revised doc. Condensed by describing index-list argument in detail under partition. For the other functions, we refer to that one. Conditions for safely handling infinite list of indices spelled out.
Diffstat (limited to 'lib.c')
-rw-r--r--lib.c68
1 files changed, 26 insertions, 42 deletions
diff --git a/lib.c b/lib.c
index fbc46683..ee3f0e58 100644
--- a/lib.c
+++ b/lib.c
@@ -2158,10 +2158,14 @@ static val partition_func(val env, val lcons)
{
cons_bind (seq, indices_base, env);
cons_bind (indices, base, indices_base);
+ val len = nil;
for (;;) {
if (indices) {
- val index = pop(&indices);
+ val raw_index = pop(&indices);
+ val index = if3((!opt_compat || opt_compat > 170) && minusp(raw_index),
+ plus(raw_index, if3(len, len, len = length(seq))),
+ raw_index);
val index_rebased = minus(index, base);
if (le(index_rebased, zero)) {
@@ -2192,10 +2196,14 @@ static val split_func(val env, val lcons)
{
cons_bind (seq, indices_base, env);
cons_bind (indices, base, indices_base);
+ val len = nil;
for (;;) {
if (indices) {
- val index = pop(&indices);
+ val raw_index = pop(&indices);
+ val index = if3((!opt_compat || opt_compat > 170) && minusp(raw_index),
+ plus(raw_index, if3(len, len, len = length(seq))),
+ raw_index);
val index_rebased = minus(index, base);
if (lt(index_rebased, zero)) {
@@ -2228,10 +2236,14 @@ static val split_star_func(val env, val lcons)
{
cons_bind (seq, indices_base, env);
cons_bind (indices, base, indices_base);
+ val len = nil;
for (;;) {
if (indices) {
- val index = pop(&indices);
+ val raw_index = pop(&indices);
+ val index = if3((!opt_compat || opt_compat > 170) && minusp(raw_index),
+ plus(raw_index, if3(len, len, len = length(seq))),
+ raw_index);
val index_rebased = minus(index, base);
if (lt(index_rebased, zero)) {
@@ -2279,23 +2291,7 @@ static val partition_split_common(val seq, val indices,
if (!seqp(indices))
indices = cons(indices, nil);
- {
- val len = nil;
- list_collect_decl (out, ptail);
-
- if (!opt_compat || opt_compat > 170) {
- for (; indices; indices = cdr(indices)) {
- val idx_raw = car(indices);
- val idx = if3(minusp(idx_raw),
- plus(idx_raw, if3(len, len, len = length(seq))),
- idx_raw);
- if (!minusp(idx))
- ptail = list_collect(ptail, idx);
- }
- }
-
- return make_lazy_cons(func_f1(cons(seq, cons(out, zero)), split_fptr));
- }
+ return make_lazy_cons(func_f1(cons(seq, cons(indices, zero)), split_fptr));
}
val partition(val seq, val indices)
@@ -2315,12 +2311,17 @@ val split_star(val seq, val indices)
static val partition_star_func(val env, val lcons)
{
+ val len = nil;
+
for (;;) {
cons_bind (seq, indices_base, env);
cons_bind (indices, base, indices_base);
if (indices) {
- val index = pop(&indices);
+ val raw_index = pop(&indices);
+ val index = if3((!opt_compat || opt_compat > 170) && minusp(raw_index),
+ plus(raw_index, if3(len, len, len = length(seq))),
+ raw_index);
val index_rebased = minus(index, base);
val first = nullify(sub(seq, zero, index_rebased));
@@ -2377,35 +2378,18 @@ val partition_star(val seq, val indices)
indices = cons(indices, nil);
{
- val len = nil;
- list_collect_decl (tindices, ptail);
-
- if (!opt_compat || opt_compat > 170) {
- for (; indices; indices = cdr(indices)) {
- val idx_raw = car(indices);
- val idx = if3(minusp(idx_raw),
- plus(idx_raw, if3(len, len, len = length(seq))),
- idx_raw);
- if (!minusp(idx))
- ptail = list_collect(ptail, idx);
- }
- }
-
- while (tindices && lt(car(tindices), zero))
- pop(&tindices);
-
- while (tindices && eql(car(tindices), base)) {
+ while (indices && eql(car(indices), base)) {
seq = nullify(cdr(seq));
if (!seq)
return nil;
base = plus(base, one);
- pop(&tindices);
+ pop(&indices);
}
- if (!tindices)
+ if (!indices)
return cons(seq, nil);
- return make_lazy_cons(func_f1(cons(seq, cons(tindices, base)),
+ return make_lazy_cons(func_f1(cons(seq, cons(indices, base)),
partition_star_func));
}
}