summaryrefslogtreecommitdiff
path: root/lisp/emacs-lisp/bytecomp.el
diff options
context:
space:
mode:
authorStefan Monnier <monnier@iro.umontreal.ca>2012-05-29 23:59:42 -0400
committerStefan Monnier <monnier@iro.umontreal.ca>2012-05-29 23:59:42 -0400
commit61b108cc62d69c96c20b9e23b248185591563c1f (patch)
treee07c24a1ec29b567b1f2de381e486f83a5da6211 /lisp/emacs-lisp/bytecomp.el
parent934f3f582d0369e95c6495748e3944405d3629b8 (diff)
downloademacs-61b108cc62d69c96c20b9e23b248185591563c1f.tar.gz
emacs-61b108cc62d69c96c20b9e23b248185591563c1f.tar.bz2
emacs-61b108cc62d69c96c20b9e23b248185591563c1f.zip
* lisp/emacs-lisp/byte-run.el (defmacro, defun): Move from C.
(macro-declaration-function): Move var from C code. (macro-declaration-function): Define function with defalias. * lisp/emacs-lisp/macroexp.el (macroexpand-all-1): * lisp/emacs-lisp/cconv.el (cconv-convert, cconv-analyse-form): * lisp/emacs-lisp/byte-opt.el (byte-optimize-form-code-walker): Don't handle defun/defmacro any more. * lisp/emacs-lisp/bytecomp.el (byte-compile-arglist-signature): Provide fallback for unknown arglist. (byte-compile-arglist-warn): Change calling convention. (byte-compile-output-file-form): Move print-vars binding. (byte-compile-output-docform): Simplify accordingly. (byte-compile-file-form-defun, byte-compile-file-form-defmacro) (byte-compile-defmacro-declaration): Remove. (byte-compile-file-form-defmumble): Generalize to defalias. (byte-compile-output-as-comment): Return byte-positions. Simplify callers accordingly. (byte-compile-lambda): Use `assert'. (byte-compile-defun, byte-compile-defmacro): Remove. (byte-compile-file-form-defalias): Use byte-compile-file-form-defmumble. (byte-compile-defalias-warn): Remove. * src/eval.c (Fdefun, Fdefmacro, Vmacro_declaration_function): Move to byte-run.el. (Fautoload): Do the hash-doc more carefully. * src/data.c (Fdefalias): Purify definition, except for keymaps. (Qdefun): Move from eval.c. * src/lisp.h (Qdefun): Remove. * src/lread.c (read1): Tiny simplification. * lib-src/make-docfile.c: Improve comment style. (search_lisp_doc_at_eol): New function. (scan_lisp_file): Use it.
Diffstat (limited to 'lisp/emacs-lisp/bytecomp.el')
-rw-r--r--lisp/emacs-lisp/bytecomp.el492
1 files changed, 230 insertions, 262 deletions
diff --git a/lisp/emacs-lisp/bytecomp.el b/lisp/emacs-lisp/bytecomp.el
index 2518d8359c3..ce4d5d64ae2 100644
--- a/lisp/emacs-lisp/bytecomp.el
+++ b/lisp/emacs-lisp/bytecomp.el
@@ -1169,12 +1169,14 @@ Each function's symbol gets added to `byte-compile-noruntime-functions'."
(t fn)))))))
(defun byte-compile-arglist-signature (arglist)
- (if (integerp arglist)
- ;; New style byte-code arglist.
- (cons (logand arglist 127) ;Mandatory.
- (if (zerop (logand arglist 128)) ;No &rest.
- (lsh arglist -8))) ;Nonrest.
- ;; Old style byte-code, or interpreted function.
+ (cond
+ ;; New style byte-code arglist.
+ ((integerp arglist)
+ (cons (logand arglist 127) ;Mandatory.
+ (if (zerop (logand arglist 128)) ;No &rest.
+ (lsh arglist -8)))) ;Nonrest.
+ ;; Old style byte-code, or interpreted function.
+ ((listp arglist)
(let ((args 0)
opts
restp)
@@ -1190,7 +1192,9 @@ Each function's symbol gets added to `byte-compile-noruntime-functions'."
(setq opts (1+ opts))
(setq args (1+ args)))))
(setq arglist (cdr arglist)))
- (cons args (if restp nil (if opts (+ args opts) args))))))
+ (cons args (if restp nil (if opts (+ args opts) args)))))
+ ;; Unknown arglist.
+ (t '(0))))
(defun byte-compile-arglist-signatures-congruent-p (old new)
@@ -1250,8 +1254,8 @@ Each function's symbol gets added to `byte-compile-noruntime-functions'."
;; and/or remember its arity if it's unknown.
(or (and (or def (fboundp (car form))) ; might be a subr or autoload.
(not (memq (car form) byte-compile-noruntime-functions)))
- (eq (car form) byte-compile-current-form) ; ## this doesn't work
- ; with recursion.
+ (eq (car form) byte-compile-current-form) ; ## This doesn't work
+ ; with recursion.
;; It's a currently-undefined function.
;; Remember number of args in call.
(let ((cons (assq (car form) byte-compile-unresolved-functions))
@@ -1316,9 +1320,8 @@ extra args."
;; Warn if the function or macro is being redefined with a different
;; number of arguments.
-(defun byte-compile-arglist-warn (form macrop)
- (let* ((name (nth 1 form))
- (old (byte-compile-fdefinition name macrop))
+(defun byte-compile-arglist-warn (name arglist macrop)
+ (let* ((old (byte-compile-fdefinition name macrop))
(initial (and macrop
(cdr (assq name
byte-compile-initial-macro-environment)))))
@@ -1337,12 +1340,12 @@ extra args."
(`(closure ,_ ,args . ,_) args)
((pred byte-code-function-p) (aref old 0))
(t '(&rest def)))))
- (sig2 (byte-compile-arglist-signature (nth 2 form))))
+ (sig2 (byte-compile-arglist-signature arglist)))
(unless (byte-compile-arglist-signatures-congruent-p sig1 sig2)
(byte-compile-set-symbol-position name)
(byte-compile-warn
"%s %s used to take %s %s, now takes %s"
- (if (eq (car form) 'defun) "function" "macro")
+ (if macrop "macro" "function")
name
(byte-compile-arglist-signature-string sig1)
(if (equal sig1 '(1 . 1)) "argument" "arguments")
@@ -1356,7 +1359,7 @@ extra args."
'byte-compile-inline-expand))
(byte-compile-warn "defsubst `%s' was used before it was defined"
name))
- (setq sig (byte-compile-arglist-signature (nth 2 form))
+ (setq sig (byte-compile-arglist-signature arglist)
nums (sort (copy-sequence (cdr calls)) (function <))
min (car nums)
max (car (nreverse nums)))
@@ -2021,31 +2024,30 @@ Call from the source buffer."
";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;\n\n"))))
(defun byte-compile-output-file-form (form)
- ;; writes the given form to the output buffer, being careful of docstrings
+ ;; Write the given form to the output buffer, being careful of docstrings
;; in defun, defmacro, defvar, defvaralias, defconst, autoload and
;; custom-declare-variable because make-docfile is so amazingly stupid.
;; defalias calls are output directly by byte-compile-file-form-defmumble;
;; it does not pay to first build the defalias in defmumble and then parse
;; it here.
- (if (and (memq (car-safe form) '(defun defmacro defvar defvaralias defconst
- autoload custom-declare-variable))
- (stringp (nth 3 form)))
- (byte-compile-output-docform nil nil '("\n(" 3 ")") form nil
- (memq (car form)
- '(defvaralias autoload
- custom-declare-variable)))
- (let ((print-escape-newlines t)
- (print-length nil)
- (print-level nil)
- (print-quoted t)
- (print-gensym t)
- (print-circle ; handle circular data structures
- (not byte-compile-disable-print-circle)))
+ (let ((print-escape-newlines t)
+ (print-length nil)
+ (print-level nil)
+ (print-quoted t)
+ (print-gensym t)
+ (print-circle ; Handle circular data structures.
+ (not byte-compile-disable-print-circle)))
+ (if (and (memq (car-safe form) '(defun defmacro defvar defvaralias defconst
+ autoload custom-declare-variable))
+ (stringp (nth 3 form)))
+ (byte-compile-output-docform nil nil '("\n(" 3 ")") form nil
+ (memq (car form)
+ '(defvaralias autoload
+ custom-declare-variable)))
(princ "\n" byte-compile--outbuffer)
(prin1 form byte-compile--outbuffer)
nil)))
-(defvar print-gensym-alist) ;Used before print-circle existed.
(defvar byte-compile--for-effect)
(defun byte-compile-output-docform (preface name info form specindex quoted)
@@ -2075,7 +2077,6 @@ list that represents a doc string reference.
(setq position
(byte-compile-output-as-comment
(nth (nth 1 info) form) nil))
- (setq position (- (position-bytes position) (point-min) -1))
;; If the doc string starts with * (a user variable),
;; negate POSITION.
(if (and (stringp (nth (nth 1 info) form))
@@ -2088,17 +2089,7 @@ list that represents a doc string reference.
(insert preface)
(prin1 name byte-compile--outbuffer)))
(insert (car info))
- (let ((print-escape-newlines t)
- (print-quoted t)
- ;; For compatibility with code before print-circle,
- ;; use a cons cell to say that we want
- ;; print-gensym-alist not to be cleared
- ;; between calls to print functions.
- (print-gensym '(t))
- (print-circle ; handle circular data structures
- (not byte-compile-disable-print-circle))
- print-gensym-alist ; was used before print-circle existed.
- (print-continuous-numbering t)
+ (let ((print-continuous-numbering t)
print-number-table
(index 0))
(prin1 (car form) byte-compile--outbuffer)
@@ -2121,8 +2112,6 @@ list that represents a doc string reference.
(byte-compile-output-as-comment
(cons (car form) (nth 1 form))
t)))
- (setq position (- (position-bytes position)
- (point-min) -1))
(princ (format "(#$ . %d) nil" position)
byte-compile--outbuffer)
(setq form (cdr form))
@@ -2317,143 +2306,132 @@ list that represents a doc string reference.
(nth 1 (nth 1 form))
(byte-compile-keep-pending form)))
-(put 'defun 'byte-hunk-handler 'byte-compile-file-form-defun)
-(defun byte-compile-file-form-defun (form)
- (byte-compile-file-form-defmumble form nil))
-
-(put 'defmacro 'byte-hunk-handler 'byte-compile-file-form-defmacro)
-(defun byte-compile-file-form-defmacro (form)
- (byte-compile-file-form-defmumble form t))
-
-(defun byte-compile-defmacro-declaration (form)
- "Generate code for declarations in macro definitions.
-Remove declarations from the body of the macro definition
-by side-effects."
- (let ((tail (nthcdr 2 form))
- (res '()))
- (when (stringp (car (cdr tail)))
- (setq tail (cdr tail)))
- (while (and (consp (car (cdr tail)))
- (eq (car (car (cdr tail))) 'declare))
- (let ((declaration (car (cdr tail))))
- (setcdr tail (cdr (cdr tail)))
- (push `(if macro-declaration-function
- (funcall macro-declaration-function
- ',(car (cdr form)) ',declaration))
- res)))
- res))
-
-(defun byte-compile-file-form-defmumble (form macrop)
- (let* ((name (car (cdr form)))
- (this-kind (if macrop 'byte-compile-macro-environment
- 'byte-compile-function-environment))
- (that-kind (if macrop 'byte-compile-function-environment
- 'byte-compile-macro-environment))
- (this-one (assq name (symbol-value this-kind)))
- (that-one (assq name (symbol-value that-kind)))
- (byte-compile-free-references nil)
- (byte-compile-free-assignments nil))
+(defun byte-compile-file-form-defmumble (name macro arglist body rest)
+ "Process a `defalias' for NAME.
+If MACRO is non-nil, the definition is known to be a macro.
+ARGLIST is the list of arguments, if it was recognized or t otherwise.
+BODY of the definition, or t if not recognized.
+Return non-nil if everything went as planned, or nil to imply that it decided
+not to take responsibility for the actual compilation of the code."
+ (let* ((this-kind (if macro 'byte-compile-macro-environment
+ 'byte-compile-function-environment))
+ (that-kind (if macro 'byte-compile-function-environment
+ 'byte-compile-macro-environment))
+ (this-one (assq name (symbol-value this-kind)))
+ (that-one (assq name (symbol-value that-kind)))
+ (byte-compile-current-form name)) ; For warnings.
+
(byte-compile-set-symbol-position name)
;; When a function or macro is defined, add it to the call tree so that
;; we can tell when functions are not used.
(if byte-compile-generate-call-tree
- (or (assq name byte-compile-call-tree)
- (setq byte-compile-call-tree
- (cons (list name nil nil) byte-compile-call-tree))))
+ (or (assq name byte-compile-call-tree)
+ (setq byte-compile-call-tree
+ (cons (list name nil nil) byte-compile-call-tree))))
- (setq byte-compile-current-form name) ; for warnings
(if (byte-compile-warning-enabled-p 'redefine)
- (byte-compile-arglist-warn form macrop))
+ (byte-compile-arglist-warn name arglist macro))
+
(if byte-compile-verbose
- (message "Compiling %s... (%s)"
- (or byte-compile-current-file "") (nth 1 form)))
- (cond (that-one
- (if (and (byte-compile-warning-enabled-p 'redefine)
- ;; don't warn when compiling the stubs in byte-run...
- (not (assq (nth 1 form)
- byte-compile-initial-macro-environment)))
- (byte-compile-warn
+ (message "Compiling %s... (%s)"
+ (or byte-compile-current-file "") name))
+ (cond ((not (or macro (listp body)))
+ ;; We do not know positively if the definition is a macro
+ ;; or a function, so we shouldn't emit warnings.
+ ;; This also silences "multiple definition" warnings for defmethods.
+ nil)
+ (that-one
+ (if (and (byte-compile-warning-enabled-p 'redefine)
+ ;; Don't warn when compiling the stubs in byte-run...
+ (not (assq name byte-compile-initial-macro-environment)))
+ (byte-compile-warn
"`%s' defined multiple times, as both function and macro"
- (nth 1 form)))
- (setcdr that-one nil))
- (this-one
- (when (and (byte-compile-warning-enabled-p 'redefine)
- ;; hack: don't warn when compiling the magic internal
+ name))
+ (setcdr that-one nil))
+ (this-one
+ (when (and (byte-compile-warning-enabled-p 'redefine)
+ ;; Hack: Don't warn when compiling the magic internal
;; byte-compiler macros in byte-run.el...
- (not (assq (nth 1 form)
- byte-compile-initial-macro-environment)))
- (byte-compile-warn "%s `%s' defined multiple times in this file"
- (if macrop "macro" "function")
- (nth 1 form))))
- ((and (fboundp name)
- (eq (car-safe (symbol-function name))
- (if macrop 'lambda 'macro)))
- (when (byte-compile-warning-enabled-p 'redefine)
- (byte-compile-warn "%s `%s' being redefined as a %s"
- (if macrop "function" "macro")
- (nth 1 form)
- (if macrop "macro" "function")))
- ;; shadow existing definition
- (set this-kind
- (cons (cons name nil)
- (symbol-value this-kind))))
- )
- (let ((body (nthcdr 3 form)))
- (when (and (stringp (car body))
- (symbolp (car-safe (cdr-safe body)))
- (car-safe (cdr-safe body))
- (stringp (car-safe (cdr-safe (cdr-safe body)))))
- (byte-compile-set-symbol-position (nth 1 form))
- (byte-compile-warn "probable `\"' without `\\' in doc string of %s"
- (nth 1 form))))
-
- ;; Generate code for declarations in macro definitions.
- ;; Remove declarations from the body of the macro definition.
- (when macrop
- (dolist (decl (byte-compile-defmacro-declaration form))
- (prin1 decl byte-compile--outbuffer)))
-
- (let* ((code (byte-compile-lambda (nthcdr 2 form) t)))
- (if this-one
- ;; A definition in b-c-initial-m-e should always take precedence
- ;; during compilation, so don't let it be redefined. (Bug#8647)
- (or (and macrop
- (assq name byte-compile-initial-macro-environment))
- (setcdr this-one code))
- (set this-kind
- (cons (cons name code)
- (symbol-value this-kind))))
- (byte-compile-flush-pending)
- (if (not (stringp (nth 3 form)))
- ;; No doc string. Provide -1 as the "doc string index"
- ;; so that no element will be treated as a doc string.
- (byte-compile-output-docform
- "\n(defalias '"
- name
- (if macrop '(" '(macro . #[" -1 "])") '(" #[" -1 "]"))
- (append code nil) ; Turn byte-code-function-p into list.
- (and (atom code) byte-compile-dynamic
- 1)
- nil)
- ;; Output the form by hand, that's much simpler than having
- ;; b-c-output-file-form analyze the defalias.
- (byte-compile-output-docform
- "\n(defalias '"
- name
- (if macrop '(" '(macro . #[" 4 "])") '(" #[" 4 "]"))
- (append code nil) ; Turn byte-code-function-p into list.
- (and (atom code) byte-compile-dynamic
- 1)
- nil))
- (princ ")" byte-compile--outbuffer)
- nil)))
+ (not (assq name byte-compile-initial-macro-environment)))
+ (byte-compile-warn "%s `%s' defined multiple times in this file"
+ (if macro "macro" "function")
+ name)))
+ ((and (fboundp name)
+ (eq (car-safe (symbol-function name))
+ (if macro 'lambda 'macro)))
+ (when (byte-compile-warning-enabled-p 'redefine)
+ (byte-compile-warn "%s `%s' being redefined as a %s"
+ (if macro "function" "macro")
+ name
+ (if macro "macro" "function")))
+ ;; Shadow existing definition.
+ (set this-kind
+ (cons (cons name nil)
+ (symbol-value this-kind))))
+ )
+
+ (when (and (listp body)
+ (stringp (car body))
+ (symbolp (car-safe (cdr-safe body)))
+ (car-safe (cdr-safe body))
+ (stringp (car-safe (cdr-safe (cdr-safe body)))))
+ ;; FIXME: We've done that already just above, so this looks wrong!
+ ;;(byte-compile-set-symbol-position name)
+ (byte-compile-warn "probable `\"' without `\\' in doc string of %s"
+ name))
+
+ (if (not (listp body))
+ ;; The precise definition requires evaluation to find out, so it
+ ;; will only be known at runtime.
+ ;; For a macro, that means we can't use that macro in the same file.
+ (progn
+ (unless macro
+ (push (cons name (if (listp arglist) `(declared ,arglist) t))
+ byte-compile-function-environment))
+ ;; Tell the caller that we didn't compile it yet.
+ nil)
+
+ (let* ((code (byte-compile-lambda (cons arglist body) t)))
+ (if this-one
+ ;; A definition in b-c-initial-m-e should always take precedence
+ ;; during compilation, so don't let it be redefined. (Bug#8647)
+ (or (and macro
+ (assq name byte-compile-initial-macro-environment))
+ (setcdr this-one code))
+ (set this-kind
+ (cons (cons name code)
+ (symbol-value this-kind))))
+
+ (if rest
+ ;; There are additional args to `defalias' (like maybe a docstring)
+ ;; that the code below can't handle: punt!
+ nil
+ ;; Otherwise, we have a bona-fide defun/defmacro definition, and use
+ ;; special code to allow dynamic docstrings and byte-code.
+ (byte-compile-flush-pending)
+ (let ((index
+ ;; If there's no doc string, provide -1 as the "doc string
+ ;; index" so that no element will be treated as a doc string.
+ (if (not (stringp (car body))) -1 4)))
+ ;; Output the form by hand, that's much simpler than having
+ ;; b-c-output-file-form analyze the defalias.
+ (byte-compile-output-docform
+ "\n(defalias '"
+ name
+ (if macro `(" '(macro . #[" ,index "])") `(" #[" ,index "]"))
+ (append code nil) ; Turn byte-code-function-p into list.
+ (and (atom code) byte-compile-dynamic
+ 1)
+ nil))
+ (princ ")" byte-compile--outbuffer)
+ t)))))
-;; Print Lisp object EXP in the output file, inside a comment,
-;; and return the file position it will have.
-;; If QUOTED is non-nil, print with quoting; otherwise, print without quoting.
(defun byte-compile-output-as-comment (exp quoted)
- (let ((position (point)))
- (with-current-buffer byte-compile--outbuffer
+ "Print Lisp object EXP in the output file, inside a comment,
+and return the file (byte) position it will have.
+If QUOTED is non-nil, print with quoting; otherwise, print without quoting."
+ (with-current-buffer byte-compile--outbuffer
+ (let ((position (point)))
;; Insert EXP, and make it a comment with #@LENGTH.
(insert " ")
@@ -2478,13 +2456,12 @@ by side-effects."
(position-bytes position))))
;; Save the file position of the object.
- ;; Note we should add 1 to skip the space
- ;; that we inserted before the actual doc string,
- ;; and subtract 1 to convert from an 1-origin Emacs position
- ;; to a file position; they cancel.
- (setq position (point))
- (goto-char (point-max)))
- position))
+ ;; Note we add 1 to skip the space that we inserted before the actual doc
+ ;; string, and subtract point-min to convert from an 1-origin Emacs
+ ;; position to a file position.
+ (prog1
+ (- (position-bytes (point)) (point-min) -1)
+ (goto-char (point-max))))))
@@ -2581,14 +2558,15 @@ If FORM is a lambda or a macro, byte-compile it as a function."
(lsh nonrest 8)
(lsh rest 7)))))
-;; Byte-compile a lambda-expression and return a valid function.
-;; The value is usually a compiled function but may be the original
-;; lambda-expression.
-;; When ADD-LAMBDA is non-nil, the symbol `lambda' is added as head
-;; of the list FUN and `byte-compile-set-symbol-position' is not called.
-;; Use this feature to avoid calling `byte-compile-set-symbol-position'
-;; for symbols generated by the byte compiler itself.
+
(defun byte-compile-lambda (fun &optional add-lambda reserved-csts)
+ "Byte-compile a lambda-expression and return a valid function.
+The value is usually a compiled function but may be the original
+lambda-expression.
+When ADD-LAMBDA is non-nil, the symbol `lambda' is added as head
+of the list FUN and `byte-compile-set-symbol-position' is not called.
+Use this feature to avoid calling `byte-compile-set-symbol-position'
+for symbols generated by the byte compiler itself."
(if add-lambda
(setq fun (cons 'lambda fun))
(unless (eq 'lambda (car-safe fun))
@@ -2649,24 +2627,23 @@ If FORM is a lambda or a macro, byte-compile it as a function."
(byte-compile-make-lambda-lexenv fun))
reserved-csts)))
;; Build the actual byte-coded function.
- (if (eq 'byte-code (car-safe compiled))
- (apply 'make-byte-code
- (if lexical-binding
- (byte-compile-make-args-desc arglist)
- arglist)
- (append
- ;; byte-string, constants-vector, stack depth
- (cdr compiled)
- ;; optionally, the doc string.
- (cond (lexical-binding
- (require 'help-fns)
- (list (help-add-fundoc-usage doc arglist)))
- ((or doc int)
- (list doc)))
- ;; optionally, the interactive spec.
- (if int
- (list (nth 1 int)))))
- (error "byte-compile-top-level did not return byte-code")))))
+ (assert (eq 'byte-code (car-safe compiled)))
+ (apply #'make-byte-code
+ (if lexical-binding
+ (byte-compile-make-args-desc arglist)
+ arglist)
+ (append
+ ;; byte-string, constants-vector, stack depth
+ (cdr compiled)
+ ;; optionally, the doc string.
+ (cond (lexical-binding
+ (require 'help-fns)
+ (list (help-add-fundoc-usage doc arglist)))
+ ((or doc int)
+ (list doc)))
+ ;; optionally, the interactive spec.
+ (if int
+ (list (nth 1 int))))))))
(defvar byte-compile-reserved-constants 0)
@@ -3066,9 +3043,9 @@ That command is designed for interactive use only" fn))
(byte-compile-check-variable var 'assign)
(let ((lex-binding (assq var byte-compile--lexical-environment)))
(if lex-binding
- ;; VAR is lexically bound
+ ;; VAR is lexically bound.
(byte-compile-stack-set (cdr lex-binding))
- ;; VAR is dynamically bound
+ ;; VAR is dynamically bound.
(unless (or (not (byte-compile-warning-enabled-p 'free-vars))
(boundp var)
(memq var byte-compile-bound-variables)
@@ -3353,6 +3330,7 @@ discarding."
(body (nthcdr 3 form))
(fun
(byte-compile-lambda `(lambda ,vars . ,body) nil (length env))))
+ (assert (> (length env) 0)) ;Otherwise, we don't need a closure.
(assert (byte-code-function-p fun))
(byte-compile-form `(make-byte-code
',(aref fun 0) ',(aref fun 1)
@@ -4074,36 +4052,11 @@ binding slots have been popped."
;;; top-level forms elsewhere
-(byte-defop-compiler-1 defun)
-(byte-defop-compiler-1 defmacro)
(byte-defop-compiler-1 defvar)
(byte-defop-compiler-1 defconst byte-compile-defvar)
(byte-defop-compiler-1 autoload)
(byte-defop-compiler-1 lambda byte-compile-lambda-form)
-(defun byte-compile-defun (form)
- ;; This is not used for file-level defuns with doc strings.
- (if (symbolp (car form))
- (byte-compile-set-symbol-position (car form))
- (byte-compile-set-symbol-position 'defun)
- (error "defun name must be a symbol, not %s" (car form)))
- (byte-compile-push-constant 'defalias)
- (byte-compile-push-constant (nth 1 form))
- (byte-compile-push-constant (byte-compile-lambda (cdr (cdr form)) t))
- (byte-compile-out 'byte-call 2))
-
-(defun byte-compile-defmacro (form)
- ;; This is not used for file-level defmacros with doc strings.
- (byte-compile-body-do-effect
- (let ((decls (byte-compile-defmacro-declaration form))
- (code (byte-compile-lambda (cdr (cdr form)) t)))
- `((defalias ',(nth 1 form)
- ,(if (eq (car-safe code) 'make-byte-code)
- `(cons 'macro ,code)
- `'(macro . ,(eval code))))
- ,@decls
- ',(nth 1 form)))))
-
;; If foo.el declares `toto' as obsolete, it is likely that foo.el will
;; actually use `toto' in order for this obsolete variable to still work
;; correctly, so paradoxically, while byte-compiling foo.el, the presence
@@ -4179,38 +4132,53 @@ binding slots have been popped."
(put 'defalias 'byte-hunk-handler 'byte-compile-file-form-defalias)
;; Used for eieio--defalias as well.
(defun byte-compile-file-form-defalias (form)
- (if (and (consp (cdr form)) (consp (nth 1 form))
- (eq (car (nth 1 form)) 'quote)
- (consp (cdr (nth 1 form)))
- (symbolp (nth 1 (nth 1 form))))
- (let ((constant
- (and (consp (nthcdr 2 form))
- (consp (nth 2 form))
- (eq (car (nth 2 form)) 'quote)
- (consp (cdr (nth 2 form)))
- (symbolp (nth 1 (nth 2 form))))))
- (byte-compile-defalias-warn (nth 1 (nth 1 form)))
- (push (cons (nth 1 (nth 1 form))
- (if constant (nth 1 (nth 2 form)) t))
- byte-compile-function-environment)))
- ;; We used to just do: (byte-compile-normal-call form)
- ;; But it turns out that this fails to optimize the code.
- ;; So instead we now do the same as what other byte-hunk-handlers do,
- ;; which is to call back byte-compile-file-form and then return nil.
- ;; Except that we can't just call byte-compile-file-form since it would
- ;; call us right back.
- (byte-compile-keep-pending form)
- ;; Return nil so the form is not output twice.
- nil)
-
-;; Turn off warnings about prior calls to the function being defalias'd.
-;; This could be smarter and compare those calls with
-;; the function it is being aliased to.
-(defun byte-compile-defalias-warn (new)
- (let ((calls (assq new byte-compile-unresolved-functions)))
- (if calls
- (setq byte-compile-unresolved-functions
- (delq calls byte-compile-unresolved-functions)))))
+ ;; For the compilation itself, we could largely get rid of this hunk-handler,
+ ;; if it weren't for the fact that we need to figure out when a defalias
+ ;; defines a macro, so as to add it to byte-compile-macro-environment.
+ ;;
+ ;; FIXME: we also use this hunk-handler to implement the function's dynamic
+ ;; docstring feature. We could actually implement it more elegantly in
+ ;; byte-compile-lambda so it applies to all lambdas, but the problem is that
+ ;; the resulting .elc format will not be recognized by make-docfile, so
+ ;; either we stop using DOC for the docstrings of preloaded elc files (at the
+ ;; cost of around 24KB on 32bit hosts, double on 64bit hosts) or we need to
+ ;; build DOC in a more clever way (e.g. handle anonymous elements).
+ (let ((byte-compile-free-references nil)
+ (byte-compile-free-assignments nil))
+ (pcase form
+ ;; Decompose `form' into:
+ ;; - `name' is the name of the defined function.
+ ;; - `arg' is the expression to which it is defined.
+ ;; - `rest' is the rest of the arguments.
+ (`(,_ ',name ,arg . ,rest)
+ (pcase-let*
+ ;; `macro' is non-nil if it defines a macro.
+ ;; `fun' is the function part of `arg' (defaults to `arg').
+ (((or (and (or `(cons 'macro ,fun) `'(macro . ,fun)) (let macro t))
+ (and (let fun arg) (let macro nil)))
+ arg)
+ ;; `lam' is the lambda expression in `fun' (or nil if not
+ ;; recognized).
+ ((or `(,(or `quote `function) ,lam) (let lam nil))
+ fun)
+ ;; `arglist' is the list of arguments (or t if not recognized).
+ ;; `body' is the body of `lam' (or t if not recognized).
+ ((or `(lambda ,arglist . ,body)
+ ;; `(closure ,_ ,arglist . ,body)
+ (and `(internal-make-closure ,arglist . ,_) (let body t))
+ (and (let arglist t) (let body t)))
+ lam))
+ (unless (byte-compile-file-form-defmumble
+ name macro arglist body rest)
+ (byte-compile-keep-pending form))))
+
+ ;; We used to just do: (byte-compile-normal-call form)
+ ;; But it turns out that this fails to optimize the code.
+ ;; So instead we now do the same as what other byte-hunk-handlers do,
+ ;; which is to call back byte-compile-file-form and then return nil.
+ ;; Except that we can't just call byte-compile-file-form since it would
+ ;; call us right back.
+ (t (byte-compile-keep-pending form)))))
(byte-defop-compiler-1 with-no-warnings byte-compile-no-warnings)
(defun byte-compile-no-warnings (form)