summaryrefslogtreecommitdiffstats
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
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.
-rw-r--r--lib.c31
-rw-r--r--tests/012/aseq.expected0
-rw-r--r--tests/012/aseq.tl15
3 files changed, 45 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);
diff --git a/tests/012/aseq.expected b/tests/012/aseq.expected
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/tests/012/aseq.expected
diff --git a/tests/012/aseq.tl b/tests/012/aseq.tl
new file mode 100644
index 00000000..7901c4ab
--- /dev/null
+++ b/tests/012/aseq.tl
@@ -0,0 +1,15 @@
+(load "../common")
+
+(defstruct (add n list) nil
+ n list
+ (:method cdr (me) (if (cdr me.list) (new (add me.n (cdr me.list)))))
+ (:method car (me) (+ me.n (car me.list)))
+ (:method nullify (me) (if me.list me))
+ (:method lambda (me i) (ref me i)))
+
+(defvarl o (new (add 3 (range 10 100 10))))
+
+(test (car o) 13)
+(test (cadr o) 23)
+(test [o 4] 53)
+(test (cadr (last o)) nil)