| 1 | ;;; byte-run.el --- byte-compiler support for inlining -*- lexical-binding: t -*- |
| 2 | |
| 3 | ;; Copyright (C) 1992, 2001-2014 Free Software Foundation, Inc. |
| 4 | |
| 5 | ;; Author: Jamie Zawinski <jwz@lucid.com> |
| 6 | ;; Hallvard Furuseth <hbf@ulrik.uio.no> |
| 7 | ;; Maintainer: emacs-devel@gnu.org |
| 8 | ;; Keywords: internal |
| 9 | ;; Package: emacs |
| 10 | |
| 11 | ;; This file is part of GNU Emacs. |
| 12 | |
| 13 | ;; GNU Emacs is free software: you can redistribute it and/or modify |
| 14 | ;; it under the terms of the GNU General Public License as published by |
| 15 | ;; the Free Software Foundation, either version 3 of the License, or |
| 16 | ;; (at your option) any later version. |
| 17 | |
| 18 | ;; GNU Emacs is distributed in the hope that it will be useful, |
| 19 | ;; but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 20 | ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 21 | ;; GNU General Public License for more details. |
| 22 | |
| 23 | ;; You should have received a copy of the GNU General Public License |
| 24 | ;; along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. |
| 25 | |
| 26 | ;;; Commentary: |
| 27 | |
| 28 | ;; interface to selectively inlining functions. |
| 29 | ;; This only happens when source-code optimization is turned on. |
| 30 | |
| 31 | ;;; Code: |
| 32 | |
| 33 | ;; `macro-declaration-function' are both obsolete (as marked at the end of this |
| 34 | ;; file) but used in many .elc files. |
| 35 | |
| 36 | (defvar macro-declaration-function #'macro-declaration-function |
| 37 | "Function to process declarations in a macro definition. |
| 38 | The function will be called with two args MACRO and DECL. |
| 39 | MACRO is the name of the macro being defined. |
| 40 | DECL is a list `(declare ...)' containing the declarations. |
| 41 | The value the function returns is not used.") |
| 42 | |
| 43 | (defalias 'macro-declaration-function |
| 44 | #'(lambda (macro decl) |
| 45 | "Process a declaration found in a macro definition. |
| 46 | This is set as the value of the variable `macro-declaration-function'. |
| 47 | MACRO is the name of the macro being defined. |
| 48 | DECL is a list `(declare ...)' containing the declarations. |
| 49 | The return value of this function is not used." |
| 50 | ;; We can't use `dolist' or `cadr' yet for bootstrapping reasons. |
| 51 | (let (d) |
| 52 | ;; Ignore the first element of `decl' (it's always `declare'). |
| 53 | (while (setq decl (cdr decl)) |
| 54 | (setq d (car decl)) |
| 55 | (if (and (consp d) |
| 56 | (listp (cdr d)) |
| 57 | (null (cdr (cdr d)))) |
| 58 | (cond ((eq (car d) 'indent) |
| 59 | (put macro 'lisp-indent-function (car (cdr d)))) |
| 60 | ((eq (car d) 'debug) |
| 61 | (put macro 'edebug-form-spec (car (cdr d)))) |
| 62 | ((eq (car d) 'doc-string) |
| 63 | (put macro 'doc-string-elt (car (cdr d)))) |
| 64 | (t |
| 65 | (message "Unknown declaration %s" d))) |
| 66 | (message "Invalid declaration %s" d)))))) |
| 67 | |
| 68 | ;; We define macro-declaration-alist here because it is needed to |
| 69 | ;; handle declarations in macro definitions and this is the first file |
| 70 | ;; loaded by loadup.el that uses declarations in macros. |
| 71 | |
| 72 | ;; Add any new entries to info node `(elisp)Declare Form'. |
| 73 | (defvar defun-declarations-alist |
| 74 | (list |
| 75 | ;; We can only use backquotes inside the lambdas and not for those |
| 76 | ;; properties that are used by functions loaded before backquote.el. |
| 77 | (list 'advertised-calling-convention |
| 78 | #'(lambda (f _args arglist when) |
| 79 | (list 'set-advertised-calling-convention |
| 80 | (list 'quote f) (list 'quote arglist) (list 'quote when)))) |
| 81 | (list 'obsolete |
| 82 | #'(lambda (f _args new-name when) |
| 83 | (list 'make-obsolete |
| 84 | (list 'quote f) (list 'quote new-name) (list 'quote when)))) |
| 85 | (list 'interactive-only |
| 86 | #'(lambda (f _args instead) |
| 87 | (list 'put (list 'quote f) ''interactive-only |
| 88 | (list 'quote instead)))) |
| 89 | (list 'compiler-macro |
| 90 | #'(lambda (f args compiler-function) |
| 91 | `(eval-and-compile |
| 92 | (put ',f 'compiler-macro |
| 93 | ,(if (eq (car-safe compiler-function) 'lambda) |
| 94 | `(lambda ,(append (cadr compiler-function) args) |
| 95 | ,@(cddr compiler-function)) |
| 96 | `#',compiler-function))))) |
| 97 | (list 'doc-string |
| 98 | #'(lambda (f _args pos) |
| 99 | (list 'put (list 'quote f) ''doc-string-elt (list 'quote pos)))) |
| 100 | (list 'indent |
| 101 | #'(lambda (f _args val) |
| 102 | (list 'put (list 'quote f) |
| 103 | ''lisp-indent-function (list 'quote val))))) |
| 104 | "List associating function properties to their macro expansion. |
| 105 | Each element of the list takes the form (PROP FUN) where FUN is |
| 106 | a function. For each (PROP . VALUES) in a function's declaration, |
| 107 | the FUN corresponding to PROP is called with the function name, |
| 108 | the function's arglist, and the VALUES and should return the code to use |
| 109 | to set this property. |
| 110 | |
| 111 | This is used by `declare'.") |
| 112 | |
| 113 | (defvar macro-declarations-alist |
| 114 | (cons |
| 115 | (list 'debug |
| 116 | #'(lambda (name _args spec) |
| 117 | (list 'progn :autoload-end |
| 118 | (list 'put (list 'quote name) |
| 119 | ''edebug-form-spec (list 'quote spec))))) |
| 120 | defun-declarations-alist) |
| 121 | "List associating properties of macros to their macro expansion. |
| 122 | Each element of the list takes the form (PROP FUN) where FUN is a function. |
| 123 | For each (PROP . VALUES) in a macro's declaration, the FUN corresponding |
| 124 | to PROP is called with the macro name, the macro's arglist, and the VALUES |
| 125 | and should return the code to use to set this property. |
| 126 | |
| 127 | This is used by `declare'.") |
| 128 | |
| 129 | (put 'defmacro 'doc-string-elt 3) |
| 130 | (put 'defmacro 'lisp-indent-function 2) |
| 131 | (defalias 'defmacro |
| 132 | (cons |
| 133 | 'macro |
| 134 | #'(lambda (name arglist &optional docstring &rest body) |
| 135 | "Define NAME as a macro. |
| 136 | When the macro is called, as in (NAME ARGS...), |
| 137 | the function (lambda ARGLIST BODY...) is applied to |
| 138 | the list ARGS... as it appears in the expression, |
| 139 | and the result should be a form to be evaluated instead of the original. |
| 140 | DECL is a declaration, optional, of the form (declare DECLS...) where |
| 141 | DECLS is a list of elements of the form (PROP . VALUES). These are |
| 142 | interpreted according to `macro-declarations-alist'. |
| 143 | The return value is undefined. |
| 144 | |
| 145 | \(fn NAME ARGLIST &optional DOCSTRING DECL &rest BODY)" |
| 146 | ;; We can't just have `decl' as an &optional argument, because we need |
| 147 | ;; to distinguish |
| 148 | ;; (defmacro foo (arg) (bar) nil) |
| 149 | ;; from |
| 150 | ;; (defmacro foo (arg) (bar)). |
| 151 | (let ((decls (cond |
| 152 | ((eq (car-safe docstring) 'declare) |
| 153 | (prog1 (cdr docstring) (setq docstring nil))) |
| 154 | ((and (stringp docstring) |
| 155 | (eq (car-safe (car body)) 'declare)) |
| 156 | (prog1 (cdr (car body)) (setq body (cdr body))))))) |
| 157 | (if docstring (setq body (cons docstring body)) |
| 158 | (if (null body) (setq body '(nil)))) |
| 159 | ;; Can't use backquote because it's not defined yet! |
| 160 | (let* ((fun (list 'function (cons 'lambda (cons arglist body)))) |
| 161 | (def (list 'defalias |
| 162 | (list 'quote name) |
| 163 | (list 'cons ''macro fun))) |
| 164 | (declarations |
| 165 | (mapcar |
| 166 | #'(lambda (x) |
| 167 | (let ((f (cdr (assq (car x) macro-declarations-alist)))) |
| 168 | (if f (apply (car f) name arglist (cdr x)) |
| 169 | (message "Warning: Unknown macro property %S in %S" |
| 170 | (car x) name)))) |
| 171 | decls))) |
| 172 | (if declarations |
| 173 | (cons 'prog1 (cons def declarations)) |
| 174 | def)))))) |
| 175 | |
| 176 | ;; Now that we defined defmacro we can use it! |
| 177 | (defmacro defun (name arglist &optional docstring &rest body) |
| 178 | "Define NAME as a function. |
| 179 | The definition is (lambda ARGLIST [DOCSTRING] BODY...). |
| 180 | See also the function `interactive'. |
| 181 | DECL is a declaration, optional, of the form (declare DECLS...) where |
| 182 | DECLS is a list of elements of the form (PROP . VALUES). These are |
| 183 | interpreted according to `defun-declarations-alist'. |
| 184 | The return value is undefined. |
| 185 | |
| 186 | \(fn NAME ARGLIST &optional DOCSTRING DECL &rest BODY)" |
| 187 | ;; We can't just have `decl' as an &optional argument, because we need |
| 188 | ;; to distinguish |
| 189 | ;; (defun foo (arg) (toto) nil) |
| 190 | ;; from |
| 191 | ;; (defun foo (arg) (toto)). |
| 192 | (declare (doc-string 3) (indent 2)) |
| 193 | (let ((decls (cond |
| 194 | ((eq (car-safe docstring) 'declare) |
| 195 | (prog1 (cdr docstring) (setq docstring nil))) |
| 196 | ((and (stringp docstring) |
| 197 | (eq (car-safe (car body)) 'declare)) |
| 198 | (prog1 (cdr (car body)) (setq body (cdr body))))))) |
| 199 | (if docstring (setq body (cons docstring body)) |
| 200 | (if (null body) (setq body '(nil)))) |
| 201 | (let ((declarations |
| 202 | (mapcar |
| 203 | #'(lambda (x) |
| 204 | (let ((f (cdr (assq (car x) defun-declarations-alist)))) |
| 205 | (cond |
| 206 | (f (apply (car f) name arglist (cdr x))) |
| 207 | ;; Yuck!! |
| 208 | ((and (featurep 'cl) |
| 209 | (memq (car x) ;C.f. cl-do-proclaim. |
| 210 | '(special inline notinline optimize warn))) |
| 211 | (push (list 'declare x) |
| 212 | (if (stringp docstring) |
| 213 | (if (eq (car-safe (cadr body)) 'interactive) |
| 214 | (cddr body) |
| 215 | (cdr body)) |
| 216 | (if (eq (car-safe (car body)) 'interactive) |
| 217 | (cdr body) |
| 218 | body))) |
| 219 | nil) |
| 220 | (t (message "Warning: Unknown defun property `%S' in %S" |
| 221 | (car x) name))))) |
| 222 | decls)) |
| 223 | (def (list 'defalias |
| 224 | (list 'quote name) |
| 225 | (list 'function |
| 226 | (cons 'lambda |
| 227 | (cons arglist body)))))) |
| 228 | (if declarations |
| 229 | (cons 'prog1 (cons def declarations)) |
| 230 | def)))) |
| 231 | \f |
| 232 | ;; Redefined in byte-optimize.el. |
| 233 | ;; This is not documented--it's not clear that we should promote it. |
| 234 | (fset 'inline 'progn) |
| 235 | |
| 236 | ;;; Interface to inline functions. |
| 237 | |
| 238 | ;; (defmacro proclaim-inline (&rest fns) |
| 239 | ;; "Cause the named functions to be open-coded when called from compiled code. |
| 240 | ;; They will only be compiled open-coded when byte-compile-optimize is true." |
| 241 | ;; (cons 'eval-and-compile |
| 242 | ;; (mapcar (lambda (x) |
| 243 | ;; (or (memq (get x 'byte-optimizer) |
| 244 | ;; '(nil byte-compile-inline-expand)) |
| 245 | ;; (error |
| 246 | ;; "%s already has a byte-optimizer, can't make it inline" |
| 247 | ;; x)) |
| 248 | ;; (list 'put (list 'quote x) |
| 249 | ;; ''byte-optimizer ''byte-compile-inline-expand)) |
| 250 | ;; fns))) |
| 251 | |
| 252 | ;; (defmacro proclaim-notinline (&rest fns) |
| 253 | ;; "Cause the named functions to no longer be open-coded." |
| 254 | ;; (cons 'eval-and-compile |
| 255 | ;; (mapcar (lambda (x) |
| 256 | ;; (if (eq (get x 'byte-optimizer) 'byte-compile-inline-expand) |
| 257 | ;; (put x 'byte-optimizer nil)) |
| 258 | ;; (list 'if (list 'eq (list 'get (list 'quote x) ''byte-optimizer) |
| 259 | ;; ''byte-compile-inline-expand) |
| 260 | ;; (list 'put x ''byte-optimizer nil))) |
| 261 | ;; fns))) |
| 262 | |
| 263 | (defmacro defsubst (name arglist &rest body) |
| 264 | "Define an inline function. The syntax is just like that of `defun'. |
| 265 | \(fn NAME ARGLIST &optional DOCSTRING DECL &rest BODY)" |
| 266 | (declare (debug defun) (doc-string 3)) |
| 267 | (or (memq (get name 'byte-optimizer) |
| 268 | '(nil byte-compile-inline-expand)) |
| 269 | (error "`%s' is a primitive" name)) |
| 270 | `(prog1 |
| 271 | (defun ,name ,arglist ,@body) |
| 272 | (eval-and-compile |
| 273 | (put ',name 'byte-optimizer 'byte-compile-inline-expand)))) |
| 274 | |
| 275 | (defvar advertised-signature-table (make-hash-table :test 'eq :weakness 'key)) |
| 276 | |
| 277 | (defun set-advertised-calling-convention (function signature _when) |
| 278 | "Set the advertised SIGNATURE of FUNCTION. |
| 279 | This will allow the byte-compiler to warn the programmer when she uses |
| 280 | an obsolete calling convention. WHEN specifies since when the calling |
| 281 | convention was modified." |
| 282 | (puthash (indirect-function function) signature |
| 283 | advertised-signature-table)) |
| 284 | |
| 285 | (defun make-obsolete (obsolete-name current-name &optional when) |
| 286 | "Make the byte-compiler warn that function OBSOLETE-NAME is obsolete. |
| 287 | OBSOLETE-NAME should be a function name or macro name (a symbol). |
| 288 | |
| 289 | The warning will say that CURRENT-NAME should be used instead. |
| 290 | If CURRENT-NAME is a string, that is the `use instead' message |
| 291 | \(it should end with a period, and not start with a capital). |
| 292 | WHEN should be a string indicating when the function |
| 293 | was first made obsolete, for example a date or a release number." |
| 294 | (declare (advertised-calling-convention |
| 295 | ;; New code should always provide the `when' argument. |
| 296 | (obsolete-name current-name when) "23.1")) |
| 297 | (put obsolete-name 'byte-obsolete-info |
| 298 | ;; The second entry used to hold the `byte-compile' handler, but |
| 299 | ;; is not used any more nowadays. |
| 300 | (purecopy (list current-name nil when))) |
| 301 | obsolete-name) |
| 302 | |
| 303 | (defmacro define-obsolete-function-alias (obsolete-name current-name |
| 304 | &optional when docstring) |
| 305 | "Set OBSOLETE-NAME's function definition to CURRENT-NAME and mark it obsolete. |
| 306 | |
| 307 | \(define-obsolete-function-alias 'old-fun 'new-fun \"22.1\" \"old-fun's doc.\") |
| 308 | |
| 309 | is equivalent to the following two lines of code: |
| 310 | |
| 311 | \(defalias 'old-fun 'new-fun \"old-fun's doc.\") |
| 312 | \(make-obsolete 'old-fun 'new-fun \"22.1\") |
| 313 | |
| 314 | See the docstrings of `defalias' and `make-obsolete' for more details." |
| 315 | (declare (doc-string 4) |
| 316 | (advertised-calling-convention |
| 317 | ;; New code should always provide the `when' argument. |
| 318 | (obsolete-name current-name when &optional docstring) "23.1")) |
| 319 | `(progn |
| 320 | (defalias ,obsolete-name ,current-name ,docstring) |
| 321 | (make-obsolete ,obsolete-name ,current-name ,when))) |
| 322 | |
| 323 | (defun make-obsolete-variable (obsolete-name current-name &optional when access-type) |
| 324 | "Make the byte-compiler warn that OBSOLETE-NAME is obsolete. |
| 325 | The warning will say that CURRENT-NAME should be used instead. |
| 326 | If CURRENT-NAME is a string, that is the `use instead' message. |
| 327 | WHEN should be a string indicating when the variable |
| 328 | was first made obsolete, for example a date or a release number. |
| 329 | ACCESS-TYPE if non-nil should specify the kind of access that will trigger |
| 330 | obsolescence warnings; it can be either `get' or `set'." |
| 331 | (declare (advertised-calling-convention |
| 332 | ;; New code should always provide the `when' argument. |
| 333 | (obsolete-name current-name when &optional access-type) "23.1")) |
| 334 | (put obsolete-name 'byte-obsolete-variable |
| 335 | (purecopy (list current-name access-type when))) |
| 336 | obsolete-name) |
| 337 | |
| 338 | |
| 339 | (defmacro define-obsolete-variable-alias (obsolete-name current-name |
| 340 | &optional when docstring) |
| 341 | "Make OBSOLETE-NAME a variable alias for CURRENT-NAME and mark it obsolete. |
| 342 | This uses `defvaralias' and `make-obsolete-variable' (which see). |
| 343 | See the Info node `(elisp)Variable Aliases' for more details. |
| 344 | |
| 345 | If CURRENT-NAME is a defcustom (more generally, any variable |
| 346 | where OBSOLETE-NAME may be set, e.g. in an init file, before the |
| 347 | alias is defined), then the define-obsolete-variable-alias |
| 348 | statement should be evaluated before the defcustom, if user |
| 349 | customizations are to be respected. The simplest way to achieve |
| 350 | this is to place the alias statement before the defcustom (this |
| 351 | is not necessary for aliases that are autoloaded, or in files |
| 352 | dumped with Emacs). This is so that any user customizations are |
| 353 | applied before the defcustom tries to initialize the |
| 354 | variable (this is due to the way `defvaralias' works). |
| 355 | |
| 356 | For the benefit of `custom-set-variables', if OBSOLETE-NAME has |
| 357 | any of the following properties, they are copied to |
| 358 | CURRENT-NAME, if it does not already have them: |
| 359 | 'saved-value, 'saved-variable-comment." |
| 360 | (declare (doc-string 4) |
| 361 | (advertised-calling-convention |
| 362 | ;; New code should always provide the `when' argument. |
| 363 | (obsolete-name current-name when &optional docstring) "23.1")) |
| 364 | `(progn |
| 365 | (defvaralias ,obsolete-name ,current-name ,docstring) |
| 366 | ;; See Bug#4706. |
| 367 | (dolist (prop '(saved-value saved-variable-comment)) |
| 368 | (and (get ,obsolete-name prop) |
| 369 | (null (get ,current-name prop)) |
| 370 | (put ,current-name prop (get ,obsolete-name prop)))) |
| 371 | (make-obsolete-variable ,obsolete-name ,current-name ,when))) |
| 372 | |
| 373 | ;; FIXME This is only defined in this file because the variable- and |
| 374 | ;; function- versions are too. Unlike those two, this one is not used |
| 375 | ;; by the byte-compiler (would be nice if it could warn about obsolete |
| 376 | ;; faces, but it doesn't really do anything special with faces). |
| 377 | ;; It only really affects M-x describe-face output. |
| 378 | (defmacro define-obsolete-face-alias (obsolete-face current-face when) |
| 379 | "Make OBSOLETE-FACE a face alias for CURRENT-FACE and mark it obsolete. |
| 380 | The string WHEN gives the Emacs version where OBSOLETE-FACE became |
| 381 | obsolete." |
| 382 | `(progn |
| 383 | (put ,obsolete-face 'face-alias ,current-face) |
| 384 | ;; Used by M-x describe-face. |
| 385 | (put ,obsolete-face 'obsolete-face (or (purecopy ,when) t)))) |
| 386 | |
| 387 | (defmacro dont-compile (&rest body) |
| 388 | "Like `progn', but the body always runs interpreted (not compiled). |
| 389 | If you think you need this, you're probably making a mistake somewhere." |
| 390 | (declare (debug t) (indent 0) (obsolete nil "24.4")) |
| 391 | (list 'eval (list 'quote (if (cdr body) (cons 'progn body) (car body))))) |
| 392 | |
| 393 | \f |
| 394 | ;; interface to evaluating things at compile time and/or load time |
| 395 | ;; these macro must come after any uses of them in this file, as their |
| 396 | ;; definition in the file overrides the magic definitions on the |
| 397 | ;; byte-compile-macro-environment. |
| 398 | |
| 399 | (defmacro eval-when-compile (&rest body) |
| 400 | "Like `progn', but evaluates the body at compile time if you're compiling. |
| 401 | Thus, the result of the body appears to the compiler as a quoted constant. |
| 402 | In interpreted code, this is entirely equivalent to `progn'." |
| 403 | (declare (debug (&rest def-form)) (indent 0)) |
| 404 | (list 'quote (eval (cons 'progn body) lexical-binding))) |
| 405 | |
| 406 | (defmacro eval-and-compile (&rest body) |
| 407 | "Like `progn', but evaluates the body at compile time and at load time." |
| 408 | (declare (debug t) (indent 0)) |
| 409 | ;; When the byte-compiler expands code, this macro is not used, so we're |
| 410 | ;; either about to run `body' (plain interpretation) or we're doing eager |
| 411 | ;; macroexpansion. |
| 412 | (list 'quote (eval (cons 'progn body) lexical-binding))) |
| 413 | |
| 414 | (defun with-no-warnings (&rest body) |
| 415 | "Like `progn', but prevents compiler warnings in the body." |
| 416 | (declare (indent 0)) |
| 417 | ;; The implementation for the interpreter is basically trivial. |
| 418 | (car (last body))) |
| 419 | |
| 420 | \f |
| 421 | ;; I nuked this because it's not a good idea for users to think of using it. |
| 422 | ;; These options are a matter of installation preference, and have nothing to |
| 423 | ;; with particular source files; it's a mistake to suggest to users |
| 424 | ;; they should associate these with particular source files. |
| 425 | ;; There is hardly any reason to change these parameters, anyway. |
| 426 | ;; --rms. |
| 427 | |
| 428 | ;; (put 'byte-compiler-options 'lisp-indent-function 0) |
| 429 | ;; (defmacro byte-compiler-options (&rest args) |
| 430 | ;; "Set some compilation-parameters for this file. This will affect only the |
| 431 | ;; file in which it appears; this does nothing when evaluated, and when loaded |
| 432 | ;; from a .el file. |
| 433 | ;; |
| 434 | ;; Each argument to this macro must be a list of a key and a value. |
| 435 | ;; |
| 436 | ;; Keys: Values: Corresponding variable: |
| 437 | ;; |
| 438 | ;; verbose t, nil byte-compile-verbose |
| 439 | ;; optimize t, nil, source, byte byte-compile-optimize |
| 440 | ;; warnings list of warnings byte-compile-warnings |
| 441 | ;; Valid elements: (callargs redefine free-vars unresolved) |
| 442 | ;; file-format emacs18, emacs19 byte-compile-compatibility |
| 443 | ;; |
| 444 | ;; For example, this might appear at the top of a source file: |
| 445 | ;; |
| 446 | ;; (byte-compiler-options |
| 447 | ;; (optimize t) |
| 448 | ;; (warnings (- free-vars)) ; Don't warn about free variables |
| 449 | ;; (file-format emacs19))" |
| 450 | ;; nil) |
| 451 | |
| 452 | (make-obsolete-variable 'macro-declaration-function |
| 453 | 'macro-declarations-alist "24.3") |
| 454 | (make-obsolete 'macro-declaration-function |
| 455 | 'macro-declarations-alist "24.3") |
| 456 | |
| 457 | ;;; byte-run.el ends here |