summaryrefslogtreecommitdiffstats
path: root/lib.c
diff options
context:
space:
mode:
authorKaz Kylheku <kaz@kylheku.com>2016-10-13 06:51:20 -0700
committerKaz Kylheku <kaz@kylheku.com>2016-10-13 06:51:20 -0700
commitd94af272503d246929556087ae687d0fa8170611 (patch)
tree1fbff7b2f64a40db40f505ef0e56bdc72d660060 /lib.c
parent98466491da86fa8d1c5071beaefcd35c057a8e60 (diff)
downloadtxr-d94af272503d246929556087ae687d0fa8170611.tar.gz
txr-d94af272503d246929556087ae687d0fa8170611.tar.bz2
txr-d94af272503d246929556087ae687d0fa8170611.zip
Bugfix: sub and length on abstract sequences.
* lib.c (length_proper_list): New static function. (length): Use length_proper_list for objects. (sub): Call nullify on COBJ object before passing to sub_list. * tests/012/aseq.tl, tests/012/aseq.expected: New files.
Diffstat (limited to 'lib.c')
-rw-r--r--lib.c31
1 files changed, 30 insertions, 1 deletions
diff --git a/lib.c b/lib.c
index a3b88366..c032bde1 100644
--- a/lib.c
+++ b/lib.c
@@ -2752,6 +2752,31 @@ val length_list(val list)
return bn_len;
}
+static val length_proper_list(val list)
+{
+ cnum len = 0;
+ val bn_len;
+
+ gc_hint(list);
+
+ while (list && len < INT_PTR_MAX) {
+ len++;
+ list = cdr(list);
+ }
+
+ if (len < INT_PTR_MAX)
+ return num(len);
+
+ bn_len = num(INT_PTR_MAX);
+
+ while (list) {
+ bn_len = succ(bn_len);
+ list = cdr(list);
+ }
+
+ return bn_len;
+}
+
val getplist(val list, val key)
{
gc_hint(list);
@@ -8178,6 +8203,8 @@ val copy(val seq)
}
}
+static val length_proper_list(val list);
+
val length(val seq)
{
switch (type(seq)) {
@@ -8198,7 +8225,7 @@ val length(val seq)
if (seq->co.cls == hash_s)
return hash_count(seq);
if (structp(seq) && maybe_slot(seq, car_s))
- return length_list(nullify(seq));
+ return length_proper_list(nullify(seq));
/* fallthrough */
default:
type_mismatch(lit("length: ~s is not a sequence"), seq, nao);
@@ -8240,6 +8267,8 @@ val sub(val seq, val from, val to)
case NIL:
return nil;
case COBJ:
+ seq = nullify(seq);
+ /* fallthrough */
case CONS:
case LCONS:
return sub_list(seq, from, to);