Function: byte-compile-form

byte-compile-form is a byte-compiled function defined in bytecomp.el.gz.

Signature

(byte-compile-form FORM &optional FOR-EFFECT)

Source Code

;; Defined in /usr/src/emacs/lisp/emacs-lisp/bytecomp.el.gz
;; This is the recursive entry point for compiling each subform of an
;; expression.
;; If for-effect is non-nil, byte-compile-form will output a byte-discard
;; before terminating (ie no value will be left on the stack).
;; A byte-compile handler may, when byte-compile--for-effect is non-nil, choose
;; output code which does not leave a value on the stack, and then set
;; byte-compile--for-effect to nil (to prevent byte-compile-form from
;; outputting the byte-discard).
;; If a handler wants to call another handler, it should do so via
;; byte-compile-form, or take extreme care to handle byte-compile--for-effect
;; correctly.  (Use byte-compile-form-do-effect to reset the
;; byte-compile--for-effect flag too.)
;;
(defun byte-compile-form (form &optional for-effect)
  (let ((byte-compile--for-effect for-effect))
    (macroexp--with-extended-form-stack form
      (cond
       ((not (consp form))
        (cond ((or (not (symbolp form)) (macroexp--const-symbol-p form))
               (byte-compile-constant form))
              ((and byte-compile--for-effect byte-compile-delete-errors)
               (setq byte-compile--for-effect nil))
              (t (byte-compile-variable-ref form))))
       ((symbolp (car form))
        (let* ((fn (car form))
               (handler (get fn 'byte-compile))
	       (interactive-only
                (or (function-get fn 'interactive-only)
		    (memq fn byte-compile-interactive-only-functions))))
          (when (memq fn '(set symbol-value run-hooks ;; add-to-list
                               add-hook remove-hook run-hook-with-args
                               run-hook-with-args-until-success
                               run-hook-with-args-until-failure))
            (pcase (cdr form)
              (`(',var . ,_)
               (when (and (memq var byte-compile-lexical-variables)
                          (byte-compile-warning-enabled-p 'lexical var))
                 (byte-compile-warn
                  (format-message "%s cannot use lexical var `%s'" fn var))))))
          ;; Warn about using obsolete hooks.
          (if (memq fn '(add-hook remove-hook))
              (let ((hook (car-safe (cdr form))))
                (if (eq (car-safe hook) 'quote)
                    (byte-compile-check-variable (cadr hook) nil))))
          (when (and (macroexp--const-symbol-p fn)
                     (byte-compile-warning-enabled-p 'suspicious))
            (byte-compile-warn-x fn "`%s' called as a function" fn))
	  (when (and interactive-only
		     (byte-compile-warning-enabled-p 'interactive-only fn))
	    (byte-compile-warn-x fn "`%s' is for interactive use only%s"
                                 fn
                                 (cond ((stringp interactive-only)
                                        (format "; %s"
                                                (substitute-command-keys
                                                 interactive-only)))
				       ((and (symbolp interactive-only)
					     (not (eq interactive-only t)))
                                        (format-message "; use `%s' instead."
                                                        interactive-only))
				       (t "."))))
          (let ((mutargs (function-get (car form) 'mutates-arguments)))
            (when mutargs
              (dolist (idx (if (symbolp mutargs)
                               (funcall mutargs form)
                             mutargs))
                (let ((arg (nth idx form)))
                  (when (and (or (and (eq (car-safe arg) 'quote)
                                      (consp (nth 1 arg)))
                                 (arrayp arg))
                             (byte-compile-warning-enabled-p
                              'mutate-constant (car form)))
                    (byte-compile-warn-x form "`%s' on constant %s (arg %d)"
                                         (car form)
                                         (if (consp arg) "list" (type-of arg))
                                         idx))))))

          (let ((funargs (function-get (car form) 'funarg-positions)))
            (dolist (funarg funargs)
              (let ((arg (if (numberp funarg)
                             (nth funarg form)
                           (cadr (memq funarg form)))))
                (when (and (eq 'quote (car-safe arg))
                           (eq 'lambda (car-safe (cadr arg))))
                  (byte-compile-warn-x
                   arg "(lambda %s ...) quoted with %s rather than with #%s"
                   (or (nth 1 (cadr arg)) "()")
                   "'" "'")))))           ; avoid styled quotes

          (if (eq (car-safe (symbol-function (car form))) 'macro)
              (byte-compile-report-error
               (format-message "`%s' defined after use in %S (missing `require' of a library file?)"
                               (car form) form)))

          (when byte-compile--for-effect
            (let ((sef (function-get (car form) 'side-effect-free)))
              (cond
               ((and sef (or (eq sef 'error-free)
                             byte-compile-delete-errors))
                ;; This transform is normally done in the Lisp optimizer,
                ;; so maybe we don't need to bother about it here?
                (setq form (cons 'progn (cdr form)))
                (setq handler #'byte-compile-progn))
               ((and (or sef (function-get (car form) 'important-return-value))
                     ;; Don't warn for arguments to `ignore'.
                     (not (eq byte-compile--for-effect 'for-effect-no-warn))
                     (bytecomp--actually-important-return-value-p form)
                     (byte-compile-warning-enabled-p
                      'ignored-return-value (car form)))
                (byte-compile-warn-x
                 (car form)
                 "value from call to `%s' is unused%s"
                 (car form)
                 (cond ((eq (car form) 'mapcar)
                        "; use `mapc' or `dolist' instead")
                       (t "")))))))

          (if (and handler
                   ;; Make sure that function exists.
                   (and (functionp handler)
                        ;; Ignore obsolete byte-compile function used by former
                        ;; CL code to handle compiler macros (we do it
                        ;; differently now).
                        (not (eq handler 'cl-byte-compile-compiler-macro))))
              (funcall handler form)
            (byte-compile-normal-call form))))
       ((and (byte-code-function-p (car form))
             (memq byte-optimize '(t lap)))
        (byte-compile-unfold-bcf form))
       ((byte-compile-normal-call form)))
      (if byte-compile--for-effect
          (byte-compile-discard)))))