summaryrefslogtreecommitdiffstats
path: root/lib.c
diff options
context:
space:
mode:
authorKaz Kylheku <kaz@kylheku.com>2016-03-27 09:41:12 -0700
committerKaz Kylheku <kaz@kylheku.com>2016-03-27 09:41:12 -0700
commit70203c5cdab161f2d12756ff382035efbbaef421 (patch)
tree4f67b9f661de3a67a547d3e15ba4e1b80ab9e7ef /lib.c
parent4d0ff5692b7da9f278681d69d8c4b5c37abdd4e3 (diff)
downloadtxr-70203c5cdab161f2d12756ff382035efbbaef421.tar.gz
txr-70203c5cdab161f2d12756ff382035efbbaef421.tar.bz2
txr-70203c5cdab161f2d12756ff382035efbbaef421.zip
Adding rightmost item search functions.
* eval.c (eval_init): Registered intrinsics rmemq, rmemql, rmemqual, rmember, rmember-if, rposqual, rposql, rposq, rpos, rpos-if, rfind, rfind-if and rsearch. * lib.c (rmemq, rmemql, rmemqual, rmember, rmember-if, rposqual, rposql, rposq, rpos, rpos-if, rfind, rfind-if, rsearch): New functions. (rsearch_list): New static function. (search): Omit unreachable return statement. * lib.h (rmemq, rmemql, rmemqual, rmember, rmember-if, rposqual, rposql, rposq, rpos, rpos-if, rfind, rfind-if, rsearch): Declared. * txr.1: Documented.
Diffstat (limited to 'lib.c')
-rw-r--r--lib.c268
1 files changed, 267 insertions, 1 deletions
diff --git a/lib.c b/lib.c
index e29ff99c..beb5762c 100644
--- a/lib.c
+++ b/lib.c
@@ -1303,6 +1303,17 @@ val memq(val obj, val list)
return make_like(list, list_orig);
}
+val rmemq(val obj, val list)
+{
+ val list_orig = list;
+ val found = nil;
+ list = nullify(list);
+ gc_hint(list);
+ while (list && (found = (car(list) != obj ? list : found)))
+ list = cdr(list);
+ return make_like(found, list_orig);
+}
+
val memql(val obj, val list)
{
val list_orig = list;
@@ -1313,6 +1324,17 @@ val memql(val obj, val list)
return make_like(list, list_orig);
}
+val rmemql(val obj, val list)
+{
+ val list_orig = list;
+ val found = nil;
+ list = nullify(list);
+ gc_hint(list);
+ while (list && (found = (eql(car(list), obj) ? list : found)))
+ list = cdr(list);
+ return make_like(found, list_orig);
+}
+
val memqual(val obj, val list)
{
val list_orig = list;
@@ -1323,6 +1345,17 @@ val memqual(val obj, val list)
return make_like(list, list_orig);
}
+val rmemqual(val obj, val list)
+{
+ val list_orig = list;
+ val found = nil;
+ list = nullify(list);
+ gc_hint(list);
+ while (list && (found = (equal(car(list), obj) ? list : found)))
+ list = cdr(list);
+ return make_like(found, list_orig);
+}
+
val member(val item, val list, val testfun, val keyfun)
{
testfun = default_arg(testfun, equal_f);
@@ -1343,6 +1376,27 @@ val member(val item, val list, val testfun, val keyfun)
return nil;
}
+val rmember(val item, val list, val testfun, val keyfun)
+{
+ val found = nil;
+ testfun = default_arg(testfun, equal_f);
+ keyfun = default_arg(keyfun, identity_f);
+
+ list = nullify(list);
+
+ gc_hint(list);
+
+ for (; list; list = cdr(list)) {
+ val elem = car(list);
+ val key = funcall1(keyfun, elem);
+
+ if (funcall2(testfun, item, key))
+ found = list;
+ }
+
+ return found;
+}
+
val member_if(val pred, val list, val key)
{
key = default_arg(key, identity_f);
@@ -1361,6 +1415,24 @@ val member_if(val pred, val list, val key)
return nil;
}
+val rmember_if(val pred, val list, val key)
+{
+ val found = nil;
+ key = default_arg(key, identity_f);
+ list = nullify(list);
+
+ gc_hint(list);
+
+ for (; list; list = cdr(list)) {
+ val item = car(list);
+ val subj = funcall1(key, item);
+
+ if (funcall1(pred, subj))
+ found = list;
+ }
+
+ return found;
+}
val remq(val obj, val list)
{
@@ -7253,6 +7325,27 @@ val find(val item, val list, val testfun, val keyfun)
return nil;
}
+val rfind(val item, val list, val testfun, val keyfun)
+{
+ val found = nil;
+ testfun = default_arg(testfun, equal_f);
+ keyfun = default_arg(keyfun, identity_f);
+
+ list = nullify(list);
+
+ gc_hint(list);
+
+ for (; list; list = cdr(list)) {
+ val elem = car(list);
+ val key = funcall1(keyfun, elem);
+
+ if (funcall2(testfun, item, key))
+ found = elem;
+ }
+
+ return found;
+}
+
val find_max(val seq, val testfun, val keyfun)
{
val maxkey;
@@ -7306,6 +7399,25 @@ val find_if(val pred, val list, val key)
return nil;
}
+val rfind_if(val pred, val list, val key)
+{
+ val found = nil;
+ key = default_arg(key, identity_f);
+ list = nullify(list);
+
+ gc_hint(list);
+
+ for (; list; list = cdr(list)) {
+ val item = car(list);
+ val subj = funcall1(key, item);
+
+ if (funcall1(pred, subj))
+ found = item;
+ }
+
+ return found;
+}
+
val posqual(val obj, val list)
{
val pos = zero;
@@ -7321,6 +7433,22 @@ val posqual(val obj, val list)
return nil;
}
+val rposqual(val obj, val list)
+{
+ val pos = zero;
+ val found = nil;
+
+ list = nullify(list);
+
+ gc_hint(list);
+
+ for (; list; list = cdr(list), pos = plus(pos, one))
+ if (equal(car(list), obj))
+ found = pos;
+
+ return found;
+}
+
val posql(val obj, val list)
{
val pos = zero;
@@ -7336,6 +7464,22 @@ val posql(val obj, val list)
return nil;
}
+val rposql(val obj, val list)
+{
+ val pos = zero;
+ val found = nil;
+
+ list = nullify(list);
+
+ gc_hint(list);
+
+ for (; list; list = cdr(list), pos = plus(pos, one))
+ if (eql(car(list), obj))
+ pos = found;
+
+ return pos;
+}
+
val posq(val obj, val list)
{
val pos = zero;
@@ -7351,6 +7495,22 @@ val posq(val obj, val list)
return nil;
}
+val rposq(val obj, val list)
+{
+ val pos = zero;
+ val found = nil;
+
+ list = nullify(list);
+
+ gc_hint(list);
+
+ for (; list; list = cdr(list), pos = plus(pos, one))
+ if (car(list) == obj)
+ found = pos;
+
+ return found;
+}
+
val pos(val item, val list, val testfun, val keyfun)
{
val pos = zero;
@@ -7371,6 +7531,26 @@ val pos(val item, val list, val testfun, val keyfun)
return nil;
}
+val rpos(val item, val list, val testfun, val keyfun)
+{
+ val pos = zero;
+ val found = nil;
+ testfun = default_arg(testfun, equal_f);
+ keyfun = default_arg(keyfun, identity_f);
+ list = nullify(list);
+
+ gc_hint(list);
+
+ for (; list; list = cdr(list), pos = plus(pos, one)) {
+ val elem = car(list);
+ val key = funcall1(keyfun, elem);
+
+ if (funcall2(testfun, item, key))
+ found = pos;
+ }
+
+ return found;
+}
val pos_if(val pred, val list, val key)
{
@@ -7391,6 +7571,26 @@ val pos_if(val pred, val list, val key)
return nil;
}
+val rpos_if(val pred, val list, val key)
+{
+ val pos = zero;
+ val found = nil;
+ key = default_arg(key, identity_f);
+ list = nullify(list);
+
+ gc_hint(list);
+
+ for (; list; list = cdr(list), pos = plus(pos, one)) {
+ val item = car(list);
+ val subj = funcall1(key, item);
+
+ if (funcall1(pred, subj))
+ found = pos;
+ }
+
+ return found;
+}
+
val pos_max(val seq, val testfun, val keyfun)
{
val pos = zero;
@@ -8015,8 +8215,74 @@ val search(val seq, val key, val testfun, val keyfun)
default:
type_mismatch(lit("search: ~s is not a sequence"), seq, nao);
}
+}
- return seq;
+static val rsearch_list(val seq, val key, val testfun, val keyfun)
+{
+ val siter, kiter;
+ val pos = zero;
+ val found = nil;
+
+ switch (type(key)) {
+ case NIL:
+ return pos;
+ case CONS:
+ case LCONS:
+ case LIT:
+ case STR:
+ case LSTR:
+ case VEC:
+ /* TODO: optimize me */
+ gc_hint(seq);
+
+ for (; seq; seq = cdr(seq)) {
+ for (siter = seq, kiter = key;
+ siter && kiter;
+ siter = cdr(siter), kiter = cdr(kiter))
+ {
+ if (!funcall2(testfun,
+ funcall1(keyfun, car(siter)),
+ funcall1(keyfun, car(kiter))))
+ {
+ pos = plus(pos, one);
+ break;
+ }
+ }
+
+ if (!kiter)
+ found = pos;
+
+ if (!siter)
+ break;
+ }
+ break;
+ default:
+ type_mismatch(lit("rsearch: ~s is not a sequence"), seq, nao);
+ }
+
+ return found;
+}
+
+val rsearch(val seq, val key, val testfun, val keyfun)
+{
+ testfun = default_arg(testfun, equal_f);
+ keyfun = default_arg(keyfun, identity_f);
+ seq = nullify(seq);
+
+ switch (type(seq)) {
+ case NIL:
+ return if3(length(key) == zero, zero, nil);
+ case CONS:
+ case LCONS:
+ case LIT:
+ case STR:
+ case LSTR:
+ case VEC:
+ /* TODO: optimize me */
+ return rsearch_list(seq, key, testfun, keyfun);
+ default:
+ type_mismatch(lit("rsearch: ~s is not a sequence"), seq, nao);
+ }
}
val where(val func, val seq)