summaryrefslogtreecommitdiffstats
path: root/lib.c
diff options
context:
space:
mode:
authorKaz Kylheku <kaz@kylheku.com>2020-06-05 20:18:58 -0700
committerKaz Kylheku <kaz@kylheku.com>2020-06-05 20:18:58 -0700
commiteb2d229637284ac6b8822357ce59c007742c825c (patch)
treef98faa041513dacb9cbec438a86a686486c086fc /lib.c
parentf64eaa8c6839247c4e3023d244fdc328fd455e8d (diff)
downloadtxr-eb2d229637284ac6b8822357ce59c007742c825c.tar.gz
txr-eb2d229637284ac6b8822357ce59c007742c825c.tar.bz2
txr-eb2d229637284ac6b8822357ce59c007742c825c.zip
nullify and empty: convert to seq_info.
Issues: (nullify 1..1) doesn't return nil as it should, and (empty 1) fails. * lib.c (seq_info): Since we would like nullify to use seq_info, seq_info cannot call nullify. Transplant the probing of the nullify method out of nullify and into here. (nullify): Obtain a seq_info_t on the object. If it's not a sequence and is not range, then just return the object. Otherwise obtain a seq_iter_t sequence and peek whether it has a next item. (empty): Similarly, obtain an iterator and peek. Definition of empty is relocated to be next to nullify. * lib.h: Relocate declaration of empty, also.
Diffstat (limited to 'lib.c')
-rw-r--r--lib.c95
1 files changed, 28 insertions, 67 deletions
diff --git a/lib.c b/lib.c
index 5b5a9367..61e89907 100644
--- a/lib.c
+++ b/lib.c
@@ -299,7 +299,13 @@ seq_info_t seq_info(val obj)
} else if (cls == carray_s) {
ret.kind = SEQ_VECLIKE;
} else if (obj_struct_p(obj)) {
- val sub = nullify(obj);
+ val sub = obj;
+
+ if (obj_struct_p(obj)) {
+ val nullify_meth = get_special_slot(obj, nullify_m);
+ if (nullify_meth)
+ sub = funcall1(nullify_meth, obj);
+ }
if (!sub) {
ret.kind = SEQ_NIL;
@@ -1418,39 +1424,31 @@ val tolist(val seq)
}
}
-val nullify(val seq)
+val nullify(val obj)
{
- switch (type(seq)) {
- case NIL:
- return nil;
- case CONS:
- case LCONS:
- return seq;
- case LIT:
- case STR:
- return c_str(seq)[0] ? seq : nil;
- case LSTR:
- return if3(length_str_gt(seq, zero), seq, nil);
- case VEC:
- return if3(length_vec(seq) != zero, seq, nil);
- case BUF:
- return if3(length_buf(seq) != zero, seq, nil);
- case COBJ:
- if (seq->co.cls == carray_s)
- return if3(length_carray(seq) != zero, seq, nil);
- if (seq->co.cls == hash_s)
- return if3(hash_count(seq) != zero, seq, nil);
- if (obj_struct_p(seq)) {
- val nullify_meth = get_special_slot(seq, nullify_m);
- if (nullify_meth)
- return funcall1(nullify_meth, seq);
- }
- /* fallthrough */
- default:
- return seq;
+ val self = lit("nullify");
+ val elem;
+ seq_info_t si = seq_info(obj);
+
+ if (si.kind == SEQ_NOTSEQ && si.type != RNG) {
+ return obj;
+ } else {
+ seq_iter_t iter;
+ seq_iter_init_with_info(self, &iter, si, 0);
+ return if2(seq_peek(&iter, &elem), obj);
}
}
+val empty(val seq)
+{
+ val self = lit("empty");
+ val elem;
+ seq_iter_t iter;
+ seq_iter_init(self, &iter, seq);
+
+ return tnil(!seq_peek(&iter, &elem));
+}
+
val seqp(val obj)
{
seq_info_t si = seq_info(obj);
@@ -10875,43 +10873,6 @@ val length(val seq)
}
}
-val empty(val seq)
-{
- switch (type(seq)) {
- case NIL:
- return t;
- case CONS:
- case LCONS:
- return nil;
- case LIT:
- case STR:
- return if2(c_str(seq)[0] == 0, t);
- case LSTR:
- return length_str_le(seq, zero);
- case VEC:
- return eq(length_vec(seq), zero);
- case RNG:
- return eql(from(seq), to(seq));
- case BUF:
- return eq(length_buf(seq), zero);
- case COBJ:
- if (seq->co.cls == hash_s)
- return eq(hash_count(seq), zero);
- if (seq->co.cls == carray_s)
- return eq(length_carray(seq), zero);
- if (obj_struct_p(seq)) {
- val length_meth = get_special_slot(seq, length_m);
- val nullify_meth = if2(nilp(length_meth), get_special_slot(seq, nullify_m));
- if (length_meth)
- return eq(funcall1(length_meth, seq), zero);
- return if3(nullify_meth && funcall1(nullify_meth, seq), nil, seq);
- }
- /* fallthrough */
- default:
- type_mismatch(lit("empty: ~s is not a sequence"), seq, nao);
- }
-}
-
val sub(val seq, val from, val to)
{
switch (type(seq)) {