diff options
author | Kaz Kylheku <kaz@kylheku.com> | 2011-12-25 00:42:19 -0800 |
---|---|---|
committer | Kaz Kylheku <kaz@kylheku.com> | 2011-12-25 00:42:19 -0800 |
commit | 894aec019d3ce82f861a5777236ac079c2f2388d (patch) | |
tree | a4e4414899200f6d66e88fa77e1cbffd5ffba804 /lib.c | |
parent | 1c8251aae0294881d0dc9fcdffeb2f86040ee24e (diff) | |
download | txr-894aec019d3ce82f861a5777236ac079c2f2388d.tar.gz txr-894aec019d3ce82f861a5777236ac079c2f2388d.tar.bz2 txr-894aec019d3ce82f861a5777236ac079c2f2388d.zip |
* eval.c (eval_init): New function interned.
* lib.c:x (lazy_flatten_scan, lazy_flatten_func): New static functions.
(lazy_flatten): New function.
* lib.h (lazy_flatten): Declared.
* match.c (v_next): Use lazy_flatten instead of flatten for
processing a :list source. This means that @(next :list ...)
can be used to process infinite lazy lists.
* txr.1: Documented lazy-flatten.
Diffstat (limited to 'lib.c')
-rw-r--r-- | lib.c | 56 |
1 files changed, 56 insertions, 0 deletions
@@ -488,6 +488,62 @@ val flatten(val list) return mappend(func_n1(flatten), list); } +/* + * Return the embedded list whose car is the non-nil atom in the given nested + * list, updating the escape stack in the process. If no such atom is found in + * the list, try to retreate up the stack to find it in the surrounding + * structure, finally returning nil if nothing is found. + */ +static val lazy_flatten_scan(val list, val *escape) +{ + for (;;) { + if (list) { + val a = car(list); + if (nullp(a)) { + list = cdr(list); + } else if (atom(a)) { + return list; + } else do { + push(cdr(list), escape); + list = a; + a = car(list); + } while (consp(a)); + return list; + } else if (*escape) { + list = pop(escape); + } else { + return nil; + } + } +} + +static val lazy_flatten_func(val env, val lcons) +{ + cons_bind (list, escape, env); + val atom = car(list); + val next = lazy_flatten_scan(cdr(list), &escape); + + rplaca(lcons, atom); + rplaca(env, next); + rplacd(env, escape); + + if (next) + rplacd(lcons, make_lazy_cons(lcons_fun(lcons))); + + return nil; +} + +val lazy_flatten(val list) +{ + val escape = nil; + val next = lazy_flatten_scan(list, &escape); + + if (!next) + return nil; + + return make_lazy_cons(func_f1(cons(next, escape), lazy_flatten_func)); +} + cnum c_num(val num); val eql(val left, val right) |