diff options
author | Kaz Kylheku <kaz@kylheku.com> | 2016-10-13 06:51:20 -0700 |
---|---|---|
committer | Kaz Kylheku <kaz@kylheku.com> | 2016-10-13 06:51:20 -0700 |
commit | d94af272503d246929556087ae687d0fa8170611 (patch) | |
tree | 1fbff7b2f64a40db40f505ef0e56bdc72d660060 /lib.c | |
parent | 98466491da86fa8d1c5071beaefcd35c057a8e60 (diff) | |
download | txr-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.c | 31 |
1 files changed, 30 insertions, 1 deletions
@@ -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); |