aboutsummaryrefslogtreecommitdiffstats
path: root/lisp
diff options
context:
space:
mode:
authorJoakim Verona2015-01-15 14:54:25 +0100
committerJoakim Verona2015-01-15 14:54:25 +0100
commit0298a2c6a10bc3b79cb2f45a1961dd7ac6da4e6d (patch)
tree6c7ea25ac137f5764d931e841598a3c1ea434ab0 /lisp
parenta1124bc117e41019de49c82d13d1a72a50df977d (diff)
parent0e97c44c3699c4606a04f589828acdf9c03f447e (diff)
downloademacs-0298a2c6a10bc3b79cb2f45a1961dd7ac6da4e6d.tar.gz
emacs-0298a2c6a10bc3b79cb2f45a1961dd7ac6da4e6d.zip
merge master
Diffstat (limited to 'lisp')
-rw-r--r--lisp/ChangeLog124
-rw-r--r--lisp/Makefile.in30
-rw-r--r--lisp/emacs-lisp/cl-generic.el607
-rw-r--r--lisp/emacs-lisp/cl-macs.el52
-rw-r--r--lisp/emacs-lisp/eieio-core.el28
-rw-r--r--lisp/files.el5
-rw-r--r--lisp/frame.el58
-rw-r--r--lisp/menu-bar.el3
-rw-r--r--lisp/net/eww.el38
-rw-r--r--lisp/progmodes/cc-bytecomp.el72
-rw-r--r--lisp/progmodes/cc-defs.el43
-rw-r--r--lisp/progmodes/cc-langs.el5
-rw-r--r--lisp/progmodes/xref.el1
13 files changed, 942 insertions, 124 deletions
diff --git a/lisp/ChangeLog b/lisp/ChangeLog
index 674b26716a4..b7a38af9609 100644
--- a/lisp/ChangeLog
+++ b/lisp/ChangeLog
@@ -1,3 +1,107 @@
12015-01-15 Stefan Monnier <monnier@iro.umontreal.ca>
2
3 * emacs-lisp/eieio-core.el: Provide support for cl-generic.
4 (eieio--generic-tagcode): New function.
5 (cl-generic-tagcode-function): Use it.
6 (eieio--generic-tag-types): New function.
7 (cl-generic-tag-types-function): Use it.
8 (eieio-object-p): Tighten up the test.
9
10 * emacs-lisp/cl-generic.el (cl-generic-define-method): Fix paren typo.
11
122015-01-14 Stefan Monnier <monnier@iro.umontreal.ca>
13
14 * emacs-lisp/cl-generic.el: New file.
15
16 * emacs-lisp/cl-macs.el (cl-flet): Allow (FUN EXP) forms.
17 (cl-load-time-value, cl-labels): Use closures rather than
18 backquoted lambdas.
19 (cl-macrolet): Use `eval' to create the function value, and support CL
20 style arguments in for the defined macros.
21
222015-01-14 Stefan Monnier <monnier@iro.umontreal.ca>
23
24 * net/eww.el: Use lexical-binding.
25 (eww-links-at-point): Remove unused arg.
26 (eww-mode-map): Inherit from special-mode-map.
27 (eww-mode): Derive from special-mode. Don't use `setq' on a hook.
28
292015-01-13 Alan Mackenzie <acm@muc.de>
30
31 Allow compilation during loading of Modes derived from a CC Mode mode.
32 Fixes debbugs#19206.
33
34 * progmodes/cc-bytecomp.el (cc-bytecomp-compiling-or-loading):
35 New function which walks the stack to discover whether we're compiling
36 or loading.
37 (cc-bytecomp-is-compiling): Reformulate, and move towards
38 beginning.
39 (cc-bytecomp-is-loading): New defsubst.
40 (cc-bytecomp-setup-environment, cc-bytecomp-restore-environment):
41 Use the above defsubsts.
42 (cc-require-when-compile, cc-bytecomp-defvar)
43 (cc-bytecomp-defun): Simplify conditionals.
44
45 * progmodes/cc-defs.el (cc-bytecomp-compiling-or-loading):
46 "Borrow" this function from cc-bytecomp.el.
47 (c-get-current-file): Reformulate using the above.
48 (c-lang-defconst): Prevent duplicate entries of file names in a
49 symbol's 'source property.
50 (c-lang-const): Use cc-bytecomp-is-compiling.
51
52 * progmodes/cc-langs.el (c-make-init-lang-vars-fun):
53 Use cc-bytecomp-is-compiling.
54
552015-01-13 Stefan Monnier <monnier@iro.umontreal.ca>
56
57 * emacs-lisp/eieio-core.el (eieio-defclass): Fix call to `defclass'
58 (bug#19552).
59
602015-01-13 Dmitry Gutov <dgutov@yandex.ru>
61
62 * menu-bar.el (menu-bar-goto-menu): Before calling
63 `xref-marker-stack-empty-p', first check that `xref' is loaded.
64 (Bug#19554)
65
662015-01-12 Martin Rudalics <rudalics@gmx.at>
67
68 * progmodes/xref.el (xref-marker-stack-empty-p): Add autoload
69 cookie (Bug#19554).
70
71 * frame.el (frame-notice-user-settings): Remove code dealing with
72 frame-initial-frame-tool-bar-height. Turn off `tool-bar-mode'
73 only if `window-system-frame-alist' or `default-frame-alist' ask
74 for it.
75 (make-frame): Update frame-adjust-size-history if needed.
76
772015-01-12 Paul Eggert <eggert@cs.ucla.edu>
78
79 Have 'make' output better GEN names
80 * Makefile.in (PHONY_EXTRAS): New macro.
81 (.PHONY): Depend on it, and on $(lisp)/loaddefs.el, so that the
82 relevant files' time stamps are ignored.
83 (custom-deps, $(lisp)/cus-load.el, finder-data)
84 ($(lisp)/finder-inf.el): Use PHONY_EXTRAS.
85 (custom-deps, $(lisp)/cus-load.el, finder-data)
86 ($(lisp)/finder-inf.el, autoloads, $(lisp)/loaddefs.el)
87 ($(lisp)/subdirs.el, update-subdirs):
88 Output more-accurate destination names with GEN.
89
90 Say "ELC foo.elc" instead of "GEN foo.elc"
91 * Makefile.in (AM_V_ELC, am__v_ELC_, am__v_ELC_0, am__v_ELC_1):
92 New macros.
93 ($(THEFILE)c, .el.elc): Use them.
94
952015-01-11 Michael Albinus <michael.albinus@gmx.de>
96
97 * files.el (directory-files-recursively): Do not include
98 superfluous remote file names.
99
1002015-01-11 Lars Magne Ingebrigtsen <larsi@gnus.org>
101
102 * net/eww.el (eww): Interpret anything that looks like a protocol
103 designator as a full URL.
104
12015-01-10 Lars Magne Ingebrigtsen <larsi@gnus.org> 1052015-01-10 Lars Magne Ingebrigtsen <larsi@gnus.org>
2 106
3 * net/shr.el (shr-urlify): Don't bother the user about 107 * net/shr.el (shr-urlify): Don't bother the user about
@@ -363,8 +467,8 @@
363 to `pre-command-hook'. 467 to `pre-command-hook'.
364 (xref--xref-buffer-mode-map): Don't remap `next-line' and 468 (xref--xref-buffer-mode-map): Don't remap `next-line' and
365 `previous-line'. Additionally bind `xref-next-line' and 469 `previous-line'. Additionally bind `xref-next-line' and
366 `xref-prev-line' to `n' and `p' respectively. Bind 470 `xref-prev-line' to `n' and `p' respectively.
367 `xref-show-location-at-point' to `C-o'. 471 Bind `xref-show-location-at-point' to `C-o'.
368 472
3692015-01-01 Eli Zaretskii <eliz@gnu.org> 4732015-01-01 Eli Zaretskii <eliz@gnu.org>
370 474
@@ -553,15 +657,15 @@
553 Add argument MSG to display user-friendly message when no process 657 Add argument MSG to display user-friendly message when no process
554 is running. 658 is running.
555 (python-shell-switch-to-shell): Call pop-to-buffer with NORECORD. 659 (python-shell-switch-to-shell): Call pop-to-buffer with NORECORD.
556 (python-shell-make-comint): Rename argument SHOW from POP. Use 660 (python-shell-make-comint): Rename argument SHOW from POP.
557 display-buffer instead of pop-to-buffer. 661 Use display-buffer instead of pop-to-buffer.
558 (run-python): Doc fix. Return process. 662 (run-python): Doc fix. Return process.
559 (python-shell-get-or-create-process): Make obsolete. 663 (python-shell-get-or-create-process): Make obsolete.
560 664
5612014-12-27 Fabián Ezequiel Gallina <fgallina@gnu.org> 6652014-12-27 Fabián Ezequiel Gallina <fgallina@gnu.org>
562 666
563 * progmodes/python.el (python-shell-buffer-substring): Handle 667 * progmodes/python.el (python-shell-buffer-substring):
564 cornercase when region sent starts at point-min. 668 Handle cornercase when region sent starts at point-min.
565 669
5662014-12-27 Eli Zaretskii <eliz@gnu.org> 6702014-12-27 Eli Zaretskii <eliz@gnu.org>
567 671
@@ -733,8 +837,8 @@
733 837
7342014-12-25 Filipp Gunbin <fgunbin@fastmail.fm> 8382014-12-25 Filipp Gunbin <fgunbin@fastmail.fm>
735 839
736 * dired-aux.el (dired-maybe-insert-subdir): Make 840 * dired-aux.el (dired-maybe-insert-subdir):
737 dired-maybe-insert-subdir always skip trivial files. 841 Make dired-maybe-insert-subdir always skip trivial files.
738 842
7392014-12-25 Helmut Eller <eller.helmut@gmail.com> 8432014-12-25 Helmut Eller <eller.helmut@gmail.com>
740 Dmitry Gutov <dgutov@yandex.ru> 844 Dmitry Gutov <dgutov@yandex.ru>
@@ -779,8 +883,8 @@
779 883
780 * window.el (mouse-autoselect-window-position-1): New variable. 884 * window.el (mouse-autoselect-window-position-1): New variable.
781 (mouse-autoselect-window-cancel) 885 (mouse-autoselect-window-cancel)
782 (mouse-autoselect-window-select, handle-select-window): With 886 (mouse-autoselect-window-select, handle-select-window):
783 delayed autoselection select window only if mouse moves after 887 With delayed autoselection select window only if mouse moves after
784 selecting its frame. 888 selecting its frame.
785 889
7862014-12-24 Michael Albinus <michael.albinus@gmx.de> 8902014-12-24 Michael Albinus <michael.albinus@gmx.de>
diff --git a/lisp/Makefile.in b/lisp/Makefile.in
index 565ca77de3b..7bf53861e71 100644
--- a/lisp/Makefile.in
+++ b/lisp/Makefile.in
@@ -31,6 +31,11 @@ XARGS_LIMIT = @XARGS_LIMIT@
31# 'make' verbosity. 31# 'make' verbosity.
32AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ 32AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
33 33
34AM_V_ELC = $(am__v_ELC_@AM_V@)
35am__v_ELC_ = $(am__v_ELC_@AM_DEFAULT_V@)
36am__v_ELC_0 = @echo " ELC " $@;
37am__v_ELC_1 =
38
34AM_V_GEN = $(am__v_GEN_@AM_V@) 39AM_V_GEN = $(am__v_GEN_@AM_V@)
35am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) 40am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@)
36am__v_GEN_0 = @echo " GEN " $@; 41am__v_GEN_0 = @echo " GEN " $@;
@@ -145,7 +150,8 @@ setwins_for_subdirs=for file in `find ${srcdir} -type d -print`; do \
145# we add them here to make sure they get built. 150# we add them here to make sure they get built.
146all: compile-main $(lisp)/cus-load.el $(lisp)/finder-inf.el 151all: compile-main $(lisp)/cus-load.el $(lisp)/finder-inf.el
147 152
148.PHONY: all custom-deps finder-data autoloads update-subdirs 153PHONY_EXTRAS =
154.PHONY: all custom-deps finder-data autoloads update-subdirs $(PHONY_EXTRAS)
149 155
150# custom-deps and finder-data both used to scan _all_ the *.el files. 156# custom-deps and finder-data both used to scan _all_ the *.el files.
151# This could lead to problems in parallel builds if automatically 157# This could lead to problems in parallel builds if automatically
@@ -161,18 +167,19 @@ all: compile-main $(lisp)/cus-load.el $(lisp)/finder-inf.el
161# Nowadays these commands don't scan automatically generated files, 167# Nowadays these commands don't scan automatically generated files,
162# since they will never contain any useful information 168# since they will never contain any useful information
163# (see finder-no-scan-regexp and custom-dependencies-no-scan-regexp). 169# (see finder-no-scan-regexp and custom-dependencies-no-scan-regexp).
164$(lisp)/cus-load.el:
165 $(MAKE) custom-deps
166custom-deps: 170custom-deps:
171 $(AM_V_at)$(MAKE) PHONY_EXTRAS=$(lisp)/cus-load.el $(lisp)/cus-load.el
172$(lisp)/cus-load.el:
167 $(AM_V_GEN)$(setwins_almost); \ 173 $(AM_V_GEN)$(setwins_almost); \
168 echo Directories: $$wins; \ 174 echo Directories: $$wins; \
169 $(emacs) -l cus-dep \ 175 $(emacs) -l cus-dep \
170 --eval '(setq generated-custom-dependencies-file (unmsys--file-name "$(srcdir)/cus-load.el"))' \ 176 --eval '(setq generated-custom-dependencies-file (unmsys--file-name "$(srcdir)/cus-load.el"))' \
171 -f custom-make-dependencies $$wins 177 -f custom-make-dependencies $$wins
172 178
173$(lisp)/finder-inf.el:
174 $(MAKE) finder-data
175finder-data: 179finder-data:
180 $(AM_V_at)$(MAKE) PHONY_EXTRAS=$(lisp)/finder-inf.el \
181 $(lisp)/finder-inf.el
182$(lisp)/finder-inf.el:
176 $(AM_V_GEN)$(setwins_finder); \ 183 $(AM_V_GEN)$(setwins_finder); \
177 echo Directories: $$wins; \ 184 echo Directories: $$wins; \
178 $(emacs) -l finder \ 185 $(emacs) -l finder \
@@ -185,21 +192,22 @@ finder-data:
185# Note that we set no-update-autoloads in _generated_ leim files. 192# Note that we set no-update-autoloads in _generated_ leim files.
186# If you want to allow autoloads in such files, remove that, 193# If you want to allow autoloads in such files, remove that,
187# and make this depend on leim. 194# and make this depend on leim.
188autoloads: $(LOADDEFS) 195autoloads .PHONY: $(lisp)/loaddefs.el
196$(lisp)/loaddefs.el: $(LOADDEFS)
189 $(AM_V_GEN)$(setwins_almost); \ 197 $(AM_V_GEN)$(setwins_almost); \
190 echo Directories: $$wins; \ 198 echo Directories: $$wins; \
191 $(emacs) -l autoload \ 199 $(emacs) -l autoload \
192 --eval '(setq autoload-ensure-writable t)' \ 200 --eval '(setq autoload-ensure-writable t)' \
193 --eval '(setq autoload-builtin-package-versions t)' \ 201 --eval '(setq autoload-builtin-package-versions t)' \
194 --eval '(setq generated-autoload-file (expand-file-name (unmsys--file-name "$(srcdir)/loaddefs.el")))' \ 202 --eval '(setq generated-autoload-file (expand-file-name (unmsys--file-name "$@")))' \
195 -f batch-update-autoloads $$wins 203 -f batch-update-autoloads $$wins
196 204
197# This is required by the bootstrap-emacs target in ../src/Makefile, so 205# This is required by the bootstrap-emacs target in ../src/Makefile, so
198# we know that if we have an emacs executable, we also have a subdirs.el. 206# we know that if we have an emacs executable, we also have a subdirs.el.
199$(lisp)/subdirs.el: 207$(lisp)/subdirs.el:
200 $(MAKE) update-subdirs 208 $(AM_V_GEN)$(MAKE) update-subdirs
201update-subdirs: 209update-subdirs:
202 $(AM_V_GEN)$(setwins_for_subdirs); \ 210 $(AM_V_at)$(setwins_for_subdirs); \
203 for file in $$wins; do \ 211 for file in $$wins; do \
204 $(srcdir)/../build-aux/update-subdirs $$file; \ 212 $(srcdir)/../build-aux/update-subdirs $$file; \
205 done; 213 done;
@@ -260,7 +268,7 @@ TAGS: $(lisptagsfiles1) $(lisptagsfiles2) $(lisptagsfiles3) $(lisptagsfiles4)
260THEFILE = no-such-file 268THEFILE = no-such-file
261.PHONY: $(THEFILE)c 269.PHONY: $(THEFILE)c
262$(THEFILE)c: 270$(THEFILE)c:
263 $(AM_V_GEN)$(emacs) $(BYTE_COMPILE_FLAGS) \ 271 $(AM_V_ELC)$(emacs) $(BYTE_COMPILE_FLAGS) \
264 -l bytecomp -f byte-compile-refresh-preloaded \ 272 -l bytecomp -f byte-compile-refresh-preloaded \
265 -f batch-byte-compile $(THEFILE) 273 -f batch-byte-compile $(THEFILE)
266 274
@@ -276,7 +284,7 @@ $(THEFILE)c:
276# An old-fashioned suffix rule, which, according to the GNU Make manual, 284# An old-fashioned suffix rule, which, according to the GNU Make manual,
277# cannot have prerequisites. 285# cannot have prerequisites.
278.el.elc: 286.el.elc:
279 $(AM_V_GEN)$(emacs) $(BYTE_COMPILE_FLAGS) -f batch-byte-compile $< 287 $(AM_V_ELC)$(emacs) $(BYTE_COMPILE_FLAGS) -f batch-byte-compile $<
280 288
281.PHONY: compile-first compile-main compile compile-always 289.PHONY: compile-first compile-main compile compile-always
282 290
diff --git a/lisp/emacs-lisp/cl-generic.el b/lisp/emacs-lisp/cl-generic.el
new file mode 100644
index 00000000000..41a419a3c4a
--- /dev/null
+++ b/lisp/emacs-lisp/cl-generic.el
@@ -0,0 +1,607 @@
1;;; cl-generic.el --- CLOS-style generic functions for Elisp -*- lexical-binding: t; -*-
2
3;; Copyright (C) 2015 Free Software Foundation, Inc.
4
5;; Author: Stefan Monnier <monnier@iro.umontreal.ca>
6
7;; This file is part of GNU Emacs.
8
9;; GNU Emacs is free software: you can redistribute it and/or modify
10;; it under the terms of the GNU General Public License as published by
11;; the Free Software Foundation, either version 3 of the License, or
12;; (at your option) any later version.
13
14;; GNU Emacs is distributed in the hope that it will be useful,
15;; but WITHOUT ANY WARRANTY; without even the implied warranty of
16;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17;; GNU General Public License for more details.
18
19;; You should have received a copy of the GNU General Public License
20;; along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>.
21
22;;; Commentary:
23
24;; This implements the most of CLOS's multiple-dispatch generic functions.
25;; To use it you need either (require 'cl-generic) or (require 'cl-lib).
26;; The main entry points are: `cl-defgeneric' and `cl-defmethod'.
27
28;; Missing elements:
29;; - We don't support next-method-p, make-method, call-method,
30;; define-method-combination.
31;; - Method and generic function objects: CLOS defines methods as objects
32;; (same for generic functions), whereas we don't offer such an abstraction.
33;; - `no-next-method' should receive the "calling method" object, but since we
34;; don't have such a thing, we pass nil instead.
35;; - In defgeneric we don't support the options:
36;; declare, :method-combination, :generic-function-class, :method-class,
37;; :method.
38;; Added elements:
39;; - We support aliases to generic functions.
40;; - The kind of thing on which to dispatch can be extended.
41;; There is support in this file for (eql <val>) dispatch as well as dispatch
42;; on the type of CL structs, and eieio-core.el adds support for EIEIO
43;; defclass objects.
44
45;;; Code:
46
47;; Note: For generic functions that dispatch on several arguments (i.e. those
48;; which use the multiple-dispatch feature), we always use the same "tagcodes"
49;; and the same set of arguments on which to dispatch. This works, but is
50;; often suboptimal since after one dispatch, the remaining dispatches can
51;; usually be simplified, or even completely skipped.
52
53(eval-when-compile (require 'cl-lib))
54(eval-when-compile (require 'pcase))
55
56(defvar cl-generic-tagcode-function
57 (lambda (type _name)
58 (if (eq type t) '(0 . 'cl--generic-type)
59 (error "Unknown specializer %S" type)))
60 "Function to get the Elisp code to extract the tag on which we dispatch.
61Takes a \"parameter-specializer-name\" and a variable name, and returns
62a pair (PRIORITY . CODE) where CODE is an Elisp expression that should be
63used to extract the \"tag\" (from the object held in the named variable)
64that should uniquely determine if we have a match
65\(i.e. the \"tag\" is the value that will be used to dispatch to the proper
66method(s)).
67Such \"tagcodes\" will be or'd together.
68PRIORITY is an integer from 0 to 100 which is used to sort the tagcodes
69in the `or'. The higher the priority, the more specific the tag should be.
70More specifically, if PRIORITY is N and we have two objects X and Y
71whose tag (according to TAGCODE) is `eql', then it should be the case
72that for all other (PRIORITY . TAGCODE) where PRIORITY ≤ N, then
73\(eval TAGCODE) for X is `eql' to (eval TAGCODE) for Y.")
74
75(defvar cl-generic-tag-types-function
76 (lambda (tag) (if (eq tag 'cl--generic-type) '(t)))
77 "Function to get the list of types that a given \"tag\" matches.
78They should be sorted from most specific to least specific.")
79
80(cl-defstruct (cl--generic
81 (:constructor nil)
82 (:constructor cl--generic-make
83 (name &optional dispatches method-table))
84 (:predicate nil))
85 (name nil :read-only t) ;Pointer back to the symbol.
86 ;; `dispatches' holds a list of (ARGNUM . TAGCODES) where ARGNUM is the index
87 ;; of the corresponding argument and TAGCODES is a list of (PRIORITY . EXP)
88 ;; where the EXPs are expressions (to be `or'd together) to compute the tag
89 ;; on which to dispatch and PRIORITY is the priority of each expression to
90 ;; decide in which order to sort them.
91 ;; The most important dispatch is last in the list (and the least is first).
92 dispatches
93 ;; `method-table' is a list of
94 ;; ((SPECIALIZERS . QUALIFIER) USES-CNM . FUNCTION), where
95 ;; USES-CNM is a boolean indicating if FUNCTION calls `cl-call-next-method'
96 ;; (and hence expects an extra argument holding the next-method).
97 method-table)
98
99(defmacro cl--generic (name)
100 `(get ,name 'cl--generic))
101
102(defun cl-generic-ensure-function (name)
103 (let (generic
104 (origname name))
105 (while (and (null (setq generic (cl--generic name)))
106 (fboundp name)
107 (symbolp (symbol-function name)))
108 (setq name (symbol-function name)))
109 (unless (or (not (fboundp name))
110 (and (functionp name) generic))
111 (error "%s is already defined as something else than a generic function"
112 origname))
113 (if generic
114 (cl-assert (eq name (cl--generic-name generic)))
115 (setf (cl--generic name) (setq generic (cl--generic-make name)))
116 (defalias name (cl--generic-make-function generic)))
117 generic))
118
119(defun cl--generic-setf-rewrite (name)
120 (let ((setter (intern (format "cl-generic-setter--%s" name))))
121 (cons setter
122 `(eval-and-compile
123 (unless (eq ',setter (get ',name 'cl-generic-setter))
124 ;; (when (get ',name 'gv-expander)
125 ;; (error "gv-expander conflicts with (setf %S)" ',name))
126 (setf (get ',name 'cl-generic-setter) ',setter)
127 (gv-define-setter ,name (val &rest args)
128 (cons ',setter (cons val args))))))))
129
130;;;###autoload
131(defmacro cl-defgeneric (name args &rest options-and-methods)
132 "Create a generic function NAME.
133DOC-STRING is the base documentation for this class. A generic
134function has no body, as its purpose is to decide which method body
135is appropriate to use. Specific methods are defined with `defmethod'.
136With this implementation the ARGS are currently ignored.
137OPTIONS-AND-METHODS is currently only used to specify the docstring,
138via (:documentation DOCSTRING)."
139 (declare (indent 2) (doc-string 3))
140 (let* ((docprop (assq :documentation options-and-methods))
141 (doc (cond ((stringp (car-safe options-and-methods))
142 (pop options-and-methods))
143 (docprop
144 (prog1
145 (cadr docprop)
146 (setq options-and-methods
147 (delq docprop options-and-methods)))))))
148 `(progn
149 ,(when (eq 'setf (car-safe name))
150 (pcase-let ((`(,setter . ,code) (cl--generic-setf-rewrite
151 (cadr name))))
152 (setq name setter)
153 code))
154 (defalias ',name
155 (cl-generic-define ',name ',args ',options-and-methods)
156 ,doc))))
157
158(defun cl--generic-mandatory-args (args)
159 (let ((res ()))
160 (while (not (memq (car args) '(nil &rest &optional &key)))
161 (push (pop args) res))
162 (nreverse res)))
163
164;;;###autoload
165(defun cl-generic-define (name args options-and-methods)
166 (let ((generic (cl-generic-ensure-function name))
167 (mandatory (cl--generic-mandatory-args args))
168 (apo (assq :argument-precedence-order options-and-methods)))
169 (setf (cl--generic-dispatches generic) nil)
170 (when apo
171 (dolist (arg (cdr apo))
172 (let ((pos (memq arg mandatory)))
173 (unless pos (error "%S is not a mandatory argument" arg))
174 (push (list (- (length mandatory) (length pos)))
175 (cl--generic-dispatches generic)))))
176 (setf (cl--generic-method-table generic) nil)
177 (cl--generic-make-function generic)))
178
179(defvar cl-generic-current-method-specializers nil
180 ;; This is let-bound during macro-expansion of method bodies, so that those
181 ;; bodies can be optimized knowing that the specializers have matched.
182 ;; FIXME: This presumes the formal arguments aren't modified via `setq' and
183 ;; aren't shadowed either ;-(
184 ;; FIXME: This might leak outside the scope of the method if, during
185 ;; macroexpansion of the method, something causes some other macroexpansion
186 ;; (e.g. an autoload).
187 "List of (VAR . TYPE) where TYPE is var's specializer.")
188
189(eval-and-compile ;Needed while compiling the cl-defmethod calls below!
190 (defun cl--generic-fgrep (vars sexp) ;Copied from pcase.el.
191 "Check which of the symbols VARS appear in SEXP."
192 (let ((res '()))
193 (while (consp sexp)
194 (dolist (var (cl--generic-fgrep vars (pop sexp)))
195 (unless (memq var res) (push var res))))
196 (and (memq sexp vars) (not (memq sexp res)) (push sexp res))
197 res))
198
199 (defun cl--generic-lambda (args body with-cnm)
200 "Make the lambda expression for a method with ARGS and BODY."
201 (let ((plain-args ())
202 (cl-generic-current-method-specializers nil)
203 (doc-string (if (stringp (car-safe body)) (pop body)))
204 (mandatory t))
205 (dolist (arg args)
206 (push (pcase arg
207 ((or '&optional '&rest '&key) (setq mandatory nil) arg)
208 ((and `(,name . ,type) (guard mandatory))
209 (push (cons name (car type))
210 cl-generic-current-method-specializers)
211 name)
212 (_ arg))
213 plain-args))
214 (setq plain-args (nreverse plain-args))
215 (let ((fun `(cl-function (lambda ,plain-args
216 ,@(if doc-string (list doc-string))
217 ,@body))))
218 (if (not with-cnm)
219 (cons nil fun)
220 ;; First macroexpand away the cl-function stuff (e.g. &key and
221 ;; destructuring args, `declare' and whatnot).
222 (pcase (macroexpand fun macroexpand-all-environment)
223 (`#'(lambda ,args . ,body)
224 (require 'cl-lib) ;Needed to expand `cl-flet'.
225 (let* ((doc-string (and doc-string (stringp (car body))
226 (pop body)))
227 (cnm (make-symbol "cl--cnm"))
228 (nbody (macroexpand-all
229 `(cl-flet ((cl-call-next-method ,cnm))
230 ,@body)
231 macroexpand-all-environment))
232 ;; FIXME: Rather than `grep' after the fact, the
233 ;; macroexpansion should directly set some flag when cnm
234 ;; is used.
235 ;; FIXME: Also, optimize the case where call-next-method is
236 ;; only called with explicit arguments.
237 (uses-cnm (cl--generic-fgrep (list cnm) nbody)))
238 (cons (not (not uses-cnm))
239 `#'(lambda (,@(if uses-cnm (list cnm)) ,@args)
240 ,@(if doc-string (list doc-string))
241 ,nbody))))
242 (f (error "Unexpected macroexpansion result: %S" f))))))))
243
244
245;;;###autoload
246(defmacro cl-defmethod (name args &rest body)
247 "Define a new method for generic function NAME.
248I.e. it defines the implementation of NAME to use for invocations where the
249value of the dispatch argument matches the specified TYPE.
250The dispatch argument has to be one of the mandatory arguments, and
251all methods of NAME have to use the same argument for dispatch.
252The dispatch argument and TYPE are specified in ARGS where the corresponding
253formal argument appears as (VAR TYPE) rather than just VAR.
254
255The optional second argument QUALIFIER is a specifier that
256modifies how the method is combined with other methods, including:
257 :before - Method will be called before the primary
258 :after - Method will be called after the primary
259 :around - Method will be called around everything else
260The absence of QUALIFIER means this is a \"primary\" method.
261
262Other than a type, TYPE can also be of the form `(eql VAL)' in
263which case this method will be invoked when the argument is `eql' to VAL.
264
265\(fn NAME [QUALIFIER] ARGS &rest [DOCSTRING] BODY)"
266 (declare (doc-string 3) (indent 2))
267 (let ((qualifiers nil))
268 (while (keywordp args)
269 (push args qualifiers)
270 (setq args (pop body)))
271 (pcase-let* ((with-cnm (not (memq (car qualifiers) '(:before :after))))
272 (`(,uses-cnm . ,fun) (cl--generic-lambda args body with-cnm)))
273 `(progn
274 ,(when (eq 'setf (car-safe name))
275 (pcase-let ((`(,setter . ,code) (cl--generic-setf-rewrite
276 (cadr name))))
277 (setq name setter)
278 code))
279 (cl-generic-define-method ',name ',qualifiers ',args
280 ,uses-cnm ,fun)))))
281
282;;;###autoload
283(defun cl-generic-define-method (name qualifiers args uses-cnm function)
284 (when (> (length qualifiers) 1)
285 (error "We only support a single qualifier per method: %S" qualifiers))
286 (unless (memq (car qualifiers) '(nil :primary :around :after :before))
287 (error "Unsupported qualifier in: %S" qualifiers))
288 (let* ((generic (cl-generic-ensure-function name))
289 (mandatory (cl--generic-mandatory-args args))
290 (specializers
291 (mapcar (lambda (arg) (if (consp arg) (cadr arg) t)) mandatory))
292 (key (cons specializers (or (car qualifiers) ':primary)))
293 (mt (cl--generic-method-table generic))
294 (me (assoc key mt))
295 (dispatches (cl--generic-dispatches generic))
296 (i 0))
297 (dolist (specializer specializers)
298 (let* ((tagcode (funcall cl-generic-tagcode-function specializer 'arg))
299 (x (assq i dispatches)))
300 (if (not x)
301 (setf (cl--generic-dispatches generic)
302 (setq dispatches (cons (list i tagcode) dispatches)))
303 (unless (member tagcode (cdr x))
304 (setf (cdr x)
305 (nreverse (sort (cons tagcode (cdr x))
306 #'car-less-than-car)))))
307 (setq i (1+ i))))
308 (if me (setcdr me (cons uses-cnm function))
309 (setf (cl--generic-method-table generic)
310 (cons `(,key ,uses-cnm . ,function) mt)))
311 ;; For aliases, cl--generic-name gives us the actual name.
312 (defalias (cl--generic-name generic)
313 (cl--generic-make-function generic))))
314
315(defmacro cl--generic-with-memoization (place &rest code)
316 (declare (indent 1) (debug t))
317 (gv-letplace (getter setter) place
318 `(or ,getter
319 ,(macroexp-let2 nil val (macroexp-progn code)
320 `(progn
321 ,(funcall setter val)
322 ,val)))))
323
324(defvar cl--generic-dispatchers (make-hash-table :test #'equal))
325
326(defun cl--generic-get-dispatcher (tagcodes dispatch-arg)
327 (cl--generic-with-memoization
328 (gethash (cons dispatch-arg tagcodes) cl--generic-dispatchers)
329 (let ((lexical-binding t)
330 (extraargs ()))
331 (dotimes (_ dispatch-arg)
332 (push (make-symbol "arg") extraargs))
333 (byte-compile
334 `(lambda (generic dispatches-left)
335 (let ((method-cache (make-hash-table :test #'eql)))
336 (lambda (,@extraargs arg &rest args)
337 (apply (cl--generic-with-memoization
338 (gethash (or ,@(mapcar #'cdr tagcodes)) method-cache)
339 (cl--generic-cache-miss
340 generic ',dispatch-arg dispatches-left
341 (list ,@(mapcar #'cdr tagcodes))))
342 ,@extraargs arg args))))))))
343
344(defun cl--generic-make-function (generic)
345 (let* ((dispatches (cl--generic-dispatches generic))
346 (dispatch
347 (progn
348 (while (and dispatches
349 (member (cdar dispatches)
350 '(nil ((0 . 'cl--generic-type)))))
351 (setq dispatches (cdr dispatches)))
352 (pop dispatches))))
353 (if (null dispatch)
354 (cl--generic-build-combined-method
355 (cl--generic-name generic)
356 (cl--generic-method-table generic))
357 (let ((dispatcher (cl--generic-get-dispatcher
358 (cdr dispatch) (car dispatch))))
359 (funcall dispatcher generic dispatches)))))
360
361(defun cl--generic-nest (fun methods)
362 (pcase-dolist (`(,uses-cnm . ,method) methods)
363 (setq fun
364 (if (not uses-cnm) method
365 (let ((next fun))
366 (lambda (&rest args)
367 (apply method
368 ;; FIXME: This sucks: passing just `next' would
369 ;; be a lot more efficient than the lambda+apply
370 ;; quasi-η, but we need this to implement the
371 ;; "if call-next-method is called with no
372 ;; arguments, then use the previous arguments".
373 (lambda (&rest cnm-args)
374 (apply next (or cnm-args args)))
375 args))))))
376 fun)
377
378(defvar cl--generic-combined-method-memoization
379 (make-hash-table :test #'equal :weakness 'value)
380 "Table storing previously built combined-methods.
381This is particularly useful when many different tags select the same set
382of methods, since this table then allows us to share a single combined-method
383for all those different tags in the method-cache.")
384
385(defun cl--generic-build-combined-method (generic-name methods)
386 (let ((mets-by-qual ()))
387 (dolist (qm methods)
388 (push (cdr qm) (alist-get (cdar qm) mets-by-qual)))
389 (cl--generic-with-memoization
390 (gethash (cons generic-name mets-by-qual)
391 cl--generic-combined-method-memoization)
392 (cond
393 ((null mets-by-qual) (lambda (&rest args)
394 (cl-no-applicable-method generic-name args)))
395 (t
396 (let* ((fun (lambda (&rest args)
397 ;; FIXME: CLOS passes as second arg the "calling method".
398 ;; We don't currently have "method objects" like CLOS
399 ;; does so we can't really do it the CLOS way.
400 ;; The closest would be to pass the lambda corresponding
401 ;; to the method, but the caller wouldn't be able to do
402 ;; much with it anyway. So we pass nil for now.
403 (apply #'cl-no-next-method generic-name nil args)))
404 ;; We use `cdr' to drop the `uses-cnm' annotations.
405 (before
406 (mapcar #'cdr (reverse (alist-get :before mets-by-qual))))
407 (after (mapcar #'cdr (alist-get :after mets-by-qual))))
408 (setq fun (cl--generic-nest fun (alist-get :primary mets-by-qual)))
409 (when (or after before)
410 (let ((next fun))
411 (setq fun (lambda (&rest args)
412 (dolist (bf before)
413 (apply bf args))
414 (apply next args)
415 (dolist (af after)
416 (apply af args))))))
417 (cl--generic-nest fun (alist-get :around mets-by-qual))))))))
418
419(defun cl--generic-cache-miss (generic dispatch-arg dispatches-left tags)
420 (let ((types (apply #'append (mapcar cl-generic-tag-types-function tags)))
421 (methods '()))
422 (dolist (method-desc (cl--generic-method-table generic))
423 (let ((m (member (nth dispatch-arg (caar method-desc)) types)))
424 (when m
425 (push (cons (length m) method-desc) methods))))
426 ;; Sort the methods, most specific first.
427 ;; It would be tempting to sort them once and for all in the method-table
428 ;; rather than here, but the order might depend on the actual argument
429 ;; (e.g. for multiple inheritance with defclass).
430 (setq methods (nreverse (mapcar #'cdr (sort methods #'car-less-than-car))))
431 (cl--generic-make-function (cl--generic-make (cl--generic-name generic)
432 dispatches-left methods))))
433
434;;; Define some pre-defined generic functions, used internally.
435
436(define-error 'cl-no-method "No method for %S")
437(define-error 'cl-no-next-method "No next method for %S" 'cl-no-method)
438(define-error 'cl-no-applicable-method "No applicable method for %S"
439 'cl-no-method)
440
441(cl-defgeneric cl-no-next-method (generic method &rest args)
442 "Function called when `cl-call-next-method' finds no next method.")
443(cl-defmethod cl-no-next-method ((generic t) method &rest args)
444 (signal 'cl-no-next-method `(,generic ,method ,@args)))
445
446(cl-defgeneric cl-no-applicable-method (generic &rest args)
447 "Function called when a method call finds no applicable method.")
448(cl-defmethod cl-no-applicable-method ((generic t) &rest args)
449 (signal 'cl-no-applicable-method `(,generic ,@args)))
450
451(defun cl-call-next-method (&rest _args)
452 "Function to call the next applicable method.
453Can only be used from within the lexical body of a primary or around method."
454 (error "cl-call-next-method only allowed inside primary and around methods"))
455
456;;; Add support for describe-function
457
458(add-hook 'help-fns-describe-function-functions 'cl--generic-describe)
459(defun cl--generic-describe (function)
460 ;; FIXME: Fix up the main "in `<file>'" hyperlink, and add such hyperlinks
461 ;; for each method.
462 (let ((generic (if (symbolp function) (cl--generic function))))
463 (when generic
464 (save-excursion
465 (insert "\n\nThis is a generic function.\n\n")
466 (insert (propertize "Implementations:\n\n" 'face 'bold))
467 ;; Loop over fanciful generics
468 (pcase-dolist (`((,type . ,qualifier) . ,method)
469 (cl--generic-method-table generic))
470 (insert "`")
471 (if (symbolp type)
472 ;; FIXME: Add support for cl-structs in help-variable.
473 (help-insert-xref-button (symbol-name type)
474 'help-variable type)
475 (insert (format "%S" type)))
476 (insert (format "' %S %S\n"
477 (car qualifier)
478 (let ((args (help-function-arglist method)))
479 ;; Drop cl--generic-next arg if present.
480 (if (memq (car qualifier) '(:after :before))
481 args (cdr args)))))
482 (insert (or (documentation method) "Undocumented") "\n\n"))))))
483
484;;; Support for (eql <val>) specializers.
485
486(defvar cl--generic-eql-used (make-hash-table :test #'eql))
487
488(add-function :before-until cl-generic-tagcode-function
489 #'cl--generic-eql-tagcode)
490(defun cl--generic-eql-tagcode (type name)
491 (when (eq (car-safe type) 'eql)
492 (puthash (cadr type) type cl--generic-eql-used)
493 `(100 . (gethash ,name cl--generic-eql-used))))
494
495(add-function :before-until cl-generic-tag-types-function
496 #'cl--generic-eql-tag-types)
497(defun cl--generic-eql-tag-types (tag)
498 (if (eq (car-safe tag) 'eql) (list tag)))
499
500;;; Support for cl-defstructs specializers.
501
502(add-function :before-until cl-generic-tagcode-function
503 #'cl--generic-struct-tagcode)
504(defun cl--generic-struct-tagcode (type name)
505 (and (symbolp type)
506 (get type 'cl-struct-type)
507 (or (eq 'vector (car (get type 'cl-struct-type)))
508 (error "Can't dispatch on cl-struct %S: type is %S"
509 type (car (get type 'cl-struct-type))))
510 (or (equal '(cl-tag-slot) (car (get type 'cl-struct-slots)))
511 (error "Can't dispatch on cl-struct %S: no tag in slot 0"
512 type))
513 ;; We could/should check the vector has length >0,
514 ;; but really, mixing vectors and structs is a bad idea,
515 ;; so let's not waste time trying to handle the case
516 ;; of an empty vector.
517 ;; BEWARE: this returns a bogus tag for non-struct vectors.
518 `(50 . (and (vectorp ,name) (aref ,name 0)))))
519
520(add-function :before-until cl-generic-tag-types-function
521 #'cl--generic-struct-tag-types)
522(defun cl--generic-struct-tag-types (tag)
523 ;; FIXME: cl-defstruct doesn't make it easy for us.
524 (and (symbolp tag)
525 ;; A method call shouldn't itself mess with the match-data.
526 (string-match-p "\\`cl-struct-\\(.*\\)" (symbol-name tag))
527 (let ((types (list (intern (substring (symbol-name tag) 10)))))
528 (while (get (car types) 'cl-struct-include)
529 (push (get (car types) 'cl-struct-include) types))
530 (push 'cl-struct types) ;The "parent type" of all cl-structs.
531 (nreverse types))))
532
533;;; Dispatch on "old-style types".
534
535(defconst cl--generic-typeof-types
536 ;; Hand made from the source code of `type-of'.
537 '((integer number) (symbol) (string array) (cons list)
538 ;; Markers aren't `numberp', yet they are accepted wherever integers are
539 ;; accepted, pretty much.
540 (marker) (overlay) (float number) (window-configuration)
541 (process) (window) (subr) (compiled-function) (buffer) (char-table array)
542 (bool-vector array)
543 (frame) (hash-table) (font-spec) (font-entity) (font-object)
544 (vector array)
545 ;; Plus, hand made:
546 (null list symbol)
547 (list)
548 (array)
549 (number)))
550
551(add-function :before-until cl-generic-tagcode-function
552 #'cl--generic-typeof-tagcode)
553(defun cl--generic-typeof-tagcode (type name)
554 ;; FIXME: Add support for other types accepted by `cl-typep' such
555 ;; as `character', `atom', `face', `function', ...
556 (and (assq type cl--generic-typeof-types)
557 (progn
558 (if (memq type '(vector array))
559 (message "`%S' also matches CL structs and EIEIO classes" type))
560 ;; FIXME: We could also change `type-of' to return `null' for nil.
561 `(10 . (if ,name (type-of ,name) 'null)))))
562
563(add-function :before-until cl-generic-tag-types-function
564 #'cl--generic-typeof-types)
565(defun cl--generic-typeof-types (tag)
566 (and (symbolp tag)
567 (assq tag cl--generic-typeof-types)))
568
569;;; Just for kicks: dispatch on major-mode
570;;
571;; Here's how you'd use it:
572;; (cl-defmethod foo ((x (major-mode text-mode)) y z) ...)
573;; And then
574;; (foo 'major-mode toto titi)
575;;
576;; FIXME: Better would be to do that via dispatch on an "implicit argument".
577
578;; (defvar cl--generic-major-modes (make-hash-table :test #'eq))
579;;
580;; (add-function :before-until cl-generic-tagcode-function
581;; #'cl--generic-major-mode-tagcode)
582;; (defun cl--generic-major-mode-tagcode (type name)
583;; (if (eq 'major-mode (car-safe type))
584;; `(50 . (if (eq ,name 'major-mode)
585;; (cl--generic-with-memoization
586;; (gethash major-mode cl--generic-major-modes)
587;; `(cl--generic-major-mode . ,major-mode))))))
588;;
589;; (add-function :before-until cl-generic-tag-types-function
590;; #'cl--generic-major-mode-types)
591;; (defun cl--generic-major-mode-types (tag)
592;; (when (eq (car-safe tag) 'cl--generic-major-mode)
593;; (if (eq tag 'fundamental-mode) '(fundamental-mode t)
594;; (let ((types `((major-mode ,(cdr tag)))))
595;; (while (get (car types) 'derived-mode-parent)
596;; (push (list 'major-mode (get (car types) 'derived-mode-parent))
597;; types))
598;; (unless (eq 'fundamental-mode (car types))
599;; (push '(major-mode fundamental-mode) types))
600;; (nreverse types)))))
601
602;; Local variables:
603;; generated-autoload-file: "cl-loaddefs.el"
604;; End:
605
606(provide 'cl-generic)
607;;; cl-generic.el ends here
diff --git a/lisp/emacs-lisp/cl-macs.el b/lisp/emacs-lisp/cl-macs.el
index fff5b27315c..0070599af6f 100644
--- a/lisp/emacs-lisp/cl-macs.el
+++ b/lisp/emacs-lisp/cl-macs.el
@@ -625,14 +625,20 @@ The result of the body appears to the compiler as a quoted constant."
625 (set `(setq ,temp ,form))) 625 (set `(setq ,temp ,form)))
626 (if (and (fboundp 'byte-compile-file-form-defmumble) 626 (if (and (fboundp 'byte-compile-file-form-defmumble)
627 (boundp 'this-kind) (boundp 'that-one)) 627 (boundp 'this-kind) (boundp 'that-one))
628 (fset 'byte-compile-file-form 628 ;; Else, we can't output right away, so we have to delay it to the
629 `(lambda (form) 629 ;; next time we're at the top-level.
630 (fset 'byte-compile-file-form 630 ;; FIXME: Use advice-add/remove.
631 ',(symbol-function 'byte-compile-file-form)) 631 (fset 'byte-compile-file-form
632 (byte-compile-file-form ',set) 632 (let ((old (symbol-function 'byte-compile-file-form)))
633 (byte-compile-file-form form))) 633 (lambda (form)
634 (print set (symbol-value 'byte-compile--outbuffer))) 634 (fset 'byte-compile-file-form old)
635 `(symbol-value ',temp)) 635 (byte-compile-file-form set)
636 (byte-compile-file-form form))))
637 ;; If we're not in the middle of compiling something, we can
638 ;; output directly to byte-compile-outbuffer, to make sure
639 ;; temp is set before we use it.
640 (print set byte-compile--outbuffer))
641 temp)
636 `',(eval form))) 642 `',(eval form)))
637 643
638 644
@@ -1824,18 +1830,30 @@ a `let' form, except that the list of symbols can be computed at run-time."
1824(defmacro cl-flet (bindings &rest body) 1830(defmacro cl-flet (bindings &rest body)
1825 "Make local function definitions. 1831 "Make local function definitions.
1826Like `cl-labels' but the definitions are not recursive. 1832Like `cl-labels' but the definitions are not recursive.
1833Each binding can take the form (FUNC EXP) where
1834FUNC is the function name, and EXP is an expression that returns the
1835function value to which it should be bound, or it can take the more common
1836form \(FUNC ARGLIST BODY...) which is a shorthand
1837for (FUNC (lambda ARGLIST BODY)).
1827 1838
1828\(fn ((FUNC ARGLIST BODY...) ...) FORM...)" 1839\(fn ((FUNC ARGLIST BODY...) ...) FORM...)"
1829 (declare (indent 1) (debug ((&rest (cl-defun)) cl-declarations body))) 1840 (declare (indent 1) (debug ((&rest (cl-defun)) cl-declarations body)))
1830 (let ((binds ()) (newenv macroexpand-all-environment)) 1841 (let ((binds ()) (newenv macroexpand-all-environment))
1831 (dolist (binding bindings) 1842 (dolist (binding bindings)
1832 (let ((var (make-symbol (format "--cl-%s--" (car binding))))) 1843 (let ((var (make-symbol (format "--cl-%s--" (car binding))))
1833 (push (list var `(cl-function (lambda . ,(cdr binding)))) binds) 1844 (args-and-body (cdr binding)))
1845 (if (and (= (length args-and-body) 1) (symbolp (car args-and-body)))
1846 ;; Optimize (cl-flet ((fun var)) body).
1847 (setq var (car args-and-body))
1848 (push (list var (if (= (length args-and-body) 1)
1849 (car args-and-body)
1850 `(cl-function (lambda . ,args-and-body))))
1851 binds))
1834 (push (cons (car binding) 1852 (push (cons (car binding)
1835 `(lambda (&rest cl-labels-args) 1853 (lambda (&rest cl-labels-args)
1836 (cl-list* 'funcall ',var 1854 (cl-list* 'funcall var cl-labels-args)))
1837 cl-labels-args)))
1838 newenv))) 1855 newenv)))
1856 ;; FIXME: Eliminate those functions which aren't referenced.
1839 `(let ,(nreverse binds) 1857 `(let ,(nreverse binds)
1840 ,@(macroexp-unprogn 1858 ,@(macroexp-unprogn
1841 (macroexpand-all 1859 (macroexpand-all
@@ -1869,9 +1887,8 @@ in closures will only work if `lexical-binding' is in use.
1869 (let ((var (make-symbol (format "--cl-%s--" (car binding))))) 1887 (let ((var (make-symbol (format "--cl-%s--" (car binding)))))
1870 (push (list var `(cl-function (lambda . ,(cdr binding)))) binds) 1888 (push (list var `(cl-function (lambda . ,(cdr binding)))) binds)
1871 (push (cons (car binding) 1889 (push (cons (car binding)
1872 `(lambda (&rest cl-labels-args) 1890 (lambda (&rest cl-labels-args)
1873 (cl-list* 'funcall ',var 1891 (cl-list* 'funcall var cl-labels-args)))
1874 cl-labels-args)))
1875 newenv))) 1892 newenv)))
1876 (macroexpand-all `(letrec ,(nreverse binds) ,@body) 1893 (macroexpand-all `(letrec ,(nreverse binds) ,@body)
1877 ;; Don't override lexical-let's macro-expander. 1894 ;; Don't override lexical-let's macro-expander.
@@ -1898,7 +1915,8 @@ This is like `cl-flet', but for macros instead of functions.
1898 (res (cl--transform-lambda (cdar bindings) name))) 1915 (res (cl--transform-lambda (cdar bindings) name)))
1899 (eval (car res)) 1916 (eval (car res))
1900 (macroexpand-all (macroexp-progn body) 1917 (macroexpand-all (macroexp-progn body)
1901 (cons (cons name `(lambda ,@(cdr res))) 1918 (cons (cons name
1919 (eval `(cl-function (lambda ,@(cdr res))) t))
1902 macroexpand-all-environment)))))) 1920 macroexpand-all-environment))))))
1903 1921
1904(defconst cl--old-macroexpand 1922(defconst cl--old-macroexpand
diff --git a/lisp/emacs-lisp/eieio-core.el b/lisp/emacs-lisp/eieio-core.el
index dc2c873eb42..bfa922bade6 100644
--- a/lisp/emacs-lisp/eieio-core.el
+++ b/lisp/emacs-lisp/eieio-core.el
@@ -264,7 +264,7 @@ Return nil if that option doesn't exist."
264 264
265(defsubst eieio-object-p (obj) 265(defsubst eieio-object-p (obj)
266 "Return non-nil if OBJ is an EIEIO object." 266 "Return non-nil if OBJ is an EIEIO object."
267 (and (arrayp obj) 267 (and (vectorp obj)
268 (condition-case nil 268 (condition-case nil
269 (eq (aref (eieio--object-class-object obj) 0) 'defclass) 269 (eq (aref (eieio--object-class-object obj) 0) 'defclass)
270 (error nil)))) 270 (error nil))))
@@ -1303,11 +1303,35 @@ method invocation orders of the involved classes."
1303(define-error 'unbound-slot "Unbound slot") 1303(define-error 'unbound-slot "Unbound slot")
1304(define-error 'inconsistent-class-hierarchy "Inconsistent class hierarchy") 1304(define-error 'inconsistent-class-hierarchy "Inconsistent class hierarchy")
1305 1305
1306;;; Hooking into cl-generic.
1307
1308(require 'cl-generic)
1309
1310(add-function :before-until cl-generic-tagcode-function
1311 #'eieio--generic-tagcode)
1312(defun eieio--generic-tagcode (type name)
1313 ;; CLHS says:
1314 ;; A class must be defined before it can be used as a parameter
1315 ;; specializer in a defmethod form.
1316 ;; So we can ignore types that are not known to denote classes.
1317 (and (class-p type)
1318 ;; Prefer (aref ,name 0) over (eieio--class-tag ,name) so that
1319 ;; the tagcode is identical to the tagcode used for cl-struct.
1320 `(50 . (and (vectorp ,name) (aref ,name 0)))))
1321
1322(add-function :before-until cl-generic-tag-types-function
1323 #'eieio--generic-tag-types)
1324(defun eieio--generic-tag-types (tag)
1325 (and (symbolp tag) (boundp tag) (eieio--class-p (symbol-value tag))
1326 (mapcar #'eieio--class-symbol
1327 (eieio--class-precedence-list (symbol-value tag)))))
1328
1306;;; Backward compatibility functions 1329;;; Backward compatibility functions
1307;; To support .elc files compiled for older versions of EIEIO. 1330;; To support .elc files compiled for older versions of EIEIO.
1308 1331
1309(defun eieio-defclass (cname superclasses slots options) 1332(defun eieio-defclass (cname superclasses slots options)
1310 (eval `(defclass ,cname ,superclasses ,slots ,options))) 1333 (declare (obsolete eieio-defclass-internal "25.1"))
1334 (eval `(defclass ,cname ,superclasses ,slots ,@options)))
1311 1335
1312 1336
1313(provide 'eieio-core) 1337(provide 'eieio-core)
diff --git a/lisp/files.el b/lisp/files.el
index 1533c35e6ca..175f85b29d0 100644
--- a/lisp/files.el
+++ b/lisp/files.el
@@ -740,7 +740,10 @@ This function works recursively. Files are returned in \"depth first\"
740and alphabetical order. 740and alphabetical order.
741If INCLUDE-DIRECTORIES, also include directories that have matching names." 741If INCLUDE-DIRECTORIES, also include directories that have matching names."
742 (let ((result nil) 742 (let ((result nil)
743 (files nil)) 743 (files nil)
744 ;; When DIR is "/", remote file names like "/method:" could
745 ;; also be offered. We shall suppress them.
746 (tramp-mode (and tramp-mode (file-remote-p dir))))
744 (dolist (file (sort (file-name-all-completions "" dir) 747 (dolist (file (sort (file-name-all-completions "" dir)
745 'string<)) 748 'string<))
746 (unless (member file '("./" "../")) 749 (unless (member file '("./" "../"))
diff --git a/lisp/frame.el b/lisp/frame.el
index 8b927309f0a..1d5bbf2317e 100644
--- a/lisp/frame.el
+++ b/lisp/frame.el
@@ -275,23 +275,22 @@ there (in decreasing order of priority)."
275 ;; by the lines added in x-create-frame for the tool-bar and 275 ;; by the lines added in x-create-frame for the tool-bar and
276 ;; switch `tool-bar-mode' off. 276 ;; switch `tool-bar-mode' off.
277 (when (display-graphic-p) 277 (when (display-graphic-p)
278 (let ((tool-bar-lines 278 (let* ((init-lines
279 (or (assq 'tool-bar-lines initial-frame-alist) 279 (assq 'tool-bar-lines initial-frame-alist))
280 (assq 'tool-bar-lines window-system-frame-alist) 280 (other-lines
281 (assq 'tool-bar-lines default-frame-alist)))) 281 (or (assq 'tool-bar-lines window-system-frame-alist)
282 ;; Shrink frame by its initial tool bar height iff either zero 282 (assq 'tool-bar-lines default-frame-alist)))
283 ;; tool bar lines have been requested in one of the frame's 283 (lines (or init-lines other-lines))
284 ;; alists or tool bar mode has been turned off explicitly in 284 (height (tool-bar-height frame-initial-frame t)))
285 ;; the user's init file. 285 ;; Adjust frame top if either zero (nil) tool bar lines have
286 (when (and tool-bar-lines 286 ;; been requested in the most relevant of the frame's alists
287 (> frame-initial-frame-tool-bar-height 0) 287 ;; or tool bar mode has been explicitly turned off in the
288 (or (not tool-bar-mode) 288 ;; user's init file.
289 (null (cdr tool-bar-lines)) 289 (when (and (> height 0)
290 (eq 0 (cdr tool-bar-lines)))) 290 (or (and lines
291 (set-frame-height 291 (or (null (cdr lines))
292 frame-initial-frame (- (frame-text-height frame-initial-frame) 292 (eq 0 (cdr lines))))
293 frame-initial-frame-tool-bar-height) 293 (not tool-bar-mode)))
294 nil t)
295 (let* ((initial-top 294 (let* ((initial-top
296 (cdr (assq 'top frame-initial-geometry-arguments))) 295 (cdr (assq 'top frame-initial-geometry-arguments)))
297 (top (frame-parameter frame-initial-frame 'top))) 296 (top (frame-parameter frame-initial-frame 'top)))
@@ -299,15 +298,19 @@ there (in decreasing order of priority)."
299 (let ((adjusted-top 298 (let ((adjusted-top
300 (cond 299 (cond
301 ((and (consp top) (eq '+ (car top))) 300 ((and (consp top) (eq '+ (car top)))
302 (list '+ (+ (cadr top) 301 (list '+ (+ (cadr top) height)))
303 frame-initial-frame-tool-bar-height)))
304 ((and (consp top) (eq '- (car top))) 302 ((and (consp top) (eq '- (car top)))
305 (list '- (- (cadr top) 303 (list '- (- (cadr top) height)))
306 frame-initial-frame-tool-bar-height))) 304 (t (+ top height)))))
307 (t (+ top frame-initial-frame-tool-bar-height)))))
308 (modify-frame-parameters 305 (modify-frame-parameters
309 frame-initial-frame `((top . ,adjusted-top)))))) 306 frame-initial-frame `((top . ,adjusted-top))))))
310 (tool-bar-mode -1)))) 307 ;; Reset `tool-bar-mode' when zero tool bar lines have been
308 ;; requested for the window-system or default frame alists.
309 (when (and tool-bar-mode
310 (and other-lines
311 (or (null (cdr other-lines))
312 (eq 0 (cdr other-lines)))))
313 (tool-bar-mode -1)))))
311 314
312 ;; The initial frame we create above always has a minibuffer. 315 ;; The initial frame we create above always has a minibuffer.
313 ;; If the user wants to remove it, or make it a minibuffer-only 316 ;; If the user wants to remove it, or make it a minibuffer-only
@@ -682,6 +685,9 @@ the new frame according to its own rules."
682 (push p params))) 685 (push p params)))
683 ;; Now make the frame. 686 ;; Now make the frame.
684 (run-hooks 'before-make-frame-hook) 687 (run-hooks 'before-make-frame-hook)
688
689;; (setq frame-adjust-size-history '(t))
690
685 (setq frame 691 (setq frame
686 (funcall (gui-method frame-creation-function w) params)) 692 (funcall (gui-method frame-creation-function w) params))
687 (normal-erase-is-backspace-setup-frame frame) 693 (normal-erase-is-backspace-setup-frame frame)
@@ -690,6 +696,12 @@ the new frame according to its own rules."
690 (unless (assq param parameters) ;Overridden by explicit parameters. 696 (unless (assq param parameters) ;Overridden by explicit parameters.
691 (let ((val (frame-parameter oldframe param))) 697 (let ((val (frame-parameter oldframe param)))
692 (when val (set-frame-parameter frame param val))))) 698 (when val (set-frame-parameter frame param val)))))
699
700 (when (eq (car frame-adjust-size-history) t)
701 (setq frame-adjust-size-history
702 (cons t (cons (list "Frame made")
703 (cdr frame-adjust-size-history)))))
704
693 (run-hook-with-args 'after-make-frame-functions frame) 705 (run-hook-with-args 'after-make-frame-functions frame)
694 frame)) 706 frame))
695 707
diff --git a/lisp/menu-bar.el b/lisp/menu-bar.el
index 67cb3273d23..cd1a4d05b55 100644
--- a/lisp/menu-bar.el
+++ b/lisp/menu-bar.el
@@ -381,7 +381,8 @@
381 381
382 (bindings--define-key menu [xref-pop] 382 (bindings--define-key menu [xref-pop]
383 '(menu-item "Back" xref-pop-marker-stack 383 '(menu-item "Back" xref-pop-marker-stack
384 :visible (not (xref-marker-stack-empty-p)) 384 :visible (and (featurep 'xref)
385 (not (xref-marker-stack-empty-p)))
385 :help "Back to the position of the last search")) 386 :help "Back to the position of the last search"))
386 387
387 (bindings--define-key menu [xref-apropos] 388 (bindings--define-key menu [xref-apropos]
diff --git a/lisp/net/eww.el b/lisp/net/eww.el
index 6a6da17d1ce..879eb53115e 100644
--- a/lisp/net/eww.el
+++ b/lisp/net/eww.el
@@ -1,4 +1,4 @@
1;;; eww.el --- Emacs Web Wowser 1;;; eww.el --- Emacs Web Wowser -*- lexical-binding:t -*-
2 2
3;; Copyright (C) 2013-2015 Free Software Foundation, Inc. 3;; Copyright (C) 2013-2015 Free Software Foundation, Inc.
4 4
@@ -255,7 +255,9 @@ word(s) will be searched for via `eww-search-prefix'."
255 ((string-match-p "\\`ftp://" url) 255 ((string-match-p "\\`ftp://" url)
256 (user-error "FTP is not supported.")) 256 (user-error "FTP is not supported."))
257 (t 257 (t
258 (if (or (string-match "\\`https?:" url) 258 ;; Anything that starts with something that vaguely looks
259 ;; like a protocol designator is interpreted as a full URL.
260 (if (or (string-match "\\`[A-Za-z]+:" url)
259 ;; Also try to match "naked" URLs like 261 ;; Also try to match "naked" URLs like
260 ;; en.wikipedia.org/wiki/Free software 262 ;; en.wikipedia.org/wiki/Free software
261 (string-match "\\`[A-Za-z_]+\\.[A-Za-z._]+/" url) 263 (string-match "\\`[A-Za-z_]+\\.[A-Za-z._]+/" url)
@@ -550,7 +552,7 @@ See the `eww-search-prefix' variable for the search engine used."
550 "Return URI of the Web page the current EWW buffer is visiting." 552 "Return URI of the Web page the current EWW buffer is visiting."
551 (plist-get eww-data :url)) 553 (plist-get eww-data :url))
552 554
553(defun eww-links-at-point (&optional pt) 555(defun eww-links-at-point ()
554 "Return list of URIs, if any, linked at point." 556 "Return list of URIs, if any, linked at point."
555 (remq nil 557 (remq nil
556 (list (get-text-property (point) 'shr-url) 558 (list (get-text-property (point) 'shr-url)
@@ -629,17 +631,13 @@ the like."
629 631
630(defvar eww-mode-map 632(defvar eww-mode-map
631 (let ((map (make-sparse-keymap))) 633 (let ((map (make-sparse-keymap)))
632 (suppress-keymap map) 634 (set-keymap-parent map special-mode-map)
633 (define-key map "q" 'quit-window) 635 (define-key map "g" 'eww-reload) ;FIXME: revert-buffer-function instead!
634 (define-key map "g" 'eww-reload)
635 (define-key map "G" 'eww) 636 (define-key map "G" 'eww)
636 (define-key map [?\t] 'shr-next-link) 637 (define-key map [?\t] 'shr-next-link)
637 (define-key map [?\M-\t] 'shr-previous-link) 638 (define-key map [?\M-\t] 'shr-previous-link)
638 (define-key map [backtab] 'shr-previous-link) 639 (define-key map [backtab] 'shr-previous-link)
639 (define-key map [delete] 'scroll-down-command) 640 (define-key map [delete] 'scroll-down-command)
640 (define-key map [?\S-\ ] 'scroll-down-command)
641 (define-key map "\177" 'scroll-down-command)
642 (define-key map " " 'scroll-up-command)
643 (define-key map "l" 'eww-back-url) 641 (define-key map "l" 'eww-back-url)
644 (define-key map "r" 'eww-forward-url) 642 (define-key map "r" 'eww-forward-url)
645 (define-key map "n" 'eww-next-url) 643 (define-key map "n" 'eww-next-url)
@@ -697,21 +695,19 @@ the like."
697 map) 695 map)
698 "Tool bar for `eww-mode'.") 696 "Tool bar for `eww-mode'.")
699 697
700(define-derived-mode eww-mode nil "eww" 698(define-derived-mode eww-mode special-mode "eww"
701 "Mode for browsing the web. 699 "Mode for browsing the web."
702
703\\{eww-mode-map}"
704 (setq-local eww-data (list :title "")) 700 (setq-local eww-data (list :title ""))
705 (setq-local browse-url-browser-function 'eww-browse-url) 701 (setq-local browse-url-browser-function #'eww-browse-url)
706 (setq-local after-change-functions 'eww-process-text-input) 702 (add-hook 'after-change-functions #'eww-process-text-input nil t)
707 (setq-local eww-history nil) 703 (setq-local eww-history nil)
708 (setq-local eww-history-position 0) 704 (setq-local eww-history-position 0)
709 (when (boundp 'tool-bar-map) 705 (when (boundp 'tool-bar-map)
710 (setq-local tool-bar-map eww-tool-bar-map)) 706 (setq-local tool-bar-map eww-tool-bar-map))
711 ;; desktop support 707 ;; desktop support
712 (setq-local desktop-save-buffer 'eww-desktop-misc-data) 708 (setq-local desktop-save-buffer #'eww-desktop-misc-data)
713 ;; multi-page isearch support 709 ;; multi-page isearch support
714 (setq-local multi-isearch-next-buffer-function 'eww-isearch-next-buffer) 710 (setq-local multi-isearch-next-buffer-function #'eww-isearch-next-buffer)
715 (setq truncate-lines t) 711 (setq truncate-lines t)
716 (buffer-disable-undo) 712 (buffer-disable-undo)
717 (setq buffer-read-only t)) 713 (setq buffer-read-only t))
@@ -1054,7 +1050,7 @@ See URL `https://developer.mozilla.org/en-US/docs/Web/HTML/Element/Input'.")
1054 (insert value) 1050 (insert value)
1055 (shr-ensure-newline) 1051 (shr-ensure-newline)
1056 (when (< (count-lines start (point)) lines) 1052 (when (< (count-lines start (point)) lines)
1057 (dotimes (i (- lines (count-lines start (point)))) 1053 (dotimes (_ (- lines (count-lines start (point))))
1058 (insert "\n"))) 1054 (insert "\n")))
1059 (setq end (point-marker)) 1055 (setq end (point-marker))
1060 (goto-char start) 1056 (goto-char start)
@@ -1846,7 +1842,7 @@ Also used when saving `eww-history'.")
1846 ;; . 1842 ;; .
1847 r)) 1843 r))
1848 1844
1849(defun eww-desktop-misc-data (directory) 1845(defun eww-desktop-misc-data (_directory)
1850 "Return a property list with data used to restore eww buffers. 1846 "Return a property list with data used to restore eww buffers.
1851This list will contain, as :history, the list, whose first element is 1847This list will contain, as :history, the list, whose first element is
1852the value of `eww-data', and the tail is `eww-history'. 1848the value of `eww-data', and the tail is `eww-history'.
@@ -1894,7 +1890,7 @@ Otherwise, the restored buffer will contain a prompt to do so by using
1894 1890
1895;;; Isearch support 1891;;; Isearch support
1896 1892
1897(defun eww-isearch-next-buffer (&optional buffer wrap) 1893(defun eww-isearch-next-buffer (&optional _buffer wrap)
1898 "Go to the next page to search using `rel' attribute for navigation." 1894 "Go to the next page to search using `rel' attribute for navigation."
1899 (if wrap 1895 (if wrap
1900 (condition-case nil 1896 (condition-case nil
diff --git a/lisp/progmodes/cc-bytecomp.el b/lisp/progmodes/cc-bytecomp.el
index bf7803c85ca..b63eeb4c7a6 100644
--- a/lisp/progmodes/cc-bytecomp.el
+++ b/lisp/progmodes/cc-bytecomp.el
@@ -89,13 +89,60 @@
89 ;;`(message ,@args) 89 ;;`(message ,@args)
90 ) 90 )
91 91
92(defun cc-bytecomp-compiling-or-loading ()
93 ;; Determine whether byte-compilation or loading is currently active,
94 ;; returning 'compiling, 'loading or nil.
95 ;; If both are active, the "innermost" activity counts. Note that
96 ;; compilation can trigger loading (various `require' type forms)
97 ;; and loading can trigger compilation (the package manager does
98 ;; this). We walk the lisp stack if necessary.
99 (cond
100 ((and load-in-progress
101 (boundp 'byte-compile-dest-file)
102 (stringp byte-compile-dest-file))
103 (let ((n 0) elt)
104 (while (and
105 (setq elt (backtrace-frame n))
106 (not (and (car elt)
107 (memq (cadr elt)
108 '(load require
109 byte-compile-file byte-recompile-directory
110 batch-byte-compile)))))
111 (setq n (1+ n)))
112 (cond
113 ((memq (cadr elt) '(load require))
114 'loading)
115 ((memq (cadr elt) '(byte-compile-file
116 byte-recompile-directory
117 batch-byte-compile))
118 'compiling)
119 (t ; Can't happen.
120 (message "cc-bytecomp-compiling-or-loading: System flags spuriously set")
121 nil))))
122 (load-in-progress
123 ;; Being loaded.
124 'loading)
125 ((and (boundp 'byte-compile-dest-file)
126 (stringp byte-compile-dest-file))
127 ;; Being compiled.
128 'compiling)
129 (t
130 ;; Being evaluated interactively.
131 nil)))
132
133(defsubst cc-bytecomp-is-compiling ()
134 "Return non-nil if eval'ed during compilation."
135 (eq (cc-bytecomp-compiling-or-loading) 'compiling))
136
137(defsubst cc-bytecomp-is-loading ()
138 "Return non-nil if eval'ed during loading.
139Nil will be returned if we're in a compilation triggered by the loading."
140 (eq (cc-bytecomp-compiling-or-loading) 'loading))
141
92(defun cc-bytecomp-setup-environment () 142(defun cc-bytecomp-setup-environment ()
93 ;; Eval'ed during compilation to setup variables, functions etc 143 ;; Eval'ed during compilation to setup variables, functions etc
94 ;; declared with `cc-bytecomp-defvar' et al. 144 ;; declared with `cc-bytecomp-defvar' et al.
95 (if (not load-in-progress) 145 (if (not (cc-bytecomp-is-loading))
96 ;; Look at `load-in-progress' to tell whether we're called
97 ;; directly in the file being compiled or just from some file
98 ;; being loaded during compilation.
99 (let (p) 146 (let (p)
100 (if cc-bytecomp-environment-set 147 (if cc-bytecomp-environment-set
101 (error "Byte compilation environment already set - \ 148 (error "Byte compilation environment already set - \
@@ -143,7 +190,7 @@ perhaps a `cc-bytecomp-restore-environment' is forgotten somewhere"))
143(defun cc-bytecomp-restore-environment () 190(defun cc-bytecomp-restore-environment ()
144 ;; Eval'ed during compilation to restore variables, functions etc 191 ;; Eval'ed during compilation to restore variables, functions etc
145 ;; declared with `cc-bytecomp-defvar' et al. 192 ;; declared with `cc-bytecomp-defvar' et al.
146 (if (not load-in-progress) 193 (if (not (cc-bytecomp-is-loading))
147 (let (p) 194 (let (p)
148 (setq p cc-bytecomp-unbound-variables) 195 (setq p cc-bytecomp-unbound-variables)
149 (while p 196 (while p
@@ -287,8 +334,7 @@ use within `eval-when-compile'."
287 `(eval-when-compile 334 `(eval-when-compile
288 (if (and (fboundp 'cc-bytecomp-is-compiling) 335 (if (and (fboundp 'cc-bytecomp-is-compiling)
289 (cc-bytecomp-is-compiling)) 336 (cc-bytecomp-is-compiling))
290 (if (or (not load-in-progress) 337 (if (not (featurep ,cc-part))
291 (not (featurep ,cc-part)))
292 (cc-bytecomp-load (symbol-name ,cc-part))) 338 (cc-bytecomp-load (symbol-name ,cc-part)))
293 (require ,cc-part)))) 339 (require ,cc-part))))
294 340
@@ -301,12 +347,6 @@ afterwards. Don't use within `eval-when-compile'."
301 (require ,feature) 347 (require ,feature)
302 (eval-when-compile (cc-bytecomp-setup-environment)))) 348 (eval-when-compile (cc-bytecomp-setup-environment))))
303 349
304(defun cc-bytecomp-is-compiling ()
305 "Return non-nil if eval'ed during compilation. Don't use outside
306`eval-when-compile'."
307 (and (boundp 'byte-compile-dest-file)
308 (stringp byte-compile-dest-file)))
309
310(defmacro cc-bytecomp-defvar (var) 350(defmacro cc-bytecomp-defvar (var)
311 "Binds the symbol as a variable during compilation of the file, 351 "Binds the symbol as a variable during compilation of the file,
312to silence the byte compiler. Don't use within `eval-when-compile'." 352to silence the byte compiler. Don't use within `eval-when-compile'."
@@ -320,8 +360,7 @@ to silence the byte compiler. Don't use within `eval-when-compile'."
320 "cc-bytecomp-defvar: Saving %s (as unbound)" ',var) 360 "cc-bytecomp-defvar: Saving %s (as unbound)" ',var)
321 (setq cc-bytecomp-unbound-variables 361 (setq cc-bytecomp-unbound-variables
322 (cons ',var cc-bytecomp-unbound-variables)))) 362 (cons ',var cc-bytecomp-unbound-variables))))
323 (if (and (cc-bytecomp-is-compiling) 363 (if (cc-bytecomp-is-compiling)
324 (not load-in-progress))
325 (progn 364 (progn
326 (defvar ,var) 365 (defvar ,var)
327 (set ',var (intern (concat "cc-bytecomp-ignore-var:" 366 (set ',var (intern (concat "cc-bytecomp-ignore-var:"
@@ -349,8 +388,7 @@ at compile time, e.g. for macros and inline functions."
349 (setq cc-bytecomp-original-functions 388 (setq cc-bytecomp-original-functions
350 (cons (list ',fun nil 'unbound) 389 (cons (list ',fun nil 'unbound)
351 cc-bytecomp-original-functions)))) 390 cc-bytecomp-original-functions))))
352 (if (and (cc-bytecomp-is-compiling) 391 (if (cc-bytecomp-is-compiling)
353 (not load-in-progress))
354 (progn 392 (progn
355 (fset ',fun (intern (concat "cc-bytecomp-ignore-fun:" 393 (fset ',fun (intern (concat "cc-bytecomp-ignore-fun:"
356 (symbol-name ',fun)))) 394 (symbol-name ',fun))))
diff --git a/lisp/progmodes/cc-defs.el b/lisp/progmodes/cc-defs.el
index 2ea566a7a25..d0beab1d485 100644
--- a/lisp/progmodes/cc-defs.el
+++ b/lisp/progmodes/cc-defs.el
@@ -1983,19 +1983,22 @@ system."
1983 1983
1984(defvar c-lang-const-expansion nil) 1984(defvar c-lang-const-expansion nil)
1985 1985
1986;; Ugly hack to pull in the definition of `cc-bytecomp-compiling-or-loading`
1987;; from cc-bytecomp to make it available at loadtime. This is the same
1988;; mechanism used in cc-mode.el for `c-populate-syntax-table'.
1989(defalias 'cc-bytecomp-compiling-or-loading
1990 (cc-eval-when-compile
1991 (let ((f (symbol-function 'cc-bytecomp-compiling-or-loading)))
1992 (if (byte-code-function-p f) f (byte-compile f)))))
1993
1986(defsubst c-get-current-file () 1994(defsubst c-get-current-file ()
1987 ;; Return the base name of the current file. 1995 ;; Return the base name of the current file.
1988 (let ((file (cond 1996 (let* ((c-or-l (cc-bytecomp-compiling-or-loading))
1989 (load-in-progress 1997 (file
1990 ;; Being loaded. 1998 (cond
1991 load-file-name) 1999 ((eq c-or-l 'loading) load-file-name)
1992 ((and (boundp 'byte-compile-dest-file) 2000 ((eq c-or-l 'compiling) byte-compile-dest-file)
1993 (stringp byte-compile-dest-file)) 2001 ((null c-or-l) (buffer-file-name)))))
1994 ;; Being compiled.
1995 byte-compile-dest-file)
1996 (t
1997 ;; Being evaluated interactively.
1998 (buffer-file-name)))))
1999 (and file 2002 (and file
2000 (file-name-sans-extension 2003 (file-name-sans-extension
2001 (file-name-nondirectory file))))) 2004 (file-name-nondirectory file)))))
@@ -2062,6 +2065,9 @@ constant. A file is identified by its base name."
2062 ;; language constant source definitions.) 2065 ;; language constant source definitions.)
2063 (c-lang-const-expansion 'call) 2066 (c-lang-const-expansion 'call)
2064 (c-langs-are-parametric t) 2067 (c-langs-are-parametric t)
2068 (file (intern
2069 (or (c-get-current-file)
2070 (error "`c-lang-defconst' can only be used in a file"))))
2065 bindings 2071 bindings
2066 pre-files) 2072 pre-files)
2067 2073
@@ -2121,9 +2127,14 @@ constant. A file is identified by its base name."
2121 ;; definitions for this symbol, to make sure the order in the 2127 ;; definitions for this symbol, to make sure the order in the
2122 ;; `source' property is correct even when files are loaded out of 2128 ;; `source' property is correct even when files are loaded out of
2123 ;; order. 2129 ;; order.
2124 (setq pre-files (nreverse 2130 (setq pre-files (mapcar 'car (get sym 'source)))
2125 ;; Reverse to get the right load order. 2131 (if (memq file pre-files)
2126 (mapcar 'car (get sym 'source)))) 2132 ;; This can happen when the source file (e.g. cc-langs.el) is first
2133 ;; loaded as source, setting a 'source property entry, and then itself
2134 ;; being compiled.
2135 (setq pre-files (cdr (memq file pre-files))))
2136 ;; Reverse to get the right load order.
2137 (setq pre-files (nreverse pre-files))
2127 2138
2128 `(eval-and-compile 2139 `(eval-and-compile
2129 (c-define-lang-constant ',name ,bindings 2140 (c-define-lang-constant ',name ,bindings
@@ -2233,9 +2244,7 @@ quoted."
2233 (if (or (eq c-lang-const-expansion 'call) 2244 (if (or (eq c-lang-const-expansion 'call)
2234 (and (not c-lang-const-expansion) 2245 (and (not c-lang-const-expansion)
2235 (not mode)) 2246 (not mode))
2236 load-in-progress 2247 (not (cc-bytecomp-is-compiling)))
2237 (not (boundp 'byte-compile-dest-file))
2238 (not (stringp byte-compile-dest-file)))
2239 ;; Either a straight call is requested in the context, or 2248 ;; Either a straight call is requested in the context, or
2240 ;; we're in an "uncontrolled" context and got no language, 2249 ;; we're in an "uncontrolled" context and got no language,
2241 ;; or we're not being byte compiled so the compile time 2250 ;; or we're not being byte compiled so the compile time
diff --git a/lisp/progmodes/cc-langs.el b/lisp/progmodes/cc-langs.el
index 17d717e740f..4d16a9b9d33 100644
--- a/lisp/progmodes/cc-langs.el
+++ b/lisp/progmodes/cc-langs.el
@@ -3260,10 +3260,7 @@ function it returns is byte compiled with all the evaluated results
3260from the language constants. Use the `c-init-language-vars' macro to 3260from the language constants. Use the `c-init-language-vars' macro to
3261accomplish that conveniently." 3261accomplish that conveniently."
3262 3262
3263 (if (and (not load-in-progress) 3263 (if (cc-bytecomp-is-compiling)
3264 (boundp 'byte-compile-dest-file)
3265 (stringp byte-compile-dest-file))
3266
3267 ;; No need to byte compile this lambda since the byte compiler is 3264 ;; No need to byte compile this lambda since the byte compiler is
3268 ;; smart enough to detect the `funcall' construct in the 3265 ;; smart enough to detect the `funcall' construct in the
3269 ;; `c-init-language-vars' macro below and compile it all straight 3266 ;; `c-init-language-vars' macro below and compile it all straight
diff --git a/lisp/progmodes/xref.el b/lisp/progmodes/xref.el
index b822619f783..7f77d218a48 100644
--- a/lisp/progmodes/xref.el
+++ b/lisp/progmodes/xref.el
@@ -301,6 +301,7 @@ backward."
301 (let ((marker (ring-remove ring))) 301 (let ((marker (ring-remove ring)))
302 (set-marker marker nil nil))))) 302 (set-marker marker nil nil)))))
303 303
304;;;###autoload
304(defun xref-marker-stack-empty-p () 305(defun xref-marker-stack-empty-p ()
305 "Return t if the marker stack is empty; nil otherwise." 306 "Return t if the marker stack is empty; nil otherwise."
306 (ring-empty-p xref--marker-ring)) 307 (ring-empty-p xref--marker-ring))