diff options
author | Kaz Kylheku <kaz@kylheku.com> | 2019-06-12 06:56:28 -0700 |
---|---|---|
committer | Kaz Kylheku <kaz@kylheku.com> | 2019-06-12 06:56:28 -0700 |
commit | d743537013689e80cb1ede22dbb4e241d601b6ea (patch) | |
tree | 83c8a4acddf5216dcdcfca158f05326b81eb25f0 /lib.c | |
parent | 2fe27a3760606616a9b859a145cb1b358cfa415a (diff) | |
download | txr-d743537013689e80cb1ede22dbb4e241d601b6ea.tar.gz txr-d743537013689e80cb1ede22dbb4e241d601b6ea.tar.bz2 txr-d743537013689e80cb1ede22dbb4e241d601b6ea.zip |
replace_list: revise, fixing several bugs.
* lib.c (replace_list): Avoid using the dubious toseq
function which turns a non-sequence object into a list of one
item. This is not documented. Rewrite the
assign-to-multiple-indices logic into one loop that uses
sequence iterators. A bug is fixed here: failing to step the
indices and items in parallel. Don't use list_vec on items;
it fails on strings. Strings are now supported properly: they
expand into a list of items that is spliced.
Diffstat (limited to 'lib.c')
-rw-r--r-- | lib.c | 86 |
1 files changed, 37 insertions, 49 deletions
@@ -1430,61 +1430,44 @@ val sub_list(val list, val from, val to) val replace_list(val list, val items, val from, val to) { + val self = lit("replace-list"); val len = nil; - items = toseq(items); - if (!list) - return items; - - if (listp(from)) { - val where = from; - val seq = list; - val idx = zero; - - if (!missingp(to)) - uw_throwf(error_s, - lit("replace-list: to-arg not applicable when from-arg is a list"), - nao); - - for (; seq && where && items; seq = cdr(seq), idx = plus(idx, one)) { - val wh = nil; + return tolist(items); - for (; where && lt(wh = car(where), idx); where = cdr(where)) - ; /* empty */ - - if (eql(wh, idx)) - rplaca(seq, pop(&items)); - } - - return list; - } else if (vectorp(from)) { - val where = from; - val seq = list; - val idx = zero; - val wlen = length_vec(where); - val widx = zero; + if (missingp(from)) { + from = zero; + } else if (from == t) { + from = nil; + } else if (!integerp(from)) { + seq_iter_t wh_iter; + val iter = list, idx = zero, item, wh; + seq_iter_t item_iter; + seq_iter_init(self, &item_iter, items); + seq_iter_init(self, &wh_iter, from); if (!missingp(to)) uw_throwf(error_s, - lit("replace-str: to-arg not applicable when from-arg is a vector"), - nao); - - for (; seq && items && lt(widx, wlen); seq = cdr(seq), idx = plus(idx, one)) { - val wh = nil; + lit("~a: to-arg not applicable when from-arg is a list"), + self, nao); - for (; lt(widx, wlen) && lt(wh = vecref(where, widx), idx); widx = plus(widx, one)) - ; /* empty */ + while (iter && seq_peek(&item_iter, &item) && seq_peek(&wh_iter, &wh)) { + if (lt(wh, idx)) { + seq_geti(&wh_iter); + seq_geti(&item_iter); + continue; + } else if (eql(wh, idx)) { + rplaca(iter, item); + seq_geti(&wh_iter); + seq_geti(&item_iter); + } - if (eql(wh, idx)) - rplaca(seq, pop(&items)); + iter = cdr(iter); + idx = plus(idx, one); } return list; - } else if (missingp(from)) { - from = zero; - } else if (from == t) { - from = nil; } else if (lt(from, zero)) { from = plus(from, len ? len : (len = length(list))); if (to == zero) @@ -1500,7 +1483,7 @@ val replace_list(val list, val items, val from, val to) if (!to || (len && ge(to, len))) { if (from && zerop(from)) { - return (listp(items)) ? items : list_vec(items); + return tolist(items); } else { val i; list_collect_decl (out, ptail); @@ -1511,8 +1494,8 @@ val replace_list(val list, val items, val from, val to) ptail = list_collect(ptail, car(list)); } - ptail = list_collect_nconc(ptail, if3(listp(items), - items, list_vec(items))); + list_collect_nconc(ptail, tolist(items)); + return out; } } else { @@ -1526,9 +1509,14 @@ val replace_list(val list, val items, val from, val to) ptail = list_collect(ptail, car(list)); } - ptail = list_collect_nconc(ptail, append2(if3(listp(items), items, - list_vec(items)), - list)); + if (listp(items)) { + ptail = list_collect_nconc(ptail, items); + list_collect_append(ptail, list); + } else { + ptail = list_collect_nconc(ptail, tolist(items)); + list_collect_nconc(ptail, list); + } + return out; } } |