From 43323e1431d5919b8e296b37c38affe1228c27d1 Mon Sep 17 00:00:00 2001 From: Kaz Kylheku Date: Fri, 28 Jun 2019 07:54:35 -0700 Subject: 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. --- lib.c | 32 +++++++++++++++++++------------- 1 file changed, 19 insertions(+), 13 deletions(-) diff --git a/lib.c b/lib.c index 522128a6..9cc20045 100644 --- a/lib.c +++ b/lib.c @@ -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; } -- cgit v1.2.3