summaryrefslogtreecommitdiffstats
path: root/stdlib
diff options
context:
space:
mode:
authorKaz Kylheku <kaz@kylheku.com>2021-06-29 07:55:08 -0700
committerKaz Kylheku <kaz@kylheku.com>2021-06-29 07:55:08 -0700
commit05500916c74317905fb6f75088f50606a9b562af (patch)
treec881cf1109afb6880daadf8428d5d8dae835c7d3 /stdlib
parentd5d2a4c79c2e6203798cf985df5f23964a04817f (diff)
downloadtxr-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.tl13
-rw-r--r--stdlib/error.tl3
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))