summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--eval.c3
-rw-r--r--lib.c54
-rw-r--r--lib.h5
-rw-r--r--txr.160
4 files changed, 120 insertions, 2 deletions
diff --git a/eval.c b/eval.c
index a3b593ef..b628257d 100644
--- a/eval.c
+++ b/eval.c
@@ -6858,6 +6858,9 @@ void eval_init(void)
reg_fun(intern(lit("where"), user_package), func_n2(where));
reg_fun(intern(lit("select"), user_package), func_n2(sel));
reg_fun(intern(lit("relate"), user_package), func_n3o(relate, 2));
+ reg_fun(intern(lit("seq-begin"), user_package), func_n1(seq_begin));
+ reg_fun(intern(lit("seq-next"), user_package), func_n2(seq_next));
+ reg_fun(intern(lit("seq-reset"), user_package), func_n2(seq_reset));
reg_fun(intern(lit("rcons"), user_package), func_n2(rcons));
reg_fun(intern(lit("rangep"), user_package), func_n1(rangep));
diff --git a/lib.c b/lib.c
index 194d8cb6..f23e40df 100644
--- a/lib.c
+++ b/lib.c
@@ -109,7 +109,7 @@ val query_error_s, file_error_s, process_error_s, syntax_error_s;
val timeout_error_s, system_error_s, alloc_error_s;
val warning_s, defr_warning_s, restart_s, continue_s;
val gensym_counter_s, nullify_s, from_list_s, lambda_set_s, length_s;
-val rplaca_s, rplacd_s;
+val rplaca_s, rplacd_s, seq_iter_s;
val nothrow_k, args_k, colon_k, auto_k, fun_k;
val wrap_k, reflect_k;
@@ -402,6 +402,57 @@ void seq_iter_init(val self, seq_iter_t *it, val obj)
}
}
+static void seq_iter_mark(val seq_iter)
+{
+ struct seq_iter *si = coerce(struct seq_iter *, seq_iter->co.handle);
+
+ gc_mark(si->inf.obj);
+
+ switch (si->inf.kind) {
+ case SEQ_LISTLIKE:
+ case SEQ_HASHLIKE:
+ gc_mark(si->ui.iter);
+ break;
+ default:
+ break;
+ }
+}
+
+static struct cobj_ops seq_iter_ops = cobj_ops_init(eq,
+ cobj_print_op,
+ cobj_destroy_free_op,
+ seq_iter_mark,
+ cobj_eq_hash_op);
+
+val seq_begin(val obj)
+{
+ val self = lit("seq-begin");
+ 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(self, si, obj);
+ si->inf.obj = nil;
+ return si_obj;
+}
+
+val seq_next(val iter, val end_val)
+{
+ val self = lit("seq-next");
+ struct seq_iter *si = coerce(struct seq_iter *,
+ cobj_handle(self, iter, seq_iter_s));
+ val item = nil;
+ return if3(seq_get(si, &item), item, end_val);
+}
+
+val seq_reset(val iter, val obj)
+{
+ val self = lit("seq-reset");
+ struct seq_iter *si = coerce(struct seq_iter *,
+ cobj_handle(self, iter, seq_iter_s));
+ seq_iter_init(self, si, obj);
+ return iter;
+}
+
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);
@@ -11087,6 +11138,7 @@ static void obj_init(void)
length_s = intern(lit("length"), user_package);
rplaca_s = intern(lit("rplaca"), user_package);
rplacd_s = intern(lit("rplacd"), user_package);
+ seq_iter_s = intern(lit("seq-iter"), user_package);
args_k = intern(lit("args"), keyword_package);
nothrow_k = intern(lit("nothrow"), keyword_package);
diff --git a/lib.h b/lib.h
index cb1b2ef6..70ba864a 100644
--- a/lib.h
+++ b/lib.h
@@ -499,7 +499,7 @@ extern val query_error_s, file_error_s, process_error_s, syntax_error_s;
extern val timeout_error_s, system_error_s, alloc_error_s;
extern val warning_s, defr_warning_s, restart_s, continue_s;
extern val gensym_counter_s;
-extern val rplaca_s, rplacd_s;
+extern val rplaca_s, rplacd_s, seq_iter_s;
#define gensym_counter (deref(lookup_var_l(nil, gensym_counter_s)))
@@ -532,6 +532,9 @@ seq_info_t seq_info(val cobj);
void seq_iter_init(val self, seq_iter_t *it, val obj);
void seq_iter_rewind(val self, seq_iter_t *it);
INLINE int seq_get(seq_iter_t *it, val *pval) { return it->get(it, pval); }
+val seq_begin(val obj);
+val seq_next(val iter, val end_val);
+val seq_reset(val iter, val obj);
val throw_mismatch(val self, val obj, type_t);
INLINE val type_check(val self, val obj, type_t typecode)
{
diff --git a/txr.1 b/txr.1
index 9571db98..7f2c5cf9 100644
--- a/txr.1
+++ b/txr.1
@@ -30332,6 +30332,66 @@ sequences using
and tests for termination with
.codn nil .
+.SS* Open Sequence Traversal
+
+Functions in this category perform efficient traversal of sequences
+of various kinds.
+
+.coNP Function @ seq-begin
+.synb
+.mets (seq-begin << object )
+.syne
+.desc
+The
+.code seq-begin
+function returns an iterator object specialized to the task of traversing
+the sequence represented by the input
+.metn object .
+
+If
+.meta object
+isn't a sequence, an exception is thrown.
+
+.coNP Function @ seq-next
+.synb
+.mets (seq-next < iter << end-value )
+.syne
+.desc
+The
+.code seq-next
+function retrieves the next available item from the sequence iterated by
+.metn iter ,
+which must be an object returned by
+.codn seq-begin .
+
+If the sequence has no more items to be traversed, then
+.meta end-value
+is returned instead.
+
+Note: to avoid ambiguities, the application should provide an
+.meta end-value
+which is guaranteed distinct from any item in the sequence, such as a
+freshly allocated object.
+
+.coNP Function @ seq-reset
+.synb
+.mets (seq-reset < iter << object )
+.syne
+.desc
+The
+.code seq-reset
+re-initializes the existing iterator object
+.meta iter
+to begin a new traversal over the given
+.metn object ,
+which must be a value of a kind that would be a suitable argument for
+.codn seq-begin .
+
+The
+.code seq-reset
+function returns
+.metn iter .
+
.SS* Procedural List Construction
\*(TL provides an a structure type called