summaryrefslogtreecommitdiff
path: root/lisp/emacs-lisp/cl-macs.el
diff options
context:
space:
mode:
Diffstat (limited to 'lisp/emacs-lisp/cl-macs.el')
-rw-r--r--lisp/emacs-lisp/cl-macs.el335
1 files changed, 214 insertions, 121 deletions
diff --git a/lisp/emacs-lisp/cl-macs.el b/lisp/emacs-lisp/cl-macs.el
index c2bf02ccece..4ef1948b0fe 100644
--- a/lisp/emacs-lisp/cl-macs.el
+++ b/lisp/emacs-lisp/cl-macs.el
@@ -186,14 +186,14 @@ The name is made by appending a number to PREFIX, default \"T\"."
;;; Program structure.
-(def-edebug-spec cl-declarations
- (&rest ("cl-declare" &rest sexp)))
+(def-edebug-elem-spec 'cl-declarations
+ '(&rest ("cl-declare" &rest sexp)))
-(def-edebug-spec cl-declarations-or-string
- (&or lambda-doc cl-declarations))
+(def-edebug-elem-spec 'cl-declarations-or-string
+ '(lambda-doc &or ("declare" def-declarations) cl-declarations))
-(def-edebug-spec cl-lambda-list
- (([&rest cl-lambda-arg]
+(def-edebug-elem-spec 'cl-lambda-list
+ '(([&rest cl-lambda-arg]
[&optional ["&optional" cl-&optional-arg &rest cl-&optional-arg]]
[&optional ["&rest" cl-lambda-arg]]
[&optional ["&key" [cl-&key-arg &rest cl-&key-arg]
@@ -202,27 +202,27 @@ The name is made by appending a number to PREFIX, default \"T\"."
&or (cl-lambda-arg &optional def-form) arg]]
. [&or arg nil])))
-(def-edebug-spec cl-&optional-arg
- (&or (cl-lambda-arg &optional def-form arg) arg))
+(def-edebug-elem-spec 'cl-&optional-arg
+ '(&or (cl-lambda-arg &optional def-form arg) arg))
-(def-edebug-spec cl-&key-arg
- (&or ([&or (symbolp cl-lambda-arg) arg] &optional def-form arg) arg))
+(def-edebug-elem-spec 'cl-&key-arg
+ '(&or ([&or (symbolp cl-lambda-arg) arg] &optional def-form arg) arg))
-(def-edebug-spec cl-lambda-arg
- (&or arg cl-lambda-list1))
+(def-edebug-elem-spec 'cl-lambda-arg
+ '(&or arg cl-lambda-list1))
-(def-edebug-spec cl-lambda-list1
- (([&optional ["&whole" arg]] ;; only allowed at lower levels
- [&rest cl-lambda-arg]
- [&optional ["&optional" cl-&optional-arg &rest cl-&optional-arg]]
- [&optional ["&rest" cl-lambda-arg]]
- [&optional ["&key" cl-&key-arg &rest cl-&key-arg
- &optional "&allow-other-keys"]]
- [&optional ["&aux" &rest
- &or (cl-lambda-arg &optional def-form) arg]]
- . [&or arg nil])))
+(def-edebug-elem-spec 'cl-lambda-list1
+ '(([&optional ["&whole" arg]] ;; only allowed at lower levels
+ [&rest cl-lambda-arg]
+ [&optional ["&optional" cl-&optional-arg &rest cl-&optional-arg]]
+ [&optional ["&rest" cl-lambda-arg]]
+ [&optional ["&key" cl-&key-arg &rest cl-&key-arg
+ &optional "&allow-other-keys"]]
+ [&optional ["&aux" &rest
+ &or (cl-lambda-arg &optional def-form) arg]]
+ . [&or arg nil])))
-(def-edebug-spec cl-type-spec sexp)
+(def-edebug-elem-spec 'cl-type-spec '(sexp))
(defconst cl--lambda-list-keywords
'(&optional &rest &key &allow-other-keys &aux &whole &body &environment))
@@ -358,7 +358,7 @@ more details.
\(fn NAME ARGLIST [DOCSTRING] BODY...)"
(declare (debug
;; Same as defun but use cl-lambda-list.
- (&define [&or name ("setf" :name setf name)]
+ (&define [&name sexp] ;Allow (setf ...) additionally to symbols.
cl-lambda-list
cl-declarations-or-string
[&optional ("interactive" interactive)]
@@ -376,7 +376,7 @@ and BODY is implicitly surrounded by (cl-block NAME ...).
\(fn NAME ARGLIST [DOCSTRING] BODY...)"
(declare (debug
;; Same as iter-defun but use cl-lambda-list.
- (&define [&or name ("setf" :name setf name)]
+ (&define [&name sexp] ;Allow (setf ...) additionally to symbols.
cl-lambda-list
cl-declarations-or-string
[&optional ("interactive" interactive)]
@@ -390,39 +390,39 @@ and BODY is implicitly surrounded by (cl-block NAME ...).
;; Note that &environment is only allowed as first or last items in the
;; top level list.
-(def-edebug-spec cl-macro-list
- (([&optional "&environment" arg]
- [&rest cl-macro-arg]
- [&optional ["&optional" &rest
- &or (cl-macro-arg &optional def-form cl-macro-arg) arg]]
- [&optional [[&or "&rest" "&body"] cl-macro-arg]]
- [&optional ["&key" [&rest
- [&or ([&or (symbolp cl-macro-arg) arg]
- &optional def-form cl-macro-arg)
- arg]]
- &optional "&allow-other-keys"]]
- [&optional ["&aux" &rest
- &or (cl-macro-arg &optional def-form) arg]]
- [&optional "&environment" arg]
- )))
-
-(def-edebug-spec cl-macro-arg
- (&or arg cl-macro-list1))
-
-(def-edebug-spec cl-macro-list1
- (([&optional "&whole" arg] ;; only allowed at lower levels
- [&rest cl-macro-arg]
- [&optional ["&optional" &rest
- &or (cl-macro-arg &optional def-form cl-macro-arg) arg]]
- [&optional [[&or "&rest" "&body"] cl-macro-arg]]
- [&optional ["&key" [&rest
- [&or ([&or (symbolp cl-macro-arg) arg]
- &optional def-form cl-macro-arg)
- arg]]
- &optional "&allow-other-keys"]]
- [&optional ["&aux" &rest
- &or (cl-macro-arg &optional def-form) arg]]
- . [&or arg nil])))
+(def-edebug-elem-spec 'cl-macro-list
+ '(([&optional "&environment" arg]
+ [&rest cl-macro-arg]
+ [&optional ["&optional" &rest
+ &or (cl-macro-arg &optional def-form cl-macro-arg) arg]]
+ [&optional [[&or "&rest" "&body"] cl-macro-arg]]
+ [&optional ["&key" [&rest
+ [&or ([&or (symbolp cl-macro-arg) arg]
+ &optional def-form cl-macro-arg)
+ arg]]
+ &optional "&allow-other-keys"]]
+ [&optional ["&aux" &rest
+ &or (cl-macro-arg &optional def-form) arg]]
+ [&optional "&environment" arg]
+ )))
+
+(def-edebug-elem-spec 'cl-macro-arg
+ '(&or arg cl-macro-list1))
+
+(def-edebug-elem-spec 'cl-macro-list1
+ '(([&optional "&whole" arg] ;; only allowed at lower levels
+ [&rest cl-macro-arg]
+ [&optional ["&optional" &rest
+ &or (cl-macro-arg &optional def-form cl-macro-arg) arg]]
+ [&optional [[&or "&rest" "&body"] cl-macro-arg]]
+ [&optional ["&key" [&rest
+ [&or ([&or (symbolp cl-macro-arg) arg]
+ &optional def-form cl-macro-arg)
+ arg]]
+ &optional "&allow-other-keys"]]
+ [&optional ["&aux" &rest
+ &or (cl-macro-arg &optional def-form) arg]]
+ . [&or arg nil])))
;;;###autoload
(defmacro cl-defmacro (name args &rest body)
@@ -452,19 +452,19 @@ more details.
(indent 2))
`(defmacro ,name ,@(cl--transform-lambda (cons args body) name)))
-(def-edebug-spec cl-lambda-expr
- (&define ("lambda" cl-lambda-list
- cl-declarations-or-string
- [&optional ("interactive" interactive)]
- def-body)))
+(def-edebug-elem-spec 'cl-lambda-expr
+ '(&define ("lambda" cl-lambda-list
+ cl-declarations-or-string
+ [&optional ("interactive" interactive)]
+ def-body)))
;; Redefine function-form to also match cl-function
-(def-edebug-spec function-form
+(def-edebug-elem-spec 'function-form
;; form at the end could also handle "function",
;; but recognize it specially to avoid wrapping function forms.
- (&or ([&or "quote" "function"] &or symbolp lambda-expr)
- ("cl-function" cl-function)
- form))
+ '(&or ([&or "quote" "function"] &or symbolp lambda-expr)
+ ("cl-function" cl-function)
+ form))
;;;###autoload
(defmacro cl-function (func)
@@ -545,7 +545,7 @@ its argument list allows full Common Lisp conventions."
(let ((p (memq '&body args))) (if p (setcar p '&rest)))
(if (memq '&environment args) (error "&environment used incorrectly"))
(let ((restarg (memq '&rest args))
- (safety (if (cl--compiling-file) cl--optimize-safety 3))
+ (safety (if (macroexp-compiling-p) cl--optimize-safety 3))
(keys t)
(laterarg nil) (exactarg nil) minarg)
(or num (setq num 0))
@@ -565,7 +565,7 @@ its argument list allows full Common Lisp conventions."
,(length (cl-ldiff args p)))
exactarg (not (eq args p)))))
(while (and args (not (memq (car args) cl--lambda-list-keywords)))
- (let ((poparg (list (if (or (cdr args) (not exactarg)) 'pop 'car)
+ (let ((poparg (list (if (or (cdr args) (not exactarg)) 'pop 'car-safe)
restarg)))
(cl--do-arglist
(pop args)
@@ -709,7 +709,7 @@ If `eval' is in WHEN, BODY is evaluated when interpreted or at non-top-level.
\(fn (WHEN...) BODY...)"
(declare (indent 1) (debug (sexp body)))
- (if (and (fboundp 'cl--compiling-file) (cl--compiling-file)
+ (if (and (macroexp-compiling-p)
(not cl--not-toplevel) (not (boundp 'for-effect))) ;Horrible kludge.
(let ((comp (or (memq 'compile when) (memq :compile-toplevel when)))
(cl--not-toplevel t))
@@ -723,7 +723,7 @@ If `eval' is in WHEN, BODY is evaluated when interpreted or at non-top-level.
(defun cl--compile-time-too (form)
(or (and (symbolp (car-safe form)) (get (car-safe form) 'byte-hunk-handler))
(setq form (macroexpand
- form (cons '(cl-eval-when) byte-compile-macro-environment))))
+ form (cons '(cl-eval-when) macroexpand-all-environment))))
(cond ((eq (car-safe form) 'progn)
(cons 'progn (mapcar #'cl--compile-time-too (cdr form))))
((eq (car-safe form) 'cl-eval-when)
@@ -738,7 +738,7 @@ If `eval' is in WHEN, BODY is evaluated when interpreted or at non-top-level.
"Like `progn', but evaluates the body at load time.
The result of the body appears to the compiler as a quoted constant."
(declare (debug (form &optional sexp)))
- (if (cl--compiling-file)
+ (if (macroexp-compiling-p)
(let* ((temp (cl-gentemp "--cl-load-time--"))
(set `(setq ,temp ,form)))
(if (and (fboundp 'byte-compile-file-form-defmumble)
@@ -941,7 +941,8 @@ For more details, see Info node `(cl)Loop Facility'.
"above" "below" "by" "in" "on" "=" "across"
"repeat" "while" "until" "always" "never"
"thereis" "collect" "append" "nconc" "sum"
- "count" "maximize" "minimize" "if" "unless"
+ "count" "maximize" "minimize"
+ "if" "when" "unless"
"return"]
form]
["using" (symbolp symbolp)]
@@ -1051,20 +1052,20 @@ For more details, see Info node `(cl)Loop Facility'.
;; [&rest loop-clause]
;; ))
-;; (def-edebug-spec loop-with
-;; ("with" loop-var
+;; (def-edebug-elem-spec 'loop-with
+;; '("with" loop-var
;; loop-type-spec
;; [&optional ["=" form]]
;; &rest ["and" loop-var
;; loop-type-spec
;; [&optional ["=" form]]]))
-;; (def-edebug-spec loop-for-as
-;; ([&or "for" "as"] loop-for-as-subclause
+;; (def-edebug-elem-spec 'loop-for-as
+;; '([&or "for" "as"] loop-for-as-subclause
;; &rest ["and" loop-for-as-subclause]))
-;; (def-edebug-spec loop-for-as-subclause
-;; (loop-var
+;; (def-edebug-elem-spec 'loop-for-as-subclause
+;; '(loop-var
;; loop-type-spec
;; &or
;; [[&or "in" "on" "in-ref" "across-ref"]
@@ -1124,19 +1125,19 @@ For more details, see Info node `(cl)Loop Facility'.
;; [&optional ["by" form]]
;; ]))
-;; (def-edebug-spec loop-initial-final
-;; (&or ["initially"
+;; (def-edebug-elem-spec 'loop-initial-final
+;; '(&or ["initially"
;; ;; [&optional &or "do" "doing"] ;; CLtL2 doesn't allow this.
;; &rest loop-non-atomic-expr]
;; ["finally" &or
;; [[&optional &or "do" "doing"] &rest loop-non-atomic-expr]
;; ["return" form]]))
-;; (def-edebug-spec loop-and-clause
-;; (loop-clause &rest ["and" loop-clause]))
+;; (def-edebug-elem-spec 'loop-and-clause
+;; '(loop-clause &rest ["and" loop-clause]))
-;; (def-edebug-spec loop-clause
-;; (&or
+;; (def-edebug-elem-spec 'loop-clause
+;; '(&or
;; [[&or "while" "until" "always" "never" "thereis"] form]
;; [[&or "collect" "collecting"
@@ -1163,10 +1164,10 @@ For more details, see Info node `(cl)Loop Facility'.
;; loop-initial-final
;; ))
-;; (def-edebug-spec loop-non-atomic-expr
-;; ([&not atom] form))
+;; (def-edebug-elem-spec 'loop-non-atomic-expr
+;; '([&not atom] form))
-;; (def-edebug-spec loop-var
+;; (def-edebug-elem-spec 'loop-var
;; ;; The symbolp must be last alternative to recognize e.g. (a b . c)
;; ;; loop-var =>
;; ;; (loop-var . [&or nil loop-var])
@@ -1175,13 +1176,13 @@ For more details, see Info node `(cl)Loop Facility'.
;; ;; (symbolp . (symbolp . [&or nil loop-var]))
;; ;; (symbolp . (symbolp . loop-var))
;; ;; (symbolp . (symbolp . symbolp)) == (symbolp symbolp . symbolp)
-;; (&or (loop-var . [&or nil loop-var]) [gate symbolp]))
+;; '(&or (loop-var . [&or nil loop-var]) [gate symbolp]))
-;; (def-edebug-spec loop-type-spec
-;; (&optional ["of-type" loop-d-type-spec]))
+;; (def-edebug-elem-spec 'loop-type-spec
+;; '(&optional ["of-type" loop-d-type-spec]))
-;; (def-edebug-spec loop-d-type-spec
-;; (&or (loop-d-type-spec . [&or nil loop-d-type-spec]) cl-type-spec))
+;; (def-edebug-elem-spec 'loop-d-type-spec
+;; '(&or (loop-d-type-spec . [&or nil loop-d-type-spec]) cl-type-spec))
(defun cl--parse-loop-clause () ; uses loop-*
(let ((word (pop cl--loop-args))
@@ -1924,7 +1925,8 @@ from OBARRAY.
\(fn (VAR [OBARRAY [RESULT]]) BODY...)"
(declare (indent 1)
- (debug ((symbolp &optional form form) cl-declarations body)))
+ (debug ((symbolp &optional form form) cl-declarations
+ def-body)))
;; Apparently this doesn't have an implicit block.
`(cl-block nil
(let (,(car spec))
@@ -1964,7 +1966,7 @@ Each symbol in the first list is bound to the corresponding value in the
second list (or to nil if VALUES is shorter than SYMBOLS); then the
BODY forms are executed and their result is returned. This is much like
a `let' form, except that the list of symbols can be computed at run-time."
- (declare (indent 2) (debug (form form body)))
+ (declare (indent 2) (debug (form form def-body)))
(let ((bodyfun (make-symbol "body"))
(binds (make-symbol "binds"))
(syms (make-symbol "syms"))
@@ -1976,7 +1978,8 @@ a `let' form, except that the list of symbols can be computed at run-time."
(,binds ()))
(while ,syms
(push (list (pop ,syms) (list 'quote (pop ,vals))) ,binds))
- (eval (list 'let ,binds (list 'funcall (list 'quote ,bodyfun))))))))
+ (eval (list 'let (nreverse ,binds)
+ (list 'funcall (list 'quote ,bodyfun))))))))
(defconst cl--labels-magic (make-symbol "cl--labels-magic"))
@@ -2016,8 +2019,9 @@ info node `(cl) Function Bindings' for details.
\(fn ((FUNC ARGLIST BODY...) ...) FORM...)"
(declare (indent 1)
- (debug ((&rest [&or (&define name :unique "cl-flet@" function-form)
- (&define name :unique "cl-flet@"
+ (debug ((&rest [&or (symbolp form)
+ (&define [&name symbolp "@cl-flet@"]
+ [&name [] gensym] ;Make it unique!
cl-lambda-list
cl-declarations-or-string
[&optional ("interactive" interactive)]
@@ -2067,6 +2071,8 @@ Like `cl-flet' but the definitions can refer to previous ones.
;; even handle mutually recursive functions.
(letrec
((done nil) ;; Non-nil if some TCO happened.
+ ;; This var always holds the value `nil' until (just before) we
+ ;; exit the loop.
(retvar (make-symbol "retval"))
(ofargs (mapcar (lambda (s) (if (memq s cl--lambda-list-keywords) s
(make-symbol (symbol-name s))))
@@ -2099,6 +2105,12 @@ Like `cl-flet' but the definitions can refer to previous ones.
(`(progn . ,exps) `(progn . ,(funcall opt-exps exps)))
(`(if ,cond ,then . ,else)
`(if ,cond ,(funcall opt then) . ,(funcall opt-exps else)))
+ (`(and . ,exps) `(and . ,(funcall opt-exps exps)))
+ (`(or ,arg) (funcall opt arg))
+ (`(or ,arg . ,args)
+ (let ((val (make-symbol "val")))
+ `(let ((,val ,arg))
+ (if ,val ,(funcall opt val) ,(funcall opt `(or . ,args))))))
(`(cond . ,conds)
(let ((cs '()))
(while conds
@@ -2108,14 +2120,18 @@ Like `cl-flet' but the definitions can refer to previous ones.
;; This returns the value of `exp' but it's
;; only in tail position if it's the
;; last condition.
+ ;; Note: This may set the var before we
+ ;; actually exit the loop, but luckily it's
+ ;; only the case if we set the var to nil,
+ ;; so it does preserve the invariant that
+ ;; the var is nil until we exit the loop.
`((setq ,retvar ,exp) nil)
`(,(funcall opt exp)))
cs))
(exps
(push (funcall opt-exps exps) cs))))
- (if (eq t (caar cs))
- `(cond . ,(nreverse cs))
- `(cond ,@(nreverse cs) (t (setq ,retvar nil))))))
+ ;; No need to set `retvar' to return nil.
+ `(cond . ,(nreverse cs))))
((and `(,(or 'let 'let*) ,bindings . ,exps)
(guard
;; Note: it's OK for this `let' to shadow any
@@ -2127,8 +2143,17 @@ Like `cl-flet' but the definitions can refer to previous ones.
;; tail-called any more.
(not (memq var shadowings)))))
`(,(car exp) ,bindings . ,(funcall opt-exps exps)))
- (_
- `(progn (setq ,retvar ,exp) nil))))))
+ ((and `(condition-case ,err-var ,bodyform . ,handlers)
+ (guard (not (eq err-var var))))
+ `(condition-case ,err-var
+ ,(if (assq :success handlers)
+ bodyform
+ `(progn (setq ,retvar ,bodyform) nil))
+ . ,(mapcar (lambda (h)
+ (cons (car h) (funcall opt-exps (cdr h))))
+ handlers)))
+ ('nil nil) ;No need to set `retvar' to return nil.
+ (_ `(progn (setq ,retvar ,exp) nil))))))
(let ((optimized-body (funcall opt-exps body)))
(if (not done)
@@ -2192,6 +2217,20 @@ details.
(macroexp-progn body)
newenv)))))
+(defvar edebug-lexical-macro-ctx)
+
+(defun cl--edebug-macrolet-interposer (bindings pf &rest specs)
+ ;; (cl-assert (null (cdr bindings)))
+ (setq bindings (car bindings))
+ (let ((edebug-lexical-macro-ctx
+ (nconc (mapcar (lambda (binding)
+ (cons (car binding)
+ (when (eq 'declare (car-safe (nth 2 binding)))
+ (nth 1 (assq 'debug (cdr (nth 2 binding)))))))
+ bindings)
+ edebug-lexical-macro-ctx)))
+ (funcall pf specs)))
+
;; The following ought to have a better definition for use with newer
;; byte compilers.
;;;###autoload
@@ -2201,7 +2240,13 @@ This is like `cl-flet', but for macros instead of functions.
\(fn ((NAME ARGLIST BODY...) ...) FORM...)"
(declare (indent 1)
- (debug (cl-macrolet-expr)))
+ (debug (&interpose (&rest (&define [&name symbolp "@cl-macrolet@"]
+ [&name [] gensym] ;Make it unique!
+ cl-macro-list
+ cl-declarations-or-string
+ def-body))
+ cl--edebug-macrolet-interposer
+ cl-declarations body)))
(if (cdr bindings)
`(cl-macrolet (,(car bindings)) (cl-macrolet ,(cdr bindings) ,@body))
(if (null bindings) (macroexp-progn body)
@@ -2254,7 +2299,7 @@ of `cl-symbol-macrolet' to additionally expand symbol macros."
;; on this behavior (haven't found any yet).
;; Such code should explicitly use `cl-letf' instead, I think.
;;
- ;; (`(,(or `let `let*) . ,(or `(,bindings . ,body) dontcare))
+ ;; (`(,(or `let `let*) . ,(or `(,bindings . ,body) pcase--dontcare))
;; (let ((letf nil) (found nil) (nbs ()))
;; (dolist (binding bindings)
;; (let* ((var (if (symbolp binding) binding (car binding)))
@@ -2277,7 +2322,7 @@ of `cl-symbol-macrolet' to additionally expand symbol macros."
;; The behavior of CL made sense in a dynamically scoped
;; language, but nowadays, lexical scoping semantics is more often
;; expected.
- (`(,(or 'let 'let*) . ,(or `(,bindings . ,body) dontcare))
+ (`(,(or 'let 'let*) . ,(or `(,bindings . ,body) pcase--dontcare))
(let ((nbs ()) (found nil))
(dolist (binding bindings)
(let* ((var (if (symbolp binding) binding (car binding)))
@@ -2372,7 +2417,7 @@ by EXPANSION, and (setq NAME ...) will act like (setf EXPANSION ...).
(append bindings venv))
macroexpand-all-environment))))
(if malformed-bindings
- (macroexp--warn-and-return
+ (macroexp-warn-and-return
(format-message "Malformed `cl-symbol-macrolet' binding(s): %S"
(nreverse malformed-bindings))
expansion)
@@ -2434,7 +2479,15 @@ values. For compatibility, (cl-values A B C) is a synonym for (list A B C).
(defmacro cl-the (type form)
"Return FORM. If type-checking is enabled, assert that it is of TYPE."
(declare (indent 1) (debug (cl-type-spec form)))
- (if (not (or (not (cl--compiling-file))
+ ;; When native compiling possibly add the appropriate type hint.
+ (when (and (boundp 'byte-native-compiling)
+ byte-native-compiling)
+ (setf form
+ (cl-case type
+ (fixnum `(comp-hint-fixnum ,form))
+ (cons `(comp-hint-cons ,form))
+ (otherwise form))))
+ (if (not (or (not (macroexp-compiling-p))
(< cl--optimize-speed 3)
(= cl--optimize-safety 3)))
form
@@ -2444,6 +2497,28 @@ values. For compatibility, (cl-values A B C) is a synonym for (list A B C).
(list ',type ,temp ',form)))
,temp))))
+;;;###autoload
+(or (assq 'cl-optimize defun-declarations-alist)
+ (let ((x (list 'cl-optimize #'cl--optimize)))
+ (push x macro-declarations-alist)
+ (push x defun-declarations-alist)))
+
+(defun cl--optimize (f _args &rest qualities)
+ "Serve 'cl-optimize' in function declarations.
+Example:
+(defun foo (x)
+ (declare (cl-optimize (speed 3) (safety 0)))
+ x)"
+ ;; FIXME this should make use of `cl--declare-stack' but I suspect
+ ;; this mechanism should be reviewed first.
+ (cl-loop for (qly val) in qualities
+ do (cl-ecase qly
+ (speed
+ (setf cl--optimize-speed val)
+ (byte-run--set-speed f nil val))
+ (safety
+ (setf cl--optimize-safety val)))))
+
(defvar cl--proclaim-history t) ; for future compilers
(defvar cl--declare-stack t) ; for future compilers
@@ -2460,12 +2535,12 @@ values. For compatibility, (cl-values A B C) is a synonym for (list A B C).
'(nil byte-compile-inline-expand))
(error "%s already has a byte-optimizer, can't make it inline"
(car spec)))
- (put (car spec) 'byte-optimizer 'byte-compile-inline-expand)))
+ (put (car spec) 'byte-optimizer #'byte-compile-inline-expand)))
((eq (car-safe spec) 'notinline)
(while (setq spec (cdr spec))
(if (eq (get (car spec) 'byte-optimizer)
- 'byte-compile-inline-expand)
+ #'byte-compile-inline-expand)
(put (car spec) 'byte-optimizer nil))))
((eq (car-safe spec) 'optimize)
@@ -2501,7 +2576,7 @@ For instance
will turn off byte-compile warnings in the function.
See Info node `(cl)Declarations' for details."
- (if (cl--compiling-file)
+ (if (macroexp-compiling-p)
(while specs
(if (listp cl--declare-stack) (push (car specs) cl--declare-stack))
(cl--do-proclaim (pop specs) nil)))
@@ -2838,7 +2913,7 @@ Supported keywords for slots are:
(copier (intern (format "copy-%s" name)))
(predicate (intern (format "%s-p" name)))
(print-func nil) (print-auto nil)
- (safety (if (cl--compiling-file) cl--optimize-safety 3))
+ (safety (if (macroexp-compiling-p) cl--optimize-safety 3))
(include nil)
;; There are 4 types of structs:
;; - `vector' type: means we should use a vector, which can come
@@ -3011,7 +3086,7 @@ Supported keywords for slots are:
forms)
(when (cl-oddp (length desc))
(push
- (macroexp--warn-and-return
+ (macroexp-warn-and-return
(format "Missing value for option `%S' of slot `%s' in struct %s!"
(car (last desc)) slot name)
'nil)
@@ -3020,7 +3095,7 @@ Supported keywords for slots are:
(not (keywordp (car desc))))
(let ((kw (car defaults)))
(push
- (macroexp--warn-and-return
+ (macroexp-warn-and-return
(format " I'll take `%s' to be an option rather than a default value."
kw)
'nil)
@@ -3201,6 +3276,13 @@ STRUCT-TYPE is a symbol naming a struct type. Return `record',
(declare (side-effect-free t) (pure t))
(cl--struct-class-type (cl--struct-get-class struct-type)))
+(defun cl--alist-to-plist (alist)
+ (let ((res '()))
+ (dolist (x alist)
+ (push (car x) res)
+ (push (cdr x) res))
+ (nreverse res)))
+
(defun cl-struct-slot-info (struct-type)
"Return a list of slot names of struct STRUCT-TYPE.
Each entry is a list (SLOT-NAME . OPTS), where SLOT-NAME is a
@@ -3218,7 +3300,7 @@ slots skipped by :initial-offset may appear in the list."
,(cl--slot-descriptor-initform slot)
,@(if (not (eq (cl--slot-descriptor-type slot) t))
`(:type ,(cl--slot-descriptor-type slot)))
- ,@(cl--slot-descriptor-props slot))
+ ,@(cl--alist-to-plist (cl--slot-descriptor-props slot)))
descs)))
(nreverse descs)))
@@ -3236,29 +3318,30 @@ does not contain SLOT-NAME."
(signal 'cl-struct-unknown-slot (list struct-type slot-name))))
(defvar byte-compile-function-environment)
-(defvar byte-compile-macro-environment)
(defun cl--macroexp-fboundp (sym)
"Return non-nil if SYM will be bound when we run the code.
Of course, we really can't know that for sure, so it's just a heuristic."
(or (fboundp sym)
- (and (cl--compiling-file)
+ (and (macroexp-compiling-p)
(or (cdr (assq sym byte-compile-function-environment))
- (cdr (assq sym byte-compile-macro-environment))))))
+ (cdr (assq sym macroexpand-all-environment))))))
(pcase-dolist (`(,type . ,pred)
;; Mostly kept in alphabetical order.
'((array . arrayp)
(atom . atom)
(base-char . characterp)
+ (bignum . bignump)
(boolean . booleanp)
(bool-vector . bool-vector-p)
(buffer . bufferp)
(character . natnump)
(char-table . char-table-p)
+ (command . commandp)
(hash-table . hash-table-p)
(cons . consp)
- (fixnum . integerp)
+ (fixnum . fixnump)
(float . floatp)
(function . functionp)
(integer . integerp)
@@ -3338,7 +3421,7 @@ Of course, we really can't know that for sure, so it's just a heuristic."
"Verify that FORM is of type TYPE; signal an error if not.
STRING is an optional description of the desired type."
(declare (debug (place cl-type-spec &optional stringp)))
- (and (or (not (cl--compiling-file))
+ (and (or (not (macroexp-compiling-p))
(< cl--optimize-speed 3) (= cl--optimize-safety 3))
(macroexp-let2 macroexp-copyable-p temp form
`(progn (or (cl-typep ,temp ',type)
@@ -3358,7 +3441,7 @@ Other args STRING and ARGS... are arguments to be passed to `error'.
They are not evaluated unless the assertion fails. If STRING is
omitted, a default message listing FORM itself is used."
(declare (debug (form &rest form)))
- (and (or (not (cl--compiling-file))
+ (and (or (not (macroexp-compiling-p))
(< cl--optimize-speed 3) (= cl--optimize-safety 3))
(let ((sargs (and show-args
(delq nil (mapcar (lambda (x)
@@ -3514,6 +3597,8 @@ The type name can then be used in `cl-typecase', `cl-check-type', etc."
(cl-function (lambda (&cl-defs ('*) ,@arglist) ,@body)))))
(cl-deftype extended-char () '(and character (not base-char)))
+;; Define fixnum so `cl-typep' recognize it and the type check emitted
+;; by `cl-the' is effective.
;;; Additional functions that we can now define because we've defined
;;; `cl-defsubst' and `cl-typep'.
@@ -3538,6 +3623,14 @@ STRUCT and SLOT-NAME are symbols. INST is a structure instance."
"use `with-eval-after-load' instead." "28.1")
(run-hooks 'cl-macs-load-hook)
+;;; Pcase type pattern.
+
+;;;###autoload
+(pcase-defmacro cl-type (type)
+ "Pcase pattern that matches objects of TYPE.
+TYPE is a type descriptor as accepted by `cl-typep', which see."
+ `(pred (pcase--flip cl-typep ',type)))
+
;; Local variables:
;; generated-autoload-file: "cl-loaddefs.el"
;; End: