]> git.eshelyaron.com Git - emacs.git/commitdiff
Add "defining symbols" to backtrace lines with lambdas.
authorAlan Mackenzie <acm@muc.de>
Mon, 17 Jul 2023 09:55:04 +0000 (09:55 +0000)
committerAlan Mackenzie <acm@muc.de>
Mon, 17 Jul 2023 09:55:04 +0000 (09:55 +0000)
This is achieved by enhancing the structures of the
interpreted, byte compiled, and native compiled functions to
include the defining symbol in them.  It is intended that the
older forms of such functions will still run OK in the current
Emacs.

* lisp/emacs-lisp/byte-run.el (byte-run--strip-list)
(byte-run--strip-vector/record)
(byte-run-strip-symbol-positions, function-put)
(byte-run--set-advertised-calling-convention)
(byte-run--set-obsolete, byte-run--set-interactive-only)
(byte-run--set-pure, byte-run--set-side-effect-free)
(byte-run--set-compiler-macro, byte-run--set-doc-string)
(byte-run--set-indent, byte-run--set-speed)
(byte-run--set-completion, byte-run--set-modes)
(byte-run--set-interactive-args, byte-run--set-debug)
(byte-run--set-no-font-lock-keyword, byte-run--parse-body)
(byte-run--parse-declarations, defmacro)
* lisp/emacs-lisp/debug-early.el (debug-early-backtrace)
(debug-early): Add in the defining symbol to the source of all
these explicit defalias's.

* lisp/emacs-lisp/byte-run.el (defmacro, defun): Insert the
NAME parameter as defining symbol into the resulting form.
(lambda-arglist, lambda-body): New macros.

* lisp/emacs-lisp/byte-opt.el (byte-optimize--rename-var)
* lisp/emacs-lisp/bytecomp.el
(byte-compile-docstring-style-warn)
(byte-compile--reify-function, byte-compile-lambda)
(byte-compile-out-toplevel, byte-compile-make-closure)
(byte-compile-file-form-defalias)
* lisp/emacs-lisp/cconv.el (cconv--convert-function)
(cconv-convert, cconv-analyze-form)
(cconv-make-interpreted-closure)
* lisp/emacs-lisp/cl-generic.el (cl-generic-define)
(cl--generic-lambda, cl-generic-define-method)
* lisp/emacs-lisp/cl-macs.el (cl-labels)
(cl--sm-macroexpand-1)
* lisp/emacs-lisp/loaddefs-gen.el
(loaddefs-generate--make-autoload)
* lisp/emacs-lisp/macroexp.el (macroexp--expand-all)
* lisp/emacs-lisp/oclosure.el (oclosure--fix-type)
* lisp/help.el (help-function-arglist)
* lisp/progmodes/elisp-mode.el (elisp--local-variables-1)
(elisp--eval-defun-1)
* lisp/simple.el (function-documentation): Amend to handle
possible or actual defining symbols in forms.

* lisp/emacs-lisp/bytecomp.el (byte-compile-from-buffer): Bind
defining-symbol to t.  Call byte-compile-flush-pending after
each top-level form to ensure the defining-symbol mechanism
works.
(byte-compile-file-form-defvar, byte-compile-defvar): bind
defining-symbol to the variable being defined for the benefit
of any forms in the value.
(byte-compile-file-form-defmumble): New parameter defsym.  Add
the defining symbol to the form passed to byte-compile-lambda.
(byte-compile, byte-compile-sexp, byte-compile-top-level): Bind
defining-symbol to t.
(byte-compile-lambda, byte-compile-make-closure): Amend the
arguments to make-byte-code.

* lisp/emacs-lisp/cconv.el (cconv--convert-function): New
parameter defsym.
(cconv-fv, cconv-make-interpreted-closure): Use lambda-body.

* lisp/emacs-lisp/cl-generic.el (cl--generic-lambda): New
parameter defsym.
(cl-defmethod): Insert defining symbol into generated code.
(cl--generic-get-dispatcher): New parameter `name'.  Add this
symbol as the defining symbol in generated code.
(cl--generic-make-function, cl--generic-make-next-function):
New parameter `name'.

* lisp/emacs-lisp/cl-macs.el (cl--sm-macroexpand-1): bind
pcase-max-duplicate to nil around this function to prevent the
creation of pcase-n functions which lead to infinite recursion.

* lisp/emacs-lisp/cl-print.el (cl-print-object/cons): For a
lambda function, print the defining symbol in braces.  This is
the main point of these changes.
(cl-print-compiled): Add extra value, `full', meaning print out
a (byte-compiled) function in full.
(cl-print-object/compiled-function): Print the defining symbol
in the pertinent function.  Add in code for (eq
cl-print-compiled 'full).

* lisp/emacs-lisp/comp.el (comp-func): New field
defining-symbol.
(comp-spill-lap-function/symbol)
(comp-spill-lap-function/lambda): Fill in the new field
defining-symbol of func.  Use lambda-arglist in the lambda
version.
(comp-spill-lap) Add a mention of lambda form to the doc
string.
(comp-emit-for-top-level/form)
(comp-emit-for-top-level/lambda): Emit the defining symbol as
the last element of the subr being created.
(comp-limplify-top-level): Add one of the two rigid
possibilities for the defining symbol into the func structure.
(comp-native-compile): Remove the condition-case to ease
debugging the compiler.

* lisp/emacs-lisp/ert.el (ert-batch-backtrace-right-margin):
Change from 70 to nil.
(ert-batch-print-length): Change from 10 to nil.
(ert-batch-print-level): Change from 5 to nil.
All these changes were to get half-usable backtraces.

* lisp/emacs-lisp/macroexp.el (macroexp--unfold-lambda): Use
lambda-arglist and lambda-body.
(macroexp--expand-all): Add in a pcase handler for defalias,
which binds defining-symbol during the expansion of the form's
contents.  Likewise add a pcase handler for defvar and
defconst, which does the same.

* lisp/emacs-lisp/nadvice.el (advice--equal): New function.
This function is, as yet, incomplete, needing code for both
interpreted functions and subrs.
(advice--member-p, advice--remove-function): Use advice--equal
rather than equal to avoid unnecessarily failing to match when
defining-symbols are not the same.

* lisp/emacs-lisp/pcase.el (pcase-max-duplicates): New
variable, replaces a constant 2
(pcase--expand): Compare `count' with the new variable rather
than the constant 2.

* lisp/progmodes/compile.el (compilation-directory-properties)
(compilation-error-properties): Check a position is not
(point-min) before testing a text-property on the position
before.

* lisp/subr.el (lambda): Ensure there is a defining symbol
(usually the variable defining-symbol) in the resultant form.

* src/bytecode.c (Fbyte_code): Add an extra (as yet unused)
parameter defsym.
(exec_byte_code): Replace a call to error with one to xsignal1.

* src/comp.c (make_subr): New parameter defining_symbol.  Set
the new field in "struct subr" to this value.
(Fcomp__register_lambda, Fcomp__register_subr)
(Fcomp__late_register_subr): New parameter defining_symbol,
passed to one of the above functions.

* src/data.c (Fsubr_native_defining_symbol): New DEFUN.
(Finteractive_form, Fcommand_modes): Amend to handle the
possible presence of a defining_symbol field.

* src/eval.c (Ffunction, Fcommandp, funcall_lambda)
(lambda_arity): Handle the possible presence of a defining
symbol.
(defvar, defconst): Bind defining_symbol to the sym parameter.

* src/lisp.h (struct Lisp_Subr): New field defining_symbol.
(enum Lisp_Compiled): Amend COMPILED_INTERACTIVE, introduce
COMPILED_DEFINIG_SYM.

* src/lread.c (defsubr): Set subr's defining_symbol field.

* test/Makefile.in (check-doit): Set
ert-batch-backtrace-right-margin to zero.

* test/lisp/emacs-lisp/bytecomp-tests.el
(bytecomp-function-attributes): Amend for the extra field in
the bytecomp structure.

* test/lisp/emacs-lisp/cconv-tests.el
(cconv-convert-lambda-lifted)
(cconv-closure-convert-remap-var): Amend the expected
structure of macro-expanded lambda expressions.

# Please enter the commit message for your changes. Lines starting
# with '#' will be ignored, and an empty message aborts the commit.
#
# On branch feature/named-lambdas
# Changes to be committed:
# modified:   lisp/Makefile.in
# modified:   lisp/emacs-lisp/byte-opt.el
# modified:   lisp/emacs-lisp/byte-run.el
# modified:   lisp/emacs-lisp/bytecomp.el
# modified:   lisp/emacs-lisp/cconv.el
# modified:   lisp/emacs-lisp/cl-generic.el
# modified:   lisp/emacs-lisp/cl-macs.el
# modified:   lisp/emacs-lisp/cl-print.el
# modified:   lisp/emacs-lisp/comp.el
# modified:   lisp/emacs-lisp/debug-early.el
# modified:   lisp/emacs-lisp/ert.el
# modified:   lisp/emacs-lisp/loaddefs-gen.el
# modified:   lisp/emacs-lisp/macroexp.el
# modified:   lisp/emacs-lisp/nadvice.el
# modified:   lisp/emacs-lisp/oclosure.el
# modified:   lisp/emacs-lisp/pcase.el
# modified:   lisp/help.el
# modified:   lisp/progmodes/compile.el
# modified:   lisp/progmodes/elisp-mode.el
# modified:   lisp/simple.el
# modified:   lisp/subr.el
# modified:   src/bytecode.c
# modified:   src/comp.c
# modified:   src/data.c
# modified:   src/eval.c
# modified:   src/lisp.h
# modified:   src/lread.c
# modified:   test/Makefile.in
# modified:   test/lisp/emacs-lisp/bytecomp-tests.el
# modified:   test/lisp/emacs-lisp/cconv-tests.el
#
# Untracked files:
# .gitignore.acm
# .gitignore.backup
# .timestamps.txt
# 20230315.outerr
# 20230317.parallel.out
# 20230320.outerr
# 20230322.parallel.out
# bytecomp.20230407.el.diff
# diff.20230228.diff
# diff.20230313b.diff
# diff.20230408.diff
# diff.20230608.diff
# diff.20230608b.diff
# diff.20230705.diff
# diff.20230706.diff
# diff.20230715.diff
# diff.20230716.diff
# diff.20230716b.diff
# doc/lispref/files.20201010.techsi
# find-quoted-lambdas.el
# lisp/diff.20230314.diff
# lisp/emacs-lisp/bo-primitives.el
# lisp/emacs-lisp/bytecomp.20230406.eeel
# lisp/emacs-lisp/bytecomp.20230407.eeel
# lisp/emacs-lisp/bytecomp.20230608.eeel
# lisp/emacs-lisp/bytecomp.20230608.no-b-c.eeel
# lisp/emacs-lisp/cconv.20230608.eeelsee
# lisp/emacs-lisp/cl-generic.20230716.eeelsee
# outerr.20230716.txt
# scratch.20230715.el
# src/diff.20230314.diff
# src/eval.20230518.see
# src/eval.20230716.see
# src/fingerprint.c
# src/syntax.20201010.see
# stderr.20230712.txt
# stdout.20230712.txt
#

30 files changed:
lisp/Makefile.in
lisp/emacs-lisp/byte-opt.el
lisp/emacs-lisp/byte-run.el
lisp/emacs-lisp/bytecomp.el
lisp/emacs-lisp/cconv.el
lisp/emacs-lisp/cl-generic.el
lisp/emacs-lisp/cl-macs.el
lisp/emacs-lisp/cl-print.el
lisp/emacs-lisp/comp.el
lisp/emacs-lisp/debug-early.el
lisp/emacs-lisp/ert.el
lisp/emacs-lisp/loaddefs-gen.el
lisp/emacs-lisp/macroexp.el
lisp/emacs-lisp/nadvice.el
lisp/emacs-lisp/oclosure.el
lisp/emacs-lisp/pcase.el
lisp/help.el
lisp/progmodes/compile.el
lisp/progmodes/elisp-mode.el
lisp/simple.el
lisp/subr.el
src/bytecode.c
src/comp.c
src/data.c
src/eval.c
src/lisp.h
src/lread.c
test/Makefile.in
test/lisp/emacs-lisp/bytecomp-tests.el
test/lisp/emacs-lisp/cconv-tests.el

index 5af2168a8279287858b7d1cfbc103a1bb7af9314..011383ed3587f27064069313f7e3b689ff2a0b17 100644 (file)
@@ -60,7 +60,7 @@ EMACS = ../src/emacs${EXEEXT}
 EMACSOPT = -batch --no-site-file --no-site-lisp
 
 # Extra flags to pass to the byte compiler
-BYTE_COMPILE_EXTRA_FLAGS =
+BYTE_COMPILE_EXTRA_FLAGS = --eval "(setq debug-on-some-signals t  cl-print-compiled 'full)"
 # For example to not display the undefined function warnings you can use this:
 # BYTE_COMPILE_EXTRA_FLAGS = --eval '(setq byte-compile-warnings (quote (not unresolved)))'
 # The example above is just for developers, it should not be used by default.
index 26a1dc4a10305b95121c7c175cd127254d862d16..74e4a83c4a5fd435ccf00cbdb6061e65c214a6ca 100644 (file)
@@ -558,9 +558,17 @@ for speeding up processing.")
                          (cons (car h)
                                (byte-optimize--rename-var-body var new-var (cdr h))))
                        handlers)))
