diff options
| author | Stefan Monnier | 2017-11-27 12:45:16 -0500 |
|---|---|---|
| committer | Stefan Monnier | 2017-11-27 12:45:16 -0500 |
| commit | cea0bca54f1fa3635591e24eba1017742b04abd0 (patch) | |
| tree | e8e0c6051b9b48a83d25548d91e4ef775b05120c | |
| parent | e896320f0e0c50aa31712b7f1bda4c4a78ff0f82 (diff) | |
| download | emacs-cea0bca54f1fa3635591e24eba1017742b04abd0.tar.gz emacs-cea0bca54f1fa3635591e24eba1017742b04abd0.zip | |
* lisp/emacs-lisp/cl-macs.el: Fix &key with no key arg
* test/lisp/emacs-lisp/cl-lib-tests.el (cl-lib-empty-keyargs): New test.
* lisp/emacs-lisp/cl-macs.el (cl--do-arglist): Fix it.
| -rw-r--r-- | lisp/emacs-lisp/cl-macs.el | 44 | ||||
| -rw-r--r-- | test/lisp/emacs-lisp/cl-lib-tests.el | 4 |
2 files changed, 31 insertions, 17 deletions
diff --git a/lisp/emacs-lisp/cl-macs.el b/lisp/emacs-lisp/cl-macs.el index e313af24975..4069db53c93 100644 --- a/lisp/emacs-lisp/cl-macs.el +++ b/lisp/emacs-lisp/cl-macs.el | |||
| @@ -555,7 +555,7 @@ its argument list allows full Common Lisp conventions." | |||
| 555 | (if (memq '&environment args) (error "&environment used incorrectly")) | 555 | (if (memq '&environment args) (error "&environment used incorrectly")) |
| 556 | (let ((restarg (memq '&rest args)) | 556 | (let ((restarg (memq '&rest args)) |
| 557 | (safety (if (cl--compiling-file) cl--optimize-safety 3)) | 557 | (safety (if (cl--compiling-file) cl--optimize-safety 3)) |
| 558 | (keys nil) | 558 | (keys t) |
| 559 | (laterarg nil) (exactarg nil) minarg) | 559 | (laterarg nil) (exactarg nil) minarg) |
| 560 | (or num (setq num 0)) | 560 | (or num (setq num 0)) |
| 561 | (setq restarg (if (listp (cadr restarg)) | 561 | (setq restarg (if (listp (cadr restarg)) |
| @@ -610,6 +610,7 @@ its argument list allows full Common Lisp conventions." | |||
| 610 | (+ ,num (length ,restarg))))) | 610 | (+ ,num (length ,restarg))))) |
| 611 | cl--bind-forms))) | 611 | cl--bind-forms))) |
| 612 | (while (and (eq (car args) '&key) (pop args)) | 612 | (while (and (eq (car args) '&key) (pop args)) |
| 613 | (unless (listp keys) (setq keys nil)) | ||
| 613 | (while (and args (not (memq (car args) cl--lambda-list-keywords))) | 614 | (while (and args (not (memq (car args) cl--lambda-list-keywords))) |
| 614 | (let ((arg (pop args))) | 615 | (let ((arg (pop args))) |
| 615 | (or (consp arg) (setq arg (list arg))) | 616 | (or (consp arg) (setq arg (list arg))) |
| @@ -648,23 +649,32 @@ its argument list allows full Common Lisp conventions." | |||
| 648 | `'(nil ,(cl--const-expr-val def)) | 649 | `'(nil ,(cl--const-expr-val def)) |
| 649 | `(list nil ,def)))))))) | 650 | `(list nil ,def)))))))) |
| 650 | (push karg keys))))) | 651 | (push karg keys))))) |
| 651 | (setq keys (nreverse keys)) | 652 | (when (consp keys) (setq keys (nreverse keys))) |
| 652 | (or (and (eq (car args) '&allow-other-keys) (pop args)) | 653 | (or (and (eq (car args) '&allow-other-keys) (pop args)) |
| 653 | (null keys) (= safety 0) | 654 | (= safety 0) |
| 654 | (let* ((var (make-symbol "--cl-keys--")) | 655 | (cond |
| 655 | (allow '(:allow-other-keys)) | 656 | ((eq keys t) nil) ;No &keys at all |
| 656 | (check `(while ,var | 657 | ((null keys) ;A &key but no actual keys specified. |
| 657 | (cond | 658 | (push `(when ,restarg |
| 658 | ((memq (car ,var) ',(append keys allow)) | 659 | (error ,(format "Keyword argument %%s not one of %s" |
| 659 | (setq ,var (cdr (cdr ,var)))) | 660 | keys) |
| 660 | ((car (cdr (memq (quote ,@allow) ,restarg))) | 661 | (car ,restarg))) |
| 661 | (setq ,var nil)) | 662 | cl--bind-forms)) |
| 662 | (t | 663 | (t |
| 663 | (error | 664 | (let* ((var (make-symbol "--cl-keys--")) |
| 664 | ,(format "Keyword argument %%s not one of %s" | 665 | (allow '(:allow-other-keys)) |
| 665 | keys) | 666 | (check `(while ,var |
| 666 | (car ,var))))))) | 667 | (cond |
| 667 | (push `(let ((,var ,restarg)) ,check) cl--bind-forms))) | 668 | ((memq (car ,var) ',(append keys allow)) |
| 669 | (setq ,var (cdr (cdr ,var)))) | ||
| 670 | ((car (cdr (memq (quote ,@allow) ,restarg))) | ||
| 671 | (setq ,var nil)) | ||
| 672 | (t | ||
| 673 | (error | ||
| 674 | ,(format "Keyword argument %%s not one of %s" | ||
| 675 | keys) | ||
| 676 | (car ,var))))))) | ||
| 677 | (push `(let ((,var ,restarg)) ,check) cl--bind-forms))))) | ||
| 668 | (cl--do-&aux args) | 678 | (cl--do-&aux args) |
| 669 | nil))) | 679 | nil))) |
| 670 | 680 | ||
diff --git a/test/lisp/emacs-lisp/cl-lib-tests.el b/test/lisp/emacs-lisp/cl-lib-tests.el index 13c9af9bd6d..ed85f5a0f66 100644 --- a/test/lisp/emacs-lisp/cl-lib-tests.el +++ b/test/lisp/emacs-lisp/cl-lib-tests.el | |||
| @@ -201,6 +201,10 @@ | |||
| 201 | :b :a :a 42) | 201 | :b :a :a 42) |
| 202 | '(42 :a)))) | 202 | '(42 :a)))) |
| 203 | 203 | ||
| 204 | (ert-deftest cl-lib-empty-keyargs () | ||
| 205 | (should-error (funcall (cl-function (lambda (&key) 1)) | ||
| 206 | :b 1))) | ||
| 207 | |||
| 204 | (cl-defstruct (mystruct | 208 | (cl-defstruct (mystruct |
| 205 | (:constructor cl-lib--con-1 (&aux (abc 1))) | 209 | (:constructor cl-lib--con-1 (&aux (abc 1))) |
| 206 | (:constructor cl-lib--con-2 (&optional def) "Constructor docstring.")) | 210 | (:constructor cl-lib--con-2 (&optional def) "Constructor docstring.")) |