diff options
author | Kaz Kylheku <kaz@kylheku.com> | 2017-04-15 18:28:36 -0700 |
---|---|---|
committer | Kaz Kylheku <kaz@kylheku.com> | 2017-04-15 18:28:36 -0700 |
commit | 9d59b9a607b0ebee9102ec7e2da00d7f24b54b0e (patch) | |
tree | b682e7f5b6b707064668ca8a8e7bdc82e20654d8 /eval.c | |
parent | c7089d15344e963397e9c58864f476729caeb225 (diff) | |
download | txr-9d59b9a607b0ebee9102ec7e2da00d7f24b54b0e.tar.gz txr-9d59b9a607b0ebee9102ec7e2da00d7f24b54b0e.tar.bz2 txr-9d59b9a607b0ebee9102ec7e2da00d7f24b54b0e.zip |
Bugfix expansion: return-from, sys:abscond-from, block*.
These three forms are not being traversed properly by the
macro expander.
* eval.c (do_expand): Do not treat return-from,
sys:abscond-from and block* in the same case as block.
block* evaluates all of its forms and so can just be walked
as a function call in the fallback case. The other two
must be in their own case because we must not use
expand_progn on them; they do not evaluate a progn-like
list of forms. This leads to inappropriate optimizations
like (return-from x (progn a b c)) -> (return-from x a b c).
Diffstat (limited to 'eval.c')
-rw-r--r-- | eval.c | 11 |
1 files changed, 8 insertions, 3 deletions
@@ -4050,15 +4050,20 @@ static val do_expand(val form, val menv) } else { return rlcp(cons(sym, cons(funcs_ex, body_ex)), form); } - } else if (sym == block_s || sym == return_from_s || - sym == sys_abscond_from_s || sym == block_star_s) - { + } else if (sym == block_s) { val name = second(form); val body = rest(rest(form)); val body_ex = expand_progn(body, menv); if (body == body_ex) return form; return rlcp(cons(sym, cons(name, body_ex)), form); + } else if (sym == return_from_s || sym == sys_abscond_from_s) { + val name = second(form); + val ret = third(form); + val ret_ex = expand(ret, menv); + if (ret == ret_ex) + return form; + return rlcp(list(sym, name, ret_ex, nao), form); } else if (sym == cond_s) { val pairs = rest(form); val pairs_ex = expand_cond_pairs(pairs, menv); |