Add static-when, static-unless like static-if

* lisp/subr.el (static-when, static-unless): define
* doc/lispref/control.texi (Conditional Compilation): document
* etc/NEWS: mention
This commit is contained in:
Daniel Colascione 2025-03-07 21:47:56 -08:00
parent 1c313f8dce
commit 0972a54a5a
3 changed files with 45 additions and 0 deletions

View file

@ -2841,6 +2841,19 @@ Test @var{condition} at macro-expansion time. If its value is
non-@code{nil}, expand the macro to @var{then-form}, otherwise expand
it to @var{else-forms} enclosed in a @code{progn}. @var{else-forms}
may be empty.
@end defmac
@defmac static-when condition body...
Test @var{condition} at macro-expansion time. If its value is
non-@code{nil}, expand the macro to evaluate all @var{body} forms
sequentially and return the value of the last one, or @code{nil} if there
are none.
@end defmac
@defmac static-unless condition body...
Test @var{condition} at macro-expansion time. If its value is @code{nil},
expand the macro to evaluate all @var{body} forms sequentially and return
the value of the last one, or @code{nil} if there are none.
Here is an example of its use from CC Mode, which prevents a
@code{defadvice} form being compiled in newer versions of Emacs:

View file

@ -1507,6 +1507,12 @@ Previously, its argument was always evaluated using dynamic binding.
* Lisp Changes in Emacs 31.1
+++
** New macros 'static-when' and 'static-unless' implement conditional
compilation like 'static-if'.
These macros evaluate their condition at macro-expansion time and are useful
for writing code that can work across different Emacs versions.
---
** You can change the default value of 'lexical-binding'.
While the default is still the use dynamic binding dialect of ELisp

View file

@ -301,6 +301,19 @@ value of last one, or nil if there are none."
(macroexp-warn-and-return (format-message "`when' with empty body")
(list 'progn cond nil) '(empty-body when) t)))
(defmacro static-when (condition &rest body)
"A conditional compilation macro.
Evaluate CONDITION at macro-expansion time. If it is non-nil,
expand the macro to evaluate all BODY forms sequentially and return
the value of the last one, or nil if there are none."
(declare (indent 1) (debug t))
(if body
(if (eval condition lexical-binding)
(cons 'progn body)
nil)
(macroexp-warn-and-return (format-message "`static-when' with empty body")
(list 'progn nil nil) '(empty-body static-when) t)))
(defmacro unless (cond &rest body)
"If COND yields nil, do BODY, else return nil.
When COND yields nil, eval BODY forms sequentially and return
@ -311,6 +324,19 @@ value of last one, or nil if there are none."
(macroexp-warn-and-return (format-message "`unless' with empty body")
(list 'progn cond nil) '(empty-body unless) t)))
(defmacro static-unless (condition &rest body)
"A conditional compilation macro.
Evaluate CONDITION at macro-expansion time. If it is nil,
expand the macro to evaluate all BODY forms sequentially and return
the value of the last one, or nil if there are none."
(declare (indent 1) (debug t))
(if body
(if (eval condition lexical-binding)
nil
(cons 'progn body))
(macroexp-warn-and-return (format-message "`static-unless' with empty body")
(list 'progn nil nil) '(empty-body static-unless) t)))
(defsubst subr-primitive-p (object)
"Return t if OBJECT is a built-in primitive written in C.
Such objects can be functions or special forms."