This has been sitting on my hard disk three-quarters cooked for a long
time.
APPROVE COMMIT
NOTE: This patch has been committed
# HG changeset patch
# User Aidan Kehoe <kehoea(a)parhasard.net>
# Date 1535899543 -3600
# Sun Sep 02 15:45:43 2018 +0100
# Node ID 9fa700dbfe93f1d05f859fc2d6fdb7377df72f8c
# Parent 8675506fce8a215642369f153edc2c88946ba743
Move #'eval-when to bytecomp.el, where it should have been long ago.
lisp/ChangeLog addition:
2018-09-02 Aidan Kehoe <kehoea(a)parhasard.net>
* bytecomp-runtime.el:
* bytecomp-runtime.el (eval-when): Move the runtime part of this
here from cl-macs.el.
* bytecomp.el:
* bytecomp.el (byte-compile-eval):
* bytecomp.el (byte-compile-eval-when-seen): New.
* bytecomp.el (byte-compile-initial-macro-environment):
Implement the bulk of #'eval-when in the compiler, where it belongs.
* cl-macs.el:
* cl-macs.el (cl-not-toplevel): Removed.
* cl-macs.el (eval-when): Removed.
* cl-macs.el (arguments): Removed.
* cl-macs.el (cl-compile-time-too): Removed.
* cl-macs.el (define-setf-method):
* cl-macs.el (defstruct):
* cl-macs.el (deftype):
* cl-macs.el (define-compiler-macro):
* cl.el (declaim):
Use the ANSI CL syntax for the stages in WHEN with #'eval-when.
No need to worry about delaying loading cl-macs.el when using that
syntax.
* cl.el (cl-random-time):
* ldap.el (:load-toplevel):
Correct the syntax of this #'eval-when call.
man/ChangeLog addition:
2018-09-02 Aidan Kehoe <kehoea(a)parhasard.net>
* cl.texi (Time of Evaluation): Use the new-style
:compile-toplevel, :load-toplevel and :execute CL keywords in the
documentation of the WHEN argument to #'eval-when.
diff -r 8675506fce8a -r 9fa700dbfe93 lisp/ChangeLog
--- a/lisp/ChangeLog Sun Aug 26 15:40:56 2018 +0100
+++ b/lisp/ChangeLog Sun Sep 02 15:45:43 2018 +0100
@@ -1,3 +1,30 @@
+2018-09-02 Aidan Kehoe <kehoea(a)parhasard.net>
+
+ * bytecomp-runtime.el:
+ * bytecomp-runtime.el (eval-when): Move the runtime part of this
+ here from cl-macs.el.
+ * bytecomp.el:
+ * bytecomp.el (byte-compile-eval):
+ * bytecomp.el (byte-compile-eval-when-seen): New.
+ * bytecomp.el (byte-compile-initial-macro-environment):
+ Implement the bulk of #'eval-when in the compiler, where it belongs.
+ * cl-macs.el:
+ * cl-macs.el (cl-not-toplevel): Removed.
+ * cl-macs.el (eval-when): Removed.
+ * cl-macs.el (arguments): Removed.
+ * cl-macs.el (cl-compile-time-too): Removed.
+ * cl-macs.el (define-setf-method):
+ * cl-macs.el (defstruct):
+ * cl-macs.el (deftype):
+ * cl-macs.el (define-compiler-macro):
+ * cl.el (declaim):
+ Use the ANSI CL syntax for the stages in WHEN with #'eval-when.
+ No need to worry about delaying loading cl-macs.el when using that
+ syntax.
+ * cl.el (cl-random-time):
+ * ldap.el (:load-toplevel):
+ Correct the syntax of this #'eval-when call.
+
2018-08-25 Aidan Kehoe <kehoea(a)parhasard.net>
* autoload.el (generate-file-autoloads):
diff -r 8675506fce8a -r 9fa700dbfe93 lisp/bytecomp-runtime.el
--- a/lisp/bytecomp-runtime.el Sun Aug 26 15:40:56 2018 +0100
+++ b/lisp/bytecomp-runtime.el Sun Sep 02 15:45:43 2018 +0100
@@ -207,6 +207,27 @@
;; Remember, it's magic.
(cons 'progn body))
+;;; The `eval-when' form. XEmacs; this has been moved from cl-macs.el.
+(defmacro eval-when (when &rest body)
+ "Control when BODY is evaluated.
+
+If :compile-toplevel is in WHEN, BODY is evaluated when compiled at
+top-level (roughly, when it is an outermost form in a file).
+If :load-toplevel is in WHEN, BODY is evaluated when loaded after
+top-level compile.
+If :execute is in WHEN, BODY is evaluated when interpreted or at
+non-top-level.
+
+The symbols `compile', `load' and `eval' are accepted as synonyms for
+:compile-toplevel, :load-toplevel and :execute, respectively.
+
+arguments: ((&rest WHEN) &body BODY)"
+ (if (set-difference when '(:compile-toplevel :load-toplevel :execute
+ compile load eval))
+ (error 'syntax-error "not a valid value for WHEN" when))
+ (if (or (member* :execute when) (member* 'eval when))
+ (cons 'progn body)))
+
;;; From Emacs 20.
(put 'eval-when-feature 'lisp-indent-hook 1)
(defmacro eval-when-feature (feature &rest body)
diff -r 8675506fce8a -r 9fa700dbfe93 lisp/bytecomp.el
--- a/lisp/bytecomp.el Sun Aug 26 15:40:56 2018 +0100
+++ b/lisp/bytecomp.el Sun Sep 02 15:45:43 2018 +0100
@@ -166,8 +166,9 @@
;;; o Forms like ((lambda ...) ...) are open-coded.
;;;
;;; o The form `eval-when-compile' is like `progn', except that the body
-;;; is evaluated at compile-time. When it appears at top-level, this
-;;; is analogous to the Common Lisp idiom (eval-when (compile) ...).
+;;; is evaluated at compile-time. When it appears at top-level, this is
+;;; analogous to the Common Lisp idiom (eval-when (:compile-toplevel)
+;;; ...).
;;; When it does not appear at top-level, it is similar to the
;;; Common Lisp #. reader macro (but not in interpreted code).
;;;
@@ -460,7 +461,7 @@
;; shouldn't be shadowed when calling #'byte-compile-eval, since
;; such code is interpreted, not compiled.
;; #### Consider giving this a docstring and a top-level value.
- (byte-compile-no-shadow '(load-time-value labels flet)))
+ (byte-compile-no-shadow '(load-time-value labels flet eval-when)))
(unwind-protect
(loop
for (sym . def) in byte-compile-macro-environment
@@ -479,6 +480,8 @@
(defvar for-effect) ; ## Kludge! This should be an arg, not a special.
+(defvar byte-compile-eval-when-seen nil)
+
(defconst byte-compile-initial-macro-environment
`((byte-compiler-options
. ,#'(lambda (&rest forms)
@@ -490,6 +493,47 @@
. ,#'(lambda (&rest body)
(byte-compile-eval (cons 'progn body))
(cons 'progn body)))
+ (eval-when
+ . ,(symbol-macrolet ((wrapper '#:eval-when-wrapper))
+ (put wrapper 'byte-compile
+ #'(lambda (form)
+ (when (member :execute (cadadr form))
+ (byte-compile-body-do-effect (cddr form)))))
+ (put wrapper 'byte-hunk-handler
+ #'(lambda (form)
+ (let ((when (cadadr form)))
+ (when (member :compile-toplevel when)
+ (let ((byte-compile-macro-environment
+ (acons wrapper
+ #'(lambda (when &rest body)
+ (if (memq :execute (cadr when))
+ (cons 'progn body)))
+ byte-compile-macro-environment)))
+ (byte-compile-eval (cons 'progn (cddr form)))))
+ (when (and (member :load-toplevel when)
+ (not byte-compile-eval-when-seen))
+ (let ((byte-compile-eval-when-seen t))
+ (mapc 'byte-compile-file-form (cddr form))))
+ ;; Do nothing if it is just :execute.
+ nil)))
+ #'(lambda (when &rest body)
+ ;; It's tempting to attempt to implement this purely with a
+ ;; byte-hunk-handler, and leave the non-toplevel expansion to
+ ;; the macro in bytecomp-runtime.el. That chokes on the output
+ ;; of defstruct as used in gnuserv.el, which is likely a bug
+ ;; in defstruct or the defsetf code used by it.
+ (and (set-difference
+ when '(:compile-toplevel :load-toplevel :execute
+ compile load eval))
+ (error 'syntax-error "not a valid value for WHEN"
when))
+ (list* wrapper
+ (list 'quote (sublis
+ ;; Make the logic within the byte compile
+ ;; handlers a little simpler:
+ '((load . :load-toplevel)
+ (compile . :compile-toplevel)
+ (eval . :execute))
+ when)) body))))
(the .
,#'(lambda (type form)
(if (cl-const-expr-p form)
diff -r 8675506fce8a -r 9fa700dbfe93 lisp/cl-macs.el
--- a/lisp/cl-macs.el Sun Aug 26 15:40:56 2018 +0100
+++ b/lisp/cl-macs.el Sun Sep 02 15:45:43 2018 +0100
@@ -573,41 +573,7 @@
(cl-do-arglist (or args '(&aux)) expr)
(nconc (list 'let* (nreverse bind-lets)) (nreverse bind-forms) body)))
-;;; The `eval-when' form.
-
-(defvar cl-not-toplevel nil)
-
-;;;###autoload
-(defmacro eval-when (when &rest body)
- "Control when BODY is evaluated.
-If `compile' is in WHEN, BODY is evaluated when compiled at top-level.
-If `load' is in WHEN, BODY is evaluated when loaded after top-level compile.
-If `eval' is in WHEN, BODY is evaluated when interpreted or at non-top-level.
-
-arguments: ((&rest WHEN) &body BODY)"
- (if (and (fboundp 'cl-compiling-file) (cl-compiling-file)
- (not cl-not-toplevel) (not (boundp 'for-effect))) ; horrible kludge
- (let ((comp (or (memq 'compile when) (memq :compile-toplevel when)))
- (cl-not-toplevel t))
- (if (or (memq 'load when) (memq :load-toplevel when))
- (if comp (cons 'progn (mapcar 'cl-compile-time-too body))
- (list* 'if nil nil body))
- (progn (if comp (eval (cons 'progn body))) nil)))
- (and (or (memq 'eval when) (memq :execute when))
- (cons 'progn body))))
-
-(defun cl-compile-time-too (form)
- (or (and (symbolp (car-safe form)) (get (car-safe form) 'byte-hunk-handler))
- (setq form (macroexpand
- form (cons '(eval-when) byte-compile-macro-environment))))
- (cond ((eq (car-safe form) 'progn)
- (cons 'progn (mapcar 'cl-compile-time-too (cdr form))))
- ((eq (car-safe form) 'eval-when)
- (let ((when (nth 1 form)))
- (if (or (memq 'eval when) (memq :execute when))
- (list* 'eval-when (cons 'compile when) (cddr form))
- form)))
- (t (eval form) form)))
+;;; XEmacs; #'eval-when has been moved to bytecomp-runtime.el and bytecomp.el.
;;; Conditional control structures.
@@ -1983,7 +1949,7 @@
return a list of five elements: a temporary-variables list, a value-forms
list, a store-variables list (of length one), a store-form, and an access-
form. See `defsetf' for a simpler way to define most setf-methods."
- (append '(eval-when (compile load eval))
+ (append '(eval-when (:compile-toplevel :load-toplevel :execute))
(if (stringp (car body))
(list (list 'put (list 'quote name) '(quote setf-documentation)
(pop body))))
@@ -2961,7 +2927,7 @@
(list 'and pred-form print-func)))
'custom-print-functions) forms))
(push (list 'setq tag-symbol (list 'list (list 'quote tag))) forms)
- (push (list* 'eval-when '(compile load eval)
+ (push (list* 'eval-when '(:compile-toplevel :load-toplevel :execute)
(list 'put (list 'quote name) '(quote cl-struct-slots)
(list 'quote descs))
(list 'put (list 'quote name) '(quote cl-struct-type)
@@ -3008,7 +2974,7 @@
(defmacro deftype (name arglist &rest body)
"Define NAME as a new data type.
The type name can then be used in `typecase', `check-type', etc."
- (list 'eval-when '(compile load eval)
+ (list 'eval-when '(:compile-toplevel :load-toplevel :execute)
(cl-transform-function-property
name 'cl-deftype-handler (cons (list* '&cl-defs ''('*) arglist)
body))))
@@ -3131,7 +3097,7 @@
(let ((p (if (listp args) args (list '&rest args))) (res nil))
(while (consp p) (push (pop p) res))
(setq args (nconc (nreverse res) (and p (list '&rest p)))))
- (list 'eval-when '(compile load eval)
+ (list 'eval-when '(:compile-toplevel :load-toplevel :execute)
(cl-transform-function-property
func 'cl-compiler-macro
(cons (if (memq '&whole args) (delete* '&whole args)
diff -r 8675506fce8a -r 9fa700dbfe93 lisp/cl.el
--- a/lisp/cl.el Sun Aug 26 15:40:56 2018 +0100
+++ b/lisp/cl.el Sun Sep 02 15:45:43 2018 +0100
@@ -237,10 +237,8 @@
nil)
(defmacro declaim (&rest specs)
- (let ((body (mapcar (function (lambda (x) (list 'proclaim (list 'quote x))))
- specs)))
- (if (cl-compiling-file) (list* 'eval-when '(compile load eval) body)
- (cons 'progn body)))) ; avoid loading cl-macs.el for eval-when
+ (list* 'eval-when '(:compile-toplevel :load-toplevel :execute)
+ (mapcar #'(lambda (x) `(proclaim ',x)) specs)))
;;; Symbols.
diff -r 8675506fce8a -r 9fa700dbfe93 lisp/ldap.el
--- a/lisp/ldap.el Sun Aug 26 15:40:56 2018 +0100
+++ b/lisp/ldap.el Sun Sep 02 15:45:43 2018 +0100
@@ -36,7 +36,7 @@
(globally-declare-fboundp '(ldapp ldap-open ldap-close ldap-add ldap-modify
ldap-delete))
-(eval-when '(load)
+(eval-when (:load-toplevel)
(if (not (fboundp 'ldap-open))
(error "No LDAP support compiled in this XEmacs")))
diff -r 8675506fce8a -r 9fa700dbfe93 man/ChangeLog
--- a/man/ChangeLog Sun Aug 26 15:40:56 2018 +0100
+++ b/man/ChangeLog Sun Sep 02 15:45:43 2018 +0100
@@ -1,3 +1,9 @@
+2018-09-02 Aidan Kehoe <kehoea(a)parhasard.net>
+
+ * cl.texi (Time of Evaluation): Use the new-style
+ :compile-toplevel, :load-toplevel and :execute CL keywords in the
+ documentation of the WHEN argument to #'eval-when.
+
2018-08-15 Aidan Kehoe <kehoea(a)parhasard.net>
* lispref/markers.texi (Information from Markers):
diff -r 8675506fce8a -r 9fa700dbfe93 man/cl.texi
--- a/man/cl.texi Sun Aug 26 15:40:56 2018 +0100
+++ b/man/cl.texi Sun Sep 02 15:45:43 2018 +0100
@@ -588,9 +588,9 @@
@defmac eval-when (situations...) forms...
This form controls when the body @var{forms} are evaluated.
The @var{situations} list may contain any set of the symbols
-@code{compile}, @code{load}, and @code{eval} (or their long-winded
-ANSI equivalents, @code{:compile-toplevel}, @code{:load-toplevel},
-and @code{:execute}).
+@code{:compile-toplevel}, @code{:load-toplevel}, and @code{:execute},
+or their shorter, deprecated equivalents, @code{compile}, @code{load},
+and @code{eval}.
The @code{eval-when} form is handled differently depending on
whether or not it is being compiled as a top-level form.
@@ -600,15 +600,16 @@
top level of the file or inside a top-level @code{progn}.
For compiled top-level @code{eval-when}s, the body @var{forms} are
-executed at compile-time if @code{compile} is in the @var{situations}
-list, and the @var{forms} are written out to the file (to be executed
-at load-time) if @code{load} is in the @var{situations} list.
-
-For non-compiled-top-level forms, only the @code{eval} situation is
+executed at compile-time if @code{:compile-toplevel} is in the
+@var{situations} list, and the @var{forms} are written out to the file
+(to be executed at load-time) if @code{:load-toplevel} is in the
+@var{situations} list.
+
+For non-compiled-top-level forms, only the @code{:execute} situation is
relevant. (This includes forms executed by the interpreter, forms
compiled with @code{byte-compile} rather than @code{byte-compile-file},
and non-top-level forms.) The @code{eval-when} acts like a
-@code{progn} if @code{eval} is specified, and like @code{nil}
+@code{progn} if @code{:execute} is specified, and like @code{nil}
(ignoring the body @var{forms}) if not.
The rules become more subtle when @code{eval-when}s are nested;
@@ -619,40 +620,40 @@
@example
;; Top-level forms in foo.el:
-(eval-when (compile) (setq foo1 'bar))
-(eval-when (load) (setq foo2 'bar))
-(eval-when (compile load) (setq foo3 'bar))
-(eval-when (eval) (setq foo4 'bar))
-(eval-when (eval compile) (setq foo5 'bar))
-(eval-when (eval load) (setq foo6 'bar))
-(eval-when (eval compile load) (setq foo7 'bar))
+(eval-when (:compile-toplevel) (setq foo1 'bar))
+(eval-when (:load-toplevel) (setq foo2 'bar))
+(eval-when (:compile-toplevel :load-toplevel) (setq foo3 'bar))
+(eval-when (:execute) (setq foo4 'bar))
+(eval-when (:execute :compile-toplevel) (setq foo5 'bar))
+(eval-when (:execute :load-toplevel) (setq foo6 'bar))
+(eval-when (:execute :compile-toplevel :load-toplevel) (setq foo7 'bar))
@end example
When @file{foo.el} is compiled, these variables will be set during
the compilation itself:
@example
-foo1 foo3 foo5 foo7 ; `compile'
+foo1 foo3 foo5 foo7 ; `:compile-toplevel'
@end example
When @file{foo.elc} is loaded, these variables will be set:
@example
-foo2 foo3 foo6 foo7 ; `load'
+foo2 foo3 foo6 foo7 ; `:load-toplevel'
@end example
And if @file{foo.el} is loaded uncompiled, these variables will
be set:
@example
-foo4 foo5 foo6 foo7 ; `eval'
+foo4 foo5 foo6 foo7 ; `:execute
@end example
If these seven @code{eval-when}s had been, say, inside a @code{defun},
then the first three would have been equivalent to @code{nil} and the
last four would have been equivalent to the corresponding @code{setq}s.
-Note that @code{(eval-when (load eval) @dots{})} is equivalent
+Note that @code{(eval-when (:load-toplevel :execute) @dots{})} is equivalent
to @code{(progn @dots{})} in all contexts. The compiler treats
certain top-level forms, like @code{defmacro} (sort-of) and
@code{require}, as if they were wrapped in @code{(eval-when
--
‘As I sat looking up at the Guinness ad, I could never figure out /
How your man stayed up on the surfboard after forty pints of stout’
(C. Moore)