Function: macroexp--unfold-lambda

macroexp--unfold-lambda is a byte-compiled function defined in macroexp.el.gz.

Signature

(macroexp--unfold-lambda FORM &optional NAME)

Source Code

;; Defined in /usr/src/emacs/lisp/emacs-lisp/macroexp.el.gz
(defun macroexp--unfold-lambda (form &optional name)
  (or name (setq name "anonymous lambda"))
  (pcase form
    ((or `(funcall (function ,lambda) . ,actuals) `(,lambda . ,actuals))
     (let* ((formals (nth 1 lambda))
            (body (cdr (macroexp-parse-body (cddr lambda))))
            optionalp restp
            (dynboundarg nil)
            bindings)
       ;; FIXME: The checks below do not belong in an optimization phase.
       (while formals
         (if (macroexp--dynamic-variable-p (car formals))
             (setq dynboundarg t))
         (cond ((eq (car formals) '&optional)
                ;; ok, I'll let this slide because funcall_lambda() does...
                ;; (if optionalp (error "Multiple &optional keywords in %s" name))
                (if restp (error "&optional found after &rest in %s" name))
                (if (null (cdr formals))
                    (error "Nothing after &optional in %s" name))
                (setq optionalp t))
               ((eq (car formals) '&rest)
                ;; ...but it is by no stretch of the imagination a reasonable
                ;; thing that funcall_lambda() allows (&rest x y) and
                ;; (&rest x &optional y) in formalss.
                (if (null (cdr formals))
                    (error "Nothing after &rest in %s" name))
                (if (cdr (cdr formals))
                    (error "Multiple vars after &rest in %s" name))
                (setq restp t))
               (restp
                (setq bindings (cons (list (car formals)
                                           (and actuals (cons 'list actuals)))
                                     bindings)
                      actuals nil))
               ((and (not optionalp) (null actuals))
                (setq formals nil actuals 'too-few))
               (t
                (setq bindings (cons (list (car formals) (car actuals))
                                     bindings)
                      actuals (cdr actuals))))
         (setq formals (cdr formals)))
       (cond
        (actuals
         (macroexp-warn-and-return
          (format-message
           (if (eq actuals 'too-few)
               "attempt to open-code `%s' with too few arguments"
             "attempt to open-code `%s' with too many arguments")
           name)
          form nil nil formals))
        ;; In lexical-binding mode, let and functions don't bind vars in
        ;; the same way (let obey special-variable-p, but functions
        ;; don't).  So if one of the vars is declared as dynamically scoped, we
        ;; can't just convert the call to `let'.
        ;; FIXME: We should α-rename the affected args and then use `let'.
        (dynboundarg form)
        (bindings `(let ,(nreverse bindings) . ,body))
        (t (macroexp-progn body)))))
    (_ (error "Not an unfoldable form: %S" form))))