diff options
-rw-r--r-- | eval.c | 5 | ||||
-rw-r--r-- | lib.c | 111 | ||||
-rw-r--r-- | lib.h | 5 | ||||
-rw-r--r-- | txr.1 | 162 |
4 files changed, 276 insertions, 7 deletions
@@ -6970,6 +6970,11 @@ void eval_init(void) 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("iter-begin"), user_package), func_n1(iter_begin)); + reg_fun(intern(lit("iter-more"), user_package), func_n1(iter_more)); + reg_fun(intern(lit("iter-item"), user_package), func_n1(iter_item)); + reg_fun(intern(lit("iter-step"), user_package), func_n1(iter_step)); + reg_fun(intern(lit("iter-reset"), user_package), func_n2(iter_reset)); reg_fun(intern(lit("rcons"), user_package), func_n2(rcons)); reg_fun(intern(lit("rangep"), user_package), func_n1(rangep)); @@ -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); @@ -556,6 +556,11 @@ void seq_setpos(val self, seq_iter_t *it, val pos); val seq_begin(val obj); val seq_next(val iter, val end_val); val seq_reset(val iter, val obj); +val iter_begin(val obj); +val iter_more(val iter); +val iter_item(val iter); +val iter_step(val iter); +val iter_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) { @@ -33080,15 +33080,167 @@ and tests for termination with .SS* Open Sequence Traversal -Functions in this category perform efficient traversal of sequences -of various kinds. +Functions in this category perform efficient traversal of sequences. + +There are two flavors of these functions: functions in the +.code iter-begin +group, and functions in the +.code seq-begin +group. The latter are obsolescent. + +.coNP Function @ iter-begin +.synb +.mets (iter-begin << seq ) +.syne +.desc +The +.code iter-begin +function returns an iterator object specialized for the task of traversing +the sequence +.metn seq . + +If +.meta object +isn't a sequence, an exception is thrown. + +Note: if +.meta seq +is a list-like sequence, then +.code iter-begin +may return +.meta seq +itself as the iterator. + +.coNP Function @ iter-more +.synb +.mets (iter-more << iter ) +.syne +.desc +The +.code iter-more +function returns +.code t +if there remain more elements to be traversed. +Otherwise it returns +.codn nil . + +The +.meta iter +argument must be a valid iterator returned by a call to +.metn iter-begin , +.meta iter-step +or +.metn iter-reset . + +The +.code iter-more +function doesn't change the state of +.metn iter . + +.coNP Function @ iter-item +.synb +.mets (iter-item << iter ) +.syne +.desc +If the +.code iter-more +function indicates that more items remain to be visited, then +the next item can be retrieved using +.codn iter-item . + +The +.meta iter +argument must be a valid iterator returned by a call to +.metn iter-begin , +.meta iter-step +or +.metn iter-reset . + +The +.code iter-more +function doesn't change the state of +.metn iter . + +If +.code iter-more +is invoked on an iterator which indicates that no more items +remain to be visited, the return value is +.codn nil . + +.coNP Function @ iter-step +.synb +.mets (iter-step << iter ) +.syne +.desc +If the +.code iter-more +function indicates that more items remain to be visited, then the +.code iter-step +function may be used to consume the next item. + +The function returns an iterator denoting the traversal of the +remaining items in the sequence. + +The +.meta iter +argument must be a valid iterator returned by a call to +.metn iter-begin , +.meta iter-step +or +.metn iter-reset . + +The +.code iter-step +function may return a new object, in which case it avoids +changing the state of +.metn iter , +or else it may change the state of +.meta iter +and return it. + +If the application discontinues the use of +.metn iter , +and continues the +traversal using the returned iterator, it will work correctly in either +situation. + +If +.code iter-step +is invoked on an iterator which indicates that no more items +remain to be visited, the return value is unspecified. + +.coNP Function @ iter-reset +.synb +.mets (iter-reset < iter << seq ) +.syne +.desc +The +.code iter-reset +function returns an iterator object specialized for the task of traversing +the sequence +.metn seq . + +If it is possible for +.meta iter +to be that object, then the function may adjust the state of +.meta iter +and return it. + +If +.code iter-reset +doesn't use +.metn iter , +then it behaves exactly like +.code iter-begin +being invoked on +.metn seq . .coNP Function @ seq-begin .synb .mets (seq-begin << object ) .syne .desc -The +The obsolescent .code seq-begin function returns an iterator object specialized to the task of traversing the sequence represented by the input @@ -33111,7 +33263,7 @@ is not suitable for indefinite iteration over infinite lists. .mets (seq-next < iter << end-value ) .syne .desc -The +The obsolescent .code seq-next function retrieves the next available item from the sequence iterated by .metn iter , @@ -33132,7 +33284,7 @@ freshly allocated object. .mets (seq-reset < iter << object ) .syne .desc -The +The obsolescent .code seq-reset re-initializes the existing iterator object .meta iter |