Function: cl-define-compiler-macro

cl-define-compiler-macro is an autoloaded macro defined in cl-macs.el.gz.

Signature

(cl-define-compiler-macro FUNC ARGS &rest BODY)

Documentation

Define a compiler-only macro.

This is like defmacro, but macro expansion occurs only if the call to FUNC is compiled (i.e., not interpreted). Compiler macros should be used for optimizing the way calls to FUNC are compiled; the form returned by BODY should do the same thing as a call to the normal function called FUNC, though possibly more efficiently. Note that, like regular macros, compiler macros are expanded repeatedly until no further expansions are possible. Unlike regular macros, BODY can decide to "punt" and leave the original function call alone by declaring an initial &whole foo parameter and then returning foo.

View in manual

Aliases

define-compiler-macro (obsolete since 27.1)

Source Code

;; Defined in /usr/src/emacs/lisp/emacs-lisp/cl-macs.el.gz
;;; Compiler macros.

;;;###autoload
(defmacro cl-define-compiler-macro (func args &rest body)
  "Define a compiler-only macro.
This is like `defmacro', but macro expansion occurs only if the call to
FUNC is compiled (i.e., not interpreted).  Compiler macros should be used
for optimizing the way calls to FUNC are compiled; the form returned by
BODY should do the same thing as a call to the normal function called
FUNC, though possibly more efficiently.  Note that, like regular macros,
compiler macros are expanded repeatedly until no further expansions are
possible.  Unlike regular macros, BODY can decide to \"punt\" and leave the
original function call alone by declaring an initial `&whole foo' parameter
and then returning foo."
  ;; Like `cl-defmacro', but with the `&whole' special case.
  (declare (debug (&define [&name symbolp "@cl-compiler-macro"]
                           cl-macro-list
                           cl-declarations-or-string def-body))
           (indent 2))
  (let ((p args) (res nil))
    (while (consp p) (push (pop p) res))
    (setq args (nconc (nreverse res) (and p (list '&rest p)))))
  ;; FIXME: The code in bytecomp mishandles top-level expressions that define
  ;; uninterned functions.  E.g. it would generate code like:
  ;;    (defalias '#1=#:foo--cmacro #[514 ...])
  ;;    (put 'foo 'compiler-macro '#:foo--cmacro)
  ;; So we circumvent this by using an interned name.
  (let ((fname (intern (concat (symbol-name func) "--cmacro"))))
    `(eval-and-compile
       ;; Name the compiler-macro function, so that `symbol-file' can find it.
       (cl-defun ,fname ,(if (memq '&whole args) (delq '&whole args)
                           (cons '_cl-whole-arg args))
         ,@body)
       (define-symbol-prop ',func 'compiler-macro #',fname))))