summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKaz Kylheku <kaz@kylheku.com>2014-02-15 04:32:23 -0800
committerKaz Kylheku <kaz@kylheku.com>2014-02-15 04:32:23 -0800
commit5e89795f66750094ccac9d13a1f2001dde3d1226 (patch)
tree69c722acb99a11502ba56a03f99824335f43b034
parentf90caa20a5a1928cc3be9bf304e3f8760b6ea8ba (diff)
downloadtxr-5e89795f66750094ccac9d13a1f2001dde3d1226.tar.gz
txr-5e89795f66750094ccac9d13a1f2001dde3d1226.tar.bz2
txr-5e89795f66750094ccac9d13a1f2001dde3d1226.zip
Bugfix: parameters of defun were not being treated by expander.
They need to be since they can contain evaluable initforms for default arguments. Ditto with lambda; lambda parameters were being treated using expand_vars, which is not appropriate. * eval.c (expand_opt_params, expand_params): New static functions. (expand_vars): Bugfix: added some missing rlcp's to propagate line number info. (expand): Move lambda to separate case, and expand its params
-rw-r--r--ChangeLog12
-rw-r--r--eval.c64
2 files changed, 68 insertions, 8 deletions
diff --git a/ChangeLog b/ChangeLog
index f7e8e5b9..bd86f3fd 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,17 @@
2014-02-15 Kaz Kylheku <kaz@kylheku.com>
+ Bugfix: parameters of defun were not being treated by expander.
+ They need to be since they can contain evaluable initforms for default
+ arguments. Ditto with lambda; lambda parameters were being treated
+ using expand_vars, which is not appropriate.
+
+ * eval.c (expand_opt_params, expand_params): New static functions.
+ (expand_vars): Bugfix: added some missing rlcp's to propagate
+ line number info.
+ (expand): Move lambda to separate case, and expand its params
+
+2014-02-15 Kaz Kylheku <kaz@kylheku.com>
+
* eval.c (bind_args, op_modplace): Use ~s consistently
in error messages.
diff --git a/eval.c b/eval.c
index 296558f3..14f561e9 100644
--- a/eval.c
+++ b/eval.c
@@ -329,6 +329,44 @@ twocol:
car(ctx_form), nao);
}
+static val expand_opt_params(val params)
+{
+ if (atom(params)) {
+ return params;
+ } else {
+ val form = car(params);
+ if (atom(form) || !consp(cdr(form))) { /* sym, or no init form */
+ val params_ex = expand_opt_params(cdr(params));
+ if (params_ex == cdr(params))
+ return params;
+ return rlcp(cons(form, params_ex), cdr(params));
+ } else { /* has initform */
+ val initform = car(cdr(form));
+ val initform_ex = rlcp(expand(initform), initform);
+ val form_ex = rlcp(cons(car(form), cons(initform_ex, cdr(cdr(form)))),
+ form);
+ return rlcp(cons(form_ex, expand_opt_params(rest(params))), cdr(params));
+ }
+ }
+}
+
+static val expand_params(val params)
+{
+ if (atom(params)) {
+ return params;
+ } else if (car(params) == colon_k) {
+ val params_ex = expand_opt_params(cdr(params));
+ if (params_ex == cdr(params))
+ return params;
+ return rlcp(cons(colon_k, params_ex), cdr(params));
+ } else {
+ val params_ex = expand_params(cdr(params));
+ if (params_ex == cdr(params))
+ return params;
+ return rlcp(cons(car(params), params_ex), cdr(params));
+ }
+}
+
val apply(val fun, val arglist, val ctx_form)
{
val arg[32], *p = arg;
@@ -1494,17 +1532,17 @@ static val expand_vars(val vars)
val rest_vars_ex = expand_vars(rest_vars);
if (rest_vars == rest_vars_ex)
return vars;
- return cons(car(vars), rest_vars_ex);
+ return rlcp(cons(car(vars), rest_vars_ex), vars);
} else {
cons_bind (var, init, car(vars));
val rest_vars = rest(vars);
- val init_ex = expand_forms(init);
- val rest_vars_ex = expand_vars(rest_vars);
+ val init_ex = rlcp(expand_forms(init), init);
+ val rest_vars_ex = rlcp(expand_vars(rest_vars), rest_vars);
if (init == init_ex && rest_vars == rest_vars_ex)
return vars;
- return cons(cons(var, init_ex), rest_vars_ex);
+ return rlcp(cons(cons(var, init_ex), rest_vars_ex), vars);
}
}
@@ -1719,7 +1757,7 @@ val expand(val form)
} else {
val sym = car(form);
- if (sym == let_s || sym == let_star_s || sym == lambda_s ||
+ if (sym == let_s || sym == let_star_s ||
sym == each_s || sym == each_star_s || sym == collect_each_s ||
sym == collect_each_star_s || sym == append_each_s ||
sym == append_each_star_s)
@@ -1753,15 +1791,25 @@ val expand(val form)
if (init == init_ex)
return form;
return rlcp(cons(sym, cons(name, cons(init_ex, nil))), form);
+ } else if (sym == lambda_s) {
+ val params = second(form);
+ val body = rest(rest(form));
+ val params_ex = expand_params(params);
+ val body_ex = expand_forms(body);
+
+ if (body == body_ex && params == params_ex)
+ return form;
+ return rlcp(cons(sym, cons(params_ex, body_ex)), form);
} else if (sym == defun_s) {
val name = second(form);
- val args = third(form);
+ val params = third(form);
+ val params_ex = expand_params(params);
val body = rest(rest(rest(form)));
val body_ex = expand_forms(body);
- if (body == body_ex)
+ if (body == body_ex && params == params_ex)
return form;
- return rlcp(cons(sym, cons(name, cons(args, body_ex))), form);
+ return rlcp(cons(sym, cons(name, cons(params_ex, body_ex))), form);
} else if (sym == set_s || sym == inc_s || sym == dec_s) {
val place = second(form);
val inc = third(form);