diff options
author | Kaz Kylheku <kaz@kylheku.com> | 2021-08-22 11:19:35 -0700 |
---|---|---|
committer | Kaz Kylheku <kaz@kylheku.com> | 2021-08-22 11:19:35 -0700 |
commit | 1819c8bea0d960f2895485e58901dbcc6193d071 (patch) | |
tree | a328d7167e976ae88f8985b2685d7a0a1592d0fd /lib.c | |
parent | 9ec47b693f9618bfd29347226157dc2f8a655ff8 (diff) | |
download | txr-1819c8bea0d960f2895485e58901dbcc6193d071.tar.gz txr-1819c8bea0d960f2895485e58901dbcc6193d071.tar.bz2 txr-1819c8bea0d960f2895485e58901dbcc6193d071.zip |
sub: allow generic iterables.
In this patch we allow the s in (sub s from to) and [s from..to]
to be any iterable.
* lib.c (iter_dynamic, sub_iter): New static function.
(generic_funcall): Handle all objects via the sequence case:
ref, sub and all that. Unfortunately, we lose some error
handling at the level of the sub function. But we allow any
iterable to be passed through to sub.
(sub): Handle default case through sub_iter.
* tests/012/iter.tl: New cases.
* txr.1: Documented.
Diffstat (limited to 'lib.c')
-rw-r--r-- | lib.c | 55 |
1 files changed, 51 insertions, 4 deletions
@@ -1172,6 +1172,14 @@ val iter_begin(val obj) } } +static val iter_dynamic(struct seq_iter *si_orig) +{ + struct seq_iter *si = coerce(struct seq_iter *, + chk_copy_obj(coerce(mem_t *, si_orig), + sizeof *si)); + return cobj(coerce(mem_t *, si), seq_iter_cls, &seq_iter_ops); +} + val iter_more(val iter) { switch (type(iter)) { @@ -2447,6 +2455,47 @@ val sub_list(val list, val from, val to) } } +static val sub_iter(val obj, val from, val to) +{ + val self = lit("sub"); + seq_iter_t iter; + seq_iter_init(self, &iter, obj); + val idx = zero, elem; + list_collect_decl (out, ptail); + + if (from == t) + return nil; + + if (null_or_missing_p(from)) + from = zero; + else if (minusp(from)) + goto list; + + if (to == t || null_or_missing_p(to)) + to = nil; + else if (!null_or_missing_p(to) && minusp(to)) + goto list; + + if (!to) { + do { + if (ge(idx, from)) + return iter_dynamic(&iter); + idx = succ(idx); + } while (seq_get(&iter, &elem)); + } else { + for (; seq_get(&iter, &elem) && lt(idx, to); idx = succ(idx)) + if (ge(idx, from)) + ptail = list_collect(ptail, elem); + } + + return out; + +list: + while (seq_get(&iter, &elem)) + ptail = list_collect(ptail, elem); + return sub_list(out, from, to); +} + val replace_list(val list, val items, val from, val to) { val self = lit("replace-list"); @@ -7727,6 +7776,7 @@ INLINE val do_generic_funcall(val fun, struct args *args_in) case LSTR: case BUF: carray: + default: bug_unless (args->argc >= ARGS_MIN); args_normalize_least(args, 3); @@ -7815,9 +7865,6 @@ INLINE val do_generic_funcall(val fun, struct args *args_in) fun = method(fun, lambda_s); break; } - /* fallthrough */ - default: - callerror(fun, lit("object is not callable")); } variadic = fun->f.variadic; @@ -11990,7 +12037,7 @@ val sub(val seq, val from, val to) } /* fallthrough */ default: - type_mismatch(lit("sub: ~s is not a sequence"), seq, nao); + return sub_iter(seq, from, to); } } |