diff options
author | Kaz Kylheku <kaz@kylheku.com> | 2013-10-06 23:56:02 -0700 |
---|---|---|
committer | Kaz Kylheku <kaz@kylheku.com> | 2013-10-06 23:56:02 -0700 |
commit | 17c8e76951ea9dc407f07bf2173e8f60ac5efd80 (patch) | |
tree | f235f35ec09cf0c82ec6477e94db6fb5edc8038f /eval.c | |
parent | 7c8c8d326bbb8b9725efa6a3c364d3426a7cdca9 (diff) | |
download | txr-17c8e76951ea9dc407f07bf2173e8f60ac5efd80.tar.gz txr-17c8e76951ea9dc407f07bf2173e8f60ac5efd80.tar.bz2 txr-17c8e76951ea9dc407f07bf2173e8f60ac5efd80.zip |
Improving behavior of op and fixing a bug.
Explicitly specifying @rest using (op ... . @rest)
did not work at all.
The then-func agument of iff and iffi may now be nil.
* eval.c (format_op_arg): New static function.
(transform_op): Handle dotted lists ending in @rest
or @<num>.
(supplement_op_syms): New static function.
(expand_op): Add missing numeric arguments,
so that all 1 through n are in the list.
Trailing rest is now added under different
conditions.
* lib.c (do_iff): Give thenfun the same
behavior on nil that elsefun enjoys.
* txr.1: Updated.
Diffstat (limited to 'eval.c')
-rw-r--r-- | eval.c | 42 |
1 files changed, 37 insertions, 5 deletions
@@ -1493,6 +1493,11 @@ static val expand_delay(val args) cons(lambda_s, cons(nil, args)), nao); } +static val format_op_arg(val num) +{ + return format(nil, lit("arg-~,02s-"), num, nao); +} + static val transform_op(val forms, val syms, val rg) { if (atom(forms)) { @@ -1501,15 +1506,19 @@ static val transform_op(val forms, val syms, val rg) val fi = first(forms); val re = rest(forms); + if (fi == var_s) { + cons_bind (outsyms, outforms, transform_op(cons(forms, nil), syms, rg)); + return cons(outsyms, rlcp(car(outforms), outforms)); + } + if (consp(fi) && car(fi) == var_s && consp(cdr(fi))) { val vararg = car(cdr(fi)); if (integerp(vararg)) { - val prefix = format(nil, lit("arg-~,02s-"), vararg, nao); val newsyms = syms; val new_p; val *place = acons_new_l(vararg, &new_p, &newsyms); - val sym = if3(new_p, set(*place, gensym(prefix)), *place); + val sym = if3(new_p, set(*place, gensym(format_op_arg(vararg))), *place); cons_bind (outsyms, outforms, transform_op(re, newsyms, rg)); return cons(outsyms, rlcp(cons(sym, outforms), outforms)); } else if (eq(vararg, rest_s)) { @@ -1538,6 +1547,25 @@ static val cons_find(val obj, val structure, val test) cons_find(obj, cdr(structure), test)); } +static val supplement_op_syms(val ssyms, val max) +{ + list_collect_decl (outsyms, tl); + val si, ni; + + for (si = ssyms, ni = one; + ssyms; + ni = plus(ni, one), ssyms = cdr(ssyms)) + { + val entry = car(si); + val num = car(entry); + + for (; lt(ni, num); ni = plus(ni, one)) + list_collect(tl, cons(ni, gensym(format_op_arg(ni)))); + list_collect(tl, entry); + } + + return outsyms; +} static val expand_op(val body) { @@ -1551,14 +1579,18 @@ static val expand_op(val body) val has_rest = cons_find(rest_gensym, body_trans, eq_f); if (!eql(max, length(nums)) && !zerop(min)) - eval_error(body, lit("op: missing numeric arguments"), nao); + ssyms = supplement_op_syms(ssyms, max); rlcp(body_trans, body); { + uses_or2; val dwim_body = rlcp(cons(dwim_s, - append2(body_trans, if3(has_rest, nil, - rest_gensym))), + if3(or3(has_rest, + ssyms, + nullp(proper_listp(body_trans))), + body_trans, + append2(body_trans, rest_gensym))), body_trans); return cons(lambda_s, |