diff options
-rw-r--r-- | eval.c | 3 | ||||
-rw-r--r-- | lib.c | 54 | ||||
-rw-r--r-- | lib.h | 5 | ||||
-rw-r--r-- | txr.1 | 60 |
4 files changed, 120 insertions, 2 deletions
@@ -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)); @@ -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); @@ -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) { @@ -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 |