diff options
author | Kaz Kylheku <kaz@kylheku.com> | 2019-06-28 07:54:35 -0700 |
---|---|---|
committer | Kaz Kylheku <kaz@kylheku.com> | 2019-06-28 07:54:35 -0700 |
commit | 43323e1431d5919b8e296b37c38affe1228c27d1 (patch) | |
tree | 49a6bb7cdc3e5de1dbad3ec7136bdf1535309d51 /lib.c | |
parent | dc7842296466eba508f791ef1f9a9c3b16f7d4da (diff) | |
download | txr-43323e1431d5919b8e296b37c38affe1228c27d1.tar.gz txr-43323e1431d5919b8e296b37c38affe1228c27d1.tar.bz2 txr-43323e1431d5919b8e296b37c38affe1228c27d1.zip |
seq_info: nullify bugfix.
A change in the nullify function to support hash tables has
broken various functions which classify an object using
seq_info, obtainig a SEQ_HASHLIKE kind, and then work with
si.obj using hash functions. But si.obj has been nullified.
An example of a broken function is find-max.
Basically, this can be attributed to a careless use of nullify
in seq_info. The purpose of nullify is to support code which
treats any sequence as if it were a list. But seq_info doesn't
do that; it classifies sequences and treats them according to
their kind. Under seq_info, the only non-list objects that get
treated as lists are list-like structures. For these it makes
sense to call nullify, in case they have a nullify method.
* lib.c (seq_info): Don't unconditionally call nullify on all
COBJ objects. Only call nullify on struct objects. If that
returns nil, then treat the object as SEQ_NIL; and if it
returns an object different from the original, then recurse.
Diffstat (limited to 'lib.c')
-rw-r--r-- | lib.c | 32 |
1 files changed, 19 insertions, 13 deletions
@@ -268,17 +268,12 @@ seq_info_t seq_info(val obj) seq_info_t ret; type_t to = type(obj); + ret.obj = obj; + if (to != COBJ) { - ret.obj = obj; ret.type = to; ret.kind = seq_kind_tab[to]; return ret; - } - - ret.obj = obj = nullify(obj); - - if (!obj || (ret.type = to = type(obj)) != COBJ) { - ret.kind = seq_kind_tab[to]; } else { val cls = obj->co.cls; @@ -287,12 +282,23 @@ seq_info_t seq_info(val obj) } else if (cls == carray_s) { ret.kind = SEQ_VECLIKE; } else if (obj_struct_p(obj)) { - if (maybe_slot(obj, length_s)) - ret.kind = SEQ_VECLIKE; - if (maybe_slot(obj, car_s)) - ret.kind = SEQ_LISTLIKE; - else - ret.kind = SEQ_NOTSEQ; + val sub = nullify(obj); + + if (!sub) { + ret.kind = SEQ_NIL; + ret.obj = nil; + } else if (sub != obj) { + return seq_info(sub); + } else { + if (maybe_slot(obj, length_s)) + ret.kind = SEQ_VECLIKE; + if (maybe_slot(obj, car_s)) + ret.kind = SEQ_LISTLIKE; + if (maybe_slot(obj, car_s)) + ret.kind = SEQ_LISTLIKE; + else + ret.kind = SEQ_NOTSEQ; + } } else { ret.kind = SEQ_NOTSEQ; } |