diff options
author | Kaz Kylheku <kaz@kylheku.com> | 2014-02-15 04:32:23 -0800 |
---|---|---|
committer | Kaz Kylheku <kaz@kylheku.com> | 2014-02-15 04:32:23 -0800 |
commit | 5e89795f66750094ccac9d13a1f2001dde3d1226 (patch) | |
tree | 69c722acb99a11502ba56a03f99824335f43b034 | |
parent | f90caa20a5a1928cc3be9bf304e3f8760b6ea8ba (diff) | |
download | txr-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-- | ChangeLog | 12 | ||||
-rw-r--r-- | eval.c | 64 |
2 files changed, 68 insertions, 8 deletions
@@ -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. @@ -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); |