summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKaz Kylheku <kaz@kylheku.com>2024-06-17 16:40:31 -0700
committerKaz Kylheku <kaz@kylheku.com>2024-06-17 16:49:05 -0700
commit881c87fa8856e0d66d1d13dda36c461dc95da0b7 (patch)
tree6a5fab43924d66514e223628f946f5e6ce2ea053
parent775e10c4007c024981d0b27f5f2e54c8ac54c73d (diff)
downloadtxr-881c87fa8856e0d66d1d13dda36c461dc95da0b7.tar.gz
txr-881c87fa8856e0d66d1d13dda36c461dc95da0b7.tar.bz2
txr-881c87fa8856e0d66d1d13dda36c461dc95da0b7.zip
More work on copy-iter.
* lib.c (copy_iter): Use the copy method for arguments which are structures, or else return just the objects if they implement list-like sequences. Error out otherwise. For an argument that is not an iterators or structure, error out if it is not a number, nil, or a list-like sequence. * txr.1: Documented.
-rw-r--r--lib.c45
-rw-r--r--txr.153
2 files changed, 88 insertions, 10 deletions
diff --git a/lib.c b/lib.c
index d967f5d8..6e097e80 100644
--- a/lib.c
+++ b/lib.c
@@ -1496,17 +1496,42 @@ val iter_catv(varg iters)
val copy_iter(val iter)
{
- if (type(iter) == COBJ && iter->co.cls == seq_iter_cls) {
- val iter_copy;
- const struct seq_iter *sit = coerce(struct seq_iter *, iter->co.handle);
- struct seq_iter *dit = coerce(struct seq_iter *,
- chk_calloc(1, sizeof *dit));
- seq_iter_clone(dit, sit);
- iter_copy = cobj(coerce(mem_t *, dit), seq_iter_cls, &seq_iter_cobj_ops);
- gc_hint(iter);
- return iter_copy;
- } else {
+ val self = lit("copy-iter");
+
+ switch (type(iter)) {
+ case CHR:
+ case NUM:
+ case BGNUM:
return iter;
+ case COBJ:
+ if (iter->co.cls == seq_iter_cls) {
+ val iter_copy;
+ const struct seq_iter *sit = coerce(struct seq_iter *, iter->co.handle);
+ struct seq_iter *dit = coerce(struct seq_iter *,
+ chk_calloc(1, sizeof *dit));
+ seq_iter_clone(dit, sit);
+ iter_copy = cobj(coerce(mem_t *, dit), seq_iter_cls, &seq_iter_cobj_ops);
+ gc_hint(iter);
+ return iter_copy;
+ }
+ if (obj_struct_p(iter)) {
+ val copy_meth = get_special_slot(iter, copy_m);
+ if (copy_meth)
+ return funcall1(copy_meth, iter);
+ }
+ unsup_obj(self, iter);
+ /* fallthrough */
+ default:
+ {
+ seq_info_t sinf = seq_info(iter);
+ switch (sinf.kind) {
+ case SEQ_NIL:
+ case SEQ_LISTLIKE:
+ return sinf.obj;
+ default:
+ unsup_obj(self, iter);
+ }
+ }
}
}
diff --git a/txr.1 b/txr.1
index 2ff9cc28..32aacb6f 100644
--- a/txr.1
+++ b/txr.1
@@ -21565,6 +21565,10 @@ as if by:
.mono
.meti (copy-cptr << object )
.onom
+.coIP seq-iter
+.mono
+.meti (copy-iter << object )
+.onom
.RE
.IP
@@ -40081,6 +40085,55 @@ is invoked on
.meta seq
and the result is returned.
+.coNP Function @ copy-iter
+.synb
+.mets (copy-iter << iter )
+.syne
+.desc
+The
+.code copy-iter
+produces a duplicate
+.meta iter
+such that the duplicate iterator will traverse
+the same sequence of items as
+.meta iter
+starting at the current point in the sequence indicated by iter.
+
+For some kinds of iterators, such as integers and conses,
+.code copy-iter
+just returns
+.metn iter .
+
+If
+.meta iter
+is a structure object, then if it supports the
+.code copy
+method, that method is invoked and its return value is taken
+as the iterator copy. Otherwise,
+.meta iter
+must implement a list-like sequence, in which case the object
+is just returned. If
+.code iter
+is a structure which neither supports a
+.code copy
+method nor implements a list-like sequence by supporting the
+.code car
+method, an error exception is thrown.
+
+Note: iterators of type
+.code seq-iter
+can be copied with the
+.code copy
+function (which for those objects is defined in terms of
+.codn copy-iter ).
+However, the
+.code copy
+function has the wrong semantics for other kinds of iterator
+objects. It refuses to copy certain atoms such as numbers,
+and in the case of conses it behaves like
+.codn copy-list ,
+which is unnecessary.
+
.coNP Function @ iter-cat
.synb
.mets (iter-cat << seq *)