Function: cl--labels-convert

cl--labels-convert is a byte-compiled function defined in cl-macs.el.gz.

Signature

(cl--labels-convert F)

Documentation

Special macro-expander to rename (function F) references in cl-labels.

Source Code

;; Defined in /usr/src/emacs/lisp/emacs-lisp/cl-macs.el.gz
(defun cl--labels-convert (f)
  "Special macro-expander to rename (function F) references in `cl-labels'."
  (cond
   ;; ¡¡Big Ugly Hack!! We can't use a compiler-macro because those are checked
   ;; *after* handling `function', but we want to stop macroexpansion from
   ;; being applied infinitely, so we use a cache to return the exact `form'
   ;; being expanded even though we don't receive it.
   ;; In Common Lisp, we'd use the `&whole' arg instead (see
   ;; "Macro Lambda Lists" in the CLHS).
   ((let ((symbols-with-pos-enabled nil)) ;Don't rewrite #'<X@5> => #'<X@3>
      (eq f (car cl--labels-convert-cache)))
    ;; This value should be `eq' to the `&whole' form.
    ;; If this is not the case, we have a bug.
    (prog1 (cdr cl--labels-convert-cache)
      ;; Drop it, so it can't accidentally interfere with some
      ;; unrelated subsequent use of `function' with the same symbol.
      (setq cl--labels-convert-cache nil)))
   (t
    (let* ((found (assq f macroexpand-all-environment))
           (replacement (and found
                             (ignore-errors
                               (funcall (cdr found) cl--labels-magic)))))
      (if (and replacement (eq cl--labels-magic (car replacement)))
          (nth 1 replacement)
        ;; FIXME: Here, we'd like to return the `&whole' form, but since ELisp
        ;; doesn't have that, we approximate it via `cl--labels-convert-cache'.
        (let ((res `(function ,f)))
          (setq cl--labels-convert-cache (cons f res))
          res))))))