aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--cppawk-cons.14
-rw-r--r--cppawk-include/cons-priv.h95
-rw-r--r--cppawk-include/cons.h3
3 files changed, 97 insertions, 5 deletions
diff --git a/cppawk-cons.1 b/cppawk-cons.1
index d7002e7..a39b563 100644
--- a/cppawk-cons.1
+++ b/cppawk-cons.1
@@ -84,6 +84,10 @@ cons \- Lisp-like data representation and control flow macros
nthcdr(i, x) // suffix of x starting at i-th item
+ ldiff(x, y) // prefix of x omitting suffix y.
+ last(x, [n]) // suffix of x of length n, defaulting to 1.
+ butlast(x, [n]) // prefix of x omitting last n, defaulting to 1.
+
reverse(x) // reverse list x
iota(x, y[, d]) // numbers from x to y, incrementing by
diff --git a/cppawk-include/cons-priv.h b/cppawk-include/cons-priv.h
index 85bbe42..4c0a767 100644
--- a/cppawk-include/cons-priv.h
+++ b/cppawk-include/cons-priv.h
@@ -93,9 +93,13 @@
!__endp(__g(i)) && ((item = __car(__g(i))) || 1); \
__prog(__g(i) = __cdr(__g(i)), index++))
+#define __doconses(iter, list) \
+ for (iter = list; __consp(iter); iter = __cdr(iter))
+
#define __list_begin() ""
#define __list_add(stk, item) __pack(stk, item)
-#define __list_end(stk) __unpack(stk)
+#define __list_end(stk) __unpack(stk, __nil)
+#define __list_end_atom(stk, atom) __unpack(stk, atom)
#define __bag_init_first(x) (x = __list_begin())
#define __bag_init_next(p, x) (p || 1) && __bag_init_first(x)
@@ -417,11 +421,9 @@ function __pack(__stk, __item)
return length(__item) ":" __item __stk
}
-function __unpack(__stk,
- __col, __out)
+function __unpack(__stk, __out,
+ __col)
{
- __out = __nil
-
while (__stk != "") {
__col = match(__stk, /:/)
if (__col == 0)
@@ -701,6 +703,89 @@ function __nthcdr(__pos, __lst)
return __lst
}
+function __ldiff(__main, __tail,
+ __out, __iter)
+{
+ if (__null(main))
+ return nil
+
+ if (__null(tail))
+ return __main
+
+ __out = __list_begin()
+
+ __doconses (__iter, __main) {
+ if (__iter == __tail)
+ break
+ __out = __list_add(__out, __car(__iter))
+ }
+
+ if (__atom(__iter) && __iter != __tail)
+ return __list_end_atom(__out, __iter)
+
+ return __list_end(__out)
+}
+
+function __last(__lst, __n,
+ __circbuf, __i)
+{
+ if (!__present(__n))
+ __n = 1
+ else if (__n < 0)
+ __error("last: number argument %s must be non-negative", __n)
+
+ if (__n == 0) {
+ __doconses (__iter, __lst)
+ ; // nothing
+ return __iter
+ }
+
+ delete __circbuf
+
+ __i = 0
+
+ __n++
+
+ __doconses (__iter, __lst)
+ __circbuf[__i++ % __n] = __iter
+
+ __i = (__i + 1) % __n
+
+ return (__i in __circbuf) ? __circbuf[__i] : __lst
+}
+
+function __butlast(__lst, __n,
+ __circbuf, __i, __out)
+{
+ if (!__present(__n))
+ __n = 1
+ else if (__n < 0)
+ __error("butlast: number argument %s must be non-negative", __n)
+
+ __out = __list_begin()
+
+ if (__n == 0) {
+ __doconses (__iter, __lst)
+ __out = __list_add(__out, __car(__iter))
+ return __list_end(__out)
+ }
+
+ delete __circbuf
+
+ __i = 0
+
+ __n++
+
+ __doconses (__iter, __lst) {
+ __circbuf[__i++ % __n] = __out
+ __out = __list_add(__out, __car(__iter))
+ }
+
+ __i = (__i + 1) % __n
+
+ return (__i in __circbuf) ? __list_end(__circbuf[__i]) : __nil
+}
+
function __iota(__from, __to, __step,
__i, __out)
{
diff --git a/cppawk-include/cons.h b/cppawk-include/cons.h
index 0087930..2cf579f 100644
--- a/cppawk-include/cons.h
+++ b/cppawk-include/cons.h
@@ -78,6 +78,9 @@
#define position __position
#define nth __nth
#define nthcdr __nthcdr
+#define ldiff __ldiff
+#define last __last
+#define butlast __butlast
#define iota __iota
#define uniq __uniq
#define mapcar __mapcar