mirror of
git://git.sv.gnu.org/emacs.git
synced 2026-01-01 09:51:22 -08:00
Remove bytecomp- prefix, plus misc changes.
* lisp/emacs-lisp/byte-opt.el (byte-compile-inline-expand): Make it work to inline lexbind interpreted functions into lexbind code. (bytedecomp-bytes): Not a dynamic var any more. (disassemble-offset): Get the bytes via an argument instead. (byte-decompile-bytecode-1): Use push. * lisp/emacs-lisp/bytecomp.el: Remove the bytecomp- prefix now that we use lexical-binding. (byte-compile-outbuffer): Rename from bytecomp-outbuffer. * lisp/emacs-lisp/cl-macs.el (load-time-value): * lisp/emacs-lisp/cl.el (cl-compiling-file): Adjust to new name. * lisp/emacs-lisp/pcase.el (pcase-mutually-exclusive-predicates): Add byte-code-function-p. (pcase--u1): Remove left-over code from early development. Fix case of variable shadowing in guards and predicates. (pcase--u1): Add a new `let' pattern. * src/image.c (parse_image_spec): Use Ffunctionp. * src/lisp.h: Declare Ffunctionp.
This commit is contained in:
parent
2663659f1f
commit
ca1055060d
14 changed files with 453 additions and 389 deletions
|
|
@ -1,3 +1,23 @@
|
||||||
|
2011-03-16 Stefan Monnier <monnier@iro.umontreal.ca>
|
||||||
|
|
||||||
|
* emacs-lisp/pcase.el (pcase-mutually-exclusive-predicates):
|
||||||
|
Add byte-code-function-p.
|
||||||
|
(pcase--u1): Remove left-over code from early development.
|
||||||
|
Fix case of variable shadowing in guards and predicates.
|
||||||
|
(pcase--u1): Add a new `let' pattern.
|
||||||
|
|
||||||
|
* emacs-lisp/bytecomp.el: Remove the bytecomp- prefix now that we use
|
||||||
|
lexical-binding.
|
||||||
|
(byte-compile-outbuffer): Rename from bytecomp-outbuffer.
|
||||||
|
* emacs-lisp/cl-macs.el (load-time-value):
|
||||||
|
* emacs-lisp/cl.el (cl-compiling-file): Adjust to new name.
|
||||||
|
|
||||||
|
* emacs-lisp/byte-opt.el (byte-compile-inline-expand): Make it work to
|
||||||
|
inline lexbind interpreted functions into lexbind code.
|
||||||
|
(bytedecomp-bytes): Not a dynamic var any more.
|
||||||
|
(disassemble-offset): Get the bytes via an argument instead.
|
||||||
|
(byte-decompile-bytecode-1): Use push.
|
||||||
|
|
||||||
2011-03-15 Stefan Monnier <monnier@iro.umontreal.ca>
|
2011-03-15 Stefan Monnier <monnier@iro.umontreal.ca>
|
||||||
|
|
||||||
* makefile.w32-in (COMPILE_FIRST): Fix up last change.
|
* makefile.w32-in (COMPILE_FIRST): Fix up last change.
|
||||||
|
|
|
||||||
|
|
@ -265,45 +265,72 @@
|
||||||
|
|
||||||
(defun byte-compile-inline-expand (form)
|
(defun byte-compile-inline-expand (form)
|
||||||
(let* ((name (car form))
|
(let* ((name (car form))
|
||||||
(fn (or (cdr (assq name byte-compile-function-environment))
|
(localfn (cdr (assq name byte-compile-function-environment)))
|
||||||
(and (fboundp name) (symbol-function name)))))
|
(fn (or localfn (and (fboundp name) (symbol-function name)))))
|
||||||
(if (null fn)
|
(when (and (consp fn) (eq (car fn) 'autoload))
|
||||||
(progn
|
(load (nth 1 fn))
|
||||||
(byte-compile-warn "attempt to inline `%s' before it was defined"
|
(setq fn (or (and (fboundp name) (symbol-function name))
|
||||||
name)
|
(cdr (assq name byte-compile-function-environment)))))
|
||||||
form)
|
(pcase fn
|
||||||
;; else
|
(`nil
|
||||||
(when (and (consp fn) (eq (car fn) 'autoload))
|
(byte-compile-warn "attempt to inline `%s' before it was defined"
|
||||||
(load (nth 1 fn))
|
name)
|
||||||
(setq fn (or (and (fboundp name) (symbol-function name))
|
form)
|
||||||
(cdr (assq name byte-compile-function-environment)))))
|
(`(autoload . ,_)
|
||||||
(if (and (consp fn) (eq (car fn) 'autoload))
|
(error "File `%s' didn't define `%s'" (nth 1 fn) name))
|
||||||
(error "File `%s' didn't define `%s'" (nth 1 fn) name))
|
((and (pred symbolp) (guard (not (eq fn t)))) ;A function alias.
|
||||||
(cond
|
(byte-compile-inline-expand (cons fn (cdr form))))
|
||||||
((and (symbolp fn) (not (eq fn t))) ;A function alias.
|
((and (pred byte-code-function-p)
|
||||||
(byte-compile-inline-expand (cons fn (cdr form))))
|
;; FIXME: This only works to inline old-style-byte-codes into
|
||||||
((and (byte-code-function-p fn)
|
;; old-style-byte-codes.
|
||||||
;; FIXME: This works to inline old-style-byte-codes into
|
(guard (not (or lexical-binding
|
||||||
;; old-style-byte-codes, but not mixed cases (not sure
|
(integerp (aref fn 0))))))
|
||||||
;; about new-style into new-style).
|
;; (message "Inlining %S byte-code" name)
|
||||||
(not lexical-binding)
|
(fetch-bytecode fn)
|
||||||
(not (integerp (aref fn 0)))) ;New lexical byte-code.
|
(let ((string (aref fn 1)))
|
||||||
;; (message "Inlining %S byte-code" name)
|
(assert (not (multibyte-string-p string)))
|
||||||
(fetch-bytecode fn)
|
;; `byte-compile-splice-in-already-compiled-code'
|
||||||
(let ((string (aref fn 1)))
|
;; takes care of inlining the body.
|
||||||
;; Isn't it an error for `string' not to be unibyte?? --stef
|
(cons `(lambda ,(aref fn 0)
|
||||||
(if (fboundp 'string-as-unibyte)
|
(byte-code ,string ,(aref fn 2) ,(aref fn 3)))
|
||||||
(setq string (string-as-unibyte string)))
|
(cdr form))))
|
||||||
;; `byte-compile-splice-in-already-compiled-code'
|
((and `(lambda . ,_)
|
||||||
;; takes care of inlining the body.
|
;; With lexical-binding we have several problems:
|
||||||
(cons `(lambda ,(aref fn 0)
|
;; - if `fn' comes from byte-compile-function-environment, we
|
||||||
(byte-code ,string ,(aref fn 2) ,(aref fn 3)))
|
;; need to preprocess `fn', so we handle it below.
|
||||||
(cdr form))))
|
;; - else, it means that `fn' is dyn-bound (otherwise it would
|
||||||
((eq (car-safe fn) 'lambda)
|
;; start with `closure') so copying the code here would cause
|
||||||
(macroexpand-all (cons fn (cdr form))
|
;; it to be mis-interpreted.
|
||||||
byte-compile-macro-environment))
|
(guard (not lexical-binding)))
|
||||||
(t ;; Give up on inlining.
|
(macroexpand-all (cons fn (cdr form))
|
||||||
form)))))
|
byte-compile-macro-environment))
|
||||||
|
((and (or (and `(lambda ,args . ,body)
|
||||||
|
(let env nil)
|
||||||
|
(guard (eq fn localfn)))
|
||||||
|
`(closure ,env ,args . ,body))
|
||||||
|
(guard lexical-binding))
|
||||||
|
(let ((renv ()))
|
||||||
|
(dolist (binding env)
|
||||||
|
(cond
|
||||||
|
((consp binding)
|
||||||
|
;; We check shadowing by the args, so that the `let' can be
|
||||||
|
;; moved within the lambda, which can then be unfolded.
|
||||||
|
;; FIXME: Some of those bindings might be unused in `body'.
|
||||||
|
(unless (memq (car binding) args) ;Shadowed.
|
||||||
|
(push `(,(car binding) ',(cdr binding)) renv)))
|
||||||
|
((eq binding t))
|
||||||
|
(t (push `(defvar ,binding) body))))
|
||||||
|
;; (message "Inlining closure %S" (car form))
|
||||||
|
(let ((newfn (byte-compile-preprocess
|
||||||
|
`(lambda ,args (let ,(nreverse renv) ,@body)))))
|
||||||
|
(if (eq (car-safe newfn) 'function)
|
||||||
|
(byte-compile-unfold-lambda `(,(cadr newfn) ,@(cdr form)))
|
||||||
|
(byte-compile-log-warning
|
||||||
|
(format "Inlining closure %S failed" name))
|
||||||
|
form))))
|
||||||
|
|
||||||
|
(t ;; Give up on inlining.
|
||||||
|
form))))
|
||||||
|
|
||||||
;; ((lambda ...) ...)
|
;; ((lambda ...) ...)
|
||||||
(defun byte-compile-unfold-lambda (form &optional name)
|
(defun byte-compile-unfold-lambda (form &optional name)
|
||||||
|
|
@ -1095,7 +1122,7 @@
|
||||||
(let ((fn (nth 1 form)))
|
(let ((fn (nth 1 form)))
|
||||||
(if (memq (car-safe fn) '(quote function))
|
(if (memq (car-safe fn) '(quote function))
|
||||||
(cons (nth 1 fn) (cdr (cdr form)))
|
(cons (nth 1 fn) (cdr (cdr form)))
|
||||||
form)))
|
form)))
|
||||||
|
|
||||||
(defun byte-optimize-apply (form)
|
(defun byte-optimize-apply (form)
|
||||||
;; If the last arg is a literal constant, turn this into a funcall.
|
;; If the last arg is a literal constant, turn this into a funcall.
|
||||||
|
|
@ -1318,43 +1345,42 @@
|
||||||
;; Used and set dynamically in byte-decompile-bytecode-1.
|
;; Used and set dynamically in byte-decompile-bytecode-1.
|
||||||
(defvar bytedecomp-op)
|
(defvar bytedecomp-op)
|
||||||
(defvar bytedecomp-ptr)
|
(defvar bytedecomp-ptr)
|
||||||
(defvar bytedecomp-bytes)
|
|
||||||
|
|
||||||
;; This function extracts the bitfields from variable-length opcodes.
|
;; This function extracts the bitfields from variable-length opcodes.
|
||||||
;; Originally defined in disass.el (which no longer uses it.)
|
;; Originally defined in disass.el (which no longer uses it.)
|
||||||
(defun disassemble-offset ()
|
(defun disassemble-offset (bytes)
|
||||||
"Don't call this!"
|
"Don't call this!"
|
||||||
;; fetch and return the offset for the current opcode.
|
;; Fetch and return the offset for the current opcode.
|
||||||
;; return nil if this opcode has no offset
|
;; Return nil if this opcode has no offset.
|
||||||
(cond ((< bytedecomp-op byte-nth)
|
(cond ((< bytedecomp-op byte-nth)
|
||||||
(let ((tem (logand bytedecomp-op 7)))
|
(let ((tem (logand bytedecomp-op 7)))
|
||||||
(setq bytedecomp-op (logand bytedecomp-op 248))
|
(setq bytedecomp-op (logand bytedecomp-op 248))
|
||||||
(cond ((eq tem 6)
|
(cond ((eq tem 6)
|
||||||
;; Offset in next byte.
|
;; Offset in next byte.
|
||||||
(setq bytedecomp-ptr (1+ bytedecomp-ptr))
|
(setq bytedecomp-ptr (1+ bytedecomp-ptr))
|
||||||
(aref bytedecomp-bytes bytedecomp-ptr))
|
(aref bytes bytedecomp-ptr))
|
||||||
((eq tem 7)
|
((eq tem 7)
|
||||||
;; Offset in next 2 bytes.
|
;; Offset in next 2 bytes.
|
||||||
(setq bytedecomp-ptr (1+ bytedecomp-ptr))
|
(setq bytedecomp-ptr (1+ bytedecomp-ptr))
|
||||||
(+ (aref bytedecomp-bytes bytedecomp-ptr)
|
(+ (aref bytes bytedecomp-ptr)
|
||||||
(progn (setq bytedecomp-ptr (1+ bytedecomp-ptr))
|
(progn (setq bytedecomp-ptr (1+ bytedecomp-ptr))
|
||||||
(lsh (aref bytedecomp-bytes bytedecomp-ptr) 8))))
|
(lsh (aref bytes bytedecomp-ptr) 8))))
|
||||||
(t tem)))) ;offset was in opcode
|
(t tem)))) ;Offset was in opcode.
|
||||||
((>= bytedecomp-op byte-constant)
|
((>= bytedecomp-op byte-constant)
|
||||||
(prog1 (- bytedecomp-op byte-constant) ;offset in opcode
|
(prog1 (- bytedecomp-op byte-constant) ;Offset in opcode.
|
||||||
(setq bytedecomp-op byte-constant)))
|
(setq bytedecomp-op byte-constant)))
|
||||||
((or (and (>= bytedecomp-op byte-constant2)
|
((or (and (>= bytedecomp-op byte-constant2)
|
||||||
(<= bytedecomp-op byte-goto-if-not-nil-else-pop))
|
(<= bytedecomp-op byte-goto-if-not-nil-else-pop))
|
||||||
(= bytedecomp-op byte-stack-set2))
|
(= bytedecomp-op byte-stack-set2))
|
||||||
;; Offset in next 2 bytes.
|
;; Offset in next 2 bytes.
|
||||||
(setq bytedecomp-ptr (1+ bytedecomp-ptr))
|
(setq bytedecomp-ptr (1+ bytedecomp-ptr))
|
||||||
(+ (aref bytedecomp-bytes bytedecomp-ptr)
|
(+ (aref bytes bytedecomp-ptr)
|
||||||
(progn (setq bytedecomp-ptr (1+ bytedecomp-ptr))
|
(progn (setq bytedecomp-ptr (1+ bytedecomp-ptr))
|
||||||
(lsh (aref bytedecomp-bytes bytedecomp-ptr) 8))))
|
(lsh (aref bytes bytedecomp-ptr) 8))))
|
||||||
((and (>= bytedecomp-op byte-listN)
|
((and (>= bytedecomp-op byte-listN)
|
||||||
(<= bytedecomp-op byte-discardN))
|
(<= bytedecomp-op byte-discardN))
|
||||||
(setq bytedecomp-ptr (1+ bytedecomp-ptr)) ;offset in next byte
|
(setq bytedecomp-ptr (1+ bytedecomp-ptr)) ;Offset in next byte.
|
||||||
(aref bytedecomp-bytes bytedecomp-ptr))))
|
(aref bytes bytedecomp-ptr))))
|
||||||
|
|
||||||
(defvar byte-compile-tag-number)
|
(defvar byte-compile-tag-number)
|
||||||
|
|
||||||
|
|
@ -1381,24 +1407,24 @@
|
||||||
(defun byte-decompile-bytecode-1 (bytes constvec &optional make-spliceable)
|
(defun byte-decompile-bytecode-1 (bytes constvec &optional make-spliceable)
|
||||||
(let ((bytedecomp-bytes bytes)
|
(let ((bytedecomp-bytes bytes)
|
||||||
(length (length bytes))
|
(length (length bytes))
|
||||||
(bytedecomp-ptr 0) optr tags bytedecomp-op offset
|
(bytedecomp-ptr 0) optr tags bytedecomp-op offset
|
||||||
lap tmp
|
lap tmp
|
||||||
endtag)
|
endtag)
|
||||||
(while (not (= bytedecomp-ptr length))
|
(while (not (= bytedecomp-ptr length))
|
||||||
(or make-spliceable
|
(or make-spliceable
|
||||||
(setq lap (cons bytedecomp-ptr lap)))
|
(push bytedecomp-ptr lap))
|
||||||
(setq bytedecomp-op (aref bytedecomp-bytes bytedecomp-ptr)
|
(setq bytedecomp-op (aref bytedecomp-bytes bytedecomp-ptr)
|
||||||
optr bytedecomp-ptr
|
optr bytedecomp-ptr
|
||||||
offset (disassemble-offset)) ; this does dynamic-scope magic
|
;; This uses dynamic-scope magic.
|
||||||
|
offset (disassemble-offset bytedecomp-bytes))
|
||||||
(setq bytedecomp-op (aref byte-code-vector bytedecomp-op))
|
(setq bytedecomp-op (aref byte-code-vector bytedecomp-op))
|
||||||
(cond ((memq bytedecomp-op byte-goto-ops)
|
(cond ((memq bytedecomp-op byte-goto-ops)
|
||||||
;; it's a pc
|
;; It's a pc.
|
||||||
(setq offset
|
(setq offset
|
||||||
(cdr (or (assq offset tags)
|
(cdr (or (assq offset tags)
|
||||||
(car (setq tags
|
(let ((new (cons offset (byte-compile-make-tag))))
|
||||||
(cons (cons offset
|
(push new tags)
|
||||||
(byte-compile-make-tag))
|
new)))))
|
||||||
tags)))))))
|
|
||||||
((cond ((eq bytedecomp-op 'byte-constant2)
|
((cond ((eq bytedecomp-op 'byte-constant2)
|
||||||
(setq bytedecomp-op 'byte-constant) t)
|
(setq bytedecomp-op 'byte-constant) t)
|
||||||
((memq bytedecomp-op byte-constref-ops)))
|
((memq bytedecomp-op byte-constref-ops)))
|
||||||
|
|
@ -1408,9 +1434,9 @@
|
||||||
offset (if (eq bytedecomp-op 'byte-constant)
|
offset (if (eq bytedecomp-op 'byte-constant)
|
||||||
(byte-compile-get-constant tmp)
|
(byte-compile-get-constant tmp)
|
||||||
(or (assq tmp byte-compile-variables)
|
(or (assq tmp byte-compile-variables)
|
||||||
(car (setq byte-compile-variables
|
(let ((new (list tmp)))
|
||||||
(cons (list tmp)
|
(push new byte-compile-variables)
|
||||||
byte-compile-variables)))))))
|
new)))))
|
||||||
((and make-spliceable
|
((and make-spliceable
|
||||||
(eq bytedecomp-op 'byte-return))
|
(eq bytedecomp-op 'byte-return))
|
||||||
(if (= bytedecomp-ptr (1- length))
|
(if (= bytedecomp-ptr (1- length))
|
||||||
|
|
@ -1427,26 +1453,26 @@
|
||||||
(setq bytedecomp-op 'byte-discardN-preserve-tos)
|
(setq bytedecomp-op 'byte-discardN-preserve-tos)
|
||||||
(setq offset (- offset #x80))))
|
(setq offset (- offset #x80))))
|
||||||
;; lap = ( [ (pc . (op . arg)) ]* )
|
;; lap = ( [ (pc . (op . arg)) ]* )
|
||||||
(setq lap (cons (cons optr (cons bytedecomp-op (or offset 0)))
|
(push (cons optr (cons bytedecomp-op (or offset 0)))
|
||||||
lap))
|
lap)
|
||||||
(setq bytedecomp-ptr (1+ bytedecomp-ptr)))
|
(setq bytedecomp-ptr (1+ bytedecomp-ptr)))
|
||||||
;; take off the dummy nil op that we replaced a trailing "return" with.
|
|
||||||
(let ((rest lap))
|
(let ((rest lap))
|
||||||
(while rest
|
(while rest
|
||||||
(cond ((numberp (car rest)))
|
(cond ((numberp (car rest)))
|
||||||
((setq tmp (assq (car (car rest)) tags))
|
((setq tmp (assq (car (car rest)) tags))
|
||||||
;; this addr is jumped to
|
;; This addr is jumped to.
|
||||||
(setcdr rest (cons (cons nil (cdr tmp))
|
(setcdr rest (cons (cons nil (cdr tmp))
|
||||||
(cdr rest)))
|
(cdr rest)))
|
||||||
(setq tags (delq tmp tags))
|
(setq tags (delq tmp tags))
|
||||||
(setq rest (cdr rest))))
|
(setq rest (cdr rest))))
|
||||||
(setq rest (cdr rest))))
|
(setq rest (cdr rest))))
|
||||||
(if tags (error "optimizer error: missed tags %s" tags))
|
(if tags (error "optimizer error: missed tags %s" tags))
|
||||||
|
;; Take off the dummy nil op that we replaced a trailing "return" with.
|
||||||
(if (null (car (cdr (car lap))))
|
(if (null (car (cdr (car lap))))
|
||||||
(setq lap (cdr lap)))
|
(setq lap (cdr lap)))
|
||||||
(if endtag
|
(if endtag
|
||||||
(setq lap (cons (cons nil endtag) lap)))
|
(setq lap (cons (cons nil endtag) lap)))
|
||||||
;; remove addrs, lap = ( [ (op . arg) | (TAG tagno) ]* )
|
;; Remove addrs, lap = ( [ (op . arg) | (TAG tagno) ]* )
|
||||||
(mapcar (function (lambda (elt)
|
(mapcar (function (lambda (elt)
|
||||||
(if (numberp elt)
|
(if (numberp elt)
|
||||||
elt
|
elt
|
||||||
|
|
|
||||||
|
|
@ -33,8 +33,6 @@
|
||||||
|
|
||||||
;;; Code:
|
;;; Code:
|
||||||
|
|
||||||
;; FIXME: get rid of the atrocious "bytecomp-" variable prefix.
|
|
||||||
|
|
||||||
;; ========================================================================
|
;; ========================================================================
|
||||||
;; Entry points:
|
;; Entry points:
|
||||||
;; byte-recompile-directory, byte-compile-file,
|
;; byte-recompile-directory, byte-compile-file,
|
||||||
|
|
@ -1563,41 +1561,33 @@ Files in subdirectories of DIRECTORY are processed also."
|
||||||
(interactive "DByte force recompile (directory): ")
|
(interactive "DByte force recompile (directory): ")
|
||||||
(byte-recompile-directory directory nil t))
|
(byte-recompile-directory directory nil t))
|
||||||
|
|
||||||
;; The `bytecomp-' prefix is applied to all local variables with
|
|
||||||
;; otherwise common names in this and similar functions for the sake
|
|
||||||
;; of the boundp test in byte-compile-variable-ref.
|
|
||||||
;; http://lists.gnu.org/archive/html/emacs-devel/2008-01/msg00237.html
|
|
||||||
;; http://lists.gnu.org/archive/html/bug-gnu-emacs/2008-02/msg00134.html
|
|
||||||
;; Note that similar considerations apply to command-line-1 in startup.el.
|
|
||||||
;;;###autoload
|
;;;###autoload
|
||||||
(defun byte-recompile-directory (bytecomp-directory &optional bytecomp-arg
|
(defun byte-recompile-directory (directory &optional arg force)
|
||||||
bytecomp-force)
|
"Recompile every `.el' file in DIRECTORY that needs recompilation.
|
||||||
"Recompile every `.el' file in BYTECOMP-DIRECTORY that needs recompilation.
|
|
||||||
This happens when a `.elc' file exists but is older than the `.el' file.
|
This happens when a `.elc' file exists but is older than the `.el' file.
|
||||||
Files in subdirectories of BYTECOMP-DIRECTORY are processed also.
|
Files in subdirectories of DIRECTORY are processed also.
|
||||||
|
|
||||||
If the `.elc' file does not exist, normally this function *does not*
|
If the `.elc' file does not exist, normally this function *does not*
|
||||||
compile the corresponding `.el' file. However, if the prefix argument
|
compile the corresponding `.el' file. However, if the prefix argument
|
||||||
BYTECOMP-ARG is 0, that means do compile all those files. A nonzero
|
ARG is 0, that means do compile all those files. A nonzero
|
||||||
BYTECOMP-ARG means ask the user, for each such `.el' file, whether to
|
ARG means ask the user, for each such `.el' file, whether to
|
||||||
compile it. A nonzero BYTECOMP-ARG also means ask about each subdirectory
|
compile it. A nonzero ARG also means ask about each subdirectory
|
||||||
before scanning it.
|
before scanning it.
|
||||||
|
|
||||||
If the third argument BYTECOMP-FORCE is non-nil, recompile every `.el' file
|
If the third argument FORCE is non-nil, recompile every `.el' file
|
||||||
that already has a `.elc' file."
|
that already has a `.elc' file."
|
||||||
(interactive "DByte recompile directory: \nP")
|
(interactive "DByte recompile directory: \nP")
|
||||||
(if bytecomp-arg
|
(if arg (setq arg (prefix-numeric-value arg)))
|
||||||
(setq bytecomp-arg (prefix-numeric-value bytecomp-arg)))
|
|
||||||
(if noninteractive
|
(if noninteractive
|
||||||
nil
|
nil
|
||||||
(save-some-buffers)
|
(save-some-buffers)
|
||||||
(force-mode-line-update))
|
(force-mode-line-update))
|
||||||
(with-current-buffer (get-buffer-create byte-compile-log-buffer)
|
(with-current-buffer (get-buffer-create byte-compile-log-buffer)
|
||||||
(setq default-directory (expand-file-name bytecomp-directory))
|
(setq default-directory (expand-file-name directory))
|
||||||
;; compilation-mode copies value of default-directory.
|
;; compilation-mode copies value of default-directory.
|
||||||
(unless (eq major-mode 'compilation-mode)
|
(unless (eq major-mode 'compilation-mode)
|
||||||
(compilation-mode))
|
(compilation-mode))
|
||||||
(let ((bytecomp-directories (list default-directory))
|
(let ((directories (list default-directory))
|
||||||
(default-directory default-directory)
|
(default-directory default-directory)
|
||||||
(skip-count 0)
|
(skip-count 0)
|
||||||
(fail-count 0)
|
(fail-count 0)
|
||||||
|
|
@ -1605,47 +1595,36 @@ that already has a `.elc' file."
|
||||||
(dir-count 0)
|
(dir-count 0)
|
||||||
last-dir)
|
last-dir)
|
||||||
(displaying-byte-compile-warnings
|
(displaying-byte-compile-warnings
|
||||||
(while bytecomp-directories
|
(while directories
|
||||||
(setq bytecomp-directory (car bytecomp-directories))
|
(setq directory (car directories))
|
||||||
(message "Checking %s..." bytecomp-directory)
|
(message "Checking %s..." directory)
|
||||||
(let ((bytecomp-files (directory-files bytecomp-directory))
|
(dolist (file (directory-files directory))
|
||||||
bytecomp-source)
|
(let ((source (expand-file-name file directory)))
|
||||||
(dolist (bytecomp-file bytecomp-files)
|
(if (and (not (member file '("RCS" "CVS")))
|
||||||
(setq bytecomp-source
|
(not (eq ?\. (aref file 0)))
|
||||||
(expand-file-name bytecomp-file bytecomp-directory))
|
(file-directory-p source)
|
||||||
(if (and (not (member bytecomp-file '("RCS" "CVS")))
|
(not (file-symlink-p source)))
|
||||||
(not (eq ?\. (aref bytecomp-file 0)))
|
;; This file is a subdirectory. Handle them differently.
|
||||||
(file-directory-p bytecomp-source)
|
(when (or (null arg) (eq 0 arg)
|
||||||
(not (file-symlink-p bytecomp-source)))
|
(y-or-n-p (concat "Check " source "? ")))
|
||||||
;; This file is a subdirectory. Handle them differently.
|
(setq directories (nconc directories (list source))))
|
||||||
(when (or (null bytecomp-arg)
|
;; It is an ordinary file. Decide whether to compile it.
|
||||||
(eq 0 bytecomp-arg)
|
(if (and (string-match emacs-lisp-file-regexp source)
|
||||||
(y-or-n-p (concat "Check " bytecomp-source "? ")))
|
(file-readable-p source)
|
||||||
(setq bytecomp-directories
|
(not (auto-save-file-name-p source))
|
||||||
(nconc bytecomp-directories (list bytecomp-source))))
|
(not (string-equal dir-locals-file
|
||||||
;; It is an ordinary file. Decide whether to compile it.
|
(file-name-nondirectory source))))
|
||||||
(if (and (string-match emacs-lisp-file-regexp bytecomp-source)
|
(progn (case (byte-recompile-file source force arg)
|
||||||
(file-readable-p bytecomp-source)
|
(no-byte-compile (setq skip-count (1+ skip-count)))
|
||||||
(not (auto-save-file-name-p bytecomp-source))
|
((t) (setq file-count (1+ file-count)))
|
||||||
(not (string-equal dir-locals-file
|
((nil) (setq fail-count (1+ fail-count))))
|
||||||
(file-name-nondirectory
|
(or noninteractive
|
||||||
bytecomp-source))))
|
(message "Checking %s..." directory))
|
||||||
(progn (let ((bytecomp-res (byte-recompile-file
|
(if (not (eq last-dir directory))
|
||||||
bytecomp-source
|
(setq last-dir directory
|
||||||
bytecomp-force bytecomp-arg)))
|
dir-count (1+ dir-count)))
|
||||||
(cond ((eq bytecomp-res 'no-byte-compile)
|
)))))
|
||||||
(setq skip-count (1+ skip-count)))
|
(setq directories (cdr directories))))
|
||||||
((eq bytecomp-res t)
|
|
||||||
(setq file-count (1+ file-count)))
|
|
||||||
((eq bytecomp-res nil)
|
|
||||||
(setq fail-count (1+ fail-count)))))
|
|
||||||
(or noninteractive
|
|
||||||
(message "Checking %s..." bytecomp-directory))
|
|
||||||
(if (not (eq last-dir bytecomp-directory))
|
|
||||||
(setq last-dir bytecomp-directory
|
|
||||||
dir-count (1+ dir-count)))
|
|
||||||
)))))
|
|
||||||
(setq bytecomp-directories (cdr bytecomp-directories))))
|
|
||||||
(message "Done (Total of %d file%s compiled%s%s%s)"
|
(message "Done (Total of %d file%s compiled%s%s%s)"
|
||||||
file-count (if (= file-count 1) "" "s")
|
file-count (if (= file-count 1) "" "s")
|
||||||
(if (> fail-count 0) (format ", %d failed" fail-count) "")
|
(if (> fail-count 0) (format ", %d failed" fail-count) "")
|
||||||
|
|
@ -1660,100 +1639,97 @@ This is normally set in local file variables at the end of the elisp file:
|
||||||
\;; Local Variables:\n;; no-byte-compile: t\n;; End: ") ;Backslash for compile-main.
|
\;; Local Variables:\n;; no-byte-compile: t\n;; End: ") ;Backslash for compile-main.
|
||||||
;;;###autoload(put 'no-byte-compile 'safe-local-variable 'booleanp)
|
;;;###autoload(put 'no-byte-compile 'safe-local-variable 'booleanp)
|
||||||
|
|
||||||
(defun byte-recompile-file (bytecomp-filename &optional bytecomp-force bytecomp-arg load)
|
(defun byte-recompile-file (filename &optional force arg load)
|
||||||
"Recompile BYTECOMP-FILENAME file if it needs recompilation.
|
"Recompile FILENAME file if it needs recompilation.
|
||||||
This happens when its `.elc' file is older than itself.
|
This happens when its `.elc' file is older than itself.
|
||||||
|
|
||||||
If the `.elc' file exists and is up-to-date, normally this
|
If the `.elc' file exists and is up-to-date, normally this
|
||||||
function *does not* compile BYTECOMP-FILENAME. However, if the
|
function *does not* compile FILENAME. However, if the
|
||||||
prefix argument BYTECOMP-FORCE is set, that means do compile
|
prefix argument FORCE is set, that means do compile
|
||||||
BYTECOMP-FILENAME even if the destination already exists and is
|
FILENAME even if the destination already exists and is
|
||||||
up-to-date.
|
up-to-date.
|
||||||
|
|
||||||
If the `.elc' file does not exist, normally this function *does
|
If the `.elc' file does not exist, normally this function *does
|
||||||
not* compile BYTECOMP-FILENAME. If BYTECOMP-ARG is 0, that means
|
not* compile FILENAME. If ARG is 0, that means
|
||||||
compile the file even if it has never been compiled before.
|
compile the file even if it has never been compiled before.
|
||||||
A nonzero BYTECOMP-ARG means ask the user.
|
A nonzero ARG means ask the user.
|
||||||
|
|
||||||
If LOAD is set, `load' the file after compiling.
|
If LOAD is set, `load' the file after compiling.
|
||||||
|
|
||||||
The value returned is the value returned by `byte-compile-file',
|
The value returned is the value returned by `byte-compile-file',
|
||||||
or 'no-byte-compile if the file did not need recompilation."
|
or 'no-byte-compile if the file did not need recompilation."
|
||||||
(interactive
|
(interactive
|
||||||
(let ((bytecomp-file buffer-file-name)
|
(let ((file buffer-file-name)
|
||||||
(bytecomp-file-name nil)
|
(file-name nil)
|
||||||
(bytecomp-file-dir nil))
|
(file-dir nil))
|
||||||
(and bytecomp-file
|
(and file
|
||||||
(eq (cdr (assq 'major-mode (buffer-local-variables)))
|
(derived-mode-p 'emacs-lisp-mode)
|
||||||
'emacs-lisp-mode)
|
(setq file-name (file-name-nondirectory file)
|
||||||
(setq bytecomp-file-name (file-name-nondirectory bytecomp-file)
|
file-dir (file-name-directory file)))
|
||||||
bytecomp-file-dir (file-name-directory bytecomp-file)))
|
|
||||||
(list (read-file-name (if current-prefix-arg
|
(list (read-file-name (if current-prefix-arg
|
||||||
"Byte compile file: "
|
"Byte compile file: "
|
||||||
"Byte recompile file: ")
|
"Byte recompile file: ")
|
||||||
bytecomp-file-dir bytecomp-file-name nil)
|
file-dir file-name nil)
|
||||||
current-prefix-arg)))
|
current-prefix-arg)))
|
||||||
(let ((bytecomp-dest
|
(let ((dest (byte-compile-dest-file filename))
|
||||||
(byte-compile-dest-file bytecomp-filename))
|
|
||||||
;; Expand now so we get the current buffer's defaults
|
;; Expand now so we get the current buffer's defaults
|
||||||
(bytecomp-filename (expand-file-name bytecomp-filename)))
|
(filename (expand-file-name filename)))
|
||||||
(if (if (file-exists-p bytecomp-dest)
|
(if (if (file-exists-p dest)
|
||||||
;; File was already compiled
|
;; File was already compiled
|
||||||
;; Compile if forced to, or filename newer
|
;; Compile if forced to, or filename newer
|
||||||
(or bytecomp-force
|
(or force
|
||||||
(file-newer-than-file-p bytecomp-filename
|
(file-newer-than-file-p filename dest))
|
||||||
bytecomp-dest))
|
(and arg
|
||||||
(and bytecomp-arg
|
(or (eq 0 arg)
|
||||||
(or (eq 0 bytecomp-arg)
|
|
||||||
(y-or-n-p (concat "Compile "
|
(y-or-n-p (concat "Compile "
|
||||||
bytecomp-filename "? ")))))
|
filename "? ")))))
|
||||||
(progn
|
(progn
|
||||||
(if (and noninteractive (not byte-compile-verbose))
|
(if (and noninteractive (not byte-compile-verbose))
|
||||||
(message "Compiling %s..." bytecomp-filename))
|
(message "Compiling %s..." filename))
|
||||||
(byte-compile-file bytecomp-filename load))
|
(byte-compile-file filename load))
|
||||||
(when load (load bytecomp-filename))
|
(when load (load filename))
|
||||||
'no-byte-compile)))
|
'no-byte-compile)))
|
||||||
|
|
||||||
;;;###autoload
|
;;;###autoload
|
||||||
(defun byte-compile-file (bytecomp-filename &optional load)
|
(defun byte-compile-file (filename &optional load)
|
||||||
"Compile a file of Lisp code named BYTECOMP-FILENAME into a file of byte code.
|
"Compile a file of Lisp code named FILENAME into a file of byte code.
|
||||||
The output file's name is generated by passing BYTECOMP-FILENAME to the
|
The output file's name is generated by passing FILENAME to the
|
||||||
function `byte-compile-dest-file' (which see).
|
function `byte-compile-dest-file' (which see).
|
||||||
With prefix arg (noninteractively: 2nd arg), LOAD the file after compiling.
|
With prefix arg (noninteractively: 2nd arg), LOAD the file after compiling.
|
||||||
The value is non-nil if there were no errors, nil if errors."
|
The value is non-nil if there were no errors, nil if errors."
|
||||||
;; (interactive "fByte compile file: \nP")
|
;; (interactive "fByte compile file: \nP")
|
||||||
(interactive
|
(interactive
|
||||||
(let ((bytecomp-file buffer-file-name)
|
(let ((file buffer-file-name)
|
||||||
(bytecomp-file-name nil)
|
(file-name nil)
|
||||||
(bytecomp-file-dir nil))
|
(file-dir nil))
|
||||||
(and bytecomp-file
|
(and file
|
||||||
(derived-mode-p 'emacs-lisp-mode)
|
(derived-mode-p 'emacs-lisp-mode)
|
||||||
(setq bytecomp-file-name (file-name-nondirectory bytecomp-file)
|
(setq file-name (file-name-nondirectory file)
|
||||||
bytecomp-file-dir (file-name-directory bytecomp-file)))
|
file-dir (file-name-directory file)))
|
||||||
(list (read-file-name (if current-prefix-arg
|
(list (read-file-name (if current-prefix-arg
|
||||||
"Byte compile and load file: "
|
"Byte compile and load file: "
|
||||||
"Byte compile file: ")
|
"Byte compile file: ")
|
||||||
bytecomp-file-dir bytecomp-file-name nil)
|
file-dir file-name nil)
|
||||||
current-prefix-arg)))
|
current-prefix-arg)))
|
||||||
;; Expand now so we get the current buffer's defaults
|
;; Expand now so we get the current buffer's defaults
|
||||||
(setq bytecomp-filename (expand-file-name bytecomp-filename))
|
(setq filename (expand-file-name filename))
|
||||||
|
|
||||||
;; If we're compiling a file that's in a buffer and is modified, offer
|
;; If we're compiling a file that's in a buffer and is modified, offer
|
||||||
;; to save it first.
|
;; to save it first.
|
||||||
(or noninteractive
|
(or noninteractive
|
||||||
(let ((b (get-file-buffer (expand-file-name bytecomp-filename))))
|
(let ((b (get-file-buffer (expand-file-name filename))))
|
||||||
(if (and b (buffer-modified-p b)
|
(if (and b (buffer-modified-p b)
|
||||||
(y-or-n-p (format "Save buffer %s first? " (buffer-name b))))
|
(y-or-n-p (format "Save buffer %s first? " (buffer-name b))))
|
||||||
(with-current-buffer b (save-buffer)))))
|
(with-current-buffer b (save-buffer)))))
|
||||||
|
|
||||||
;; Force logging of the file name for each file compiled.
|
;; Force logging of the file name for each file compiled.
|
||||||
(setq byte-compile-last-logged-file nil)
|
(setq byte-compile-last-logged-file nil)
|
||||||
(let ((byte-compile-current-file bytecomp-filename)
|
(let ((byte-compile-current-file filename)
|
||||||
(byte-compile-current-group nil)
|
(byte-compile-current-group nil)
|
||||||
(set-auto-coding-for-load t)
|
(set-auto-coding-for-load t)
|
||||||
target-file input-buffer output-buffer
|
target-file input-buffer output-buffer
|
||||||
byte-compile-dest-file)
|
byte-compile-dest-file)
|
||||||
(setq target-file (byte-compile-dest-file bytecomp-filename))
|
(setq target-file (byte-compile-dest-file filename))
|
||||||
(setq byte-compile-dest-file target-file)
|
(setq byte-compile-dest-file target-file)
|
||||||
(with-current-buffer
|
(with-current-buffer
|
||||||
(setq input-buffer (get-buffer-create " *Compiler Input*"))
|
(setq input-buffer (get-buffer-create " *Compiler Input*"))
|
||||||
|
|
@ -1762,7 +1738,7 @@ The value is non-nil if there were no errors, nil if errors."
|
||||||
;; Always compile an Emacs Lisp file as multibyte
|
;; Always compile an Emacs Lisp file as multibyte
|
||||||
;; unless the file itself forces unibyte with -*-coding: raw-text;-*-
|
;; unless the file itself forces unibyte with -*-coding: raw-text;-*-
|
||||||
(set-buffer-multibyte t)
|
(set-buffer-multibyte t)
|
||||||
(insert-file-contents bytecomp-filename)
|
(insert-file-contents filename)
|
||||||
;; Mimic the way after-insert-file-set-coding can make the
|
;; Mimic the way after-insert-file-set-coding can make the
|
||||||
;; buffer unibyte when visiting this file.
|
;; buffer unibyte when visiting this file.
|
||||||
(when (or (eq last-coding-system-used 'no-conversion)
|
(when (or (eq last-coding-system-used 'no-conversion)
|
||||||
|
|
@ -1772,7 +1748,7 @@ The value is non-nil if there were no errors, nil if errors."
|
||||||
(set-buffer-multibyte nil))
|
(set-buffer-multibyte nil))
|
||||||
;; Run hooks including the uncompression hook.
|
;; Run hooks including the uncompression hook.
|
||||||
;; If they change the file name, then change it for the output also.
|
;; If they change the file name, then change it for the output also.
|
||||||
(letf ((buffer-file-name bytecomp-filename)
|
(letf ((buffer-file-name filename)
|
||||||
((default-value 'major-mode) 'emacs-lisp-mode)
|
((default-value 'major-mode) 'emacs-lisp-mode)
|
||||||
;; Ignore unsafe local variables.
|
;; Ignore unsafe local variables.
|
||||||
;; We only care about a few of them for our purposes.
|
;; We only care about a few of them for our purposes.
|
||||||
|
|
@ -1780,15 +1756,15 @@ The value is non-nil if there were no errors, nil if errors."
|
||||||
(enable-local-eval nil))
|
(enable-local-eval nil))
|
||||||
;; Arg of t means don't alter enable-local-variables.
|
;; Arg of t means don't alter enable-local-variables.
|
||||||
(normal-mode t)
|
(normal-mode t)
|
||||||
(setq bytecomp-filename buffer-file-name))
|
(setq filename buffer-file-name))
|
||||||
;; Set the default directory, in case an eval-when-compile uses it.
|
;; Set the default directory, in case an eval-when-compile uses it.
|
||||||
(setq default-directory (file-name-directory bytecomp-filename)))
|
(setq default-directory (file-name-directory filename)))
|
||||||
;; Check if the file's local variables explicitly specify not to
|
;; Check if the file's local variables explicitly specify not to
|
||||||
;; compile this file.
|
;; compile this file.
|
||||||
(if (with-current-buffer input-buffer no-byte-compile)
|
(if (with-current-buffer input-buffer no-byte-compile)
|
||||||
(progn
|
(progn
|
||||||
;; (message "%s not compiled because of `no-byte-compile: %s'"
|
;; (message "%s not compiled because of `no-byte-compile: %s'"
|
||||||
;; (file-relative-name bytecomp-filename)
|
;; (file-relative-name filename)
|
||||||
;; (with-current-buffer input-buffer no-byte-compile))
|
;; (with-current-buffer input-buffer no-byte-compile))
|
||||||
(when (file-exists-p target-file)
|
(when (file-exists-p target-file)
|
||||||
(message "%s deleted because of `no-byte-compile: %s'"
|
(message "%s deleted because of `no-byte-compile: %s'"
|
||||||
|
|
@ -1798,7 +1774,7 @@ The value is non-nil if there were no errors, nil if errors."
|
||||||
;; We successfully didn't compile this file.
|
;; We successfully didn't compile this file.
|
||||||
'no-byte-compile)
|
'no-byte-compile)
|
||||||
(when byte-compile-verbose
|
(when byte-compile-verbose
|
||||||
(message "Compiling %s..." bytecomp-filename))
|
(message "Compiling %s..." filename))
|
||||||
(setq byte-compiler-error-flag nil)
|
(setq byte-compiler-error-flag nil)
|
||||||
;; It is important that input-buffer not be current at this call,
|
;; It is important that input-buffer not be current at this call,
|
||||||
;; so that the value of point set in input-buffer
|
;; so that the value of point set in input-buffer
|
||||||
|
|
@ -1809,7 +1785,7 @@ The value is non-nil if there were no errors, nil if errors."
|
||||||
(if byte-compiler-error-flag
|
(if byte-compiler-error-flag
|
||||||
nil
|
nil
|
||||||
(when byte-compile-verbose
|
(when byte-compile-verbose
|
||||||
(message "Compiling %s...done" bytecomp-filename))
|
(message "Compiling %s...done" filename))
|
||||||
(kill-buffer input-buffer)
|
(kill-buffer input-buffer)
|
||||||
(with-current-buffer output-buffer
|
(with-current-buffer output-buffer
|
||||||
(goto-char (point-max))
|
(goto-char (point-max))
|
||||||
|
|
@ -1849,9 +1825,9 @@ The value is non-nil if there were no errors, nil if errors."
|
||||||
(if (and byte-compile-generate-call-tree
|
(if (and byte-compile-generate-call-tree
|
||||||
(or (eq t byte-compile-generate-call-tree)
|
(or (eq t byte-compile-generate-call-tree)
|
||||||
(y-or-n-p (format "Report call tree for %s? "
|
(y-or-n-p (format "Report call tree for %s? "
|
||||||
bytecomp-filename))))
|
filename))))
|
||||||
(save-excursion
|
(save-excursion
|
||||||
(display-call-tree bytecomp-filename)))
|
(display-call-tree filename)))
|
||||||
(if load
|
(if load
|
||||||
(load target-file))
|
(load target-file))
|
||||||
t))))
|
t))))
|
||||||
|
|
@ -1885,11 +1861,11 @@ With argument ARG, insert value in current buffer after the form."
|
||||||
|
|
||||||
;; Dynamically bound in byte-compile-from-buffer.
|
;; Dynamically bound in byte-compile-from-buffer.
|
||||||
;; NB also used in cl.el and cl-macs.el.
|
;; NB also used in cl.el and cl-macs.el.
|
||||||
(defvar bytecomp-outbuffer)
|
(defvar byte-compile-outbuffer)
|
||||||
|
|
||||||
(defun byte-compile-from-buffer (bytecomp-inbuffer)
|
(defun byte-compile-from-buffer (inbuffer)
|
||||||
(let (bytecomp-outbuffer
|
(let (byte-compile-outbuffer
|
||||||
(byte-compile-current-buffer bytecomp-inbuffer)
|
(byte-compile-current-buffer inbuffer)
|
||||||
(byte-compile-read-position nil)
|
(byte-compile-read-position nil)
|
||||||
(byte-compile-last-position nil)
|
(byte-compile-last-position nil)
|
||||||
;; Prevent truncation of flonums and lists as we read and print them
|
;; Prevent truncation of flonums and lists as we read and print them
|
||||||
|
|
@ -1910,23 +1886,23 @@ With argument ARG, insert value in current buffer after the form."
|
||||||
(byte-compile-output nil)
|
(byte-compile-output nil)
|
||||||
;; This allows us to get the positions of symbols read; it's
|
;; This allows us to get the positions of symbols read; it's
|
||||||
;; new in Emacs 22.1.
|
;; new in Emacs 22.1.
|
||||||
(read-with-symbol-positions bytecomp-inbuffer)
|
(read-with-symbol-positions inbuffer)
|
||||||
(read-symbol-positions-list nil)
|
(read-symbol-positions-list nil)
|
||||||
;; #### This is bound in b-c-close-variables.
|
;; #### This is bound in b-c-close-variables.
|
||||||
;; (byte-compile-warnings byte-compile-warnings)
|
;; (byte-compile-warnings byte-compile-warnings)
|
||||||
)
|
)
|
||||||
(byte-compile-close-variables
|
(byte-compile-close-variables
|
||||||
(with-current-buffer
|
(with-current-buffer
|
||||||
(setq bytecomp-outbuffer (get-buffer-create " *Compiler Output*"))
|
(setq byte-compile-outbuffer (get-buffer-create " *Compiler Output*"))
|
||||||
(set-buffer-multibyte t)
|
(set-buffer-multibyte t)
|
||||||
(erase-buffer)
|
(erase-buffer)
|
||||||
;; (emacs-lisp-mode)
|
;; (emacs-lisp-mode)
|
||||||
(setq case-fold-search nil))
|
(setq case-fold-search nil))
|
||||||
(displaying-byte-compile-warnings
|
(displaying-byte-compile-warnings
|
||||||
(with-current-buffer bytecomp-inbuffer
|
(with-current-buffer inbuffer
|
||||||
(and byte-compile-current-file
|
(and byte-compile-current-file
|
||||||
(byte-compile-insert-header byte-compile-current-file
|
(byte-compile-insert-header byte-compile-current-file
|
||||||
bytecomp-outbuffer))
|
byte-compile-outbuffer))
|
||||||
(goto-char (point-min))
|
(goto-char (point-min))
|
||||||
;; Should we always do this? When calling multiple files, it
|
;; Should we always do this? When calling multiple files, it
|
||||||
;; would be useful to delay this warning until all have been
|
;; would be useful to delay this warning until all have been
|
||||||
|
|
@ -1943,7 +1919,7 @@ With argument ARG, insert value in current buffer after the form."
|
||||||
(setq byte-compile-read-position (point)
|
(setq byte-compile-read-position (point)
|
||||||
byte-compile-last-position byte-compile-read-position)
|
byte-compile-last-position byte-compile-read-position)
|
||||||
(let* ((old-style-backquotes nil)
|
(let* ((old-style-backquotes nil)
|
||||||
(form (read bytecomp-inbuffer)))
|
(form (read inbuffer)))
|
||||||
;; Warn about the use of old-style backquotes.
|
;; Warn about the use of old-style backquotes.
|
||||||
(when old-style-backquotes
|
(when old-style-backquotes
|
||||||
(byte-compile-warn "!! The file uses old-style backquotes !!
|
(byte-compile-warn "!! The file uses old-style backquotes !!
|
||||||
|
|
@ -1959,9 +1935,9 @@ and will be removed soon. See (elisp)Backquote in the manual."))
|
||||||
;; Fix up the header at the front of the output
|
;; Fix up the header at the front of the output
|
||||||
;; if the buffer contains multibyte characters.
|
;; if the buffer contains multibyte characters.
|
||||||
(and byte-compile-current-file
|
(and byte-compile-current-file
|
||||||
(with-current-buffer bytecomp-outbuffer
|
(with-current-buffer byte-compile-outbuffer
|
||||||
(byte-compile-fix-header byte-compile-current-file)))))
|
(byte-compile-fix-header byte-compile-current-file)))))
|
||||||
bytecomp-outbuffer))
|
byte-compile-outbuffer))
|
||||||
|
|
||||||
(defun byte-compile-fix-header (filename)
|
(defun byte-compile-fix-header (filename)
|
||||||
"If the current buffer has any multibyte characters, insert a version test."
|
"If the current buffer has any multibyte characters, insert a version test."
|
||||||
|
|
@ -2070,8 +2046,8 @@ Call from the source buffer."
|
||||||
(print-gensym t)
|
(print-gensym t)
|
||||||
(print-circle ; handle circular data structures
|
(print-circle ; handle circular data structures
|
||||||
(not byte-compile-disable-print-circle)))
|
(not byte-compile-disable-print-circle)))
|
||||||
(princ "\n" bytecomp-outbuffer)
|
(princ "\n" byte-compile-outbuffer)
|
||||||
(prin1 form bytecomp-outbuffer)
|
(prin1 form byte-compile-outbuffer)
|
||||||
nil)))
|
nil)))
|
||||||
|
|
||||||
(defvar print-gensym-alist) ;Used before print-circle existed.
|
(defvar print-gensym-alist) ;Used before print-circle existed.
|
||||||
|
|
@ -2091,7 +2067,7 @@ list that represents a doc string reference.
|
||||||
;; We need to examine byte-compile-dynamic-docstrings
|
;; We need to examine byte-compile-dynamic-docstrings
|
||||||
;; in the input buffer (now current), not in the output buffer.
|
;; in the input buffer (now current), not in the output buffer.
|
||||||
(let ((dynamic-docstrings byte-compile-dynamic-docstrings))
|
(let ((dynamic-docstrings byte-compile-dynamic-docstrings))
|
||||||
(with-current-buffer bytecomp-outbuffer
|
(with-current-buffer byte-compile-outbuffer
|
||||||
(let (position)
|
(let (position)
|
||||||
|
|
||||||
;; Insert the doc string, and make it a comment with #@LENGTH.
|
;; Insert the doc string, and make it a comment with #@LENGTH.
|
||||||
|
|
@ -2115,7 +2091,7 @@ list that represents a doc string reference.
|
||||||
(if preface
|
(if preface
|
||||||
(progn
|
(progn
|
||||||
(insert preface)
|
(insert preface)
|
||||||
(prin1 name bytecomp-outbuffer)))
|
(prin1 name byte-compile-outbuffer)))
|
||||||
(insert (car info))
|
(insert (car info))
|
||||||
(let ((print-escape-newlines t)
|
(let ((print-escape-newlines t)
|
||||||
(print-quoted t)
|
(print-quoted t)
|
||||||
|
|
@ -2130,7 +2106,7 @@ list that represents a doc string reference.
|
||||||
(print-continuous-numbering t)
|
(print-continuous-numbering t)
|
||||||
print-number-table
|
print-number-table
|
||||||
(index 0))
|
(index 0))
|
||||||
(prin1 (car form) bytecomp-outbuffer)
|
(prin1 (car form) byte-compile-outbuffer)
|
||||||
(while (setq form (cdr form))
|
(while (setq form (cdr form))
|
||||||
(setq index (1+ index))
|
(setq index (1+ index))
|
||||||
(insert " ")
|
(insert " ")
|
||||||
|
|
@ -2153,35 +2129,35 @@ list that represents a doc string reference.
|
||||||
(setq position (- (position-bytes position)
|
(setq position (- (position-bytes position)
|
||||||
(point-min) -1))
|
(point-min) -1))
|
||||||
(princ (format "(#$ . %d) nil" position)
|
(princ (format "(#$ . %d) nil" position)
|
||||||
bytecomp-outbuffer)
|
byte-compile-outbuffer)
|
||||||
(setq form (cdr form))
|
(setq form (cdr form))
|
||||||
(setq index (1+ index))))
|
(setq index (1+ index))))
|
||||||
((= index (nth 1 info))
|
((= index (nth 1 info))
|
||||||
(if position
|
(if position
|
||||||
(princ (format (if quoted "'(#$ . %d)" "(#$ . %d)")
|
(princ (format (if quoted "'(#$ . %d)" "(#$ . %d)")
|
||||||
position)
|
position)
|
||||||
bytecomp-outbuffer)
|
byte-compile-outbuffer)
|
||||||
(let ((print-escape-newlines nil))
|
(let ((print-escape-newlines nil))
|
||||||
(goto-char (prog1 (1+ (point))
|
(goto-char (prog1 (1+ (point))
|
||||||
(prin1 (car form) bytecomp-outbuffer)))
|
(prin1 (car form) byte-compile-outbuffer)))
|
||||||
(insert "\\\n")
|
(insert "\\\n")
|
||||||
(goto-char (point-max)))))
|
(goto-char (point-max)))))
|
||||||
(t
|
(t
|
||||||
(prin1 (car form) bytecomp-outbuffer)))))
|
(prin1 (car form) byte-compile-outbuffer)))))
|
||||||
(insert (nth 2 info)))))
|
(insert (nth 2 info)))))
|
||||||
nil)
|
nil)
|
||||||
|
|
||||||
(defun byte-compile-keep-pending (form &optional bytecomp-handler)
|
(defun byte-compile-keep-pending (form &optional handler)
|
||||||
(if (memq byte-optimize '(t source))
|
(if (memq byte-optimize '(t source))
|
||||||
(setq form (byte-optimize-form form t)))
|
(setq form (byte-optimize-form form t)))
|
||||||
(if bytecomp-handler
|
(if handler
|
||||||
(let ((byte-compile--for-effect t))
|
(let ((byte-compile--for-effect t))
|
||||||
;; To avoid consing up monstrously large forms at load time, we split
|
;; To avoid consing up monstrously large forms at load time, we split
|
||||||
;; the output regularly.
|
;; the output regularly.
|
||||||
(and (memq (car-safe form) '(fset defalias))
|
(and (memq (car-safe form) '(fset defalias))
|
||||||
(nthcdr 300 byte-compile-output)
|
(nthcdr 300 byte-compile-output)
|
||||||
(byte-compile-flush-pending))
|
(byte-compile-flush-pending))
|
||||||
(funcall bytecomp-handler form)
|
(funcall handler form)
|
||||||
(if byte-compile--for-effect
|
(if byte-compile--for-effect
|
||||||
(byte-compile-discard)))
|
(byte-compile-discard)))
|
||||||
(byte-compile-form form t))
|
(byte-compile-form form t))
|
||||||
|
|
@ -2219,11 +2195,11 @@ list that represents a doc string reference.
|
||||||
|
|
||||||
;; byte-hunk-handlers can call this.
|
;; byte-hunk-handlers can call this.
|
||||||
(defun byte-compile-file-form (form)
|
(defun byte-compile-file-form (form)
|
||||||
(let (bytecomp-handler)
|
(let (handler)
|
||||||
(cond ((and (consp form)
|
(cond ((and (consp form)
|
||||||
(symbolp (car form))
|
(symbolp (car form))
|
||||||
(setq bytecomp-handler (get (car form) 'byte-hunk-handler)))
|
(setq handler (get (car form) 'byte-hunk-handler)))
|
||||||
(cond ((setq form (funcall bytecomp-handler form))
|
(cond ((setq form (funcall handler form))
|
||||||
(byte-compile-flush-pending)
|
(byte-compile-flush-pending)
|
||||||
(byte-compile-output-file-form form))))
|
(byte-compile-output-file-form form))))
|
||||||
(t
|
(t
|
||||||
|
|
@ -2385,32 +2361,30 @@ by side-effects."
|
||||||
res))
|
res))
|
||||||
|
|
||||||
(defun byte-compile-file-form-defmumble (form macrop)
|
(defun byte-compile-file-form-defmumble (form macrop)
|
||||||
(let* ((bytecomp-name (car (cdr form)))
|
(let* ((name (car (cdr form)))
|
||||||
(bytecomp-this-kind (if macrop 'byte-compile-macro-environment
|
(this-kind (if macrop 'byte-compile-macro-environment
|
||||||
'byte-compile-function-environment))
|
'byte-compile-function-environment))
|
||||||
(bytecomp-that-kind (if macrop 'byte-compile-function-environment
|
(that-kind (if macrop 'byte-compile-function-environment
|
||||||
'byte-compile-macro-environment))
|
'byte-compile-macro-environment))
|
||||||
(bytecomp-this-one (assq bytecomp-name
|
(this-one (assq name (symbol-value this-kind)))
|
||||||
(symbol-value bytecomp-this-kind)))
|
(that-one (assq name (symbol-value that-kind)))
|
||||||
(bytecomp-that-one (assq bytecomp-name
|
|
||||||
(symbol-value bytecomp-that-kind)))
|
|
||||||
(byte-compile-free-references nil)
|
(byte-compile-free-references nil)
|
||||||
(byte-compile-free-assignments nil))
|
(byte-compile-free-assignments nil))
|
||||||
(byte-compile-set-symbol-position bytecomp-name)
|
(byte-compile-set-symbol-position name)
|
||||||
;; When a function or macro is defined, add it to the call tree so that
|
;; When a function or macro is defined, add it to the call tree so that
|
||||||
;; we can tell when functions are not used.
|
;; we can tell when functions are not used.
|
||||||
(if byte-compile-generate-call-tree
|
(if byte-compile-generate-call-tree
|
||||||
(or (assq bytecomp-name byte-compile-call-tree)
|
(or (assq name byte-compile-call-tree)
|
||||||
(setq byte-compile-call-tree
|
(setq byte-compile-call-tree
|
||||||
(cons (list bytecomp-name nil nil) byte-compile-call-tree))))
|
(cons (list name nil nil) byte-compile-call-tree))))
|
||||||
|
|
||||||
(setq byte-compile-current-form bytecomp-name) ; for warnings
|
(setq byte-compile-current-form name) ; for warnings
|
||||||
(if (byte-compile-warning-enabled-p 'redefine)
|
(if (byte-compile-warning-enabled-p 'redefine)
|
||||||
(byte-compile-arglist-warn form macrop))
|
(byte-compile-arglist-warn form macrop))
|
||||||
(if byte-compile-verbose
|
(if byte-compile-verbose
|
||||||
(message "Compiling %s... (%s)"
|
(message "Compiling %s... (%s)"
|
||||||
(or byte-compile-current-file "") (nth 1 form)))
|
(or byte-compile-current-file "") (nth 1 form)))
|
||||||
(cond (bytecomp-that-one
|
(cond (that-one
|
||||||
(if (and (byte-compile-warning-enabled-p 'redefine)
|
(if (and (byte-compile-warning-enabled-p 'redefine)
|
||||||
;; don't warn when compiling the stubs in byte-run...
|
;; don't warn when compiling the stubs in byte-run...
|
||||||
(not (assq (nth 1 form)
|
(not (assq (nth 1 form)
|
||||||
|
|
@ -2418,8 +2392,8 @@ by side-effects."
|
||||||
(byte-compile-warn
|
(byte-compile-warn
|
||||||
"`%s' defined multiple times, as both function and macro"
|
"`%s' defined multiple times, as both function and macro"
|
||||||
(nth 1 form)))
|
(nth 1 form)))
|
||||||
(setcdr bytecomp-that-one nil))
|
(setcdr that-one nil))
|
||||||
(bytecomp-this-one
|
(this-one
|
||||||
(when (and (byte-compile-warning-enabled-p 'redefine)
|
(when (and (byte-compile-warning-enabled-p 'redefine)
|
||||||
;; hack: don't warn when compiling the magic internal
|
;; hack: don't warn when compiling the magic internal
|
||||||
;; byte-compiler macros in byte-run.el...
|
;; byte-compiler macros in byte-run.el...
|
||||||
|
|
@ -2428,8 +2402,8 @@ by side-effects."
|
||||||
(byte-compile-warn "%s `%s' defined multiple times in this file"
|
(byte-compile-warn "%s `%s' defined multiple times in this file"
|
||||||
(if macrop "macro" "function")
|
(if macrop "macro" "function")
|
||||||
(nth 1 form))))
|
(nth 1 form))))
|
||||||
((and (fboundp bytecomp-name)
|
((and (fboundp name)
|
||||||
(eq (car-safe (symbol-function bytecomp-name))
|
(eq (car-safe (symbol-function name))
|
||||||
(if macrop 'lambda 'macro)))
|
(if macrop 'lambda 'macro)))
|
||||||
(when (byte-compile-warning-enabled-p 'redefine)
|
(when (byte-compile-warning-enabled-p 'redefine)
|
||||||
(byte-compile-warn "%s `%s' being redefined as a %s"
|
(byte-compile-warn "%s `%s' being redefined as a %s"
|
||||||
|
|
@ -2437,9 +2411,9 @@ by side-effects."
|
||||||
(nth 1 form)
|
(nth 1 form)
|
||||||
(if macrop "macro" "function")))
|
(if macrop "macro" "function")))
|
||||||
;; shadow existing definition
|
;; shadow existing definition
|
||||||
(set bytecomp-this-kind
|
(set this-kind
|
||||||
(cons (cons bytecomp-name nil)
|
(cons (cons name nil)
|
||||||
(symbol-value bytecomp-this-kind))))
|
(symbol-value this-kind))))
|
||||||
)
|
)
|
||||||
(let ((body (nthcdr 3 form)))
|
(let ((body (nthcdr 3 form)))
|
||||||
(when (and (stringp (car body))
|
(when (and (stringp (car body))
|
||||||
|
|
@ -2454,27 +2428,27 @@ by side-effects."
|
||||||
;; Remove declarations from the body of the macro definition.
|
;; Remove declarations from the body of the macro definition.
|
||||||
(when macrop
|
(when macrop
|
||||||
(dolist (decl (byte-compile-defmacro-declaration form))
|
(dolist (decl (byte-compile-defmacro-declaration form))
|
||||||
(prin1 decl bytecomp-outbuffer)))
|
(prin1 decl byte-compile-outbuffer)))
|
||||||
|
|
||||||
(let* ((new-one (byte-compile-lambda (nthcdr 2 form) t))
|
(let* ((new-one (byte-compile-lambda (nthcdr 2 form) t))
|
||||||
(code (byte-compile-byte-code-maker new-one)))
|
(code (byte-compile-byte-code-maker new-one)))
|
||||||
(if bytecomp-this-one
|
(if this-one
|
||||||
(setcdr bytecomp-this-one new-one)
|
(setcdr this-one new-one)
|
||||||
(set bytecomp-this-kind
|
(set this-kind
|
||||||
(cons (cons bytecomp-name new-one)
|
(cons (cons name new-one)
|
||||||
(symbol-value bytecomp-this-kind))))
|
(symbol-value this-kind))))
|
||||||
(if (and (stringp (nth 3 form))
|
(if (and (stringp (nth 3 form))
|
||||||
(eq 'quote (car-safe code))
|
(eq 'quote (car-safe code))
|
||||||
(eq 'lambda (car-safe (nth 1 code))))
|
(eq 'lambda (car-safe (nth 1 code))))
|
||||||
(cons (car form)
|
(cons (car form)
|
||||||
(cons bytecomp-name (cdr (nth 1 code))))
|
(cons name (cdr (nth 1 code))))
|
||||||
(byte-compile-flush-pending)
|
(byte-compile-flush-pending)
|
||||||
(if (not (stringp (nth 3 form)))
|
(if (not (stringp (nth 3 form)))
|
||||||
;; No doc string. Provide -1 as the "doc string index"
|
;; No doc string. Provide -1 as the "doc string index"
|
||||||
;; so that no element will be treated as a doc string.
|
;; so that no element will be treated as a doc string.
|
||||||
(byte-compile-output-docform
|
(byte-compile-output-docform
|
||||||
"\n(defalias '"
|
"\n(defalias '"
|
||||||
bytecomp-name
|
name
|
||||||
(cond ((atom code)
|
(cond ((atom code)
|
||||||
(if macrop '(" '(macro . #[" -1 "])") '(" #[" -1 "]")))
|
(if macrop '(" '(macro . #[" -1 "])") '(" #[" -1 "]")))
|
||||||
((eq (car code) 'quote)
|
((eq (car code) 'quote)
|
||||||
|
|
@ -2489,7 +2463,7 @@ by side-effects."
|
||||||
;; b-c-output-file-form analyze the defalias.
|
;; b-c-output-file-form analyze the defalias.
|
||||||
(byte-compile-output-docform
|
(byte-compile-output-docform
|
||||||
"\n(defalias '"
|
"\n(defalias '"
|
||||||
bytecomp-name
|
name
|
||||||
(cond ((atom code)
|
(cond ((atom code)
|
||||||
(if macrop '(" '(macro . #[" 4 "])") '(" #[" 4 "]")))
|
(if macrop '(" '(macro . #[" 4 "])") '(" #[" 4 "]")))
|
||||||
((eq (car code) 'quote)
|
((eq (car code) 'quote)
|
||||||
|
|
@ -2500,7 +2474,7 @@ by side-effects."
|
||||||
(and (atom code) byte-compile-dynamic
|
(and (atom code) byte-compile-dynamic
|
||||||
1)
|
1)
|
||||||
nil))
|
nil))
|
||||||
(princ ")" bytecomp-outbuffer)
|
(princ ")" byte-compile-outbuffer)
|
||||||
nil))))
|
nil))))
|
||||||
|
|
||||||
;; Print Lisp object EXP in the output file, inside a comment,
|
;; Print Lisp object EXP in the output file, inside a comment,
|
||||||
|
|
@ -2508,13 +2482,13 @@ by side-effects."
|
||||||
;; If QUOTED is non-nil, print with quoting; otherwise, print without quoting.
|
;; If QUOTED is non-nil, print with quoting; otherwise, print without quoting.
|
||||||
(defun byte-compile-output-as-comment (exp quoted)
|
(defun byte-compile-output-as-comment (exp quoted)
|
||||||
(let ((position (point)))
|
(let ((position (point)))
|
||||||
(with-current-buffer bytecomp-outbuffer
|
(with-current-buffer byte-compile-outbuffer
|
||||||
|
|
||||||
;; Insert EXP, and make it a comment with #@LENGTH.
|
;; Insert EXP, and make it a comment with #@LENGTH.
|
||||||
(insert " ")
|
(insert " ")
|
||||||
(if quoted
|
(if quoted
|
||||||
(prin1 exp bytecomp-outbuffer)
|
(prin1 exp byte-compile-outbuffer)
|
||||||
(princ exp bytecomp-outbuffer))
|
(princ exp byte-compile-outbuffer))
|
||||||
(goto-char position)
|
(goto-char position)
|
||||||
;; Quote certain special characters as needed.
|
;; Quote certain special characters as needed.
|
||||||
;; get_doc_string in doc.c does the unquoting.
|
;; get_doc_string in doc.c does the unquoting.
|
||||||
|
|
@ -2693,41 +2667,41 @@ If FORM is a lambda or a macro, byte-compile it as a function."
|
||||||
;; of the list FUN and `byte-compile-set-symbol-position' is not called.
|
;; of the list FUN and `byte-compile-set-symbol-position' is not called.
|
||||||
;; Use this feature to avoid calling `byte-compile-set-symbol-position'
|
;; Use this feature to avoid calling `byte-compile-set-symbol-position'
|
||||||
;; for symbols generated by the byte compiler itself.
|
;; for symbols generated by the byte compiler itself.
|
||||||
(defun byte-compile-lambda (bytecomp-fun &optional add-lambda reserved-csts)
|
(defun byte-compile-lambda (fun &optional add-lambda reserved-csts)
|
||||||
(if add-lambda
|
(if add-lambda
|
||||||
(setq bytecomp-fun (cons 'lambda bytecomp-fun))
|
(setq fun (cons 'lambda fun))
|
||||||
(unless (eq 'lambda (car-safe bytecomp-fun))
|
(unless (eq 'lambda (car-safe fun))
|
||||||
(error "Not a lambda list: %S" bytecomp-fun))
|
(error "Not a lambda list: %S" fun))
|
||||||
(byte-compile-set-symbol-position 'lambda))
|
(byte-compile-set-symbol-position 'lambda))
|
||||||
(byte-compile-check-lambda-list (nth 1 bytecomp-fun))
|
(byte-compile-check-lambda-list (nth 1 fun))
|
||||||
(let* ((bytecomp-arglist (nth 1 bytecomp-fun))
|
(let* ((arglist (nth 1 fun))
|
||||||
(byte-compile-bound-variables
|
(byte-compile-bound-variables
|
||||||
(append (and (not lexical-binding)
|
(append (and (not lexical-binding)
|
||||||
(byte-compile-arglist-vars bytecomp-arglist))
|
(byte-compile-arglist-vars arglist))
|
||||||
byte-compile-bound-variables))
|
byte-compile-bound-variables))
|
||||||
(bytecomp-body (cdr (cdr bytecomp-fun)))
|
(body (cdr (cdr fun)))
|
||||||
(bytecomp-doc (if (stringp (car bytecomp-body))
|
(doc (if (stringp (car body))
|
||||||
(prog1 (car bytecomp-body)
|
(prog1 (car body)
|
||||||
;; Discard the doc string
|
;; Discard the doc string
|
||||||
;; unless it is the last element of the body.
|
;; unless it is the last element of the body.
|
||||||
(if (cdr bytecomp-body)
|
(if (cdr body)
|
||||||
(setq bytecomp-body (cdr bytecomp-body))))))
|
(setq body (cdr body))))))
|
||||||
(bytecomp-int (assq 'interactive bytecomp-body)))
|
(int (assq 'interactive body)))
|
||||||
;; Process the interactive spec.
|
;; Process the interactive spec.
|
||||||
(when bytecomp-int
|
(when int
|
||||||
(byte-compile-set-symbol-position 'interactive)
|
(byte-compile-set-symbol-position 'interactive)
|
||||||
;; Skip (interactive) if it is in front (the most usual location).
|
;; Skip (interactive) if it is in front (the most usual location).
|
||||||
(if (eq bytecomp-int (car bytecomp-body))
|
(if (eq int (car body))
|
||||||
(setq bytecomp-body (cdr bytecomp-body)))
|
(setq body (cdr body)))
|
||||||
(cond ((consp (cdr bytecomp-int))
|
(cond ((consp (cdr int))
|
||||||
(if (cdr (cdr bytecomp-int))
|
(if (cdr (cdr int))
|
||||||
(byte-compile-warn "malformed interactive spec: %s"
|
(byte-compile-warn "malformed interactive spec: %s"
|
||||||
(prin1-to-string bytecomp-int)))
|
(prin1-to-string int)))
|
||||||
;; If the interactive spec is a call to `list', don't
|
;; If the interactive spec is a call to `list', don't
|
||||||
;; compile it, because `call-interactively' looks at the
|
;; compile it, because `call-interactively' looks at the
|
||||||
;; args of `list'. Actually, compile it to get warnings,
|
;; args of `list'. Actually, compile it to get warnings,
|
||||||
;; but don't use the result.
|
;; but don't use the result.
|
||||||
(let* ((form (nth 1 bytecomp-int))
|
(let* ((form (nth 1 int))
|
||||||
(newform (byte-compile-top-level form)))
|
(newform (byte-compile-top-level form)))
|
||||||
(while (memq (car-safe form) '(let let* progn save-excursion))
|
(while (memq (car-safe form) '(let let* progn save-excursion))
|
||||||
(while (consp (cdr form))
|
(while (consp (cdr form))
|
||||||
|
|
@ -2739,48 +2713,46 @@ If FORM is a lambda or a macro, byte-compile it as a function."
|
||||||
;; it won't be eval'd in the right mode.
|
;; it won't be eval'd in the right mode.
|
||||||
(not lexical-binding))
|
(not lexical-binding))
|
||||||
nil
|
nil
|
||||||
(setq bytecomp-int `(interactive ,newform)))))
|
(setq int `(interactive ,newform)))))
|
||||||
((cdr bytecomp-int)
|
((cdr int)
|
||||||
(byte-compile-warn "malformed interactive spec: %s"
|
(byte-compile-warn "malformed interactive spec: %s"
|
||||||
(prin1-to-string bytecomp-int)))))
|
(prin1-to-string int)))))
|
||||||
;; Process the body.
|
;; Process the body.
|
||||||
(let ((compiled
|
(let ((compiled
|
||||||
(byte-compile-top-level (cons 'progn bytecomp-body) nil 'lambda
|
(byte-compile-top-level (cons 'progn body) nil 'lambda
|
||||||
;; If doing lexical binding, push a new
|
;; If doing lexical binding, push a new
|
||||||
;; lexical environment containing just the
|
;; lexical environment containing just the
|
||||||
;; args (since lambda expressions should be
|
;; args (since lambda expressions should be
|
||||||
;; closed by now).
|
;; closed by now).
|
||||||
(and lexical-binding
|
(and lexical-binding
|
||||||
(byte-compile-make-lambda-lexenv
|
(byte-compile-make-lambda-lexenv fun))
|
||||||
bytecomp-fun))
|
|
||||||
reserved-csts)))
|
reserved-csts)))
|
||||||
;; Build the actual byte-coded function.
|
;; Build the actual byte-coded function.
|
||||||
(if (eq 'byte-code (car-safe compiled))
|
(if (eq 'byte-code (car-safe compiled))
|
||||||
(apply 'make-byte-code
|
(apply 'make-byte-code
|
||||||
(if lexical-binding
|
(if lexical-binding
|
||||||
(byte-compile-make-args-desc bytecomp-arglist)
|
(byte-compile-make-args-desc arglist)
|
||||||
bytecomp-arglist)
|
arglist)
|
||||||
(append
|
(append
|
||||||
;; byte-string, constants-vector, stack depth
|
;; byte-string, constants-vector, stack depth
|
||||||
(cdr compiled)
|
(cdr compiled)
|
||||||
;; optionally, the doc string.
|
;; optionally, the doc string.
|
||||||
(cond (lexical-binding
|
(cond (lexical-binding
|
||||||
(require 'help-fns)
|
(require 'help-fns)
|
||||||
(list (help-add-fundoc-usage
|
(list (help-add-fundoc-usage doc arglist)))
|
||||||
bytecomp-doc bytecomp-arglist)))
|
((or doc int)
|
||||||
((or bytecomp-doc bytecomp-int)
|
(list doc)))
|
||||||
(list bytecomp-doc)))
|
|
||||||
;; optionally, the interactive spec.
|
;; optionally, the interactive spec.
|
||||||
(if bytecomp-int
|
(if int
|
||||||
(list (nth 1 bytecomp-int)))))
|
(list (nth 1 int)))))
|
||||||
(setq compiled
|
(setq compiled
|
||||||
(nconc (if bytecomp-int (list bytecomp-int))
|
(nconc (if int (list int))
|
||||||
(cond ((eq (car-safe compiled) 'progn) (cdr compiled))
|
(cond ((eq (car-safe compiled) 'progn) (cdr compiled))
|
||||||
(compiled (list compiled)))))
|
(compiled (list compiled)))))
|
||||||
(nconc (list 'lambda bytecomp-arglist)
|
(nconc (list 'lambda arglist)
|
||||||
(if (or bytecomp-doc (stringp (car compiled)))
|
(if (or doc (stringp (car compiled)))
|
||||||
(cons bytecomp-doc (cond (compiled)
|
(cons doc (cond (compiled)
|
||||||
(bytecomp-body (list nil))))
|
(body (list nil))))
|
||||||
compiled))))))
|
compiled))))))
|
||||||
|
|
||||||
(defun byte-compile-closure (form &optional add-lambda)
|
(defun byte-compile-closure (form &optional add-lambda)
|
||||||
|
|
@ -2951,14 +2923,14 @@ If FORM is a lambda or a macro, byte-compile it as a function."
|
||||||
((cdr body) (cons 'progn (nreverse body)))
|
((cdr body) (cons 'progn (nreverse body)))
|
||||||
((car body)))))
|
((car body)))))
|
||||||
|
|
||||||
;; Given BYTECOMP-BODY, compile it and return a new body.
|
;; Given BODY, compile it and return a new body.
|
||||||
(defun byte-compile-top-level-body (bytecomp-body &optional for-effect)
|
(defun byte-compile-top-level-body (body &optional for-effect)
|
||||||
(setq bytecomp-body
|
(setq body
|
||||||
(byte-compile-top-level (cons 'progn bytecomp-body) for-effect t))
|
(byte-compile-top-level (cons 'progn body) for-effect t))
|
||||||
(cond ((eq (car-safe bytecomp-body) 'progn)
|
(cond ((eq (car-safe body) 'progn)
|
||||||
(cdr bytecomp-body))
|
(cdr body))
|
||||||
(bytecomp-body
|
(body
|
||||||
(list bytecomp-body))))
|
(list body))))
|
||||||
|
|
||||||
;; Special macro-expander used during byte-compilation.
|
;; Special macro-expander used during byte-compilation.
|
||||||
(defun byte-compile-macroexpand-declare-function (fn file &rest args)
|
(defun byte-compile-macroexpand-declare-function (fn file &rest args)
|
||||||
|
|
@ -3002,28 +2974,28 @@ If FORM is a lambda or a macro, byte-compile it as a function."
|
||||||
(t
|
(t
|
||||||
(byte-compile-variable-ref form))))
|
(byte-compile-variable-ref form))))
|
||||||
((symbolp (car form))
|
((symbolp (car form))
|
||||||
(let* ((bytecomp-fn (car form))
|
(let* ((fn (car form))
|
||||||
(bytecomp-handler (get bytecomp-fn 'byte-compile)))
|
(handler (get fn 'byte-compile)))
|
||||||
(when (byte-compile-const-symbol-p bytecomp-fn)
|
(when (byte-compile-const-symbol-p fn)
|
||||||
(byte-compile-warn "`%s' called as a function" bytecomp-fn))
|
(byte-compile-warn "`%s' called as a function" fn))
|
||||||
(and (byte-compile-warning-enabled-p 'interactive-only)
|
(and (byte-compile-warning-enabled-p 'interactive-only)
|
||||||
(memq bytecomp-fn byte-compile-interactive-only-functions)
|
(memq fn byte-compile-interactive-only-functions)
|
||||||
(byte-compile-warn "`%s' used from Lisp code\n\
|
(byte-compile-warn "`%s' used from Lisp code\n\
|
||||||
That command is designed for interactive use only" bytecomp-fn))
|
That command is designed for interactive use only" fn))
|
||||||
(if (and (fboundp (car form))
|
(if (and (fboundp (car form))
|
||||||
(eq (car-safe (symbol-function (car form))) 'macro))
|
(eq (car-safe (symbol-function (car form))) 'macro))
|
||||||
(byte-compile-report-error
|
(byte-compile-report-error
|
||||||
(format "Forgot to expand macro %s" (car form))))
|
(format "Forgot to expand macro %s" (car form))))
|
||||||
(if (and bytecomp-handler
|
(if (and handler
|
||||||
;; Make sure that function exists. This is important
|
;; Make sure that function exists. This is important
|
||||||
;; for CL compiler macros since the symbol may be
|
;; for CL compiler macros since the symbol may be
|
||||||
;; `cl-byte-compile-compiler-macro' but if CL isn't
|
;; `cl-byte-compile-compiler-macro' but if CL isn't
|
||||||
;; loaded, this function doesn't exist.
|
;; loaded, this function doesn't exist.
|
||||||
(and (not (eq bytecomp-handler
|
(and (not (eq handler
|
||||||
;; Already handled by macroexpand-all.
|
;; Already handled by macroexpand-all.
|
||||||
'cl-byte-compile-compiler-macro))
|
'cl-byte-compile-compiler-macro))
|
||||||
(functionp bytecomp-handler)))
|
(functionp handler)))
|
||||||
(funcall bytecomp-handler form)
|
(funcall handler form)
|
||||||
(byte-compile-normal-call form))
|
(byte-compile-normal-call form))
|
||||||
(if (byte-compile-warning-enabled-p 'cl-functions)
|
(if (byte-compile-warning-enabled-p 'cl-functions)
|
||||||
(byte-compile-cl-warn form))))
|
(byte-compile-cl-warn form))))
|
||||||
|
|
@ -3609,14 +3581,14 @@ discarding."
|
||||||
(byte-defop-compiler-1 quote)
|
(byte-defop-compiler-1 quote)
|
||||||
|
|
||||||
(defun byte-compile-setq (form)
|
(defun byte-compile-setq (form)
|
||||||
(let ((bytecomp-args (cdr form)))
|
(let ((args (cdr form)))
|
||||||
(if bytecomp-args
|
(if args
|
||||||
(while bytecomp-args
|
(while args
|
||||||
(byte-compile-form (car (cdr bytecomp-args)))
|
(byte-compile-form (car (cdr args)))
|
||||||
(or byte-compile--for-effect (cdr (cdr bytecomp-args))
|
(or byte-compile--for-effect (cdr (cdr args))
|
||||||
(byte-compile-out 'byte-dup 0))
|
(byte-compile-out 'byte-dup 0))
|
||||||
(byte-compile-variable-set (car bytecomp-args))
|
(byte-compile-variable-set (car args))
|
||||||
(setq bytecomp-args (cdr (cdr bytecomp-args))))
|
(setq args (cdr (cdr args))))
|
||||||
;; (setq), with no arguments.
|
;; (setq), with no arguments.
|
||||||
(byte-compile-form nil byte-compile--for-effect))
|
(byte-compile-form nil byte-compile--for-effect))
|
||||||
(setq byte-compile--for-effect nil)))
|
(setq byte-compile--for-effect nil)))
|
||||||
|
|
@ -3653,14 +3625,14 @@ discarding."
|
||||||
|
|
||||||
;;; control structures
|
;;; control structures
|
||||||
|
|
||||||
(defun byte-compile-body (bytecomp-body &optional for-effect)
|
(defun byte-compile-body (body &optional for-effect)
|
||||||
(while (cdr bytecomp-body)
|
(while (cdr body)
|
||||||
(byte-compile-form (car bytecomp-body) t)
|
(byte-compile-form (car body) t)
|
||||||
(setq bytecomp-body (cdr bytecomp-body)))
|
(setq body (cdr body)))
|
||||||
(byte-compile-form (car bytecomp-body) for-effect))
|
(byte-compile-form (car body) for-effect))
|
||||||
|
|
||||||
(defsubst byte-compile-body-do-effect (bytecomp-body)
|
(defsubst byte-compile-body-do-effect (body)
|
||||||
(byte-compile-body bytecomp-body byte-compile--for-effect)
|
(byte-compile-body body byte-compile--for-effect)
|
||||||
(setq byte-compile--for-effect nil))
|
(setq byte-compile--for-effect nil))
|
||||||
|
|
||||||
(defsubst byte-compile-form-do-effect (form)
|
(defsubst byte-compile-form-do-effect (form)
|
||||||
|
|
@ -3818,10 +3790,10 @@ that suppresses all warnings during execution of BODY."
|
||||||
|
|
||||||
(defun byte-compile-and (form)
|
(defun byte-compile-and (form)
|
||||||
(let ((failtag (byte-compile-make-tag))
|
(let ((failtag (byte-compile-make-tag))
|
||||||
(bytecomp-args (cdr form)))
|
(args (cdr form)))
|
||||||
(if (null bytecomp-args)
|
(if (null args)
|
||||||
(byte-compile-form-do-effect t)
|
(byte-compile-form-do-effect t)
|
||||||
(byte-compile-and-recursion bytecomp-args failtag))))
|
(byte-compile-and-recursion args failtag))))
|
||||||
|
|
||||||
;; Handle compilation of a nontrivial `and' call.
|
;; Handle compilation of a nontrivial `and' call.
|
||||||
;; We use tail recursion so we can use byte-compile-maybe-guarded.
|
;; We use tail recursion so we can use byte-compile-maybe-guarded.
|
||||||
|
|
@ -3837,10 +3809,10 @@ that suppresses all warnings during execution of BODY."
|
||||||
|
|
||||||
(defun byte-compile-or (form)
|
(defun byte-compile-or (form)
|
||||||
(let ((wintag (byte-compile-make-tag))
|
(let ((wintag (byte-compile-make-tag))
|
||||||
(bytecomp-args (cdr form)))
|
(args (cdr form)))
|
||||||
(if (null bytecomp-args)
|
(if (null args)
|
||||||
(byte-compile-form-do-effect nil)
|
(byte-compile-form-do-effect nil)
|
||||||
(byte-compile-or-recursion bytecomp-args wintag))))
|
(byte-compile-or-recursion args wintag))))
|
||||||
|
|
||||||
;; Handle compilation of a nontrivial `or' call.
|
;; Handle compilation of a nontrivial `or' call.
|
||||||
;; We use tail recursion so we can use byte-compile-maybe-guarded.
|
;; We use tail recursion so we can use byte-compile-maybe-guarded.
|
||||||
|
|
@ -4554,57 +4526,54 @@ already up-to-date."
|
||||||
(defvar command-line-args-left) ;Avoid 'free variable' warning
|
(defvar command-line-args-left) ;Avoid 'free variable' warning
|
||||||
(if (not noninteractive)
|
(if (not noninteractive)
|
||||||
(error "`batch-byte-compile' is to be used only with -batch"))
|
(error "`batch-byte-compile' is to be used only with -batch"))
|
||||||
(let ((bytecomp-error nil))
|
(let ((error nil))
|
||||||
(while command-line-args-left
|
(while command-line-args-left
|
||||||
(if (file-directory-p (expand-file-name (car command-line-args-left)))
|
(if (file-directory-p (expand-file-name (car command-line-args-left)))
|
||||||
;; Directory as argument.
|
;; Directory as argument.
|
||||||
(let ((bytecomp-files (directory-files (car command-line-args-left)))
|
(let (source dest)
|
||||||
bytecomp-source bytecomp-dest)
|
(dolist (file (directory-files (car command-line-args-left)))
|
||||||
(dolist (bytecomp-file bytecomp-files)
|
(if (and (string-match emacs-lisp-file-regexp file)
|
||||||
(if (and (string-match emacs-lisp-file-regexp bytecomp-file)
|
(not (auto-save-file-name-p file))
|
||||||
(not (auto-save-file-name-p bytecomp-file))
|
(setq source
|
||||||
(setq bytecomp-source
|
(expand-file-name file
|
||||||
(expand-file-name bytecomp-file
|
|
||||||
(car command-line-args-left)))
|
(car command-line-args-left)))
|
||||||
(setq bytecomp-dest (byte-compile-dest-file
|
(setq dest (byte-compile-dest-file source))
|
||||||
bytecomp-source))
|
(file-exists-p dest)
|
||||||
(file-exists-p bytecomp-dest)
|
(file-newer-than-file-p source dest))
|
||||||
(file-newer-than-file-p bytecomp-source bytecomp-dest))
|
(if (null (batch-byte-compile-file source))
|
||||||
(if (null (batch-byte-compile-file bytecomp-source))
|
(setq error t)))))
|
||||||
(setq bytecomp-error t)))))
|
|
||||||
;; Specific file argument
|
;; Specific file argument
|
||||||
(if (or (not noforce)
|
(if (or (not noforce)
|
||||||
(let* ((bytecomp-source (car command-line-args-left))
|
(let* ((source (car command-line-args-left))
|
||||||
(bytecomp-dest (byte-compile-dest-file
|
(dest (byte-compile-dest-file source)))
|
||||||
bytecomp-source)))
|
(or (not (file-exists-p dest))
|
||||||
(or (not (file-exists-p bytecomp-dest))
|
(file-newer-than-file-p source dest))))
|
||||||
(file-newer-than-file-p bytecomp-source bytecomp-dest))))
|
|
||||||
(if (null (batch-byte-compile-file (car command-line-args-left)))
|
(if (null (batch-byte-compile-file (car command-line-args-left)))
|
||||||
(setq bytecomp-error t))))
|
(setq error t))))
|
||||||
(setq command-line-args-left (cdr command-line-args-left)))
|
(setq command-line-args-left (cdr command-line-args-left)))
|
||||||
(kill-emacs (if bytecomp-error 1 0))))
|
(kill-emacs (if error 1 0))))
|
||||||
|
|
||||||
(defun batch-byte-compile-file (bytecomp-file)
|
(defun batch-byte-compile-file (file)
|
||||||
(if debug-on-error
|
(if debug-on-error
|
||||||
(byte-compile-file bytecomp-file)
|
(byte-compile-file file)
|
||||||
(condition-case err
|
(condition-case err
|
||||||
(byte-compile-file bytecomp-file)
|
(byte-compile-file file)
|
||||||
(file-error
|
(file-error
|
||||||
(message (if (cdr err)
|
(message (if (cdr err)
|
||||||
">>Error occurred processing %s: %s (%s)"
|
">>Error occurred processing %s: %s (%s)"
|
||||||
">>Error occurred processing %s: %s")
|
">>Error occurred processing %s: %s")
|
||||||
bytecomp-file
|
file
|
||||||
(get (car err) 'error-message)
|
(get (car err) 'error-message)
|
||||||
(prin1-to-string (cdr err)))
|
(prin1-to-string (cdr err)))
|
||||||
(let ((bytecomp-destfile (byte-compile-dest-file bytecomp-file)))
|
(let ((destfile (byte-compile-dest-file file)))
|
||||||
(if (file-exists-p bytecomp-destfile)
|
(if (file-exists-p destfile)
|
||||||
(delete-file bytecomp-destfile)))
|
(delete-file destfile)))
|
||||||
nil)
|
nil)
|
||||||
(error
|
(error
|
||||||
(message (if (cdr err)
|
(message (if (cdr err)
|
||||||
">>Error occurred processing %s: %s (%s)"
|
">>Error occurred processing %s: %s (%s)"
|
||||||
">>Error occurred processing %s: %s")
|
">>Error occurred processing %s: %s")
|
||||||
bytecomp-file
|
file
|
||||||
(get (car err) 'error-message)
|
(get (car err) 'error-message)
|
||||||
(prin1-to-string (cdr err)))
|
(prin1-to-string (cdr err)))
|
||||||
nil))))
|
nil))))
|
||||||
|
|
|
||||||
|
|
@ -65,8 +65,16 @@
|
||||||
;;
|
;;
|
||||||
;;; Code:
|
;;; Code:
|
||||||
|
|
||||||
;; TODO:
|
;; TODO: (not just for cconv but also for the lexbind changes in general)
|
||||||
|
;; - inline lexical byte-code functions.
|
||||||
|
;; - investigate some old v18 stuff in bytecomp.el.
|
||||||
|
;; - optimize away unused cl-block-wrapper.
|
||||||
|
;; - let (e)debug find the value of lexical variables from the stack.
|
||||||
;; - byte-optimize-form should be applied before cconv.
|
;; - byte-optimize-form should be applied before cconv.
|
||||||
|
;; OTOH, the warnings emitted by cconv-analyze need to come before optimize
|
||||||
|
;; since afterwards they can because obnoxious (warnings about an "unused
|
||||||
|
;; variable" should not be emitted when the variable use has simply been
|
||||||
|
;; optimized away).
|
||||||
;; - canonize code in macro-expand so we don't have to handle (let (var) body)
|
;; - canonize code in macro-expand so we don't have to handle (let (var) body)
|
||||||
;; and other oddities.
|
;; and other oddities.
|
||||||
;; - new byte codes for unwind-protect, catch, and condition-case so that
|
;; - new byte codes for unwind-protect, catch, and condition-case so that
|
||||||
|
|
@ -213,7 +221,7 @@ Returns a form where all lambdas don't have any free variables."
|
||||||
(if (assq arg new-env) (push `(,arg) new-env))
|
(if (assq arg new-env) (push `(,arg) new-env))
|
||||||
(push `(,arg . (car ,arg)) new-env)
|
(push `(,arg . (car ,arg)) new-env)
|
||||||
(push `(,arg (list ,arg)) letbind)))
|
(push `(,arg (list ,arg)) letbind)))
|
||||||
|
|
||||||
(setq body-new (mapcar (lambda (form)
|
(setq body-new (mapcar (lambda (form)
|
||||||
(cconv-convert form new-env nil))
|
(cconv-convert form new-env nil))
|
||||||
body))
|
body))
|
||||||
|
|
@ -255,7 +263,7 @@ places where they originally did not directly appear."
|
||||||
(cconv--set-diff (cdr (cddr mapping))
|
(cconv--set-diff (cdr (cddr mapping))
|
||||||
extend)))
|
extend)))
|
||||||
env))))
|
env))))
|
||||||
|
|
||||||
;; What's the difference between fvrs and envs?
|
;; What's the difference between fvrs and envs?
|
||||||
;; Suppose that we have the code
|
;; Suppose that we have the code
|
||||||
;; (lambda (..) fvr (let ((fvr 1)) (+ fvr 1)))
|
;; (lambda (..) fvr (let ((fvr 1)) (+ fvr 1)))
|
||||||
|
|
@ -377,6 +385,7 @@ places where they originally did not directly appear."
|
||||||
; first element is lambda expression
|
; first element is lambda expression
|
||||||
(`(,(and `(lambda . ,_) fun) . ,args)
|
(`(,(and `(lambda . ,_) fun) . ,args)
|
||||||
;; FIXME: it's silly to create a closure just to call it.
|
;; FIXME: it's silly to create a closure just to call it.
|
||||||
|
;; Running byte-optimize-form earlier will resolve this.
|
||||||
`(funcall
|
`(funcall
|
||||||
,(cconv-convert `(function ,fun) env extend)
|
,(cconv-convert `(function ,fun) env extend)
|
||||||
,@(mapcar (lambda (form)
|
,@(mapcar (lambda (form)
|
||||||
|
|
@ -486,9 +495,9 @@ places where they originally did not directly appear."
|
||||||
`(interactive . ,(mapcar (lambda (form)
|
`(interactive . ,(mapcar (lambda (form)
|
||||||
(cconv-convert form nil nil))
|
(cconv-convert form nil nil))
|
||||||
forms)))
|
forms)))
|
||||||
|
|
||||||
(`(declare . ,_) form) ;The args don't contain code.
|
(`(declare . ,_) form) ;The args don't contain code.
|
||||||
|
|
||||||
(`(,func . ,forms)
|
(`(,func . ,forms)
|
||||||
;; First element is function or whatever function-like forms are: or, and,
|
;; First element is function or whatever function-like forms are: or, and,
|
||||||
;; if, progn, prog1, prog2, while, until
|
;; if, progn, prog1, prog2, while, until
|
||||||
|
|
@ -623,7 +632,7 @@ and updates the data stored in ENV."
|
||||||
|
|
||||||
(`(function (lambda ,vrs . ,body-forms))
|
(`(function (lambda ,vrs . ,body-forms))
|
||||||
(cconv--analyse-function vrs body-forms env form))
|
(cconv--analyse-function vrs body-forms env form))
|
||||||
|
|
||||||
(`(setq . ,forms)
|
(`(setq . ,forms)
|
||||||
;; If a local variable (member of env) is modified by setq then
|
;; If a local variable (member of env) is modified by setq then
|
||||||
;; it is a mutated variable.
|
;; it is a mutated variable.
|
||||||
|
|
@ -646,8 +655,8 @@ and updates the data stored in ENV."
|
||||||
|
|
||||||
(`(condition-case ,var ,protected-form . ,handlers)
|
(`(condition-case ,var ,protected-form . ,handlers)
|
||||||
;; FIXME: The bytecode for condition-case forces us to wrap the
|
;; FIXME: The bytecode for condition-case forces us to wrap the
|
||||||
;; form and handlers in closures (for handlers, it's probably
|
;; form and handlers in closures (for handlers, it's understandable
|
||||||
;; unavoidable, but not for the protected form).
|
;; but not for the protected form).
|
||||||
(cconv--analyse-function () (list protected-form) env form)
|
(cconv--analyse-function () (list protected-form) env form)
|
||||||
(dolist (handler handlers)
|
(dolist (handler handlers)
|
||||||
(cconv--analyse-function (if var (list var)) (cdr handler) env form)))
|
(cconv--analyse-function (if var (list var)) (cdr handler) env form)))
|
||||||
|
|
@ -657,8 +666,8 @@ and updates the data stored in ENV."
|
||||||
(cconv-analyse-form form env)
|
(cconv-analyse-form form env)
|
||||||
(cconv--analyse-function () body env form))
|
(cconv--analyse-function () body env form))
|
||||||
|
|
||||||
;; FIXME: The bytecode for save-window-excursion and the lack of
|
;; FIXME: The lack of bytecode for track-mouse forces us to wrap the body.
|
||||||
;; bytecode for track-mouse forces us to wrap the body.
|
;; `track-mouse' really should be made into a macro.
|
||||||
(`(track-mouse . ,body)
|
(`(track-mouse . ,body)
|
||||||
(cconv--analyse-function () body env form))
|
(cconv--analyse-function () body env form))
|
||||||
|
|
||||||
|
|
@ -686,7 +695,7 @@ and updates the data stored in ENV."
|
||||||
(dolist (form forms) (cconv-analyse-form form nil)))
|
(dolist (form forms) (cconv-analyse-form form nil)))
|
||||||
|
|
||||||
(`(declare . ,_) nil) ;The args don't contain code.
|
(`(declare . ,_) nil) ;The args don't contain code.
|
||||||
|
|
||||||
(`(,_ . ,body-forms) ; First element is a function or whatever.
|
(`(,_ . ,body-forms) ; First element is a function or whatever.
|
||||||
(dolist (form body-forms) (cconv-analyse-form form env)))
|
(dolist (form body-forms) (cconv-analyse-form form env)))
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -282,7 +282,7 @@ Not documented
|
||||||
;;;;;; flet progv psetq do-all-symbols do-symbols dotimes dolist
|
;;;;;; flet progv psetq do-all-symbols do-symbols dotimes dolist
|
||||||
;;;;;; do* do loop return-from return block etypecase typecase ecase
|
;;;;;; do* do loop return-from return block etypecase typecase ecase
|
||||||
;;;;;; case load-time-value eval-when destructuring-bind function*
|
;;;;;; case load-time-value eval-when destructuring-bind function*
|
||||||
;;;;;; defmacro* defun* gentemp gensym) "cl-macs" "cl-macs.el" "864a28dc0495ad87d39637a965387526")
|
;;;;;; defmacro* defun* gentemp gensym) "cl-macs" "cl-macs.el" "80cb83265399ce021c8c0c7d1a8562f2")
|
||||||
;;; Generated autoloads from cl-macs.el
|
;;; Generated autoloads from cl-macs.el
|
||||||
|
|
||||||
(autoload 'gensym "cl-macs" "\
|
(autoload 'gensym "cl-macs" "\
|
||||||
|
|
|
||||||
|
|
@ -497,7 +497,7 @@ The result of the body appears to the compiler as a quoted constant."
|
||||||
(symbol-function 'byte-compile-file-form)))
|
(symbol-function 'byte-compile-file-form)))
|
||||||
(list 'byte-compile-file-form (list 'quote set))
|
(list 'byte-compile-file-form (list 'quote set))
|
||||||
'(byte-compile-file-form form)))
|
'(byte-compile-file-form form)))
|
||||||
(print set (symbol-value 'bytecomp-outbuffer)))
|
(print set (symbol-value 'byte-compile-outbuffer)))
|
||||||
(list 'symbol-value (list 'quote temp)))
|
(list 'symbol-value (list 'quote temp)))
|
||||||
(list 'quote (eval form))))
|
(list 'quote (eval form))))
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -278,9 +278,9 @@ definitions to shadow the loaded ones for use in file byte-compilation.
|
||||||
(defvar cl-compiling-file nil)
|
(defvar cl-compiling-file nil)
|
||||||
(defun cl-compiling-file ()
|
(defun cl-compiling-file ()
|
||||||
(or cl-compiling-file
|
(or cl-compiling-file
|
||||||
(and (boundp 'bytecomp-outbuffer)
|
(and (boundp 'byte-compile-outbuffer)
|
||||||
(bufferp (symbol-value 'bytecomp-outbuffer))
|
(bufferp (symbol-value 'byte-compile-outbuffer))
|
||||||
(equal (buffer-name (symbol-value 'bytecomp-outbuffer))
|
(equal (buffer-name (symbol-value 'byte-compile-outbuffer))
|
||||||
" *Compiler Output*"))))
|
" *Compiler Output*"))))
|
||||||
|
|
||||||
(defvar cl-proclaims-deferred nil)
|
(defvar cl-proclaims-deferred nil)
|
||||||
|
|
|
||||||
|
|
@ -27,16 +27,21 @@
|
||||||
|
|
||||||
;; Todo:
|
;; Todo:
|
||||||
|
|
||||||
|
;; - (pcase e (`(,x . ,x) foo)) signals an "x unused" warning if `foo' doesn't
|
||||||
|
;; use x, because x is bound separately for the equality constraint
|
||||||
|
;; (as well as any pred/guard) and for the body, so uses at one place don't
|
||||||
|
;; count for the other.
|
||||||
;; - provide ways to extend the set of primitives, with some kind of
|
;; - provide ways to extend the set of primitives, with some kind of
|
||||||
;; define-pcase-matcher. We could easily make it so that (guard BOOLEXP)
|
;; define-pcase-matcher. We could easily make it so that (guard BOOLEXP)
|
||||||
;; could be defined this way, as a shorthand for (pred (lambda (_) BOOLEXP)).
|
;; could be defined this way, as a shorthand for (pred (lambda (_) BOOLEXP)).
|
||||||
;; But better would be if we could define new ways to match by having the
|
;; But better would be if we could define new ways to match by having the
|
||||||
;; extension provide its own `pcase--split-<foo>' thingy.
|
;; extension provide its own `pcase--split-<foo>' thingy.
|
||||||
|
;; - along these lines, provide patterns to match CL structs.
|
||||||
;; - provide something like (setq VAR) so a var can be set rather than
|
;; - provide something like (setq VAR) so a var can be set rather than
|
||||||
;; let-bound.
|
;; let-bound.
|
||||||
;; - provide a way to fallthrough to other cases.
|
;; - provide a way to fallthrough to subsequent cases.
|
||||||
;; - try and be more clever to reduce the size of the decision tree, and
|
;; - try and be more clever to reduce the size of the decision tree, and
|
||||||
;; to reduce the number of leafs that need to be turned into function:
|
;; to reduce the number of leaves that need to be turned into function:
|
||||||
;; - first, do the tests shared by all remaining branches (it will have
|
;; - first, do the tests shared by all remaining branches (it will have
|
||||||
;; to be performed anyway, so better so it first so it's shared).
|
;; to be performed anyway, so better so it first so it's shared).
|
||||||
;; - then choose the test that discriminates more (?).
|
;; - then choose the test that discriminates more (?).
|
||||||
|
|
@ -67,6 +72,7 @@ UPatterns can take the following forms:
|
||||||
`QPAT matches if the QPattern QPAT matches.
|
`QPAT matches if the QPattern QPAT matches.
|
||||||
(pred PRED) matches if PRED applied to the object returns non-nil.
|
(pred PRED) matches if PRED applied to the object returns non-nil.
|
||||||
(guard BOOLEXP) matches if BOOLEXP evaluates to non-nil.
|
(guard BOOLEXP) matches if BOOLEXP evaluates to non-nil.
|
||||||
|
(let UPAT EXP) matches if EXP matches UPAT.
|
||||||
If a SYMBOL is used twice in the same pattern (i.e. the pattern is
|
If a SYMBOL is used twice in the same pattern (i.e. the pattern is
|
||||||
\"non-linear\"), then the second occurrence is turned into an `eq'uality test.
|
\"non-linear\"), then the second occurrence is turned into an `eq'uality test.
|
||||||
|
|
||||||
|
|
@ -297,15 +303,21 @@ MATCH is the pattern that needs to be matched, of the form:
|
||||||
(symbolp . consp)
|
(symbolp . consp)
|
||||||
(symbolp . arrayp)
|
(symbolp . arrayp)
|
||||||
(symbolp . stringp)
|
(symbolp . stringp)
|
||||||
|
(symbolp . byte-code-function-p)
|
||||||
(integerp . consp)
|
(integerp . consp)
|
||||||
(integerp . arrayp)
|
(integerp . arrayp)
|
||||||
(integerp . stringp)
|
(integerp . stringp)
|
||||||
|
(integerp . byte-code-function-p)
|
||||||
(numberp . consp)
|
(numberp . consp)
|
||||||
(numberp . arrayp)
|
(numberp . arrayp)
|
||||||
(numberp . stringp)
|
(numberp . stringp)
|
||||||
|
(numberp . byte-code-function-p)
|
||||||
(consp . arrayp)
|
(consp . arrayp)
|
||||||
(consp . stringp)
|
(consp . stringp)
|
||||||
(arrayp . stringp)))
|
(consp . byte-code-function-p)
|
||||||
|
(arrayp . stringp)
|
||||||
|
(arrayp . byte-code-function-p)
|
||||||
|
(stringp . byte-code-function-p)))
|
||||||
|
|
||||||
(defun pcase--split-match (sym splitter match)
|
(defun pcase--split-match (sym splitter match)
|
||||||
(cond
|
(cond
|
||||||
|
|
@ -514,11 +526,10 @@ Otherwise, it defers to REST which is a list of branches of the form
|
||||||
(cond
|
(cond
|
||||||
((memq upat '(t _)) (pcase--u1 matches code vars rest))
|
((memq upat '(t _)) (pcase--u1 matches code vars rest))
|
||||||
((eq upat 'dontcare) :pcase--dontcare)
|
((eq upat 'dontcare) :pcase--dontcare)
|
||||||
((functionp upat) (error "Feature removed, use (pred %s)" upat))
|
|
||||||
((memq (car-safe upat) '(guard pred))
|
((memq (car-safe upat) '(guard pred))
|
||||||
(if (eq (car upat) 'pred) (put sym 'pcase-used t))
|
(if (eq (car upat) 'pred) (put sym 'pcase-used t))
|
||||||
(let* ((splitrest
|
(let* ((splitrest
|
||||||
(pcase--split-rest
|
(pcase--split-rest
|
||||||
sym (apply-partially #'pcase--split-pred upat) rest))
|
sym (apply-partially #'pcase--split-pred upat) rest))
|
||||||
(then-rest (car splitrest))
|
(then-rest (car splitrest))
|
||||||
(else-rest (cdr splitrest)))
|
(else-rest (cdr splitrest)))
|
||||||
|
|
@ -527,21 +538,24 @@ Otherwise, it defers to REST which is a list of branches of the form
|
||||||
(let* ((exp (cadr upat))
|
(let* ((exp (cadr upat))
|
||||||
;; `vs' is an upper bound on the vars we need.
|
;; `vs' is an upper bound on the vars we need.
|
||||||
(vs (pcase--fgrep (mapcar #'car vars) exp))
|
(vs (pcase--fgrep (mapcar #'car vars) exp))
|
||||||
(call (cond
|
(env (mapcar (lambda (var)
|
||||||
((eq 'guard (car upat)) exp)
|
(list var (cdr (assq var vars))))
|
||||||
((functionp exp) `(,exp ,sym))
|
vs))
|
||||||
(t `(,@exp ,sym)))))
|
(call (if (eq 'guard (car upat))
|
||||||
|
exp
|
||||||
|
(when (memq sym vs)
|
||||||
|
;; `sym' is shadowed by `env'.
|
||||||
|
(let ((newsym (make-symbol "x")))
|
||||||
|
(push (list newsym sym) env)
|
||||||
|
(setq sym newsym)))
|
||||||
|
(if (functionp exp) `(,exp ,sym)
|
||||||
|
`(,@exp ,sym)))))
|
||||||
(if (null vs)
|
(if (null vs)
|
||||||
call
|
call
|
||||||
;; Let's not replace `vars' in `exp' since it's
|
;; Let's not replace `vars' in `exp' since it's
|
||||||
;; too difficult to do it right, instead just
|
;; too difficult to do it right, instead just
|
||||||
;; let-bind `vars' around `exp'.
|
;; let-bind `vars' around `exp'.
|
||||||
`(let ,(mapcar (lambda (var)
|
`(let* ,env ,call))))
|
||||||
(list var (cdr (assq var vars))))
|
|
||||||
vs)
|
|
||||||
;; FIXME: `vars' can capture `sym'. E.g.
|
|
||||||
;; (pcase x ((and `(,x . ,y) (pred (fun x)))))
|
|
||||||
,call))))
|
|
||||||
(pcase--u1 matches code vars then-rest)
|
(pcase--u1 matches code vars then-rest)
|
||||||
(pcase--u else-rest))))
|
(pcase--u else-rest))))
|
||||||
((symbolp upat)
|
((symbolp upat)
|
||||||
|
|
@ -552,6 +566,25 @@ Otherwise, it defers to REST which is a list of branches of the form
|
||||||
(pcase--u1 (cons `(match ,sym . (pred (eq ,(cdr (assq upat vars)))))
|
(pcase--u1 (cons `(match ,sym . (pred (eq ,(cdr (assq upat vars)))))
|
||||||
matches)
|
matches)
|
||||||
code vars rest)))
|
code vars rest)))
|
||||||
|
((eq (car-safe upat) 'let)
|
||||||
|
;; A upat of the form (let VAR EXP).
|
||||||
|
;; (pcase--u1 matches code
|
||||||
|
;; (cons (cons (nth 1 upat) (nth 2 upat)) vars) rest)
|
||||||
|
(let* ((exp
|
||||||
|
(let* ((exp (nth 2 upat))
|
||||||
|
(found (assq exp vars)))
|
||||||
|
(if found (cdr found)
|
||||||
|
(let* ((vs (pcase--fgrep (mapcar #'car vars) exp))
|
||||||
|
(env (mapcar (lambda (v) (list v (cdr (assq v vars))))
|
||||||
|
vs)))
|
||||||
|
(if env `(let* ,env ,exp) exp)))))
|
||||||
|
(sym (if (symbolp exp) exp (make-symbol "x")))
|
||||||
|
(body
|
||||||
|
(pcase--u1 (cons `(match ,sym . ,(nth 1 upat)) matches)
|
||||||
|
code vars rest)))
|
||||||
|
(if (eq sym exp)
|
||||||
|
body
|
||||||
|
`(let* ((,sym ,exp)) ,body))))
|
||||||
((eq (car-safe upat) '\`)
|
((eq (car-safe upat) '\`)
|
||||||
(put sym 'pcase-used t)
|
(put sym 'pcase-used t)
|
||||||
(pcase--q1 sym (cadr upat) matches code vars rest))
|
(pcase--q1 sym (cadr upat) matches code vars rest))
|
||||||
|
|
|
||||||
|
|
@ -2082,6 +2082,7 @@ A fancy display is used on graphic displays, normal otherwise."
|
||||||
;; Note that any local variables in this function affect the
|
;; Note that any local variables in this function affect the
|
||||||
;; ability of -f batch-byte-compile to detect free variables.
|
;; ability of -f batch-byte-compile to detect free variables.
|
||||||
;; So we give some of them with common names a cl1- prefix.
|
;; So we give some of them with common names a cl1- prefix.
|
||||||
|
;; FIXME: A better fix would be to make this file use lexical-binding.
|
||||||
(let ((cl1-dir command-line-default-directory)
|
(let ((cl1-dir command-line-default-directory)
|
||||||
cl1-tem
|
cl1-tem
|
||||||
;; This approach loses for "-batch -L DIR --eval "(require foo)",
|
;; This approach loses for "-batch -L DIR --eval "(require foo)",
|
||||||
|
|
|
||||||
|
|
@ -187,10 +187,13 @@ Then evaluate RESULT to get return value, default nil.
|
||||||
;; It would be cleaner to create an uninterned symbol,
|
;; It would be cleaner to create an uninterned symbol,
|
||||||
;; but that uses a lot more space when many functions in many files
|
;; but that uses a lot more space when many functions in many files
|
||||||
;; use dolist.
|
;; use dolist.
|
||||||
|
;; FIXME: This cost disappears in byte-compiled lexical-binding files.
|
||||||
(let ((temp '--dolist-tail--))
|
(let ((temp '--dolist-tail--))
|
||||||
`(let ((,temp ,(nth 1 spec))
|
`(let ((,temp ,(nth 1 spec))
|
||||||
,(car spec))
|
,(car spec))
|
||||||
(while ,temp
|
(while ,temp
|
||||||
|
;; FIXME: In lexical-binding code, a `let' inside the loop might
|
||||||
|
;; turn out to be faster than the an outside `let' this `setq'.
|
||||||
(setq ,(car spec) (car ,temp))
|
(setq ,(car spec) (car ,temp))
|
||||||
,@body
|
,@body
|
||||||
(setq ,temp (cdr ,temp)))
|
(setq ,temp (cdr ,temp)))
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,8 @@
|
||||||
|
2011-03-16 Stefan Monnier <monnier@iro.umontreal.ca>
|
||||||
|
|
||||||
|
* image.c (parse_image_spec): Use Ffunctionp.
|
||||||
|
* lisp.h: Declare Ffunctionp.
|
||||||
|
|
||||||
2011-03-13 Stefan Monnier <monnier@iro.umontreal.ca>
|
2011-03-13 Stefan Monnier <monnier@iro.umontreal.ca>
|
||||||
|
|
||||||
* eval.c (Ffunction): Use simpler format for closures.
|
* eval.c (Ffunction): Use simpler format for closures.
|
||||||
|
|
|
||||||
|
|
@ -939,27 +939,27 @@ exec_byte_code (Lisp_Object bytestr, Lisp_Object vector, Lisp_Object maxdepth,
|
||||||
save_restriction_save ());
|
save_restriction_save ());
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case Bcatch:
|
case Bcatch: /* FIXME: ill-suited for lexbind */
|
||||||
{
|
{
|
||||||
Lisp_Object v1;
|
Lisp_Object v1;
|
||||||
BEFORE_POTENTIAL_GC ();
|
BEFORE_POTENTIAL_GC ();
|
||||||
v1 = POP;
|
v1 = POP;
|
||||||
TOP = internal_catch (TOP, eval_sub, v1); /* FIXME: lexbind */
|
TOP = internal_catch (TOP, eval_sub, v1);
|
||||||
AFTER_POTENTIAL_GC ();
|
AFTER_POTENTIAL_GC ();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case Bunwind_protect:
|
case Bunwind_protect: /* FIXME: avoid closure for lexbind */
|
||||||
record_unwind_protect (Fprogn, POP); /* FIXME: lexbind */
|
record_unwind_protect (Fprogn, POP);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case Bcondition_case:
|
case Bcondition_case: /* FIXME: ill-suited for lexbind */
|
||||||
{
|
{
|
||||||
Lisp_Object handlers, body;
|
Lisp_Object handlers, body;
|
||||||
handlers = POP;
|
handlers = POP;
|
||||||
body = POP;
|
body = POP;
|
||||||
BEFORE_POTENTIAL_GC ();
|
BEFORE_POTENTIAL_GC ();
|
||||||
TOP = internal_lisp_condition_case (TOP, body, handlers); /* FIXME: lexbind */
|
TOP = internal_lisp_condition_case (TOP, body, handlers);
|
||||||
AFTER_POTENTIAL_GC ();
|
AFTER_POTENTIAL_GC ();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -835,10 +835,7 @@ parse_image_spec (Lisp_Object spec, struct image_keyword *keywords,
|
||||||
|
|
||||||
case IMAGE_FUNCTION_VALUE:
|
case IMAGE_FUNCTION_VALUE:
|
||||||
value = indirect_function (value);
|
value = indirect_function (value);
|
||||||
/* FIXME: Shouldn't we use Ffunctionp here? */
|
if (!NILP (Ffunctionp (value)))
|
||||||
if (SUBRP (value)
|
|
||||||
|| COMPILEDP (value)
|
|
||||||
|| (CONSP (value) && EQ (XCAR (value), Qlambda)))
|
|
||||||
break;
|
break;
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2864,6 +2864,7 @@ extern void xsignal2 (Lisp_Object, Lisp_Object, Lisp_Object) NO_RETURN;
|
||||||
extern void xsignal3 (Lisp_Object, Lisp_Object, Lisp_Object, Lisp_Object) NO_RETURN;
|
extern void xsignal3 (Lisp_Object, Lisp_Object, Lisp_Object, Lisp_Object) NO_RETURN;
|
||||||
extern void signal_error (const char *, Lisp_Object) NO_RETURN;
|
extern void signal_error (const char *, Lisp_Object) NO_RETURN;
|
||||||
EXFUN (Fcommandp, 2);
|
EXFUN (Fcommandp, 2);
|
||||||
|
EXFUN (Ffunctionp, 1);
|
||||||
EXFUN (Feval, 2);
|
EXFUN (Feval, 2);
|
||||||
extern Lisp_Object eval_sub (Lisp_Object form);
|
extern Lisp_Object eval_sub (Lisp_Object form);
|
||||||
EXFUN (Fapply, MANY);
|
EXFUN (Fapply, MANY);
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue