summaryrefslogtreecommitdiffstats
path: root/eval.c
diff options
context:
space:
mode:
authorKaz Kylheku <kaz@kylheku.com>2013-10-06 23:56:02 -0700
committerKaz Kylheku <kaz@kylheku.com>2013-10-06 23:56:02 -0700
commit17c8e76951ea9dc407f07bf2173e8f60ac5efd80 (patch)
treef235f35ec09cf0c82ec6477e94db6fb5edc8038f /eval.c
parent7c8c8d326bbb8b9725efa6a3c364d3426a7cdca9 (diff)
downloadtxr-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.c42
1 files changed, 37 insertions, 5 deletions
diff --git a/eval.c b/eval.c
index 3aeeefda..1471e9be 100644
--- a/eval.c
+++ b/eval.c
@@ -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,