-      (`(internal-make-closure ,vars ,env . ,rest)
+      ((or `(internal-make-closure ,vars ,env
+                                   ,(and (pred (lambda (e) (and e (symbolp e))))
+                                         def)
+                                   . ,rest)
+           (and
+            `(internal-make-closure ,vars ,env . ,rest)
+            (let def nil)))
        `(,fn
-         ,vars ,(byte-optimize--rename-var-body var new-var env) . ,rest))
+         ,vars ,(byte-optimize--rename-var-body var new-var env) 
+         ,@(if def `(,def))
+         . ,rest))
       (`(defvar ,name . ,rest)
        ;; NAME is not renamed here; we only care about lexical variables.
        `(,fn ,name . ,(byte-optimize--rename-var-body var new-var rest)))
index a377ec395e16b25ff3bf6509996c75f72a7bae30..9c86561339901e839e9f2d114c2eb7537eece901 100644 (file)
@@ -37,7 +37,9 @@ The value is a hash table, the keys being the elements and the values being t.
 The purpose of this is to detect circular structures.")
 
 (defalias 'byte-run--strip-list
-  #'(lambda (arg)
+  #'(lambda
+      byte-run--strip-list
+            (arg)
       "Strip the positions from symbols with position in the list ARG.
 This is done by destructively modifying ARG.  Return ARG."
       (let ((a arg))
@@ -63,7 +65,9 @@ This is done by destructively modifying ARG.  Return ARG."
         arg)))
 
 (defalias 'byte-run--strip-vector/record
-  #'(lambda (arg)
+  #'(lambda
+      byte-run--strip-vector/record
+      (arg)
       "Strip the positions from symbols with position in the vector/record ARG.
 This is done by destructively modifying ARG.  Return ARG."
       (unless (gethash arg byte-run--ssp-seen)
@@ -84,7 +88,9 @@ This is done by destructively modifying ARG.  Return ARG."
       arg))
 
 (defalias 'byte-run-strip-symbol-positions
-  #'(lambda (arg)
+  #'(lambda
+      byte-run-strip-symbol-positions
+      (arg)
       "Strip all positions from symbols in ARG.
 This modifies destructively then returns ARG.
 
@@ -104,7 +110,9 @@ record, containing symbols with position."
   ;; We don't want people to just use `put' because we can't conveniently
   ;; hook into `put' to remap old properties to new ones.  But for now, there's
   ;; no such remapping, so we just call `put'.
-  #'(lambda (function prop value)
+  #'(lambda
+      function-put
+      (function prop value)
       "Set FUNCTION's property PROP to VALUE.
 The namespace for PROP is shared with symbols.
 So far, FUNCTION can only be a symbol, not a lambda expression."
@@ -121,27 +129,37 @@ So far, FUNCTION can only be a symbol, not a lambda expression."
 ;; loaded before backquote.el.
 
 (defalias 'byte-run--set-advertised-calling-convention
-  #'(lambda (f _args arglist when)
+  #'(lambda
+      byte-run--set-advertised-calling-convention
+      (f _args arglist when)
       (list 'set-advertised-calling-convention
             (list 'quote f) (list 'quote arglist) (list 'quote when))))
 
 (defalias 'byte-run--set-obsolete
-  #'(lambda (f _args new-name when)
+  #'(lambda
+      byte-run--set-obsolete
+      (f _args new-name when)
       (list 'make-obsolete
             (list 'quote f) (list 'quote new-name) when)))
 
 (defalias 'byte-run--set-interactive-only
-  #'(lambda (f _args instead)
+  #'(lambda
+      byte-run--set-interactive-only
+      (f _args instead)
       (list 'function-put (list 'quote f)
             ''interactive-only (list 'quote instead))))
 
 (defalias 'byte-run--set-pure
-  #'(lambda (f _args val)
+  #'(lambda
+      byte-run--set-pure
+      (f _args val)
       (list 'function-put (list 'quote f)
             ''pure (list 'quote val))))
 
 (defalias 'byte-run--set-side-effect-free
-  #'(lambda (f _args val)
+  #'(lambda
+      byte-run--set-side-effect-free
+      (f _args val)
       (list 'function-put (list 'quote f)
             ''side-effect-free (list 'quote val))))
 
@@ -154,7 +172,9 @@ So far, FUNCTION can only be a symbol, not a lambda expression."
      '(&or symbolp ("lambda" &define lambda-list lambda-doc def-body)))
 
 (defalias 'byte-run--set-compiler-macro
-  #'(lambda (f args compiler-function)
+  #'(lambda
+      byte-run--set-compiler-macro
+      (f args compiler-function)
       (if (not (eq (car-safe compiler-function) 'lambda))
           `(eval-and-compile
              (function-put ',f 'compiler-macro #',compiler-function))
@@ -175,36 +195,48 @@ So far, FUNCTION can only be a symbol, not a lambda expression."
                  ,@(cdr data))))))))
 
 (defalias 'byte-run--set-doc-string
-  #'(lambda (f _args pos)
+  #'(lambda
+      byte-run--set-doc-string
+      (f _args pos)
       (list 'function-put (list 'quote f)
             ''doc-string-elt (if (numberp pos)
                                  pos
                                (list 'quote pos)))))
 
 (defalias 'byte-run--set-indent
-  #'(lambda (f _args val)
+  #'(lambda
+      byte-run--set-indent
+      (f _args val)
       (list 'function-put (list 'quote f)
             ''lisp-indent-function (if (numberp val)
                                        val
                                      (list 'quote val)))))
 
 (defalias 'byte-run--set-speed
-  #'(lambda (f _args val)
+  #'(lambda
+      byte-run--set-speed
+      (f _args val)
       (list 'function-put (list 'quote f)
             ''speed (list 'quote val))))
 
 (defalias 'byte-run--set-completion
-  #'(lambda (f _args val)
+  #'(lambda
+      byte-run--set-completion
+      (f _args val)
       (list 'function-put (list 'quote f)
             ''completion-predicate (list 'function val))))
 
 (defalias 'byte-run--set-modes
-  #'(lambda (f _args &rest val)
+  #'(lambda
+      byte-run--set-modes
+      (f _args &rest val)
       (list 'function-put (list 'quote f)
             ''command-modes (list 'quote val))))
 
 (defalias 'byte-run--set-interactive-args
-  #'(lambda (f args &rest val)
+  #'(lambda
+      byte-run--set-interactive-args
+      (f args &rest val)
       (setq args (remove '&optional (remove '&rest args)))
       (list 'function-put (list 'quote f)
             ''interactive-args
@@ -250,18 +282,24 @@ to set this property.
 This is used by `declare'.")
 
 (defalias 'byte-run--set-debug
-  #'(lambda (name _args spec)
+  #'(lambda
+      byte-run--set-debug
+      (name _args spec)
       (list 'progn :autoload-end
            (list 'put (list 'quote name)
                  ''edebug-form-spec (list 'quote spec)))))
 
 (defalias 'byte-run--set-no-font-lock-keyword
-  #'(lambda (name _args val)
+  #'(lambda
+      byte-run--set-no-font-lock-keyword
+      (name _args val)
       (list 'function-put (list 'quote name)
            ''no-font-lock-keyword (list 'quote val))))
 
 (defalias 'byte-run--parse-body
-  #'(lambda (body allow-interactive)
+  #'(lambda
+      byte-run--parse-body
+      (body allow-interactive)
       "Decompose BODY into (DOCSTRING DECLARE INTERACTIVE BODY-REST WARNINGS)."
       (let* ((top body)
              (docstring nil)
@@ -308,7 +346,9 @@ This is used by `declare'.")
         (list docstring declare-form interactive-form body warnings))))
 
 (defalias 'byte-run--parse-declarations
-  #'(lambda (name arglist clauses construct declarations-alist)
+  #'(lambda
+      byte-run--parse-declarations
+      (name arglist clauses construct declarations-alist)
       (let* ((cl-decls nil)
              (actions
               (mapcar
@@ -318,7 +358,7 @@ This is used by `declare'.")
                       (f (apply (car f) name arglist (cdr x)))
                       ;; Yuck!!
                       ((and (featurep 'cl)
-                            (memq (car x)  ;C.f. cl--do-proclaim.
+                            (memq (car x) ;C.f. cl--do-proclaim.
                                   '(special inline notinline optimize warn)))
                        (push (list 'declare x) cl-decls)
                        nil)
@@ -347,7 +387,9 @@ This is used by `declare'.")
 (defalias 'defmacro
   (cons
    'macro
-   #'(lambda (name arglist &rest body)
+   #'(lambda
+       defmacro
+       (name arglist &rest body)
        "Define NAME as a macro.
 When the macro is called, as in (NAME ARGS...),
 the function (lambda ARGLIST BODY...) is applied to
@@ -374,7 +416,10 @@ The return value is undefined.
              (setq body (cons docstring body)))
          (if (null body)
              (setq body '(nil)))
-         (let* ((fun (list 'function (cons 'lambda (cons arglist body))))
+         (let* ((fun (list 'function (cons 'lambda
+                                           (cons
+                                            (bare-symbol name)
+                                            (cons arglist body)))))
                (def (list 'defalias
                           (list 'quote name)
                           (list 'cons ''macro fun))))
@@ -421,11 +466,37 @@ The return value is undefined.
                      (list 'quote name)
                      (list 'function
                            (cons 'lambda
-                                 (cons arglist body))))))
-      (if declarations
-          (cons 'prog1 (cons def (car declarations)))
-        def))))
-
+                                 (cons 
+                                  (bare-symbol name)
+                                  (cons arglist body)
+                                  ))))))
+                    (if declarations
+                        (cons 'prog1 (cons def (car declarations)))
+                      def))))
+
+(defmacro lambda-arglist (l)
+  "Given a lambda form L, return its arglist.
+Note that this takes into account the possible presence of a
+defining symbol field."
+  ;; `(if (and (cadr ,l) (symbolp (cadr ,l)))
+  ;;      (caddr ,l)
+  ;;    (cadr ,l))
+  (list 'if (list 'and (list 'car (list 'cdr l))
+                  (list 'symbolp (list 'car (list 'cdr l))))
+        (list 'car (list 'cdr (list 'cdr l)))
+        (list 'car (list 'cdr l))))
+
+(defmacro lambda-body (l)
+  "Given a lambda form L, return its body.
+Note that this takes into account the possible presence of a
+defining symbol field."
+  ;; `(if (and (cadr ,l) (symbolp (cadr ,l)))
+  ;;      (cdddr ,l)
+  ;;    (cddr ,l))
+  (list 'if (list 'and (list 'car (list 'cdr l))
+                  (list 'symbolp (list 'car (list 'cdr l))))
+        (list 'cdr (list 'cdr (list 'cdr l)))
+        (list 'cdr (list 'cdr l))))
 \f
 ;; Redefined in byte-opt.el.
 ;; This was undocumented and unused for decades.
index 489a9724fc465433e0dd00b73ff01ade76f1732e..e3210438a1beab2599752e9de06393c79b76d078 100644 (file)
@@ -1800,8 +1800,10 @@ It is too wide if it has any lines longer than the largest of
          (setq docs (nth 3 form)))
         ('lambda
           (setq kind "")          ; can't be "function", unfortunately
-          (setq docs (and (stringp (nth 2 form))
-                          (nth 2 form)))))
+          (let* ((definer (and (cadr form) (symbolp (cadr form))))
+                 (docstring (nth (if definer 3 2) form)))
+            (setq docs (and (stringp docstring)
+                            docstring)))))
       (when (and (consp name) (eq (car name) 'quote))
         (setq name (cadr name)))
       (setq name (if name (format " `%s' " name) ""))
@@ -2366,6 +2368,7 @@ With argument ARG, insert value in current buffer after the form."
        (byte-compile-tag-number 0)
        (byte-compile-depth 0)
        (byte-compile-maxdepth 0)
+        (defining-symbol t)
        (byte-compile-output nil)
        ;;        #### This is bound in b-c-close-variables.
        ;;        (byte-compile-warnings byte-compile-warnings)
@@ -2429,7 +2432,10 @@ With argument ARG, insert value in current buffer after the form."
                  (form (read-positioning-symbols inbuffer))
                  (warning (byte-run--unescaped-character-literals-warning)))
             (when warning (byte-compile-warn-x form "%s" warning))
-           (byte-compile-toplevel-file-form form)))
+           (byte-compile-toplevel-file-form form)
+            (when byte-compile-output
+              (byte-compile-flush-pending))))   ; To ensure pending byte-code's get
+                                               ; the correct `defining-symbol'.
        ;; Compile pending forms at end of file.
        (byte-compile-flush-pending)
        (byte-compile-warn-about-unresolved-functions)))
@@ -2721,16 +2727,17 @@ list that represents a doc string reference.
   (let ((sym (nth 1 form)))
     (byte-compile--declare-var sym)
     (if (eq (car form) 'defconst)
-        (push sym byte-compile-const-variables)))
-  (if (and (null (cddr form))          ;No `value' provided.
-           (eq (car form) 'defvar))     ;Just a declaration.
-      nil
-    (byte-compile-docstring-style-warn form)
-    (setq form (copy-sequence form))
-    (when (consp (nth 2 form))
-      (setcar (cdr (cdr form))
-              (byte-compile-top-level (nth 2 form) nil 'file)))
-    form))
+        (push sym byte-compile-const-variables))
+    (if (and (null (cddr form))                ;No `value' provided.
+             (eq (car form) 'defvar))   ;Just a declaration.
+        nil
+      (byte-compile-docstring-style-warn form)
+      (setq form (copy-sequence form))
+      (when (consp (nth 2 form))
+        (setcar (cdr (cdr form))
+                (let ((defining-symbol sym))
+                  (byte-compile-top-level (nth 2 form) nil 'file))))
+      form)))
 
 (put 'define-abbrev-table 'byte-hunk-handler
      'byte-compile-file-form-defvar-function)
@@ -2812,11 +2819,12 @@ list that represents a doc string reference.
     (apply 'make-obsolete
            (mapcar 'eval (cdr form)))))
 
-(defun byte-compile-file-form-defmumble (name macro arglist body rest)
+(defun byte-compile-file-form-defmumble (name macro arglist body defsym 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.
+BODY of the definition, or t if not recognized.  DEFSYM is the defining
+symbol for the lambda, usually the same as NAME.
 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
@@ -2827,7 +2835,7 @@ not to take responsibility for the actual compilation of the code."
          (that-one (assq name (symbol-value that-kind)))
          (bare-name (bare-symbol name))
          (byte-compile-current-form name)) ; For warnings.
-
+    (setq defining-symbol (or defsym t))
     (push bare-name byte-compile-new-defuns)
     ;; When a function or macro is defined, add it to the call tree so that
     ;; we can tell when functions are not used.
@@ -2900,7 +2908,9 @@ not to take responsibility for the actual compilation of the code."
           ;; Tell the caller that we didn't compile it yet.
           nil)
 
-      (let* ((code (byte-compile-lambda (cons arglist body) t)))
+      (let* ((code (byte-compile-lambda (cons defining-symbol
+                                              (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)
@@ -2985,8 +2995,18 @@ If QUOTED is non-nil, print with quoting; otherwise, print without quoting."
 (defun byte-compile--reify-function (fun)
   "Return an expression which will evaluate to a function value FUN.
 FUN should be either a `lambda' value or a `closure' value."
-  (pcase-let* (((or (and `(lambda ,args . ,body) (let env nil))
-                    `(closure ,env ,args . ,body))
+  (pcase-let* (((or (and
+                     (or `(lambda ,(and
+                                    (pred (lambda (e) (and e (symbolp e))))
+                                    def)
+                            ,args . ,body)
+                         (and `(lambda ,args . ,body) (let def nil)))
+                     (let env nil))
+                    `(closure ,env ,(and
+                                     (pred (lambda (e) (and e (symbolp e))))
+                                     def)
+                       ,args . ,body)
+                    (and `(closure ,env ,args . ,body) (let def nil)))
                 fun)
                (preamble nil)
                (renv ()))
@@ -3004,8 +3024,11 @@ FUN should be either a `lambda' value or a `closure' value."
        ((eq binding t))
        (t (push `(defvar ,binding) body))))
     (if (null renv)
-        `(lambda ,args ,@preamble ,@body)
-      `(let ,renv (lambda ,args ,@preamble ,@body)))))
+        `(lambda ,@(if def `(,def))
+           ,args ,@preamble ,@body)
+      `(let ,renv (lambda
+                    ,@(if def `(,def))
+                    ,args ,@preamble ,@body)))))
 \f
 ;;;###autoload
 (defun byte-compile (form)
@@ -3031,7 +3054,8 @@ If FORM is a lambda or a macro, byte-compile it as a function."
                      (if (symbolp form) form "provided"))
             fun)
            (t
-            (let (final-eval)
+            (let ((defining-symbol t)
+                  final-eval)
               (when (or (symbolp form) (eq (car-safe fun) 'closure))
                 ;; `fun' is a function *value*, so try to recover its corresponding
                 ;; source code.
@@ -3057,7 +3081,8 @@ If FORM is a lambda or a macro, byte-compile it as a function."
   "Compile and return SEXP."
   (displaying-byte-compile-warnings
    (byte-compile-close-variables
-    (byte-compile-top-level (byte-compile-preprocess sexp)))))
+    (let ((defining-symbol t))
+    (byte-compile-top-level (byte-compile-preprocess sexp))))))
 
 (defun byte-compile-check-lambda-list (list)
   "Check lambda-list LIST for errors."
@@ -3150,15 +3175,20 @@ lambda-expression."
       (setq fun (cons 'lambda fun))
     (unless (eq 'lambda (car-safe fun))
       (error "Not a lambda list: %S" fun)))
-  (byte-compile-docstring-style-warn fun)
-  (byte-compile-check-lambda-list (nth 1 fun))
-  (let* ((arglist (nth 1 fun))
+  (let ((definer (and (car-safe (cdr-safe fun))
+                      (symbolp (cadr fun))
+                      (cadr fun))))
+    (byte-compile-docstring-style-warn fun)
+    (byte-compile-check-lambda-list (nth (if definer 2 1) fun))
+    (let* (
+         (fun1 (if definer (cdr fun) fun))
+         (arglist (nth 1 fun1))
          (arglistvars (byte-run-strip-symbol-positions
                        (byte-compile-arglist-vars arglist)))
         (byte-compile-bound-variables
          (append (if (not lexical-binding) arglistvars)
                   byte-compile-bound-variables))
-        (body (cdr (cdr fun)))
+        (body (cdr (cdr fun1)))
         (doc (if (stringp (car body))
                   (prog1 (car body)
                     ;; Discard the doc string
@@ -3167,6 +3197,10 @@ lambda-expression."
                         (setq body (cdr body))))))
         (int (assq 'interactive body))
          command-modes)
+      (setq defining-symbol (or (and (not (eq definer t))
+                                     definer)
+                                defining-symbol
+                                t))
     (when lexical-binding
       (dolist (var arglistvars)
         (when (assq var byte-compile--known-dynamic-vars)
@@ -3231,8 +3265,9 @@ lambda-expression."
                            ;; byte-compile-make-args-desc lost the args's names,
                            ;; so preserve them in the docstring.
                            (list (help-add-fundoc-usage doc bare-arglist)))
-                          ((or doc int)
-                           (list doc)))
+                          (t (list doc)))
+                     ;; The defining symbol.
+                     `(,defining-symbol)
                     ;; optionally, the interactive spec (and the modes the
                     ;; command applies to).
                     (cond
@@ -3248,7 +3283,7 @@ lambda-expression."
                  (gethash (cadr compiled)
                           byte-to-native-lambdas-h))
                 out))
-       out))))
+       out)))))
 
 (defvar byte-compile-reserved-constants 0)
 
@@ -3301,6 +3336,7 @@ lambda-expression."
        (byte-compile-tag-number 0)
        (byte-compile-depth 0)
        (byte-compile-maxdepth 0)
+        (defining-symbol t)
         (byte-compile--lexical-environment lexenv)
         (byte-compile-reserved-constants (or reserved-csts 0))
        (byte-compile-output nil)
@@ -3400,9 +3436,16 @@ lambda-expression."
                       (not (delq nil (mapcar 'consp (cdr (car body))))))))
              (setq rest (cdr rest)))
            rest))
-      (let ((byte-compile-vector (byte-compile-constants-vector)))
-       (list 'byte-code (byte-compile-lapcode byte-compile-output)
-             byte-compile-vector byte-compile-maxdepth)))
+      (let ((byte-compile-vector (byte-compile-constants-vector))
+            (definer-suffix
+             (and (eq output-type 'file)
+                  defining-symbol
+                  (not (eq defining-symbol t))
+                  (symbolp defining-symbol)
+                  `(',defining-symbol))))
+        (nconc (list 'byte-code (byte-compile-lapcode byte-compile-output)
+                    byte-compile-vector byte-compile-maxdepth)
+               definer-suffix)))
      ;; it's a trivial function
      ((cdr body) (cons 'progn (nreverse body)))
      ((car body)))))
@@ -4212,13 +4255,21 @@ This function is never called when `lexical-binding' is nil."
   (if byte-compile--for-effect (setq byte-compile--for-effect nil)
     (let* ((vars (nth 1 form))
            (env (nth 2 form))
-           (docstring-exp (nth 3 form))
-           (body (nthcdr 4 form))
+           (def (and (symbolp (nth 3 form)) (nth 3 form)))
+           (docstring-exp (nth (if def 4 3) form))
+           (body (nthcdr (if def 5 4) form))
            (fun
-            (byte-compile-lambda `(lambda ,vars . ,body) nil (length env))))
+            (byte-compile-lambda `(lambda
+                                    ,defining-symbol
+                                    ,vars . ,body)
+                                 nil (length env))))
       (cl-assert (or (> (length env) 0)
                     docstring-exp))    ;Otherwise, we don't need a closure.
       (cl-assert (byte-code-function-p fun))
+      (setq defining-symbol (or (and (not (eq def t))
+                                     def)
+                                defining-symbol
+                                t))
       (byte-compile-form
        (if (macroexp-const-p docstring-exp)
            ;; Use symbols V0, V1 ... as placeholders for closure variables:
@@ -4237,15 +4288,22 @@ This function is never called when `lexical-binding' is nil."
                           ;; to get the indices right when disassembling.
                           (vconcat dummy-vars (aref fun 2))
                           (aref fun 3)  ; Stack depth of function
-                          (if docstring-exp
-                              (cons
-                               (eval (byte-run-strip-symbol-positions
-                                      docstring-exp)
-                                     t)
-                               (cdr opt-args)) ; The interactive spec will
-                                               ; have been stripped in
-                                               ; `byte-compile-lambda'.
-                            opt-args))))
+                          (cond
+                           (defining-symbol
+                            (cons (if docstring-exp
+                                      (eval (byte-run-strip-symbol-positions
+                                             docstring-exp)
+                                            t)
+                                    (car opt-args))
+                                  (cons defining-symbol
+                                        (nthcdr 2 opt-args))))
+                           (docstring-exp
+                            (cons
+                             (eval (byte-run-strip-symbol-positions
+                                    docstring-exp)
+                                   t)
+                             (cdr opt-args)))
+                           (t opt-args)))))
              `(make-closure ,proto-fun ,@env))
          ;; Nontrivial doc string expression: create a bytecode object
          ;; from small pieces at run time.
@@ -4254,12 +4312,17 @@ This function is never called when `lexical-binding' is nil."
            ',(aref fun 1)         ; The byte-code.
            (vconcat (vector . ,env) ',(aref fun 2)) ; constant vector.
            ,@(let ((rest (nthcdr 3 (mapcar (lambda (x) `',x) fun))))
-               (if docstring-exp
-                   `(,(car rest)
-                     ,(byte-run-strip-symbol-positions docstring-exp)
-                     ,@(cddr rest))
-                 rest))))
-         ))))
+               (cond
+                (defining-symbol
+                 `(,(car rest)
+                   ,(byte-run-strip-symbol-positions docstring-exp)
+                   ',defining-symbol
+                   ,@(nthcdr 3 rest)))
+                (docstring-exp
+                 `(,(car rest)
+                   ,(byte-run-strip-symbol-positions docstring-exp)
+                   ,@(cddr rest)))
+                (t rest)))))))))
 
 (defun byte-compile-get-closed-var (form)
   "Byte-compile the special `internal-get-closed-var' form."
@@ -5190,6 +5253,7 @@ binding slots have been popped."
     ;; Delegate the actual work to the function version of the
     ;; special form, named with a "-1" suffix.
     (byte-compile-form-do-effect
+     (let ((defining-symbol var))
      (cond
       ((eq fun 'defconst) `(defconst-1 ',var ,@(nthcdr 2 form)))
       ((not (cddr form)) `',var) ; A simple (defvar foo) just returns foo.
@@ -5197,7 +5261,7 @@ binding slots have been popped."
                     ;; Don't eval `value' if `defvar' wouldn't eval it either.
                     ,(if (macroexp-const-p value) value
                        `(if (boundp ',var) nil ,value))
-                    ,@(nthcdr 3 form)))))))
+                    ,@(nthcdr 3 form))))))))
 
 (defun byte-compile-autoload (form)
   (and (macroexp-const-p (nth 1 form))
@@ -5252,13 +5316,18 @@ binding slots have been popped."
              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)
+            ((or `(lambda ,(and (pred (lambda (e)
+                                        (and e (symbolp e))))
+                                def)
+                    ,arglist . ,body)
+                 (and `(lambda ,arglist . ,body) (let def nil))
                  ;; `(closure ,_ ,arglist . ,body)
-                 (and `(internal-make-closure ,arglist . ,_) (let body t))
-                 (and (let arglist t) (let body t)))
+                 (and `(internal-make-closure ,arglist . ,_) (let body t)
+                      (let def nil))
+                 (and (let arglist t) (let body t) (let def nil)))
              lam))
          (unless (byte-compile-file-form-defmumble
-                  name macro arglist body rest)
+                  name macro arglist body def rest)
            (when macro
              (if (null fun)
                  (message "Macro %s unrecognized, won't work in file" name)
index 3e75020a0135d9dbf00fe4112f2a4d4bbc21af66..95aefba8b669aa0fbeb968b5ca6f8668fc90420a 100644 (file)
@@ -167,8 +167,9 @@ Returns a form where all lambdas don't have any free variables."
       (unless (memq (car b) s) (push b res)))
     (nreverse res)))
 
-(defun cconv--convert-function (args body env parentform &optional docstring)
-  (cl-assert (equal body (caar cconv-freevars-alist)))
+(defun cconv--convert-function (args body env
+                                     defsym parentform &optional docstring)
+  ;; (cl-assert (equal body (caar cconv-freevars-alist))) ; STOUGH, 2023-02-21.
   (let* ((fvs (cdr (pop cconv-freevars-alist)))
          (body-new '())
          (envector ())
@@ -198,10 +199,12 @@ Returns a form where all lambdas don't have any free variables."
                      args body new-env parentform))
     (cond
      ((not (or envector docstring))     ;If no freevars - do nothing.
-      `(function (lambda ,args . ,body-new)))
+      `(function (lambda ,@(if defsym `(,defsym)) ,args . ,body-new)))
      (t
       `(internal-make-closure
-        ,args ,envector ,docstring . ,body-new)))))
+        ,args ,envector
+        ,@(if defsym `(,defsym))
+        ,docstring . ,body-new)))))
 
 (defun cconv--remap-llv (new-env var closedsym)
   ;; In a case such as:
@@ -362,13 +365,13 @@ places where they originally did not directly appear."
                              (progn
                                (cl-assert (and (eq (car value) 'function)
                                                (eq (car (cadr value)) 'lambda)))
-                               (cl-assert (equal (cddr (cadr value))
+                               (cl-assert (equal (lambda-body (cadr value))
                                                  (caar cconv-freevars-alist)))
                                ;; Peek at the freevars to decide whether
                                ;; to Î»-lift.
                                (let* ((fvs (cdr (car cconv-freevars-alist)))
                                       (fun (cadr value))
-                                      (funargs (cadr fun))
+                                      (funargs (lambda-arglist fun))
                                       (funcvars (append fvs funargs)))
                                        ; lambda lifting condition
                                  (and fvs (>= cconv-liftwhen
@@ -376,9 +379,12 @@ places where they originally did not directly appear."
                                        ; Lift.
                        (let* ((fvs (cdr (pop cconv-freevars-alist)))
                               (fun (cadr value))
-                              (funargs (cadr fun))
+                              (func-defsym (or (and (symbolp (cadr fun))
+                                                    (cadr fun))
+                                               t))
+                              (funargs (lambda-arglist fun))
                               (funcvars (append fvs funargs))
-                              (funcbody (cddr fun))
+                              (funcbody (lambda-body fun))
                               (funcbody-env ()))
                          (push `(,var . (apply-partially ,var . ,fvs)) new-env)
                          (dolist (fv fvs)
@@ -387,7 +393,7 @@ places where they originally did not directly appear."
                                                    (cdr (assq fv env))))
                                     (not (memq fv funargs)))
                                (push `(,fv . (car-safe ,fv)) funcbody-env)))
-                         `(function (lambda ,funcvars .
+                         `(function (lambda ,func-defsym ,funcvars .
                                       ,(cconv--convert-funcbody
                                         funargs funcbody funcbody-env value)))))
 
@@ -477,7 +483,11 @@ places where they originally did not directly appear."
                                         branch))
                               cond-forms)))
 
-    (`(function (lambda ,args . ,body) . ,rest)
+    (`(function
+       ,(or `(lambda ,(and (pred (lambda (e) (and e (symbolp e)))) def)
+               ,args . ,body)
+            (and `(lambda ,args . ,body) (let def nil)))
+       . ,rest)
      (let* ((docstring (if (eq :documentation (car-safe (car body)))
                            (cconv-convert (cadr (pop body)) env extend)))
             (bf (if (stringp (car body)) (cdr body) body))
@@ -510,7 +520,7 @@ places where they originally did not directly appear."
          ;; it with the new one.
          (let ((entry (pop cconv-freevars-alist)))
            (push (cons body (cdr entry)) cconv-freevars-alist)))
-       (setq cf (cconv--convert-function args body env form docstring))
+       (setq cf (cconv--convert-function args body env def form docstring))
        (if (not cif)
            ;; Normal case, the interactive form needs no special treatment.
            cf
@@ -562,7 +572,9 @@ places where they originally did not directly appear."
 
     (`(unwind-protect ,form1 . ,body)
      `(,(car form) ,(cconv-convert form1 env extend)
-        :fun-body ,(cconv--convert-function () body env form1)))
+        :fun-body ,(cconv--convert-function () body env
+                                            (or defining-symbol t)
+                                            form1)))
 
     (`(setq ,var ,expr)
      (let ((var-new (or (cdr (assq var env)) var))
@@ -751,6 +763,20 @@ This function does not return anything but instead fills the
        (dolist (vardata newvars)
          (cconv--analyze-use vardata form "variable"))))
 
+    (`(function (lambda ,(pred (lambda (e) (and e (symbolp e))))
+                        ,vrs . ,body-forms))
+     (when (eq :documentation (car-safe (car body-forms)))
+       (cconv-analyze-form (cadr (pop body-forms)) env))
+     (let ((bf (if (stringp (car body-forms)) (cdr body-forms) body-forms)))
+       (when (eq 'interactive (car-safe (car bf)))
+         (let ((if (cadr (car bf))))
+           (unless (macroexp-const-p if) ;Optimize this common case.
+             (let ((f (if (eq 'function (car-safe if)) if
+                        `#'(lambda (&rest _cconv--dummy) ,if))))
+               (setf (gethash form cconv--interactive-form-funs) f)
+               (cconv-analyze-form f env))))))
+     (cconv--analyze-function vrs body-forms env form))
+
     (`(function (lambda ,vrs . ,body-forms))
      (when (eq :documentation (car-safe (car body-forms)))
        (cconv-analyze-form (cadr (pop body-forms)) env))
@@ -872,7 +898,7 @@ lexically and dynamically bound symbols actually used by FORM."
          (cconv--dynbindings nil)
          (cconv-freevars-alist '())
         (cconv-var-classification '()))
-    (let* ((body (cddr (cadr fun))))
+    (let* ((body (lambda-body (cadr fun))))
       ;; Analyze form - fill these variables with new information.
       (cconv-analyze-form fun analysis-env)
       (setq cconv-freevars-alist (nreverse cconv-freevars-alist))
@@ -899,21 +925,29 @@ i.e. a list whose elements can be either plain symbols (which indicate
 that this symbol should use dynamic scoping) or pairs (SYMBOL . VALUE)
 for the lexical bindings."
   (cl-assert (eq (car-safe fun) 'lambda))
-  (let ((lexvars (delq nil (mapcar #'car-safe env))))
+  (let ((lexvars (delq nil (mapcar #'car-safe env)))
+        (defsym (and (car-safe (cdr-safe fun))
+                     (symbolp (cadr fun))
+                     (cadr fun))))
     (if (or (null lexvars)
             ;; Functions with a `:closure-dont-trim-context' marker
             ;; should keep their whole context untrimmed (bug#59213).
-            (and (eq :closure-dont-trim-context (nth 2 fun))
+            (and (eq :closure-dont-trim-context
+                     (car (lambda-body fun)))
                  ;; Check the function doesn't just return the magic keyword.
-                 (nthcdr 3 fun)))
+                 (cdr (lambda-body fun))))
         ;; The lexical environment is empty, or needs to be preserved,
         ;; so there's no need to look for free variables.
         ;; Attempting to replace ,(cdr fun) by a macroexpanded version
         ;; causes bootstrap to fail.
-        `(closure ,env . ,(cdr fun))
+        `(closure ,env
+             ,(or defsym defining-symbol t)
+           ,(lambda-arglist fun) . ,(lambda-body fun))
       ;; We could try and cache the result of the macroexpansion and
       ;; `cconv-fv' analysis.  Not sure it's worth the trouble.
-      (let* ((form `#',fun)
+      (let* ((form `#'(lambda ,(or defsym defining-symbol t)
+                        ,(lambda-arglist fun)
+                        . ,(lambda-body fun)))
              (expanded-form
               (let ((lexical-binding t) ;; Tell macros which dialect is in use.
                    ;; Make the macro aware of any defvar declarations in scope.
index b062c280a410ffdb887e9188b47995a75e1355ef..5ff1bcfa471570c52b4816f7fc9a9b0ef927b170 100644 (file)
@@ -337,7 +337,7 @@ DEFAULT-BODY, if present, is used as the body of a default method.
             (setf (cl--generic-dispatches generic)
                   (cons dispatch (delq dispatch dispatches)))))))
     (setf (cl--generic-options generic) options)
-    (cl--generic-make-function generic)))
+    (cl--generic-make-function generic name)))
 
 (defmacro cl-generic-current-method-specializers ()
   "List of (VAR . TYPE) where TYPE is var's specializer.
@@ -387,7 +387,7 @@ the specializer used will be the one returned by BODY."
       (cons (nreverse specializers)
             (nreverse (delq nil plain-args)))))
 
-  (defun cl--generic-lambda (args body)
+  (defun cl--generic-lambda (defsym args body)
     "Make the lambda expression for a method with ARGS and BODY."
     (pcase-let* ((`(,spec-args . ,plain-args)
                   (cl--generic-split-args args))
@@ -402,7 +402,9 @@ the specializer used will be the one returned by BODY."
       ;; First macroexpand away the cl-function stuff (e.g. &key and
       ;; destructuring args, `declare' and whatnot).
       (pcase (macroexpand fun macroenv)
-        (`#'(lambda ,args . ,body)
+        ((or `#'(lambda ,(and (pred (lambda (e) (and e (symbolp e)))) def)
+                  ,args . ,body)
+             (and `#'(lambda ,args . ,body) (let def nil)))
          (let* ((parsed-body (macroexp-parse-body body))
                 (nm (make-symbol "cl--nm"))
                 (arglist (make-symbol "cl--args"))
@@ -423,12 +425,12 @@ the specializer used will be the one returned by BODY."
            (cond
             ((not uses-cnm)
              (cons nil
-                   `#'(lambda (,@args)
+                   `#'(lambda ,defsym (,@args)
                         ,@(car parsed-body)
                         ,nbody)))
             (lexical-binding
              (cons 'curried
-                   `#'(lambda (,nm) ;Called when constructing the effective method.
+                   `#'(lambda ,defsym (,nm) ;Called when constructing the effective method.
                         (let ((,nmp (if (cl--generic-isnot-nnm-p ,nm)
                                         #'always #'ignore)))
                           ;; This `(λ (&rest x) .. (apply (λ (args) ..) x))'
@@ -464,17 +466,16 @@ the specializer used will be the one returned by BODY."
                               (apply (lambda (,@λ-lift ,@args) ,nbody)
                                      ,@λ-lift ,arglist)))))))
             (t
-             (cons t
-                 `#'(lambda (,cnm ,@args)
-                      ,@(car parsed-body)
-                      ,(macroexp-warn-and-return
-                        "cl-defmethod used without lexical-binding"
-                        (if (not (assq nmp uses-cnm))
-                            nbody
-                          `(let ((,nmp (lambda ()
-                                         (cl--generic-isnot-nnm-p ,cnm))))
-                             ,nbody))
-                        'lexical t)))))
+             (cons t `#'(lambda ,defsym (,cnm ,@args)
+                          ,@(car parsed-body)
+                          ,(macroexp-warn-and-return
+                            "cl-defmethod used without lexical-binding"
+                            (if (not (assq nmp uses-cnm))
+                                nbody
+                              `(let ((,nmp (lambda ()
+                                             (cl--generic-isnot-nnm-p ,cnm))))
+                                 ,nbody))
+                            'lexical t)))))
            ))
         (f (error "Unexpected macroexpansion result: %S" f))))))
 
@@ -572,7 +573,9 @@ The set of acceptable TYPEs (also called \"specializers\") is defined
       (require 'gv)
       (declare-function gv-setter "gv" (name))
       (setq name (gv-setter (cadr name))))
-    (pcase-let* ((`(,call-con . ,fun) (cl--generic-lambda args body)))
+    (pcase-let* ((`(,call-con . ,fun) (cl--generic-lambda
+                                       (bare-symbol name)
+                                       args body)))
       `(progn
          ;; You could argue that `defmethod' modifies rather than defines the
          ;; function, so warnings like "not known to be defined" are fair game.
@@ -643,7 +646,7 @@ The set of acceptable TYPEs (also called \"specializers\") is defined
     (let ((sym (cl--generic-name generic)) ; Actual name (for aliases).
           ;; FIXME: Try to avoid re-constructing a new function if the old one
           ;; is still valid (e.g. still empty method cache)?
-          (gfun (cl--generic-make-function generic)))
+          (gfun (cl--generic-make-function generic name)))
       (unless (symbol-function sym)
         (defalias sym 'dummy))   ;Record definition into load-history.
       (cl-pushnew `(cl-defmethod . ,(cl--generic-load-hist-format
@@ -681,7 +684,7 @@ The set of acceptable TYPEs (also called \"specializers\") is defined
     ;; see `cl--generic-prefill-dispatchers'.
     #'byte-compile))
 
-(defun cl--generic-get-dispatcher (dispatch)
+(defun cl--generic-get-dispatcher (dispatch &optional name)
   (with-memoization
       ;; We need `copy-sequence` here because this `dispatch' object might be
       ;; modified by side-effect in `cl-generic-define-method' (bug#46722).
@@ -745,7 +748,9 @@ You might need to add: %S"
        cl--generic-compiler
        `(lambda (generic dispatches-left methods)
           (let ((method-cache (make-hash-table :test #'eql)))
-            (lambda (,@fixedargs &rest args)
+            (lambda
+              ,(or name 'cl--generic-get-dispatcher)
+              (,@fixedargs &rest args)
               (let ,bindings
                 (apply (with-memoization
                            (gethash ,tag-exp method-cache)
@@ -755,12 +760,13 @@ You might need to add: %S"
                                `(append ,@typescodes) (car typescodes))))
                        ,@fixedargs args)))))))))
 
-(defun cl--generic-make-function (generic)
+(defun cl--generic-make-function (generic &optional name)
   (cl--generic-make-next-function generic
                                   (cl--generic-dispatches generic)
-                                  (cl--generic-method-table generic)))
+                                  (cl--generic-method-table generic)
+                                  name))
 
-(defun cl--generic-make-next-function (generic dispatches methods)
+(defun cl--generic-make-next-function (generic dispatches methods &optional name)
   (let* ((dispatch
           (progn
             (while (and dispatches
@@ -774,7 +780,7 @@ You might need to add: %S"
                   ;; further arguments.
                   methods))
         (cl--generic-build-combined-method generic methods)
-      (let ((dispatcher (cl--generic-get-dispatcher dispatch)))
+      (let ((dispatcher (cl--generic-get-dispatcher dispatch name)))
         (funcall dispatcher generic dispatches methods)))))
 
 (defvar cl--generic-combined-method-memoization
index 0a3181561bd5508dcad4cc1bea39f4ae660ab234..23ca692a131df5019416d7508e336d8d76ee1d95 100644 (file)
@@ -2255,7 +2255,9 @@ details.
                  (lambda (bind)
                    (pcase-let*
                        ((`(,var ,sargs . ,sbody) bind)
-                        (`(function (lambda ,fargs . ,ebody))
+                        (`(function ,(or `(lambda ,(pred (lambda (e) (and e (symbolp e))))
+                                            ,fargs . ,ebody)
+                                         `(lambda ,fargs . ,ebody)))
                          (macroexpand-all `(cl-function (lambda ,sargs . ,sbody))
                                           newenv))
                         (`(,ofargs . ,obody)
@@ -2314,6 +2316,11 @@ This is like `cl-flet', but for macros instead of functions.
   (while (not (eq exp (setq exp (macroexpand-1 exp env)))))
   exp)
 
+;; pcase-n functions must not be created in `cl--sm-macroexpand-1',
+;; because of infinite recursion.
+(eval-when-compile (defvar save-p-m-d pcase-max-duplicates)
+                   (setq save-p-m-d pcase-max-duplicates)
+                   (setq pcase-max-duplicates nil))
 (defun cl--sm-macroexpand-1 (orig-fun exp &optional env)
   "Special macro expander advice used inside `cl-symbol-macrolet'.
 This function extends `macroexpand-1' during macro expansion
@@ -2399,7 +2406,10 @@ of `cl-symbol-macrolet' to additionally expand symbol macros."
            exp)))
       ;; Do the same as for `let' but for variables introduced
       ;; via other means, such as `lambda' and `condition-case'.
-      (`(function (lambda ,args . ,body))
+      (`(function
+         ,(or `(lambda ,(and (pred (lambda (e) (and e (symbolp e)))) def)
+                 ,args . ,body)
+              (and `(lambda ,args . ,body) (let def nil))))
        (let ((nargs ()) (found nil))
          (dolist (var args)
            (push (cond
@@ -2414,7 +2424,8 @@ of `cl-symbol-macrolet' to additionally expand symbol macros."
                  nargs))
          (if found
              `(function
-               (lambda ,(nreverse nargs)
+               (lambda
+                 ,@(if def `(,def)) ,(nreverse nargs)
                  . ,(mapcar (lambda (exp)
                               (macroexpand-all exp env))
                             body)))
@@ -2433,6 +2444,7 @@ of `cl-symbol-macrolet' to additionally expand symbol macros."
                                (cdr clause))))
                 clauses))))
       (_ exp))))
+(eval-when-compile (setq pcase-max-duplicates save-p-m-d))
 
 ;;;###autoload
 (defmacro cl-symbol-macrolet (bindings &rest body)
index 71929caabb82b90f47d5aeea34e8e77e6ababa6f..06c4f092d156a212a3def7a8efe9a0e902fb2da4 100644 (file)
@@ -69,7 +69,17 @@ Print the contents hidden by the ellipsis to STREAM."
   (if (and cl-print--depth (natnump print-level)
            (> cl-print--depth print-level))
       (cl-print-insert-ellipsis object nil stream)
-    (let ((car (pop object)))
+    (let ((car (pop object))
+          defsym)
+      (cond
+       ((eq car 'lambda)
+        (setq defsym (car-safe object)))
+       ((eq car 'closure)
+        (setq defsym (car-safe (cdr-safe object)))))
+      (when (and defsym (not (eq defsym t)) (symbolp defsym))
+        (princ "{" stream)
+        (prin1 defsym stream)
+        (princ "} " stream))
       (if (and print-quoted
                (memq car '(\, quote function \` \,@ \,.))
                (consp object)
@@ -165,6 +175,7 @@ Print the contents hidden by the ellipsis to STREAM."
 (defvar cl-print-compiled nil
   "Control how to print byte-compiled functions.
 Acceptable values include:
+- `full' to print out the full contents of the function using `prin1'.
 - `static' to print the vector of constants.
 - `disassemble' to print the disassembly of the code.
 - nil to skip printing any details about the code.")
@@ -181,48 +192,63 @@ into a button whose action shows the function's disassembly.")
 
 (cl-defmethod cl-print-object ((object compiled-function) stream)
   (unless stream (setq stream standard-output))
+  (let ((defsym
+         (cond
+          ((subrp object)
+           (subr-native-defining-symbol object))
+          ((> (length object) 5)
+           (aref object 5)))))
+    (when (and defsym (not (eq defsym t)) (symbolp defsym))
+      (princ "{" stream)
+      (;; cl-
+       prin1 defsym stream)
+      (princ "} " stream)))
   ;; We use "#f(...)" rather than "#<...>" so that pp.el gives better results.
   (princ "#f(compiled-function " stream)
   (let ((args (help-function-arglist object 'preserve-names)))
     (if args
         (prin1 args stream)
       (princ "()" stream)))
-  (pcase (help-split-fundoc (documentation object 'raw) object)
-    ;; Drop args which `help-function-arglist' already printed.
-    (`(,_usage . ,(and doc (guard (stringp doc))))
-     (princ " " stream)
-     (prin1 doc stream)))
-  (let ((inter (interactive-form object)))
-    (when inter
-      (princ " " stream)
-      (cl-print-object
-       (if (eq 'byte-code (car-safe (cadr inter)))
-           `(interactive ,(make-byte-code nil (nth 1 (cadr inter))
-                                          (nth 2 (cadr inter))
-                                          (nth 3 (cadr inter))))
-         inter)
-       stream)))
-  (if (eq cl-print-compiled 'disassemble)
-      (princ
-       (with-temp-buffer
-         (insert "\n")
-         (disassemble-1 object 0)
-         (buffer-string))
-       stream)
-    (princ " " stream)
-    (let ((button-start (and cl-print-compiled-button
-                             (bufferp stream)
-                             (with-current-buffer stream (point)))))
-      (princ (format "#<bytecode %#x>" (sxhash object)) stream)
-      (when (eq cl-print-compiled 'static)
+  (if (eq cl-print-compiled 'full)
+      (progn
+        (princ " " stream)
+        (prin1 object stream))
+    (pcase (help-split-fundoc (documentation object 'raw) object)
+      ;; Drop args which `help-function-arglist' already printed.
+      (`(,_usage . ,(and doc (guard (stringp doc))))
+       (princ " " stream)
+       (prin1 doc stream)))
+    (let ((inter (interactive-form object)))
+      (when inter
         (princ " " stream)
-        (cl-print-object (aref object 2) stream))
-      (when button-start
-        (with-current-buffer stream
-          (make-text-button button-start (point)
-                            :type 'help-byte-code
-                            'byte-code-function object)))))
-  (princ ")" stream))
+        (cl-print-object
+         (if (eq 'byte-code (car-safe (cadr inter)))
+             `(interactive ,(make-byte-code nil (nth 1 (cadr inter))
+                                            (nth 2 (cadr inter))
+                                            (nth 3 (cadr inter))))
+           inter)
+         stream)))
+    (if (eq cl-print-compiled 'disassemble)
+        (princ
+         (with-temp-buffer
+           (insert "\n")
+           (disassemble-1 object 0)
+           (buffer-string))
+         stream)
+      (princ " " stream)
+      (let ((button-start (and cl-print-compiled-button
+                               (bufferp stream)
+                               (with-current-buffer stream (point)))))
+        (princ (format "#<bytecode %#x>" (sxhash object)) stream)
+        (when (eq cl-print-compiled 'static)
+          (princ " " stream)
+          (cl-print-object (aref object 2) stream))
+        (when button-start
+          (with-current-buffer stream
+            (make-text-button button-start (point)
+                              :type 'help-byte-code
+                              'byte-code-function object)))))
+    (princ ")" stream)))
 
 ;; This belongs in oclosure.el, of course, but some load-ordering issues make it
 ;; complicated.
index 4892733d4565e7181a01fdd0d2933ad1c413c090..f228523d801c45b827a8fda2ecde374de6fa9afe 100644 (file)
@@ -983,7 +983,10 @@ CFG is mutated by a pass.")
   (pure nil :type boolean
         :documentation "t if pure nil otherwise.")
   (type nil :type (or null comp-mvar)
-        :documentation "Mvar holding the derived return type."))
+        :documentation "Mvar holding the derived return type.")
+  (defining-symbol nil :type symbol
+                   :documentation "The symbol (usually of a defun) where the
+function was defined."))
 
 (cl-defstruct (comp-func-l (:include comp-func))
   "Lexically-scoped function."
@@ -1309,7 +1312,8 @@ clashes."
                                  :command-modes (command-modes f)
                                  :speed (comp-spill-speed function-name)
                                  :pure (comp-spill-decl-spec function-name
-                                                             'pure))))
+                                                             'pure)
+                                 :defining-symbol function-name)))
       (when (byte-code-function-p f)
         (signal 'native-compiler-error
                 '("can't native compile an already byte-compiled function")))
@@ -1342,17 +1346,21 @@ clashes."
           (make-temp-file "comp-lambda-" nil ".eln")))
   (let* ((byte-code (byte-compile form))
          (c-name (comp-c-func-name "anonymous-lambda" "F"))
+         (defsym (and (> (length byte-code) 5)
+                      (aref byte-code 5)))
          (func (if (comp-lex-byte-func-p byte-code)
                    (make-comp-func-l :c-name c-name
                                      :doc (documentation form t)
                                      :int-spec (interactive-form form)
                                      :command-modes (command-modes form)
-                                     :speed (comp-ctxt-speed comp-ctxt))
+                                     :speed (comp-ctxt-speed comp-ctxt)
+                                     :defining-symbol defsym)
                  (make-comp-func-d :c-name c-name
                                    :doc (documentation form t)
                                    :int-spec (interactive-form form)
                                    :command-modes (command-modes form)
-                                   :speed (comp-ctxt-speed comp-ctxt)))))
+                                   :speed (comp-ctxt-speed comp-ctxt)
+                                   :defining-symbol defsym))))
     (let ((lap (byte-to-native-lambda-lap
                 (gethash (aref byte-code 1)
                          byte-to-native-lambdas-h))))
@@ -1361,7 +1369,7 @@ clashes."
       (if (comp-func-l-p func)
           (setf (comp-func-l-args func)
                 (comp-decrypt-arg-list (aref byte-code 0) byte-code))
-        (setf (comp-func-d-lambda-list func) (cadr form)))
+        (setf (comp-func-d-lambda-list func) (lambda-arglist form)))
       (setf (comp-func-lap func) lap
             (comp-func-frame-size func) (comp-byte-frame-size
                                          byte-code))
@@ -1453,6 +1461,7 @@ clashes."
 (defun comp-spill-lap (input)
   "Byte-compile and spill the LAP representation for INPUT.
 If INPUT is a symbol, it is the function-name to be compiled.
+If INPUT is a lambda form, it is compiled as such.
 If INPUT is a string, it is the filename to be compiled."
   (let* ((byte-native-compiling t)
          (byte-to-native-lambdas-h (make-hash-table :test #'eq))
@@ -2161,7 +2170,8 @@ and the annotation emission."
                          (comp-func-command-modes f)))
                        ;; This is the compilation unit it-self passed as
                        ;; parameter.
-                       (make-comp-mvar :slot 0))))))
+                       (make-comp-mvar :slot 0)
+                       (make-comp-mvar :constant name))))))
 
 (cl-defmethod comp-emit-for-top-level ((form byte-to-native-top-level)
                                        for-late-load)
@@ -2205,7 +2215,9 @@ These are stored in the reloc data array."
                   (comp-func-command-modes func)))
                 ;; This is the compilation unit it-self passed as
                 ;; parameter.
-                (make-comp-mvar :slot 0)))))
+                (make-comp-mvar :slot 0)
+                (make-comp-mvar :constant
+                                (comp-func-defining-symbol func))))))
 
 (defun comp-limplify-top-level (for-late-load)
   "Create a Limple function to modify the global environment at load.
@@ -2233,7 +2245,10 @@ into the C code forwarding the compilation unit."
                                  ;; the last function being
                                  ;; registered.
                                  :frame-size 2
-                                 :speed (comp-ctxt-speed comp-ctxt)))
+                                 :speed (comp-ctxt-speed comp-ctxt)
+                                 :defining-symbol (if for-late-load
+                                                      'late_top_level_run
+                                                    'top_level_run)))
          (comp-func func)
          (comp-pass (make-comp-limplify
                      :curr-block (make--comp-block-lap -1 0 'top-level)
@@ -4156,45 +4171,26 @@ the deferred compilation mechanism."
         (comp-log "\n\f\n" 1)
         (unwind-protect
             (progn
-              (condition-case err
-                  (cl-loop
-                   with report = nil
-                   for t0 = (current-time)
-                   for pass in comp-passes
-                   unless (memq pass comp-disabled-passes)
-                   do
-                   (comp-log (format "(%s) Running pass %s:\n"
-                                     function-or-file pass)
-                             2)
-                   (setf data (funcall pass data))
-                   (push (cons pass (float-time (time-since t0))) report)
-                   (cl-loop for f in (alist-get pass comp-post-pass-hooks)
-                            do (funcall f data))
-                   finally
-                   (when comp-log-time-report
-                     (comp-log (format "Done compiling %s" data) 0)
-                     (cl-loop for (pass . time) in (reverse report)
-                              do (comp-log (format "Pass %s took: %fs."
-                                                   pass time) 0))))
-                (native-compiler-skip)
-                (t
-                 (let ((err-val (cdr err)))
-                   ;; If we are doing an async native compilation print the
-                   ;; error in the correct format so is parsable and abort.
-                   (if (and comp-async-compilation
-                            (not (eq (car err) 'native-compiler-error)))
-                       (progn
-                         (message (if err-val
-                                      "%s: Error: %s %s"
-                                    "%s: Error %s")
-                                  function-or-file
-                                  (get (car err) 'error-message)
-                                  (car-safe err-val))
-                         (kill-emacs -1))
-                     ;; Otherwise re-signal it adding the compilation input.
-                    (signal (car err) (if (consp err-val)
-                                          (cons function-or-file err-val)
-                                        (list function-or-file err-val)))))))
+              (cl-loop
+               with report = nil
+               for t0 = (current-time)
+               for pass in comp-passes
+               unless (memq pass comp-disabled-passes)
+               do
+               (comp-log (format "(%s) Running pass %s:\n"
+                                 function-or-file pass)
+                         2)
+               (setf data (funcall pass data))
+               (push (cons pass (float-time (time-since t0))) report)
+               (cl-loop for f in (alist-get pass comp-post-pass-hooks)
+                        do (funcall f data))
+               finally
+               (when comp-log-time-report
+                 (comp-log (format "Done compiling %s" data) 0)
+                 (cl-loop for (pass . time) in (reverse report)
+                          do (comp-log (format "Pass %s took: %fs."
+                                               pass time)
+                                       0))))
               (if (stringp function-or-file)
                   data
                 ;; So we return the compiled function.
index e393daee8793b30f23c34d814487e15616075069..55fd55f1a3993bfef17ef35099e39c56d5d7d446 100644 (file)
@@ -34,7 +34,7 @@
 ;;; Code:
 
 (defalias 'debug-early-backtrace
-  #'(lambda ()
+  #'(lambda debug-early-backtrace ()
       "Print a trace of Lisp function calls currently active.
 The output stream used is the value of `standard-output'.
 
@@ -71,7 +71,7 @@ of the build process."
               (princ ")\n")))))))
 
 (defalias 'debug-early
-  #'(lambda (&rest args)
+  #'(lambda debug-early (&rest args)
   "Print an error message with a backtrace of active Lisp function calls.
 The output stream used is the value of `standard-output'.
 
index be9f013ebcf3b32e06b7910429f26f75ef05292d..96b7fe3b400576675c06cdabdfb59e0f73912cec 100644 (file)
   :prefix "ert-"
   :group 'lisp)
 
-(defcustom ert-batch-backtrace-right-margin 70
+(defcustom ert-batch-backtrace-right-margin nil ; 70 STOUGH, 2023-06-09
   "Maximum length of lines in ERT backtraces in batch mode.
 Use nil for no limit (caution: backtrace lines can be very long)."
   :type '(choice (const :tag "No truncation" nil) integer))
 
-(defvar ert-batch-print-length 10
+(defvar ert-batch-print-length nil ; 10 STOUGH, 2023-06-09
   "`print-length' setting used in `ert-run-tests-batch'.
 
 When formatting lists in test conditions, `print-length' will be
@@ -83,7 +83,7 @@ temporarily set to this value.  See also
 `ert-batch-backtrace-line-length' for its effect on stack
 traces.")
 
-(defvar ert-batch-print-level 5
+(defvar ert-batch-print-level nil ; 5 STOUGH, 2023-06-09
   "`print-level' setting used in `ert-run-tests-batch'.
 
 When formatting lists in test conditions, `print-level' will be
index 5db9af21508cf55c4b4547134c8ecfc9089ca77d..fa3436bfd1e44c340fe5ce057d9c050186662cae 100644 (file)
@@ -162,7 +162,9 @@ expression, in which case we want to handle forms differently."
            (lam (if (memq (car-safe fun) '(quote function)) (cadr fun)))
            ;; `args' is the list of arguments (or t if not recognized).
            ;; `body' is the body of `lam' (or t if not recognized).
-           ((or `(lambda ,args . ,body)
+           ((or `(lambda ,(pred (lambda (e) (and e (symbolp e))))
+                   ,args . ,body)
+                `(lambda ,args . ,body)
                 (and (let args t) (let body t)))
             lam)
            ;; Get the `doc' from `body' or `rest'.
index 290bf1c933a11ecd957bd4ab5206042c6263f648..4f23fd379e5b382366dc101075af37f1e5f828ce 100644 (file)
@@ -247,8 +247,8 @@ It should normally be a symbol with position and it defaults to FORM."
   (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))))
+     (let* ((formals (lambda-arglist lambda))
+            (body (cdr (macroexp-parse-body (lambda-body lambda))))
             optionalp restp
             (dynboundarg nil)
             bindings)
@@ -332,6 +332,16 @@ Assumes the caller has bound `macroexpand-all-environment'."
         ;; I tried it, it broke the bootstrap :-(
         (let ((fn (car-safe form)))
           (pcase form
+            (`(defalias ,(and `(quote ,def)
+                              (pred (lambda (e) (and e (symbolp e)))))
+                . ,_rest)
+             (let ((defining-symbol def))
+               (macroexp--all-forms form 2)))
+            (`(,(or `defvar `defconst)
+               ,(and def (pred (lambda (e) (and e (symbolp e)))))
+               . ,(and _rest (pred (not null))))
+             (let ((defining-symbol def))
+               (macroexp--all-forms form 2)))
             (`(cond . ,clauses)
              (macroexp--cons fn (macroexp--all-clauses clauses) form))
             (`(condition-case . ,(or `(,err ,body . ,handlers) pcase--dontcare))
@@ -351,10 +361,15 @@ Assumes the caller has bound `macroexpand-all-environment'."
             (`(,(or 'defvar 'defconst) ,(and name (pred symbolp)) . ,_)
              (push name macroexp--dynvars)
              (macroexp--all-forms form 2))
-            (`(function ,(and f `(lambda . ,_)))
-             (let ((macroexp--dynvars macroexp--dynvars))
+            (`(function ,(and f (or `(lambda
+                                       ,(and def
+                                             (pred (lambda (e) (and e (symbolp e)))))
+                                       . ,_)
+                                    (and `(lambda . ,_) (let def nil)))))
+             (let ((defining-symbol def)
+                   (macroexp--dynvars macroexp--dynvars))
                (macroexp--cons fn
-                               (macroexp--cons (macroexp--all-forms f 2)
+                               (macroexp--cons (macroexp--all-forms f (if def 3 2))
                                                nil
                                                (cdr form))
                                form)))
@@ -432,8 +447,12 @@ Assumes the caller has bound `macroexpand-all-environment'."
                        (push assignment assignments))
                      (setq args (cddr args)))
                    (cons 'progn (nreverse assignments))))))
-            (`(,(and fun `(lambda . ,_)) . ,args)
-            (macroexp--cons (macroexp--all-forms fun 2)
+            (`(,(and fun `(lambda . ,_))
+               (or `(lambda ,(and (pred (lambda (e) (and e (symbolp e)))) def)
+                                . ,_)
+                   (and `(lambda . ,_) (let def nil)))
+               . ,args)
+            (macroexp--cons (macroexp--all-forms fun (if def 3 2))
                              (macroexp--all-forms args)
                              form))
             (`(funcall ,exp . ,args)
index cd80df2c41d8b29c62f9f4c355879eb846d6a042..7700927bd67eecd3ad0bfa6c9a0d036918875473 100644 (file)
@@ -257,16 +257,54 @@ HOW is a symbol to select an entry in `advice--how-alist'."
         (advice--copy (cadr proto)
                       function main how props)))))
 
+(defun advice--equal (function adv)
+  "Return non-nil when FUNCTION is essentially the same as ADV.
+FUNCTION and ADV are both functions.  They are considered
+essentially the same when all components apart, possibly, from
+the \"defining-symbol\" are `equal'.
+
+On such sameness, ADV is returned, otherwise nil."
+  (cond
+   ((and (byte-code-function-p function)
+         (byte-code-function-p adv))
+    (and (equal (aref function 0) (aref adv 0))  ;  parameter spec.
+         (equal (aref function 1) (aref adv 1)) ; byte code.
+         (equal (aref function 2) (aref adv 2)) ; constant vector.
+         (equal (aref function 3) (aref adv 3)) ; Stack usage.
+         (equal (aref function 4) (aref adv 4)) ; Doc string.
+         (or (< (length function) 6)
+             (< (length adv) 6)
+             (symbolp (aref function 5)) ; Is element 5 the defining-symbol...
+             (symbolp (aref adv 5))      ; ...(or absent)?
+             (equal (aref function 5) (aref adv 5))) ; It's an interactive spec.
+         (or (< (length function) 7)
+             (< (length adv) 7)
+             (equal (aref function 6) (aref adv 6))) ; Interactive spec (new format).
+         adv))
+   ((and (consp function)
+         (consp adv))                   ; Interpreted functions.
+    (and (equal function adv)           ; FIXME!!!  Flesh this out!
+         adv))
+   ;; Insert an arm for native-compiled functions here.  FIXME!!!
+   (t (and (equal function adv)
+           adv))
+   ))
+
 (defun advice--member-p (function use-name definition)
   (let ((found nil))
+    ;; (message "advice--member-p: function: %S" function)
     (while (and (not found) (advice--p definition))
+      ;; (message "advice--member-p: elt:      %S" (advice--car definition))
       (if (if (eq use-name :use-both)
-             (or (equal function
-                        (cdr (assq 'name (advice--props definition))))
-                 (equal function (advice--car definition)))
-           (equal function (if use-name
-                               (cdr (assq 'name (advice--props definition)))
-                             (advice--car definition))))
+             (or (advice--equal
+                   function
+                  (cdr (assq 'name (advice--props definition))))
+                 (advice--equal
+                   function (advice--car definition)))
+           (advice--equal
+             function (if use-name
+                         (cdr (assq 'name (advice--props definition)))
+                       (advice--car definition))))
           (setq found definition)
         (setq definition (advice--cdr definition))))
     found))
@@ -288,7 +326,8 @@ HOW is a symbol to select an entry in `advice--how-alist'."
   (advice--tweak flist
                  (lambda (first rest props)
                    (cond ((not first) rest)
-                         ((or (equal function first)
+                         ((or (advice--equal
+                               function first)
                               (equal function (cdr (assq 'name props))))
                           (list (advice--remove-function rest function)))))))
 
index 40f1f54eed0c5d011be3a027d70d3c2f0331316c..29b69b0cd8c6854139b6ae566abaf4889ee31da3 100644 (file)
@@ -442,8 +442,10 @@ This has 2 uses:
     ;; stuff it into the environment part of the closure with a special
     ;; marker so we can distinguish this entry from actual variables.
     (cl-assert (eq 'closure (car-safe oclosure)))
-    (let ((typename (nth 3 oclosure))) ;; The "docstring".
-      (cl-assert (stringp typename))
+    (let ((typename (if (and (nth 2 oclosure) (symbolp (nth 2 oclosure)))
+                        (nth 4 oclosure)
+                      (nth 3 oclosure)))) ;; The "docstring".
+      (cl-assert (stringp typename) t)
       (push (cons :type (intern typename))
             (cadr oclosure))
       oclosure)))
index 1c5ce5169ab998d449d2f09662bbb3f6a06e0a26..00cda84ab402e4a59f1a06c7f17fc77f1f4cb903 100644 (file)
@@ -438,6 +438,10 @@ how many time this CODEGEN is called."
                  main nil nil (car case)))))
       main)))
 
+(defvar pcase-max-duplicates 1
+  "The max number of pattern uses before pcase creates an internal function for it.
+This can be nil, meaning never create such a function.")
+
 (defun pcase--expand (exp cases)
   ;; (message "pid=%S (pcase--expand %S ...hash=%S)"
   ;;          (emacs-pid) exp (sxhash cases))
@@ -460,7 +464,9 @@ how many time this CODEGEN is called."
                     ;; code explosion, we need to keep track of how many
                     ;; times we've used each leaf and move it
                     ;; to a separate function if that number is too high.
-                    (if (or (< count 2) (pcase--small-branch-p code))
+                    (if (or (null pcase-max-duplicates)
+                            (<= count pcase-max-duplicates)
+                            (pcase--small-branch-p code))
                         `(let ,(mapcar (lambda (vv) (list (car vv) (cadr vv)))
                                        varvals)
                            ;; Try and silence some of the most common
@@ -469,13 +475,13 @@ how many time this CODEGEN is called."
                            ,@code)
                     ;; Several occurrence of this non-small branch in
                     ;; the output.
-                    (unless bsym
-                      (setq bsym (make-symbol
-                                  (format "pcase-%d" (length defs))))
-                      (push `(,bsym (lambda ,(mapcar #'car varvals)
-                                      ,@ignores ,@code))
-                            defs))
-                    `(funcall ,bsym ,@(mapcar #'cadr varvals)))))))))
+                      (unless bsym
+                        (setq bsym (make-symbol
+                                    (format "pcase-%d" (length defs))))
+                        (push `(,bsym (lambda ,(mapcar #'car varvals)
+                                        ,@ignores ,@code))
+                              defs))
+                      `(funcall ,bsym ,@(mapcar #'cadr varvals)))))))))
          (main
           (pcase-compile-patterns
            exp
index 6f55136049b24933fd58901a54964fb0fa29f1d1..11e1d5e509bf20aafde295e175874c66ac8f0d9d 100644 (file)
@@ -2275,8 +2275,14 @@ the same names as used in the original source code, when possible."
   (if (eq (car-safe def) 'macro) (setq def (cdr def)))
   (cond
    ((and (byte-code-function-p def) (listp (aref def 0))) (aref def 0))
-   ((eq (car-safe def) 'lambda) (nth 1 def))
-   ((eq (car-safe def) 'closure) (nth 2 def))
+   ((eq (car-safe def) 'lambda)
+    (if (and (nth 1 def) (symbolp (nth 1 def)))
+        (nth 2 def)
+      (nth 1 def)))
+   ((eq (car-safe def) 'closure)
+    (if (and (nth 2 def) (symbolp (nth 2 def)))
+        (nth 3 def)
+      (nth 2 def)))
    ((and (featurep 'native-compile)
          (subrp def)
          (listp (subr-native-lambda-list def)))
index 6d151db8a8372ded3b6dd3f087f92d5f70cfe309..a68f76608d99a82f19591a9bafc9131fd1ebe806 100644 (file)
@@ -1214,7 +1214,9 @@ POS and RES.")
   (if leave (setq leave (match-end leave)))
   ;; find previous stack, and push onto it, or if `leave' pop it
   (let ((dir (compilation--previous-directory (match-beginning 0))))
-    (setq dir (if dir (or (get-text-property (1- dir) 'compilation-directory)
+    (setq dir (if dir (or
+                       (and (> dir 1)
+                            (get-text-property (1- dir) 'compilation-directory))
                          (get-text-property dir 'compilation-directory))))
     `(font-lock-face ,(if leave
                           compilation-leave-directory-face
@@ -1302,8 +1304,10 @@ POS and RES.")
                    (let ((pos (compilation--previous-directory
                                (match-beginning 0))))
                      (when pos
-                       (or (get-text-property (1- pos) 'compilation-directory)
-                           (get-text-property pos 'compilation-directory)))))))
+                       (or
+                        (and (> pos 1)
+                             (get-text-property (1- pos) 'compilation-directory))
+                        (get-text-property pos 'compilation-directory)))))))
            (setq file (cons file (car dir)))))
       ;; This message didn't mention one, get it from previous
       (let ((prev-pos
index 955b708aee9cd60bbdfbf9ec91676cd718fb16f9..4963785e56f086dc789ba170531966bb8c3e49d4 100644 (file)
@@ -388,10 +388,15 @@ be used instead.
                        (dolist (binding bindings)
                          (push (or (car-safe binding) binding) vars))
                        (elisp--local-variables-1 vars (car (last body)))))
-                    (`(lambda ,_args)
+                    ((or
+                      `(lambda ,(pred (lambda (e) (and e (symbolp e)))) ,_args)
+                      `(lambda ,_args))
                      ;; FIXME: Look for the witness inside `args'.
                      (setq sexp nil))
-                    (`(lambda ,args . ,body)
+                    ((or
+                      `(lambda ,(pred (lambda (e) (and e (symbolp e))))
+                         ,args . ,body)
+                      `(lambda ,args . ,body))
                      (elisp--local-variables-1
                       (let ((args (if (listp args) args)))
                         ;; FIXME: Exit the loop if witness is in args.
@@ -1614,8 +1619,9 @@ Reinitialize the face according to the `defface' specification."
              (cdr-safe (cdr-safe form))
              (boundp (cadr form)))
         ;; Force variable to be re-set.
-        `(progn (defvar ,(nth 1 form) nil ,@(nthcdr 3 form))
-                (setq-default ,(nth 1 form) ,(nth 2 form))))
+         `(let ((defining-symbol ,(nth 1 form)))
+            (defvar ,(nth 1 form) nil ,@(nthcdr 3 form))
+           (setq-default ,(nth 1 form) ,(nth 2 form))))
        ;; `defcustom' is now macroexpanded to
        ;; `custom-declare-variable' with a quoted value arg.
        ((and (eq (car form) 'custom-declare-variable)
index 54e71e1b040ce1314d9231b7b55a2fb7ac873012..d0fbc68d47e3b22f2de3dff20050ba2d78d16368 100644 (file)
@@ -2715,7 +2715,11 @@ function as needed."
       ((or (pred stringp) (pred vectorp)) "Keyboard macro.")
       (`(keymap . ,_)
        "Prefix command (definition is a keymap associating keystrokes with commands).")
-      ((or `(lambda ,_args . ,body) `(closure ,_env ,_args . ,body)
+      ((or `(lambda ,(pred (lambda (e) (and e (symbolp e))))
+              ,_args . ,body)
+           `(closure ,_env ,(pred (lambda (e) (and e (symbolp e))))
+              ,_args . ,body)
+           `(lambda ,_args . ,body) `(closure ,_env ,_args . ,body)
            `(autoload ,_file . ,body))
        (let ((doc (car body)))
         (when (funcall docstring-p doc)
index 2e2caf9fe277a7a52323c9ea5c457076898c45f7..db709cb600ae9c9b2f53abd6e56ae41e31ab422f 100644 (file)
@@ -132,7 +132,11 @@ BODY should be a list of Lisp expressions.
                            def-body)))
   ;; Note that this definition should not use backquotes; subr.el should not
   ;; depend on backquote.el.
-  (list 'function (cons 'lambda cdr)))
+  (if (and (car cdr) (symbolp (car cdr)))
+      (list 'function (cons 'lambda cdr))
+    (list 'function
+          (cons 'lambda
+                (cons (or defining-symbol t) cdr)))))
 
 (defmacro prog2 (form1 form2 &rest body)
   "Eval FORM1, FORM2 and BODY sequentially; return value from FORM2.
index 2eb53b0428a608653c647e71bf1e56930aa4f53a..f3ff19269d005bb7c1834e5049fd6d1e0c958182 100644 (file)
@@ -305,13 +305,16 @@ enum byte_code_op
 
 #define TOP (*top)
 
-DEFUN ("byte-code", Fbyte_code, Sbyte_code, 3, 3, 0,
+DEFUN ("byte-code", Fbyte_code, Sbyte_code, 3, 4, 0,
        doc: /* Function used internally in byte-compiled code.
 The first argument, BYTESTR, is a string of byte code;
 the second, VECTOR, a vector of constants;
-the third, MAXDEPTH, the maximum stack depth used in this function.
+the third, MAXDEPTH, the maximum stack depth used in this function;
+the fourth DEFSYM, if non-nil, the symbol which defined the byte code -
+this is used in diagnostics.
 If the third argument is incorrect, Emacs may crash.  */)
-  (Lisp_Object bytestr, Lisp_Object vector, Lisp_Object maxdepth)
+  (Lisp_Object bytestr, Lisp_Object vector, Lisp_Object maxdepth,
+   Lisp_Object defsym)
 {
   if (! (STRINGP (bytestr) && VECTORP (vector) && FIXNATP (maxdepth)))
     error ("Invalid byte-code");
@@ -776,7 +779,7 @@ exec_byte_code (Lisp_Object fun, ptrdiff_t args_template,
                if (max_lisp_eval_depth < 100)
                  max_lisp_eval_depth = 100;
                if (lisp_eval_depth > max_lisp_eval_depth)
-                 error ("Lisp nesting exceeds `max-lisp-eval-depth'");
+                 xsignal1 (Qexcessive_lisp_nesting, make_fixnum (max_lisp_eval_depth));
              }
 
            ptrdiff_t call_nargs = op;
index 1bde4ae5821ebf9bc2810b8e041b7258adbe78d9..7cd69a6c0b1dcac0f88004713571db11a79649f8 100644 (file)
@@ -5475,7 +5475,8 @@ native_function_doc (Lisp_Object function)
 static Lisp_Object
 make_subr (Lisp_Object symbol_name, Lisp_Object minarg, Lisp_Object maxarg,
           Lisp_Object c_name, Lisp_Object type, Lisp_Object doc_idx,
-          Lisp_Object intspec, Lisp_Object command_modes, Lisp_Object comp_u)
+          Lisp_Object intspec, Lisp_Object command_modes, Lisp_Object comp_u,
+          Lisp_Object defining_symbol)
 {
   struct Lisp_Native_Comp_Unit *cu = XNATIVE_COMP_UNIT (comp_u);
   dynlib_handle_ptr handle = cu->handle;
@@ -5515,6 +5516,7 @@ make_subr (Lisp_Object symbol_name, Lisp_Object minarg, Lisp_Object maxarg,
   x->s.native_comp_u = comp_u;
   x->s.native_c_name = xstrdup (SSDATA (c_name));
   x->s.type = type;
+  x->s.defining_symbol = defining_symbol;
 #endif
   Lisp_Object tem;
   XSETSUBR (tem, &x->s);
@@ -5523,12 +5525,12 @@ make_subr (Lisp_Object symbol_name, Lisp_Object minarg, Lisp_Object maxarg,
 }
 
 DEFUN ("comp--register-lambda", Fcomp__register_lambda, Scomp__register_lambda,
-       7, 7, 0,
+       8, 8, 0,
        doc: /* Register anonymous lambda.
 This gets called by top_level_run during the load phase.  */)
   (Lisp_Object reloc_idx, Lisp_Object c_name, Lisp_Object minarg,
    Lisp_Object maxarg, Lisp_Object type, Lisp_Object rest,
-   Lisp_Object comp_u)
+   Lisp_Object comp_u, Lisp_Object defining_symbol)
 {
   Lisp_Object doc_idx = FIRST (rest);
   Lisp_Object intspec = SECOND (rest);
@@ -5540,7 +5542,7 @@ This gets called by top_level_run during the load phase.  */)
 
   Lisp_Object tem =
     make_subr (c_name, minarg, maxarg, c_name, type, doc_idx, intspec,
-              command_modes, comp_u);
+              command_modes, comp_u, defining_symbol);
 
   /* We must protect it against GC because the function is not
      reachable through symbols.  */
@@ -5556,12 +5558,12 @@ This gets called by top_level_run during the load phase.  */)
 }
 
 DEFUN ("comp--register-subr", Fcomp__register_subr, Scomp__register_subr,
-       7, 7, 0,
+       8, 8, 0,
        doc: /* Register exported subr.
 This gets called by top_level_run during the load phase.  */)
   (Lisp_Object name, Lisp_Object c_name, Lisp_Object minarg,
    Lisp_Object maxarg, Lisp_Object type, Lisp_Object rest,
-   Lisp_Object comp_u)
+   Lisp_Object comp_u, Lisp_Object defining_symbol)
 {
   Lisp_Object doc_idx = FIRST (rest);
   Lisp_Object intspec = SECOND (rest);
@@ -5569,7 +5571,7 @@ This gets called by top_level_run during the load phase.  */)
 
   Lisp_Object tem =
     make_subr (SYMBOL_NAME (name), minarg, maxarg, c_name, type, doc_idx,
-              intspec, command_modes, comp_u);
+              intspec, command_modes, comp_u, defining_symbol);
 
   defalias (name, tem);
 
@@ -5577,16 +5579,17 @@ This gets called by top_level_run during the load phase.  */)
 }
 
 DEFUN ("comp--late-register-subr", Fcomp__late_register_subr,
-       Scomp__late_register_subr, 7, 7, 0,
+       Scomp__late_register_subr, 8, 8, 0,
        doc: /* Register exported subr.
 This gets called by late_top_level_run during the load phase.  */)
   (Lisp_Object name, Lisp_Object c_name, Lisp_Object minarg,
    Lisp_Object maxarg, Lisp_Object type, Lisp_Object rest,
-   Lisp_Object comp_u)
+   Lisp_Object comp_u, Lisp_Object defining_symbol)
 {
   if (!NILP (Fequal (Fsymbol_function (name),
                     Fgethash (name, Vcomp_deferred_pending_h, Qnil))))
-    Fcomp__register_subr (name, c_name, minarg, maxarg, type, rest, comp_u);
+    Fcomp__register_subr (name, c_name, minarg, maxarg, type, rest, comp_u,
+                         defining_symbol);
   Fremhash (name, Vcomp_deferred_pending_h);
   return Qnil;
 }
index 108ed97d1f632e49ac88b9184c157218b0993d57..a56efa7fcc4d46b0c72ca4cd1ae7961b1de9fa43 100644 (file)
@@ -1039,6 +1039,20 @@ function or t otherwise.  */)
   return Qt;
 }
 
+DEFUN ("subr-native-defining-symbol", Fsubr_native_defining_symbol,
+       Ssubr_native_defining_symbol, 1, 1, 0,
+       doc: /* Return the symbol (usually of a defun) where the native compiled
+function was defined, or nil if this information is missing.  */)
+  (Lisp_Object subr)
+{
+  CHECK_SUBR (subr);
+
+#ifdef HAVE_NATIVE_COMP
+  return XSUBR (subr)->defining_symbol;
+#endif
+  return Qnil;
+}
+
 DEFUN ("subr-type", Fsubr_type,
        Ssubr_type, 1, 1, 0,
        doc: /* Return the type of SUBR.  */)
@@ -1121,14 +1135,23 @@ Value, if non-nil, is a list (interactive SPEC).  */)
     }
   else if (COMPILEDP (fun))
     {
+      Lisp_Object form;
       if (PVSIZE (fun) > COMPILED_INTERACTIVE)
        {
-         Lisp_Object form = AREF (fun, COMPILED_INTERACTIVE);
+         /* Lisp_Object */ form = AREF (fun, COMPILED_INTERACTIVE);
          /* The vector form is the new form, where the first
             element is the interactive spec, and the second is the
             command modes. */
          return list2 (Qinteractive, VECTORP (form) ? AREF (form, 0) : form);
        }
+      else if (PVSIZE (fun) > COMPILED_DEFINING_SYM
+              && (NILP (form = AREF (fun, COMPILED_DEFINING_SYM))
+                  || !SYMBOLP (form)))
+       {
+         /* We have a FUN from before the defining symbol was included. */
+         form = AREF (fun, COMPILED_DEFINING_SYM);
+         return list2 (Qinteractive, VECTORP (form) ? AREF (form, 0) : form);
+       }
       else if (PVSIZE (fun) > COMPILED_DOC_STRING)
         {
           Lisp_Object doc = AREF (fun, COMPILED_DOC_STRING);
@@ -1203,9 +1226,14 @@ The value, if non-nil, is a list of mode name symbols.  */)
     }
   else if (COMPILEDP (fun))
     {
-      if (PVSIZE (fun) <= COMPILED_INTERACTIVE)
+      Lisp_Object form;
+
+      if (PVSIZE (fun) <= COMPILED_DEFINING_SYM)
        return Qnil;
-      Lisp_Object form = AREF (fun, COMPILED_INTERACTIVE);
+      if (PVSIZE (fun) == COMPILED_INTERACTIVE)
+       form = AREF (fun, COMPILED_DEFINING_SYM);
+      else
+       form = AREF (fun, COMPILED_INTERACTIVE);
       if (VECTORP (form))
        /* New form -- the second element is the command modes. */
        return AREF (form, 1);
@@ -4347,6 +4375,7 @@ syms_of_data (void)
   defsubr (&Ssubr_name);
   defsubr (&Ssubr_native_elisp_p);
   defsubr (&Ssubr_native_lambda_list);
+  defsubr (&Ssubr_native_defining_symbol);
   defsubr (&Ssubr_type);
 #ifdef HAVE_NATIVE_COMP
   defsubr (&Ssubr_native_comp_unit);
index 3f4e77cd3b19edd39c4f4fc72f89e7d967ccba79..83877008d8fa2f49fcf1d09d6a5d773326b1b1ab 100644 (file)
@@ -536,6 +536,12 @@ usage: (function ARG)  */)
         return an interpreted closure instead of a simple lambda.  */
       Lisp_Object cdr = XCDR (quoted);
       Lisp_Object tmp = cdr;
+      bool with_definer = false;
+      if (!NILP (XCAR (tmp)) && SYMBOLP (XCAR (tmp))) /* Defining symbol */
+       {
+         tmp = XCDR (tmp);
+         with_definer = true;
+       }
       if (CONSP (tmp)
          && (tmp = XCDR (tmp), CONSP (tmp))
          && (tmp = XCAR (tmp), CONSP (tmp))
@@ -548,14 +554,19 @@ usage: (function ARG)  */)
              * (the OClosure's type).  */
            docstring = Fsymbol_name (docstring);
          CHECK_STRING (docstring);
-         cdr = Fcons (XCAR (cdr), Fcons (docstring, XCDR (XCDR (cdr))));
+         if (with_definer)
+           cdr = Fcons (XCAR (cdr), Fcons (XCAR (XCDR (cdr)),
+                                           Fcons (docstring,
+                                                  XCDR (XCDR (XCDR (cdr))))));
+         else
+           cdr = Fcons (XCAR (cdr), Fcons (docstring, XCDR (XCDR (cdr))));
        }
       if (NILP (Vinternal_make_interpreted_closure_function))
         return Fcons (Qclosure, Fcons (Vinternal_interpreter_environment, cdr));
       else
-        return call2 (Vinternal_make_interpreted_closure_function,
+       return call2 (Vinternal_make_interpreted_closure_function,
                       Fcons (Qlambda, cdr),
-                      Vinternal_interpreter_environment);
+                     Vinternal_interpreter_environment);
     }
   else
     /* Simply quote the argument.  */
@@ -764,9 +775,13 @@ static Lisp_Object
 defvar (Lisp_Object sym, Lisp_Object initvalue, Lisp_Object docstring, bool eval)
 {
   Lisp_Object tem;
+  specpdl_ref count = SPECPDL_INDEX ();
 
   CHECK_SYMBOL (sym);
 
+  /* Bind `defining-symbol' in case `initvalue' defines a lambda function.  */
+  specbind (Qdefining_symbol, sym);
+
   tem = Fdefault_boundp (sym);
 
   /* Do it before evaluating the initial value, for self-references.  */
@@ -784,7 +799,7 @@ defvar (Lisp_Object sym, Lisp_Object initvalue, Lisp_Object docstring, bool eval
                                 eval ? eval_sub (initvalue) : initvalue);
        }
     }
-  return sym;
+  return unbind_to (count, sym);
 }
 
 DEFUN ("defvar", Fdefvar, Sdefvar, 1, UNEVALLED, 0,
@@ -874,9 +889,11 @@ usage: (defconst SYMBOL INITVALUE [DOCSTRING])  */)
   (Lisp_Object args)
 {
   Lisp_Object sym, tem;
+  specpdl_ref count = SPECPDL_INDEX ();
 
   sym = XCAR (args);
   CHECK_SYMBOL (sym);
+  specbind (Qdefining_symbol, sym); /* In case INITVALUE defines a function.  */
   Lisp_Object docstring = Qnil;
   if (!NILP (XCDR (XCDR (args))))
     {
@@ -885,7 +902,7 @@ usage: (defconst SYMBOL INITVALUE [DOCSTRING])  */)
       docstring = XCAR (XCDR (XCDR (args)));
     }
   tem = eval_sub (XCAR (XCDR (args)));
-  return Fdefconst_1 (sym, tem, docstring);
+  return unbind_to (count, Fdefconst_1 (sym, tem, docstring));
 }
 
 DEFUN ("defconst-1", Fdefconst_1, Sdefconst_1, 2, 3, 0,
@@ -2144,8 +2161,14 @@ then strings and vectors are not accepted.  */)
      where the interactive spec is stored.  */
   else if (COMPILEDP (fun))
     {
+      Lisp_Object obj;
       if (PVSIZE (fun) > COMPILED_INTERACTIVE)
         return Qt;
+      else if (PVSIZE (fun) > COMPILED_DEFINING_SYM
+              && (NILP (obj = AREF (fun, COMPILED_DEFINING_SYM))
+                  || !SYMBOLP (obj)))
+       /* An old function where the interactive spec is still here.  */
+       return Qt;
       else if (PVSIZE (fun) > COMPILED_DOC_STRING)
         {
           Lisp_Object doc = AREF (fun, COMPILED_DOC_STRING);
@@ -2608,7 +2631,7 @@ eval_sub (Lisp_Object form)
     val = call_debugger (list2 (Qexit, val));
   specpdl_ptr--;
 
-  return val;
+  return unbind_to (count, val);
 }
 \f
 DEFUN ("apply", Fapply, Sapply, 1, MANY, 0,
@@ -3151,6 +3174,13 @@ funcall_lambda (Lisp_Object fun, ptrdiff_t nargs,
       else
        lexenv = Qnil;
       syms_left = XCDR (fun);
+      if (CONSP (syms_left)
+         && !NILP (XCAR (syms_left))
+         && SYMBOLP (XCAR (syms_left))) /* Defining symbol. */
+       {
+         syms_left = XCDR (syms_left);
+         fun = XCDR (fun);
+       }
       if (CONSP (syms_left))
        syms_left = XCAR (syms_left);
       else
@@ -3330,6 +3360,9 @@ lambda_arity (Lisp_Object fun)
          CHECK_CONS (fun);
        }
       syms_left = XCDR (fun);
+      if (CONSP (syms_left) && !NILP (XCAR (syms_left))
+         && SYMBOLP (XCAR (syms_left)))
+       syms_left = XCDR (syms_left);
       if (CONSP (syms_left))
        syms_left = XCAR (syms_left);
       else
@@ -4259,6 +4292,14 @@ before making `inhibit-quit' nil.  */);
   DEFSYM (Qautoload, "autoload");
   DEFSYM (Qinhibit_debugger, "inhibit-debugger");
   DEFSYM (Qmacro, "macro");
+  DEFSYM (Qdefining_symbol, "defining-symbol");
+  DEFVAR_LISP ("defining-symbol", Vdefining_symbol,
+              doc: /* The symbol being defined by `defun' or `defmacro', etc..
+We use this to include in the structure of closures/lambdas defined inside
+the function or macro.  A value of nil means the variable is not in use.
+A value of t means, e.g. the byte compiler is active, but there is not yet
+a current defining symbol.  */);
+  Vdefining_symbol = Qnil;
 
   /* Note that the process handling also uses Qexit, but we don't want
      to staticpro it twice, so we just do it here.  */
index 3fc78cd19191c36bd74bb8bee05d269a7ea5cd88..ab91341603f16759843697735476870267db4e1f 100644 (file)
@@ -2173,6 +2173,7 @@ struct Lisp_Subr
     char *native_c_name;
     Lisp_Object lambda_list;
     Lisp_Object type;
+    Lisp_Object defining_symbol;
 #endif
   } GCALIGNED_STRUCT;
 union Aligned_Lisp_Subr
@@ -2966,7 +2967,8 @@ enum Lisp_Compiled
     COMPILED_CONSTANTS = 2,
     COMPILED_STACK_DEPTH = 3,
     COMPILED_DOC_STRING = 4,
-    COMPILED_INTERACTIVE = 5
+    COMPILED_DEFINING_SYM = 5,
+    COMPILED_INTERACTIVE = 6
   };
 
 /* Flag bits in a character.  These also get used in termhooks.h.
index 6792ef27206d442a75ca4153fc07229bea8cdce0..e6dba3bb8c1d869a8038362792afd2306eff14d1 100644 (file)
@@ -5091,6 +5091,7 @@ defsubr (union Aligned_Lisp_Subr *aname)
 #ifdef HAVE_NATIVE_COMP
   eassert (NILP (Vcomp_abi_hash));
   Vcomp_subr_list = Fpurecopy (Fcons (tem, Vcomp_subr_list));
+  sname->defining_symbol = sym;
 #endif
 }
 
index e2a14c4dd9237d6c676298bded1d52e32f12c90e..5083532537362eb788cda37f4a700ccee8f67eeb 100644 (file)
@@ -339,7 +339,8 @@ ifeq ($(TEST_INTERACTIVE), yes)
 else
        -@${MAKE} -k ${LOGFILES}
        @$(emacs) --batch -l ert --eval \
-       "(ert-summarize-tests-batch-and-exit ${SUMMARIZE_TESTS})" ${LOGFILES}
+       "(setq ert-batch-backtrace-right-margin 0)" \
+        --eval "(ert-summarize-tests-batch-and-exit ${SUMMARIZE_TESTS})" ${LOGFILES}
 endif
 
 .PHONY: mostlyclean clean bootstrap-clean distclean maintainer-clean
index 9813e9459c88de9e7f2fad67d3f7a7c4430f96d8..34d03c5446dbe3cb654cfbfd518603167285cffe 100644 (file)
@@ -1826,7 +1826,7 @@ EXPECTED-POINT BINDINGS (MODES \\='\\='(ruby-mode js-mode python-mode)) \
     (let ((bc (byte-compile fname)))
       (should (byte-code-function-p bc))
       (should (equal (funcall bc 'titi) '(toto titi)))
-      (should (equal (aref bc 5) "P"))
+      (should (equal (aref bc 6) "P"))
       (should (equal (get fname 'pure) t))
       (should (equal (get fname 'lisp-indent-function) 1))
       (should (equal (aref bc 4) "tata\n\n(fn X)")))))
index 6facd3452ea08dfcde8ba278e5225edffb603559..7b7c671b1cba71362b1b1d8452ba1b0da42eb2cc 100644 (file)
   (should (equal (cconv-closure-convert
                   '#'(lambda (x) (let ((f #'(lambda () (+ x 1))))
                                    (funcall f))))
-                 '#'(lambda (x) (let ((f #'(lambda (x) (+ x 1))))
+                 '#'(lambda (x) (let ((f #'(lambda (x) (+ x 1))))
                                   (funcall f x)))))
 
   ;; Bug#30872.
   ;; Basic case:
   (should (equal (cconv-tests--intern-all
                   (cconv-closure-convert
-                   '#'(lambda (x)
-                        (let ((f #'(lambda () x)))
+                   '#'(lambda (x)
+                        (let ((f #'(lambda () x)))
                           (let ((x 'b))
                             (list x (funcall f)))))))
-                 '#'(lambda (x)
-                      (let ((f #'(lambda (x) x)))
+                 '#'(lambda (x)
+                      (let ((f #'(lambda (x) x)))
                         (let ((x 'b)
                               (closed-x x))
                           (list x (funcall f closed-x)))))))
   (should (equal (cconv-tests--intern-all
                   (cconv-closure-convert
-                   '#'(lambda (x)
+                   '#'(lambda (x)
                         (let ((f #'(lambda () x)))
                           (let* ((x 'b))
                             (list x (funcall f)))))))
-                 '#'(lambda (x)
-                      (let ((f #'(lambda (x) x)))
+                 '#'(lambda (x)
+                      (let ((f #'(lambda (x) x)))
                         (let* ((closed-x x)
                                (x 'b))
                           (list x (funcall f closed-x)))))))
            '#'(lambda (x)
                 (internal-make-closure
                  nil (x) nil
-                 (let ((f #'(lambda (x) x)))
+                 (let ((f #'(lambda (x) x)))
                    (let ((x 'a)
                          (closed-x (internal-get-closed-var 0)))
                      (list x (funcall f closed-x))))))))
            '#'(lambda (x)
                 (internal-make-closure
                  nil (x) nil
-                 (let ((f #'(lambda (x) x)))
+                 (let ((f #'(lambda (x) x)))
                    (let* ((closed-x (internal-get-closed-var 0))
                           (x 'a))
                      (list x (funcall f closed-x))))))))
                 (let ((x (list x)))
                   (internal-make-closure
                    nil (x) nil
-                   (let ((f #'(lambda (x) (car-safe x))))
+                   (let ((f #'(lambda (x) (car-safe x))))
                      (setcar (internal-get-closed-var 0)
                              (car-safe (internal-get-closed-var 0)))
                      (let ((x 'a)
                 (let ((x (list x)))
                   (internal-make-closure
                    nil (x) nil
-                   (let ((f #'(lambda (x) (car-safe x))))
+                   (let ((f #'(lambda (x) (car-safe x))))
                      (setcar (internal-get-closed-var 0)
                              (car-safe (internal-get-closed-var 0)))
                      (let* ((closed-x (internal-get-closed-var 0))
                       (list x (funcall g) (funcall h)))))))
            '#'(lambda (x)
                 (let ((x (list x)))
-                  (let ((g #'(lambda (x) (car-safe x)))
-                        (h #'(lambda (x) (setcar x (car-safe x)))))
+                  (let ((g #'(lambda (x) (car-safe x)))
+                        (h #'(lambda (x) (setcar x (car-safe x)))))
                     (let ((x 'b)
                           (closed-x x))
                       (list x (funcall g closed-x) (funcall h closed-x))))))))
                       (list x (funcall g) (funcall h)))))))
            '#'(lambda (x)
                 (let ((x (list x)))
-                  (let ((g #'(lambda (x) (car-safe x)))
-                        (h #'(lambda (x) (setcar x (car-safe x)))))
+                  (let ((g #'(lambda (x) (car-safe x)))
+                        (h #'(lambda (x) (setcar x (car-safe x)))))
                     (let* ((closed-x x)
                            (x 'b))
                       (list x (funcall g closed-x) (funcall h closed-x))))))))