diff options
author | Kaz Kylheku <kaz@kylheku.com> | 2020-06-02 06:13:00 -0700 |
---|---|---|
committer | Kaz Kylheku <kaz@kylheku.com> | 2020-06-02 06:13:00 -0700 |
commit | dcd0c4e0485ad5f8cf571bffa99add57c8aed183 (patch) | |
tree | cd17a850e3434b749a7366adf9668cd5e1a11fe9 /lib.c | |
parent | 7d6e2b419916c915543e36f14891773294687b99 (diff) | |
download | txr-dcd0c4e0485ad5f8cf571bffa99add57c8aed183.tar.gz txr-dcd0c4e0485ad5f8cf571bffa99add57c8aed183.tar.bz2 txr-dcd0c4e0485ad5f8cf571bffa99add57c8aed183.zip |
New style iteration functions.
iter-begin provides a paradigm for iteration that is more
compatible with lists. If the sequence is a list, then the
list itself is returned as the iterator, and the other
functions are basicaly wrappers for car/cdr and null testing.
Yet the API is defined in such a way that other objects can be
iterated with good efficiency, at the cost of allocating a new
iterator object (which can be re-used).
* eval.c (eval_init): Register iter-begin, iter-more,
iter-item, iter-step and iter-reset.
* lib.c (seq_iter_init_with_info): New static function.
(seq_iter_init): Now a thin wrapper for
seq_iter_init_with_info.
(iter_begin, iter_more, iter_item, iter_step, iter_reset): New
functions.
* lib.h (iter_begin, iter_more, iter_item, iter_step,
iter_reset): New functions.
* txr.1: Documented.
Diffstat (limited to 'lib.c')
-rw-r--r-- | lib.c | 111 |
1 files changed, 109 insertions, 2 deletions
@@ -416,9 +416,10 @@ void seq_iter_rewind(seq_iter_t *it) } } -void seq_iter_init(val self, seq_iter_t *it, val obj) +static void seq_iter_init_with_info(val self, seq_iter_t *it, + val obj, seq_info_t si) { - it->inf = seq_info(obj); + it->inf = si; switch (it->inf.kind) { case SEQ_NIL: @@ -450,6 +451,11 @@ void seq_iter_init(val self, seq_iter_t *it, val obj) } } +void seq_iter_init(val self, seq_iter_t *it, val obj) +{ + seq_iter_init_with_info(self, it, obj, seq_info(obj)); +} + val seq_getpos(val self, seq_iter_t *it) { switch (it->inf.kind) { @@ -528,6 +534,107 @@ val seq_reset(val iter, val obj) return iter; } +val iter_begin(val obj) +{ + val self = lit("iter-begin"); + seq_info_t sinf = seq_info(obj); + + switch (sinf.kind) { + case SEQ_NIL: + case SEQ_LISTLIKE: + return sinf.obj; + default: + { + val si_obj; + struct seq_iter *si = coerce(struct seq_iter *, + chk_calloc(1, sizeof *si)); + si_obj = cobj(coerce(mem_t *, si), seq_iter_s, &seq_iter_ops); + seq_iter_init_with_info(self, si, obj, sinf); + return si_obj; + } + } +} + +val iter_more(val iter) +{ + switch (type(iter)) { + case NIL: + return nil; + case COBJ: + if (iter->co.cls == seq_iter_s) + { + struct seq_iter *si = coerce(struct seq_iter *, iter->co.handle); + val item = nil; + return if2(seq_peek(si, &item), t); + } + /* fallthrough */ + default: + return t; + } +} + +val iter_item(val iter) +{ + switch (type(iter)) { + case NIL: + return nil; + case COBJ: + if (iter->co.cls == seq_iter_s) + { + struct seq_iter *si = coerce(struct seq_iter *, iter->co.handle); + val item = nil; + return if2(seq_peek(si, &item), item); + } + /* fallthrough */ + default: + return car(iter); + } +} + +val iter_step(val iter) +{ + switch (type(iter)) { + case NIL: + return nil; + case COBJ: + if (iter->co.cls == seq_iter_s) + { + struct seq_iter *si = coerce(struct seq_iter *, iter->co.handle); + val item = nil; + (void) seq_get(si, &item); + return iter; + } + /* fallthrough */ + default: + return cdr(iter); + } +} + +val iter_reset(val iter, val obj) +{ + val self = lit("iter-reset"); + seq_info_t sinf = seq_info(obj); + + switch (sinf.kind) { + case SEQ_NIL: + case SEQ_LISTLIKE: + return sinf.obj; + default: + switch (type(iter)) { + case COBJ: + if (iter->co.cls == seq_iter_s) + { + struct seq_iter *si = coerce(struct seq_iter *, iter->co.handle); + seq_iter_init_with_info(self, si, obj, sinf); + return iter; + } + /* fallthrough */ + default: + return iter_begin(obj); + } + } +} + val throw_mismatch(val self, val obj, type_t t) { type_mismatch(lit("~a: ~s is not of type ~s"), self, obj, code2type(t), nao); |