diff options
| author | Stefan Monnier | 2020-03-10 18:23:41 -0400 |
|---|---|---|
| committer | Stefan Monnier | 2020-03-10 18:23:41 -0400 |
| commit | 0d6c51320d8066db867aae0e623d9731c69121ed (patch) | |
| tree | 44c3fa2734b584d3c1fc6b5a8e3f62b61373b994 | |
| parent | efe85a5b60b016eb3d11829c9590b54d935dd0c6 (diff) | |
| download | emacs-0d6c51320d8066db867aae0e623d9731c69121ed.tar.gz emacs-0d6c51320d8066db867aae0e623d9731c69121ed.zip | |
* lisp/emacs-lisp/cl-macs.el: More care with `eval` and with `cl-typep`
(cl-eval-when, cl--compile-time-too, cl-load-time-value):
Obey lexical-binding.
(cl-check-type): Prefer the predicate rather than the type in the
error signal when it's easy to do (as is done outside of CL).
(cl-deftype-satisfies): Add definitions for standard types.
| -rw-r--r-- | lisp/emacs-lisp/cl-macs.el | 57 |
1 files changed, 37 insertions, 20 deletions
diff --git a/lisp/emacs-lisp/cl-macs.el b/lisp/emacs-lisp/cl-macs.el index ef3bc8548d2..954731b06b8 100644 --- a/lisp/emacs-lisp/cl-macs.el +++ b/lisp/emacs-lisp/cl-macs.el | |||
| @@ -75,7 +75,7 @@ | |||
| 75 | ;; one, you may want to amend the other, too. | 75 | ;; one, you may want to amend the other, too. |
| 76 | ;;;###autoload | 76 | ;;;###autoload |
| 77 | (define-obsolete-function-alias 'cl--compiler-macro-cXXr | 77 | (define-obsolete-function-alias 'cl--compiler-macro-cXXr |
| 78 | 'internal--compiler-macro-cXXr "25.1") | 78 | #'internal--compiler-macro-cXXr "25.1") |
| 79 | 79 | ||
| 80 | ;;; Some predicates for analyzing Lisp forms. | 80 | ;;; Some predicates for analyzing Lisp forms. |
| 81 | ;; These are used by various | 81 | ;; These are used by various |
| @@ -714,9 +714,9 @@ If `eval' is in WHEN, BODY is evaluated when interpreted or at non-top-level. | |||
| 714 | (let ((comp (or (memq 'compile when) (memq :compile-toplevel when))) | 714 | (let ((comp (or (memq 'compile when) (memq :compile-toplevel when))) |
| 715 | (cl--not-toplevel t)) | 715 | (cl--not-toplevel t)) |
| 716 | (if (or (memq 'load when) (memq :load-toplevel when)) | 716 | (if (or (memq 'load when) (memq :load-toplevel when)) |
| 717 | (if comp (cons 'progn (mapcar 'cl--compile-time-too body)) | 717 | (if comp (cons 'progn (mapcar #'cl--compile-time-too body)) |
| 718 | `(if nil nil ,@body)) | 718 | `(if nil nil ,@body)) |
| 719 | (progn (if comp (eval (cons 'progn body))) nil))) | 719 | (progn (if comp (eval (cons 'progn body) lexical-binding)) nil))) |
| 720 | (and (or (memq 'eval when) (memq :execute when)) | 720 | (and (or (memq 'eval when) (memq :execute when)) |
| 721 | (cons 'progn body)))) | 721 | (cons 'progn body)))) |
| 722 | 722 | ||
| @@ -725,13 +725,13 @@ If `eval' is in WHEN, BODY is evaluated when interpreted or at non-top-level. | |||
| 725 | (setq form (macroexpand | 725 | (setq form (macroexpand |
| 726 | form (cons '(cl-eval-when) byte-compile-macro-environment)))) | 726 | form (cons '(cl-eval-when) byte-compile-macro-environment)))) |
| 727 | (cond ((eq (car-safe form) 'progn) | 727 | (cond ((eq (car-safe form) 'progn) |
| 728 | (cons 'progn (mapcar 'cl--compile-time-too (cdr form)))) | 728 | (cons 'progn (mapcar #'cl--compile-time-too (cdr form)))) |
| 729 | ((eq (car-safe form) 'cl-eval-when) | 729 | ((eq (car-safe form) 'cl-eval-when) |
| 730 | (let ((when (nth 1 form))) | 730 | (let ((when (nth 1 form))) |
| 731 | (if (or (memq 'eval when) (memq :execute when)) | 731 | (if (or (memq 'eval when) (memq :execute when)) |
| 732 | `(cl-eval-when (compile ,@when) ,@(cddr form)) | 732 | `(cl-eval-when (compile ,@when) ,@(cddr form)) |
| 733 | form))) | 733 | form))) |
| 734 | (t (eval form) form))) | 734 | (t (eval form lexical-binding) form))) |
| 735 | 735 | ||
| 736 | ;;;###autoload | 736 | ;;;###autoload |
| 737 | (defmacro cl-load-time-value (form &optional _read-only) | 737 | (defmacro cl-load-time-value (form &optional _read-only) |
| @@ -757,7 +757,7 @@ The result of the body appears to the compiler as a quoted constant." | |||
| 757 | ;; temp is set before we use it. | 757 | ;; temp is set before we use it. |
| 758 | (print set byte-compile--outbuffer)) | 758 | (print set byte-compile--outbuffer)) |
| 759 | temp) | 759 | temp) |
| 760 | `',(eval form))) | 760 | `',(eval form lexical-binding))) |
| 761 | 761 | ||
| 762 | 762 | ||
| 763 | ;;; Conditional control structures. | 763 | ;;; Conditional control structures. |
| @@ -1495,8 +1495,8 @@ For more details, see Info node `(cl)Loop Facility'. | |||
| 1495 | (pop cl--loop-args)) | 1495 | (pop cl--loop-args)) |
| 1496 | (if (and ands loop-for-bindings) | 1496 | (if (and ands loop-for-bindings) |
| 1497 | (push (nreverse loop-for-bindings) cl--loop-bindings) | 1497 | (push (nreverse loop-for-bindings) cl--loop-bindings) |
| 1498 | (setq cl--loop-bindings (nconc (mapcar 'list loop-for-bindings) | 1498 | (setq cl--loop-bindings (nconc (mapcar #'list loop-for-bindings) |
| 1499 | cl--loop-bindings))) | 1499 | cl--loop-bindings))) |
| 1500 | (if loop-for-sets | 1500 | (if loop-for-sets |
| 1501 | (push `(progn | 1501 | (push `(progn |
| 1502 | ,(cl--loop-let (nreverse loop-for-sets) 'setq ands) | 1502 | ,(cl--loop-let (nreverse loop-for-sets) 'setq ands) |
| @@ -1504,7 +1504,7 @@ For more details, see Info node `(cl)Loop Facility'. | |||
| 1504 | cl--loop-body)) | 1504 | cl--loop-body)) |
| 1505 | (when loop-for-steps | 1505 | (when loop-for-steps |
| 1506 | (push (cons (if ands 'cl-psetq 'setq) | 1506 | (push (cons (if ands 'cl-psetq 'setq) |
| 1507 | (apply 'append (nreverse loop-for-steps))) | 1507 | (apply #'append (nreverse loop-for-steps))) |
| 1508 | cl--loop-steps)))) | 1508 | cl--loop-steps)))) |
| 1509 | 1509 | ||
| 1510 | ((eq word 'repeat) | 1510 | ((eq word 'repeat) |
| @@ -1697,7 +1697,7 @@ If BODY is `setq', then use SPECS for assignments rather than for bindings." | |||
| 1697 | (push binding new)))) | 1697 | (push binding new)))) |
| 1698 | (if (eq body 'setq) | 1698 | (if (eq body 'setq) |
| 1699 | (let ((set (cons (if par 'cl-psetq 'setq) | 1699 | (let ((set (cons (if par 'cl-psetq 'setq) |
| 1700 | (apply 'nconc (nreverse new))))) | 1700 | (apply #'nconc (nreverse new))))) |
| 1701 | (if temps `(let* ,(nreverse temps) ,set) set)) | 1701 | (if temps `(let* ,(nreverse temps) ,set) set)) |
| 1702 | `(,(if par 'let 'let*) | 1702 | `(,(if par 'let 'let*) |
| 1703 | ,(nconc (nreverse temps) (nreverse new)) ,@body)))) | 1703 | ,(nconc (nreverse temps) (nreverse new)) ,@body)))) |
| @@ -1823,7 +1823,7 @@ For more details, see `cl-do*' description in Info node `(cl) Iteration'. | |||
| 1823 | (and sets | 1823 | (and sets |
| 1824 | (list (cons (if (or star (not (cdr sets))) | 1824 | (list (cons (if (or star (not (cdr sets))) |
| 1825 | 'setq 'cl-psetq) | 1825 | 'setq 'cl-psetq) |
| 1826 | (apply 'append sets)))))) | 1826 | (apply #'append sets)))))) |
| 1827 | ,@(or (cdr endtest) '(nil))))) | 1827 | ,@(or (cdr endtest) '(nil))))) |
| 1828 | 1828 | ||
| 1829 | ;;;###autoload | 1829 | ;;;###autoload |
| @@ -2468,7 +2468,7 @@ Each PLACE may be a symbol, or any generalized variable allowed by `setf'. | |||
| 2468 | 2468 | ||
| 2469 | \(fn PLACE...)" | 2469 | \(fn PLACE...)" |
| 2470 | (declare (debug (&rest place))) | 2470 | (declare (debug (&rest place))) |
| 2471 | (if (not (memq nil (mapcar 'symbolp args))) | 2471 | (if (not (memq nil (mapcar #'symbolp args))) |
| 2472 | (and (cdr args) | 2472 | (and (cdr args) |
| 2473 | (let ((sets nil) | 2473 | (let ((sets nil) |
| 2474 | (first (car args))) | 2474 | (first (car args))) |
| @@ -3128,13 +3128,27 @@ Of course, we really can't know that for sure, so it's just a heuristic." | |||
| 3128 | (or (cdr (assq sym byte-compile-function-environment)) | 3128 | (or (cdr (assq sym byte-compile-function-environment)) |
| 3129 | (cdr (assq sym byte-compile-macro-environment)))))) | 3129 | (cdr (assq sym byte-compile-macro-environment)))))) |
| 3130 | 3130 | ||
| 3131 | (put 'null 'cl-deftype-satisfies #'null) | 3131 | (pcase-dolist (`(,type . ,pred) |
| 3132 | (put 'atom 'cl-deftype-satisfies #'atom) | 3132 | '((null . null) |
| 3133 | (put 'real 'cl-deftype-satisfies #'numberp) | 3133 | (atom . atom) |
| 3134 | (put 'fixnum 'cl-deftype-satisfies #'integerp) | 3134 | (real . numberp) |
| 3135 | (put 'base-char 'cl-deftype-satisfies #'characterp) | 3135 | (fixnum . integerp) |
| 3136 | (put 'character 'cl-deftype-satisfies #'natnump) | 3136 | (base-char . characterp) |
| 3137 | 3137 | (character . natnump) | |
| 3138 | ;; "Obvious" mappings. | ||
| 3139 | (string . stringp) | ||
| 3140 | (list . listp) | ||
| 3141 | (symbol . symbolp) | ||
| 3142 | (function . functionp) | ||
| 3143 | (integer . integerp) | ||
| 3144 | (float . floatp) | ||
| 3145 | (boolean . booleanp) | ||
| 3146 | (vector . vectorp) | ||
| 3147 | (array . arrayp) | ||
| 3148 | ;; FIXME: Do we really want to consider this a type? | ||
| 3149 | (integer-or-marker . integer-or-marker-p) | ||
| 3150 | )) | ||
| 3151 | (put type 'cl-deftype-satisfies pred)) | ||
| 3138 | 3152 | ||
| 3139 | ;;;###autoload | 3153 | ;;;###autoload |
| 3140 | (define-inline cl-typep (val type) | 3154 | (define-inline cl-typep (val type) |
| @@ -3203,7 +3217,10 @@ STRING is an optional description of the desired type." | |||
| 3203 | (macroexp-let2 macroexp-copyable-p temp form | 3217 | (macroexp-let2 macroexp-copyable-p temp form |
| 3204 | `(progn (or (cl-typep ,temp ',type) | 3218 | `(progn (or (cl-typep ,temp ',type) |
| 3205 | (signal 'wrong-type-argument | 3219 | (signal 'wrong-type-argument |
| 3206 | (list ,(or string `',type) ,temp ',form))) | 3220 | (list ,(or string `',(if (eq 'satisfies |
| 3221 | (car-safe type)) | ||
| 3222 | (cadr type) type)) | ||
| 3223 | ,temp ',form))) | ||
| 3207 | nil)))) | 3224 | nil)))) |
| 3208 | 3225 | ||
| 3209 | ;;;###autoload | 3226 | ;;;###autoload |