summaryrefslogtreecommitdiffstats
path: root/lib.c
diff options
context:
space:
mode:
authorKaz Kylheku <kaz@kylheku.com>2020-06-02 06:13:00 -0700
committerKaz Kylheku <kaz@kylheku.com>2020-06-02 06:13:00 -0700
commitdcd0c4e0485ad5f8cf571bffa99add57c8aed183 (patch)
treecd17a850e3434b749a7366adf9668cd5e1a11fe9 /lib.c
parent7d6e2b419916c915543e36f14891773294687b99 (diff)
downloadtxr-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.c111
1 files changed, 109 insertions, 2 deletions
diff --git a/lib.c b/lib.c
index 1b9fefa9..cc8d00bb 100644
--- a/lib.c
+++ b/lib.c
@@ -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);