diff options
author | Kaz Kylheku <kaz@kylheku.com> | 2021-06-29 07:55:08 -0700 |
---|---|---|
committer | Kaz Kylheku <kaz@kylheku.com> | 2021-06-29 07:55:08 -0700 |
commit | 05500916c74317905fb6f75088f50606a9b562af (patch) | |
tree | c881cf1109afb6880daadf8428d5d8dae835c7d3 /stdlib | |
parent | d5d2a4c79c2e6203798cf985df5f23964a04817f (diff) | |
download | txr-05500916c74317905fb6f75088f50606a9b562af.tar.gz txr-05500916c74317905fb6f75088f50606a9b562af.tar.bz2 txr-05500916c74317905fb6f75088f50606a9b562af.zip |
compiler: bug: diagnose excess args from apply list.
When we compile an immediately applied lambda like
(apply (lambda (a b c) ...) list), we are not emitting code to
handle the run-time situation when there are too many elements
in the list. This shows up in exception handling, for
instance; the compiled version of this executes silently and
returns 42:
(catch (throw 'foo 5) (foo () 42)))
foo is must have a parameter to capture the 5; interpreted
code enforces this.
* stdlib/compiler.tl (lambda-apply-transform): In the
apply-list case, at the end of binding all the optional
arguments, if the parameter list doesn't have a rest
parameter to take any remaining items, we emit code to check
that there aren't any; that everything has been popped out of
the apply list, leaving it nil. If not, we call the
run-time support function lambda-excess-apply-list.
* stdlib/error.tl (lambda-excess-apply-list): New function.
Diffstat (limited to 'stdlib')
-rw-r--r-- | stdlib/compiler.tl | 13 | ||||
-rw-r--r-- | stdlib/error.tl | 3 |
2 files changed, 11 insertions, 5 deletions
diff --git a/stdlib/compiler.tl b/stdlib/compiler.tl index 05ed2a80..d00e8d1e 100644 --- a/stdlib/compiler.tl +++ b/stdlib/compiler.tl @@ -2008,7 +2008,8 @@ (mac-param-bind lm-expr (lambda lm-args . lm-body) lm-expr (let* ((pars (new (fun-param-parser lm-args lm-expr))) (fix-vals (mapcar (ret (gensym)) fix-arg-exprs)) - (ign-sym (gensym)) + (ign-1 (gensym)) + (ign-2 (gensym)) (al-val (gensym)) (shadow-p (let ((all-vars (append pars.req pars.(opt-syms) (if pars.rest (list pars.rest))))) @@ -2036,12 +2037,12 @@ ^(,*fix-arg-exprs ,apply-list-expr))))) (lambda-too-many-args lm-expr)) (when (or pars.rest apply-list-expr) - (add ^(,(or pars.rest ign-sym) ,apply-list-expr))))) + (add ^(,(or pars.rest ign-1) ,apply-list-expr))))) ((and fix-vals apply-list-expr) (lambda-too-many-args lm-expr)) (apply-list-expr (when pars.req - (add ^(,ign-sym (if (< (len ,al-val) ,(len pars.req)) + (add ^(,ign-1 (if (< (len ,al-val) ,(len pars.req)) (lambda-short-apply-list))))) (while pars.req (add ^(,(pop pars.req) (pop ,al-val)))) @@ -2058,8 +2059,10 @@ (t (add ^(,var-sym (if ,al-val (pop ,al-val) ,init-form))))))) - (when pars.rest - (add ^(,pars.rest ,al-val)))) + (if pars.rest + (add ^(,pars.rest ,al-val)) + (add ^(,ign-2 (if ,al-val + (lambda-excess-apply-list)))))) (pars.req (lambda-too-few-args lm-expr)) (pars.opt diff --git a/stdlib/error.tl b/stdlib/error.tl index 7f70391e..1058a8d2 100644 --- a/stdlib/error.tl +++ b/stdlib/error.tl @@ -93,3 +93,6 @@ (defun lambda-short-apply-list () (throwf 'eval-error "~s: applied argument list too short" 'lambda)) + +(defun lambda-excess-apply-list () + (throwf 'eval-error "~s: applied argument list too long" 'lambda)) |