Function: define-inline
define-inline is an autoloaded macro defined in inline.el.gz.
Signature
(define-inline NAME ARGS &rest BODY)
Documentation
Define an inline function NAME with arguments ARGS and body in BODY.
This is halfway between A (noinline t) in the `declaredefmacro and defun. BODY is used as a blueprint
both for the body of the function and for the body of the compiler-macro
used to generate the code inlined at each call site.
See Info node (elisp)Inline Functions for more details.
Probably introduced at or before Emacs version 25.1.
Source Code
;; Defined in /usr/src/emacs/lisp/emacs-lisp/inline.el.gz
;; (defmacro inline-if (testfun testexp then else)
;; (declare (indent 2) (debug (sexp symbolp form form)))
;; (macroexp-let2 macroexp-copyable-p testsym testexp
;; `(if (inline-const-p ,testexp)
;; (if (,testfun (inline-const-val ,testexp)) ,then ,else)
;; (inline-quote (if (,testfun ,testexp) ,(list '\, then)
;; ,(list '\, else))))))
;;;###autoload
(defmacro define-inline (name args &rest body)
"Define an inline function NAME with arguments ARGS and body in BODY.
This is halfway between `defmacro' and `defun'. BODY is used as a blueprint
both for the body of the function and for the body of the compiler-macro
used to generate the code inlined at each call site.
See Info node `(elisp)Inline Functions for more details.
A (noinline t) in the `declare' form prevents the definition of the
compiler macro. This is for the rare case in which you want to use this
macro to define a function that should not be inlined."
;; FIXME: How can this work with CL arglists?
(declare (indent defun) (debug defun) (doc-string 3)
(autoload-macro expand)) ; expand to the defun on autoload gen
(let* ((doc (if (stringp (car-safe body)) (list (pop body))))
(declares (if (eq (car-safe (car-safe body)) 'declare) (pop body)))
(cm-name (intern (format "%s--inliner" name)))
(noinline-decl (assq 'noinline declares))
(inline (not (cadr noinline-decl)))
(bodyexp (macroexp-progn body)))
(when noinline-decl
(setq declares (delq noinline-decl declares)))
;; If the function is autoloaded then when we load the .el file, the
;; `compiler-macro' property is already set (from loaddefs.el) and might
;; hence be called during the macroexpand-all calls below (if the function
;; is recursive).
;; So we disable any pre-loaded compiler-macro setting to avoid this.
(function-put name 'compiler-macro nil)
`(progn
(defun ,name ,args
,@doc
(declare ,@(when inline `((compiler-macro ,cm-name)))
,@(cdr declares))
,(macroexpand-all bodyexp
`((inline-quote . inline--dont-quote)
;; (inline-\` . inline--dont-quote)
(inline--leteval . inline--dont-leteval)
(inline--letlisteval . inline--dont-letlisteval)
(inline-const-p . inline--alwaysconst-p)
(inline-const-val . inline--alwaysconst-val)
(inline-error . inline--error)
,@macroexpand-all-environment)))
,@(when inline
`(:autoload-end
(eval-and-compile
(defun ,cm-name ,(cons 'inline--form args)
(ignore inline--form) ;In case it's not used!
(catch 'inline--just-use
,(macroexpand-all
bodyexp
`((inline-quote . inline--do-quote)
;; (inline-\` . inline--do-quote)
(inline--leteval . inline--do-leteval)
(inline--letlisteval
. inline--do-letlisteval)
(inline-const-p . inline--testconst-p)
(inline-const-val . inline--getconst-val)
(inline-error . inline--warning)
,@macroexpand-all-environment))))))))))