emacs-diffs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

feature/positioned-lambdas 569fc297b85 1/3: Use ; POS... position inform


From: Alan Mackenzie
Subject: feature/positioned-lambdas 569fc297b85 1/3: Use ; POS... position information in backtraces
Date: Sun, 10 Mar 2024 14:53:04 -0400 (EDT)

branch: feature/positioned-lambdas
commit 569fc297b850d1b9bf4ad0d022d20822988fbb57
Author: Alan Mackenzie <acm@muc.de>
Commit: Alan Mackenzie <acm@muc.de>

    Use ;POS... position information in backtraces
    
    Also code up adding this information for defvars, defconsts,
    and cl-defmethods.  This is progress on bug #67455.
    
    * lisp/emacs-lisp/byte-run.el (byte-run-position-vec): New
    function.
    (byte-run--fun-put-new-string): Tidy up the coding.
    (byte-run-posify-existing-defaliases-1): Actually fset the
    result to the pertinent symbol.
    (byte-run-posify-existing-defvars/consts-1)
    (byte-run-posify-existing-defvars/consts): New functions.
    
    * lisp/emacs-lisp/bytecomp.el: Remove commented out old code.
    
    * lisp/emacs-lisp/cl-generic.el (cl-defmethod): Insert the
    ;POS... structure into the form being defined, but using
    explicit code rather than the (defining-symbol ...) declare
    clause.  Add a byte-run-defined-form property to cl-defmethod
    so the reader will position the generated symbols.
    
    * lisp/emacs-lisp/cl-print.el (cl-print-object/cons): On
    encountering a lambda or closure form, print the defining
    symbol in braces.
    (cl-print-object/compiled-function): Print the defining symbol
    in braces.
    
    * lisp/emacs-lisp/comp.el (comp-intern-func-in-ctxt): Pass
    `also-pos' to `documentation' to get the doc's
    ;POS... information too.
    
    * lisp/emacs-lisp/macroexp.el (macroexp--expand-all): Add code
    to the defvar/defconst pcase arm to set `defining-symbol' to
    the var/const being defined, and to strip the position from
    that symbol.
    
    * lisp/loadup.el: Set symbols-with-pos-enabled to t sooner.
    Call the new function byte-run-posify-existing-defvars/consts
    to posify variables/constants defined early in the boot
    process.
    
    * lisp/startup.el (normal-top-level): Set `debug' to debugger
    for interactive sessions.
    
    * src/data.c (syms_of_data): Give `defalias' a
    byte-run-defined-form propery of 1, so that the reader will
    position the symbol it defines.
    
    * src/eval.c (Finternal__define_uninitialized_variable): Posify
    the doc string argument, or give the symbol a
    byte-run--early-defvar-const property early in the boot
    procedure.
    (handle_defvar_defconst_positions): New function.
    (Fmacroexpand): Call the above function for a defvar/defconst.
    (eval_sub): Also call the new function for a defvar/defconst.
    (syms_of_eval): Declare two new symbols in byte-run.el.  Give
    `defvar' and `defconst' byte-run-defined-form properties so as
    to trigger the reader to position new symbols.
---
 lisp/emacs-lisp/byte-run.el   |  69 +++++++++++++++++++-----
 lisp/emacs-lisp/bytecomp.el   | 119 ++----------------------------------------
 lisp/emacs-lisp/cl-generic.el |  27 ++++++++--
 lisp/emacs-lisp/cl-print.el   |  27 ++++++++--
 lisp/emacs-lisp/comp.el       |   2 +-
 lisp/emacs-lisp/macroexp.el   |  10 ++--
 lisp/loadup.el                |  10 ++--
 lisp/startup.el               |   5 ++
 src/data.c                    |   1 +
 src/doc.c                     |   4 +-
 src/eval.c                    |  36 +++++++++++++
 src/lread.c                   |   4 +-
 12 files changed, 166 insertions(+), 148 deletions(-)

diff --git a/lisp/emacs-lisp/byte-run.el b/lisp/emacs-lisp/byte-run.el
index 846c383094a..8b98290609e 100644
--- a/lisp/emacs-lisp/byte-run.el
+++ b/lisp/emacs-lisp/byte-run.el
@@ -188,7 +188,7 @@ This is done by destructively modifying ARG.  Return ARG."
                (puthash a t byte-run--ssp-seen)
                (cond
                 ((symbol-with-pos-p (car a))
-                 (message "SWP in %S,  %S" name (car a)))
+                 (message "SWP(1) in %S,  %S" name (car a)))
                 ((consp (car a))
                  (byte-run--report-list name (car a)))
                 ((or (vectorp (car a)) (recordp (car a)))
@@ -199,7 +199,7 @@ This is done by destructively modifying ARG.  Return ARG."
           (setq a (cdr a)))
         (cond
          ((symbol-with-pos-p (cdr a))
-          (message "SWP in %S,  %S" name (cdr a)))
+          (message "SWP(2) in %S,  %S" name (cdr a)))
          ;; ((or (vectorp (cdr a)) (recordp (cdr a)))
          ;;  (byte-run--strip-vector/record (cdr a)))
          )
@@ -214,7 +214,7 @@ record, containing symbols with position."
       (setq byte-run--ssp-seen (make-hash-table :test 'eq))
       (cond
        ((symbol-with-pos-p arg)
-        (message "SWP in %S,  %S" name arg))
+        (message "SWP(3) in %S,  %S" name arg))
        ((consp arg)
         (byte-run--report-list name arg))
        ((or (vectorp arg) (recordp arg))
@@ -522,6 +522,15 @@ unchanged."
           doc-string
           ))))))
 
+(defalias 'byte-run-position-vec
+  #'(lambda (doc-string)
+      "Extract the position information, if any, from DOC-STRING.
+This will be returned as a four element vector, or nil if there is
+no position information in DOC-STRING."
+      (and (stringp doc-string)
+           (string-match "\\`;POS\036\001\001\001 \\[" doc-string)
+           (read (substring doc-string (1- (match-end 0)))))))
+
 (defalias 'byte-run-posify-lambda-form
   #'(lambda (form position)
       "Put position structure on the lambda form FORM.
@@ -1130,7 +1139,7 @@ and MAC is `macro' if additionally FUN is a macro, else 
nil.
 
 If it's something else, return nil."
   (if (consp fun)
-      (let ((mac (and (eq (car-safe fun) 'macro) 'macro)))
+      (let ((mac (and (eq (car fun) 'macro) 'macro)))
         (if (eq mac 'macro)
             (setq fun (cdr fun)))
         (if (consp fun)
@@ -1160,13 +1169,16 @@ Create and return a new form rather than altering the 
old one."
   (if (cdr doc-pos/m)
       (setq fun (cdr fun)))
   (let* ((doc-pos (car doc-pos/m))
-         (insert (null (stringp (nth doc-pos fun)))))
-    (nconc (take doc-pos fun)
-         (list doc-string)
-         (nthcdr (if insert doc-pos (1+ doc-pos)) fun))))
+         (insert (null (stringp (nth doc-pos fun))))
+         (form (append (take doc-pos fun)
+                       (list doc-string)
+                       (nthcdr (if insert doc-pos (1+ doc-pos)) fun))))
+    (if (cdr doc-pos/m)
+        (cons 'macro form)
+      form)))
 
 (defun byte-run--fun-get-lambda-pos (fun doc-pos/m)
-  "Get the position (if any) of the lambda symbol from FUN.
+  "Get the position (if any) from the lambda symbol in FUN.
 FUN is a function form, DOC-POS/M is a cons of FUN's DOC-POS and
 whether it's a macro.
 
@@ -1207,18 +1219,49 @@ no characters other than the POS info, return nil 
instead."
                    (old-doc-string (byte-run--fun-get-string fun doc-pos/m))
                    (bare-doc-string (byte-run-strip-pos-info old-doc-string))
                    (new-doc-string (byte-run-posify-doc-string bare-doc-string
-                                                               lambda-pos)))
-                (byte-run--fun-put-new-string fun new-doc-string 
doc-pos/m)))))))
+                                                               lambda-pos))
+                   (new-fun (byte-run--fun-put-new-string fun new-doc-string
+                                                          doc-pos/m)))
+                (fset sym new-fun)))))))
 
 (defun byte-run-posify-existing-defaliases ()
   "Create the position structure in the doc strings of existing functions.
-At the same time, strip the positions from the defining symbol and the
-lambda."
+Do not strip the positions from the defining symbol or the lambda."
   ;; This function should be run with `symbols-with-pos-enabled'
   ;; non-nil.  We can't use a lambda form here, since it would have a
   ;; position on the lambda symbol.
   (mapatoms #'byte-run-posify-existing-defaliases-1))
 
+(defun byte-run-posify-existing-defvars/consts-1 (sym)
+  "Sub function of `byte-run-posify-existing-defvars/consts'."
+  (if (get sym 'byte-run--early-defvar-const)
+      (let* ((defining-symbol (get sym 'byte-run--early))
+             (doc-string (get sym 'variable-documentation))
+             (plist (symbol-plist sym))
+             (ptr plist)
+             ;; (tail (memq 'byte-run--early-defvar-const plist))
+             )
+        (if (or (stringp doc-string) (null doc-string))
+            (progn
+              (setq doc-string (byte-run-posify-doc-string doc-string))
+              (put sym 'variable-documentation doc-string)))
+        ;; Remove the property from the property list so that the symbol
+        ;; with pos doesn't later hinder the dumping process.
+        (if (eq (car plist) 'byte-run--early-defvar-const)
+            (progn
+              (setplist sym (cdr (cdr plist))))
+          (while (and ptr
+                      (null (eq (car (cdr (cdr ptr)))
+                                'byte-run--early-defvar-const)))
+            (setq ptr (cdr (cdr ptr))))
+          (if ptr
+              (setcdr (cdr ptr) (cdr (cdr (cdr (cdr ptr))))))))))
+
+(defun byte-run-posify-existing-defvars/consts ()
+  "Create the position structure in the doc strings of existing defvars.
+Also defconsts.  Do not strip the positions from the symbols."
+  (mapatoms #'byte-run-posify-existing-defvars/consts-1))
+
 (defun byte-run-posify-existing-lambdas ()
   "Create the position structure in the doc strings of existing lambdas.
 At the same time, strip the positions from the defining symbol and
diff --git a/lisp/emacs-lisp/bytecomp.el b/lisp/emacs-lisp/bytecomp.el
index c7e82cb3ccd..b936cfb4a1f 100644
--- a/lisp/emacs-lisp/bytecomp.el
+++ b/lisp/emacs-lisp/bytecomp.el
@@ -1769,37 +1769,6 @@ It is too wide if it has any lines longer than the 
largest of
            (prefix (lambda ()
                      (format "%s%s"
                              kind
-;;;; Merge STOUGH, 2024-03-03
-;; <<<<<<< HEAD
-;;                              (if name (format-message " `%s' " name) "")))))
-;;       (pcase (car form)
-;;         ((or 'autoload 'custom-declare-variable 'defalias
-;;              'defconst 'define-abbrev-table
-;;              'defvar 'defvaralias
-;;              'custom-declare-face)
-;;          (setq kind (nth 0 form))
-;;          (setq name (nth 1 form))
-;;          (when (and (consp name) (eq (car name) 'quote))
-;;            (setq name (cadr name)))
-;;          (setq docs (nth 3 form)))
-;;         ('lambda
-;;           (setq kind "")          ; can't be "function", unfortunately
-;;           (setq docs (nth 2 form))))
-;;       (when (and kind docs (stringp docs)
-;;                  (setq docs (help-strip-pos-info docs)))
-;;         (let ((col (max byte-compile-docstring-max-column fill-column)))
-;;           (when (and (byte-compile-warning-enabled-p 'docstrings-wide)
-;;                      (byte-compile--wide-docstring-p docs col))
-;;             (byte-compile-warn-x
-;;              name
-;;              "%sdocstring wider than %s characters" (funcall prefix) col)))
-;;         ;; There's a "naked" ' character before a symbol/list, so it
-;;         ;; should probably be quoted with \=.
-;;         (when (string-match-p (rx (| (in " \t") bol)
-;;                                   (? (in "\"#"))
-;;                                   "'"
-;;                                   (in "A-Za-z" "("))
-;; =======
                              (if name (format-message " `%S' " name) "")))))
       (let ((col (max byte-compile-docstring-max-column fill-column)))
         (when (and (byte-compile-warning-enabled-p 'docstrings-wide)
@@ -1824,7 +1793,6 @@ It is too wide if it has any lines longer than the 
largest of
       (when (byte-compile-warning-enabled-p 'docstrings-non-ascii-quotes)
         (when (string-match-p (rx (| " \"" (in " \t") bol)
                                   (in "‘’"))
-;; >>>>>>> master
                               docs)
           (byte-compile-warn-x
            name
@@ -2665,31 +2633,7 @@ Call from the source buffer."
   (push sym byte-compile--seen-defvars))
 
 (defun byte-compile-file-form-defvar (form)
-;;;; MERGED AWAY STOUGH, 2024-03-03
-;; <<<<<<< HEAD
-;;   (let* ((sym (nth 1 form))
-;;          (defining-symbol sym))
-;;     (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)))
-;;     (let ((posified-doc-string
-;;            (byte-run-posify-doc-string
-;;             (and (nth 3 form) (stringp (nth 3 form)) (nth 3 form)))))
-;;       (if (nthcdr 3 form)
-;;           (setcar (nthcdr 3 form) posified-doc-string)
-;;         (nconc form (list posified-doc-string))))
-;;     form)))
-;; =======
   (byte-compile-defvar form 'toplevel))
-;; >>>>>>> master
 
 (put 'define-abbrev-table 'byte-hunk-handler
      'byte-compile-file-form-defvar-function)
@@ -2896,24 +2840,9 @@ not to take responsibility for the actual compilation of 
the code."
                (make-byte-to-native-func-def :name name
                                              :byte-func code))
              byte-to-native-top-level-forms))
-;;;; OLD STOUGH, 2024-03-03
-;; <<<<<<< HEAD
-;;           ;; Output the form by hand, that's much simpler than having
-;;           ;; b-c-output-file-form analyze the defalias.
-;;           (byte-compile-output-docform
-;;            "\n(defalias '" ")"
-;;            bare-name
-;;            (if macro '(" '(macro . #[" "])") '(" #[" "]"))
-;;            (append code nil)    ; Turn byte-code-function-p into list.
-;;            2 4
-;;            (and (atom code) byte-compile-dynamic 1)
-;;            nil)
-;;           t)))))
-;;=======
           (let ((byte-native-compiling nil))
            (byte-compile-output-file-form newform)))
         t))))
-;; >>>>>>> master
 
 (defun byte-compile-output-as-comment (exp quoted)
   "Print Lisp object EXP in the output file at point, inside a comment.
@@ -2983,44 +2912,6 @@ If FORM is a lambda or a macro, byte-compile it as a 
function."
            (fun (if (symbolp form)
                    (symbol-function form)
                  form))
-;;;; MERGE STOUGH, 2024-03-03
-;; <<<<<<< HEAD
-;;        (macro (eq (car-safe fun) 'macro)))
-;;       (if macro
-;;       (setq fun (cdr fun)))
-;;       (prog1
-;;           (cond
-;;            ;; Up until Emacs-24.1, byte-compile silently did nothing
-;;            ;; when asked to compile something invalid.  So let's tone
-;;            ;; down the complaint from an error to a simple message for
-;;            ;; the known case where signaling an error causes problems.
-;;            ((compiled-function-p fun)
-;;             (message "Function %s is already compiled"
-;;                      (if (symbolp form) form "provided"))
-;;             fun)
-;;            (t
-;;             (let (final-eval defining-symbol)
-;;               (when (or (symbolp form) (eq (car-safe fun) 'closure))
-;;                 ;; `fun' is a function *value*, so try to recover its 
corresponding
-;;                 ;; source code.
-;;                 (setq lexical-binding (eq (car fun) 'closure))
-;;                 (setq fun (byte-compile--reify-function fun))
-;;                 (setq final-eval t))
-;;               ;; Expand macros.
-;;               (setq fun (byte-compile-preprocess fun))
-;;               (setq fun (byte-compile-top-level fun nil 'eval))
-;;               (if (symbolp form)
-;;                   ;; byte-compile-top-level returns an *expression* 
equivalent to the
-;;                   ;; `fun' expression, so we need to evaluate it, tho 
normally
-;;                   ;; this is not needed because the expression is just a 
constant
-;;                   ;; byte-code object, which is self-evaluating.
-;;                   (setq fun (eval fun t)))
-;;               (if final-eval
-;;                   (setq fun (eval fun t)))
-;;               (if macro (push 'macro fun))
-;;               (if (symbolp form) (fset form fun))
-;;               fun))))))))
-;; =======
           (macro (eq (car-safe fun) 'macro))
            (need-a-value nil))
       (when macro
@@ -3054,7 +2945,6 @@ If FORM is a lambda or a macro, byte-compile it as a 
function."
         (if macro (push 'macro fun))
         (if (symbolp form) (fset form fun))
         fun))))))
-;; >>>>>>> master
 
 (defun byte-compile-sexp (sexp)
   "Compile and return SEXP."
@@ -5135,9 +5025,7 @@ binding slots have been popped."
        string
        "third arg to `%s %s' is not a string: %s"
        fun var string)))
-;;;; NEW STOUGH FROM MERGE, 2024-02-24
     (setq string (byte-run-posify-doc-string (and (stringp string) string)))
-;;;; END OF NEW STOUGH
     (if toplevel
         ;; At top-level we emit calls to defvar/defconst.
         (if (and (null (cddr form))       ;No `value' provided.
@@ -5206,8 +5094,11 @@ binding slots have been popped."
        (pcase-let*
            ;; `macro' is non-nil if it defines a macro.
            ;; `fun' is the function part of `arg' (defaults to `arg').
-           (((or (and (or `(cons 'macro ,fun) `'(macro . ,fun)) (let macro t))
-                 (and (let fun arg) (let macro nil)))
+           (((or (and (or `(cons 'macro ,fun)
+                          `'(macro . ,fun))
+                      (let macro t))
+                 (and (let fun arg)
+                      (let macro nil)))
              arg)
             ;; `lam' is the lambda expression in `fun' (or nil if not
             ;; recognized).
diff --git a/lisp/emacs-lisp/cl-generic.el b/lisp/emacs-lisp/cl-generic.el
index 63a1347d7e2..1168d8e3184 100644
--- a/lisp/emacs-lisp/cl-generic.el
+++ b/lisp/emacs-lisp/cl-generic.el
@@ -565,9 +565,10 @@ The set of acceptable TYPEs (also called \"specializers\") 
is defined
 
 \(fn NAME [EXTRA] [QUALIFIER] ARGS &rest [DOCSTRING] BODY)"
   (declare (doc-string cl--defmethod-doc-pos) (indent defun)
-           ;; Because there are a variable number of parameters preceding
-           ;; any doc string, it is currently not possible to code a
-           ;; defining-symbol clause.  ACM, 2024-03-02.
+           ;; Because there are a variable number of parameters
+           ;; preceding any doc string, it is not practiable to code a
+           ;; defining-symbol clause.  Instead we code the procedure
+           ;; explicitly in this function.  ACM, 2023-03-09.
            (debug
             (&define                    ; this means we are defining something
              [&name [sexp   ;Allow (setf ...) additionally to symbols.
@@ -584,6 +585,25 @@ The set of acceptable TYPEs (also called \"specializers\") 
is defined
       (require 'gv)
       (declare-function gv-setter "gv" (name))
       (setq name (gv-setter (cadr name))))
+
+    (setq defining-symbol name)
+    (let* ((old-ds
+            (or (and (stringp (car body)) (car body))
+                (and (eq (car-safe (car body)) ':documentation)
+                     (car body))))
+           (new-ds (byte-run-posify-doc-string old-ds)))
+      (setq body
+            (cond
+             ;; Doc string supplied and non-null (cdr body).
+             ((and old-ds (cdr body))
+              (cons new-ds (cdr body)))
+             ;; Doc string supplied but no further body.
+             (old-ds (list new-ds old-ds))
+             ;; Neither doc string nor body.
+             ((null body) (list new-ds 'nil))
+             ;; No doc string but body.
+             (t (cons new-ds body)))))
+
     (pcase-let* ((`(,call-con . ,fun) (cl--generic-lambda args body)))
       `(progn
          ;; You could argue that `defmethod' modifies rather than defines the
@@ -596,6 +616,7 @@ The set of acceptable TYPEs (also called \"specializers\") 
is defined
          ;; obsolescence warning when applicable.
          (cl-generic-define-method #',name ',(nreverse qualifiers) ',args
                                    ',call-con ,fun)))))
+(put 'cl-defmethod 'byte-run-defined-form 1)
 
 (defun cl--generic-member-method (specializers qualifiers methods)
   (while
diff --git a/lisp/emacs-lisp/cl-print.el b/lisp/emacs-lisp/cl-print.el
index c35353ec3d0..4d40c3e0778 100644
--- a/lisp/emacs-lisp/cl-print.el
+++ b/lisp/emacs-lisp/cl-print.el
@@ -66,6 +66,15 @@ Print the contents hidden by the ellipsis to STREAM."
   (error "Missing cl-print-object-contents method"))
 
 (cl-defmethod cl-print-object ((object cons) stream)
+  (when (memq (car object) '(lambda closure))
+    (let* ((doc-string (documentation object 'also-pos))
+           (pos-info (byte-run-position-vec doc-string))
+           (defsym (and (vectorp pos-info)
+                        (aref pos-info 0))))
+      (when defsym
+        (princ "{" stream)
+        (prin1 defsym stream)
+        (princ "} " stream))))
   (if (and cl-print--depth (natnump print-level)
            (> cl-print--depth print-level))
       (cl-print-insert-ellipsis object nil stream)
@@ -183,11 +192,19 @@ 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))
   ;; 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)))
+  (let* ((args (help-function-arglist object 'preserve-names))
+         (doc-string (documentation object 'also-pos))
+         (pos-info (byte-run-position-vec doc-string))
+         (defsym (and (vectorp pos-info)
+                      (aref pos-info 0))))
+    (when defsym
+      (princ "{" stream)
+      (prin1 defsym stream)
+      (princ "} " stream))
+    (princ "#f(compiled-function " stream)
     (if args
         (prin1 args stream)
-      (princ "()" stream)))
+      (princ "()" stream))
   (if (eq cl-print-compiled 'raw)
       (let ((button-start
              (and cl-print-compiled-button
@@ -200,7 +217,7 @@ into a button whose action shows the function's 
disassembly.")
             (make-text-button button-start (point)
                               :type 'help-byte-code
                               'byte-code-function object))))
-    (pcase (help-split-fundoc (documentation object 'raw) object)
+    (pcase (help-split-fundoc doc-string object)
       ;; Drop args which `help-function-arglist' already printed.
       (`(,_usage . ,(and doc (guard (stringp doc))))
        (princ " " stream)
@@ -214,7 +231,7 @@ into a button whose action shows the function's 
disassembly.")
                                             (nth 2 (cadr inter))
                                             (nth 3 (cadr inter))))
            inter)
-         stream)))
+         stream))))
     (if (eq cl-print-compiled 'disassemble)
         (princ
          (with-temp-buffer
diff --git a/lisp/emacs-lisp/comp.el b/lisp/emacs-lisp/comp.el
index 431d2aaf918..1203d72e41c 100644
--- a/lisp/emacs-lisp/comp.el
+++ b/lisp/emacs-lisp/comp.el
@@ -784,7 +784,7 @@ clashes."
                    (make-comp-func-d :lambda-list (aref byte-func 0)))))
       (setf (comp-func-name func) name
             (comp-func-byte-func func) byte-func
-            (comp-func-doc func) (documentation byte-func t)
+            (comp-func-doc func) (documentation byte-func 'also-pos)
             (comp-func-int-spec func) (interactive-form byte-func)
             (comp-func-command-modes func) (command-modes byte-func)
             (comp-func-c-name func) c-name
diff --git a/lisp/emacs-lisp/macroexp.el b/lisp/emacs-lisp/macroexp.el
index e55eb72b985..f53fac6680c 100644
--- a/lisp/emacs-lisp/macroexp.el
+++ b/lisp/emacs-lisp/macroexp.el
@@ -406,9 +406,13 @@ Assumes the caller has bound 
`macroexpand-all-environment'."
                  (macroexp-warn-and-return
                   (format-message "`condition-case' without handlers")
                   exp-body (list 'suspicious 'condition-case) t form))))
-            (`(,(or 'defvar 'defconst) ,(and name (pred symbolp)) . ,_)
-             (push name macroexp--dynvars)
-             (macroexp--all-forms form 2))
+            (`(,(and sf (or 'defvar 'defconst))
+               ,(and name (pred symbolp)) . ,rest)
+             (push (bare-symbol name) macroexp--dynvars)
+             (if (and (null defining-symbol)
+                      (symbol-with-pos-p name))
+                 (setq defining-symbol name))
+             (macroexp--all-forms (cons sf (cons (bare-symbol name) rest)) 2))
             (`(function ,(and f `(lambda ,_ . ,_)))
              (progn
                (let ((macroexp--dynvars macroexp--dynvars))
diff --git a/lisp/loadup.el b/lisp/loadup.el
index f2f0897853c..e25b2d7ed8a 100644
--- a/lisp/loadup.el
+++ b/lisp/loadup.el
@@ -112,6 +112,8 @@
 
 (message "Using load-path %s" load-path)
 
+(setq symbols-with-pos-enabled t)
+
 (if dump-mode
     (progn
       ;; To reduce the size of dumped Emacs, we avoid making huge char-tables.
@@ -125,12 +127,12 @@
 (setq buffer-undo-list t)
 
 (defvar real-defvar (symbol-function 'defvar))
-(setq symbols-with-pos-enabled t)
 (fset 'defvar (symbol-function 'defvar-bootstrap))
 (load "emacs-lisp/debug-early")
 (load "emacs-lisp/byte-run")
 (byte-run-posify-existing-defaliases)
 (byte-run-posify-existing-lambdas)
+(byte-run-posify-existing-defvars/consts)
 ;; (makunbound 'early-lambda-lists)
 (setq early-lambda-lists nil) ; We don't want its symbols with
                               ; position in the dumped image.
@@ -177,10 +179,6 @@
 (load "emacs-lisp/debug-early")
 (load "emacs-lisp/byte-run")
 (message "loadup.el, just after second load of byte-run.el.")
-(message "loadup.el.  base-loaded %S bound."
-         (if (boundp 'base-loaded) "is" "isn't"))
-(message "loadup.el.  base-loaded %S a SWP.  symbols-with-pos-enabled is %S"
-         (symbol-with-pos-p 'base-loaded) symbols-with-pos-enabled)
 (message "loadup.el, just after setting base-loaded to t")
 (unintern 'base-loaded nil) ; So that it can't be messed with from Lisp.
 (load "emacs-lisp/backquote")
@@ -238,7 +236,7 @@
                     (setq plist (delq 'function-history plist))
                     (setplist elt plist))))))
 (fset 'defvar real-defvar)
-(message "Just after (fset defvar real-defvar)")
+(message "Just after (fset 'defvar real-defvar)")
 (setq symbols-with-pos-enabled nil)
 (message "Just after setting symbols-with-pos-enabled back to nil")
 
diff --git a/lisp/startup.el b/lisp/startup.el
index 773765a4b97..0a2ab7011b3 100644
--- a/lisp/startup.el
+++ b/lisp/startup.el
@@ -565,6 +565,11 @@ On Android, Emacs uses this variable internally at 
startup.")
 It sets `command-line-processed', processes the command-line,
 reads the initialization files, etc.
 It is the default value of the variable `top-level'."
+  ;; Set the debugger to `debug' only for interactive sessions, otherwise
+  ;; leave it with `debug-early'.
+  (if (null noninteractive)
+      (setq debugger #'debug))
+
   ;; Initialize the Android font driver late.
   ;; This is done here because it needs the `mac-roman' coding system
   ;; to be loaded.
diff --git a/src/data.c b/src/data.c
index 755c49f0272..a66d387cb1f 100644
--- a/src/data.c
+++ b/src/data.c
@@ -4311,6 +4311,7 @@ syms_of_data (void)
   defsubr (&Sfboundp);
   defsubr (&Sfset);
   defsubr (&Sdefalias);
+  Fput (Qdefalias, Qbyte_run_defined_form, make_fixnum (1));
   defsubr (&Ssetplist);
   defsubr (&Ssymbol_value);
   defsubr (&Sset);
diff --git a/src/doc.c b/src/doc.c
index 45028ebe8c0..bf034a83037 100644
--- a/src/doc.c
+++ b/src/doc.c
@@ -374,7 +374,9 @@ OBJECT can be either a string or a reference if it's kept 
externally.  */)
 DEFUN ("documentation", Fdocumentation, Sdocumentation, 1, 2, 0,
        doc: /* Return the documentation string of FUNCTION.
 Unless a non-nil second argument RAW is given, the
-string is passed through `substitute-command-keys'.  */)
+string is passed through `substitute-command-keys'
+Any position information at the start of the doc string
+is removed unless RAW is the symbol `also-pos'.  */)
   (Lisp_Object function, Lisp_Object raw)
 {
   Lisp_Object doc;
diff --git a/src/eval.c b/src/eval.c
index 23beff2ee30..4c69d13560f 100644
--- a/src/eval.c
+++ b/src/eval.c
@@ -746,6 +746,12 @@ value.  */)
              symbol);
 
   XSYMBOL (symbol)->u.s.declared_special = true;
+  /* The original symbol with position of `symbol' will be in
+     `defining-symbol'.  */
+  if (Ffboundp (Qbyte_run_posify_doc_string))
+    doc = call2 (Qbyte_run_posify_doc_string, doc, Qnil);
+  else
+    Fput (symbol, Qbyte_run__early_defvar_const, Vdefining_symbol);
   if (!NILP (doc))
     {
       if (!NILP (Vpurify_flag))
@@ -1153,6 +1159,24 @@ is not displayed.  */)
   return unbind_to (count, result);
 }
 
+/* We must strip the positions from `defvar' and `defconst'
+   here, if any.  */
+static Lisp_Object handle_defvar_defconst_positions (Lisp_Object form)
+{
+  Lisp_Object sym = (XCAR (form));
+
+  if (!byte_compile_in_progress
+      && (EQ (sym, Qdefvar) || EQ (sym, Qdefconst))
+      && Fsymbol_with_pos_p (Fcar_safe (Fcdr_safe (form))))
+    {
+      if (NILP (Vdefining_symbol))
+       Vdefining_symbol = XCAR (XCDR (form));
+      form = Fcons (sym, Fcons (Fbare_symbol (XCAR (XCDR (form))),
+                               XCDR (XCDR (form))));
+    }
+  return form;
+}
+
 DEFUN ("macroexpand", Fmacroexpand, Smacroexpand, 1, 2, 0,
        doc: /* Return result of expanding macros at top level of FORM.
 If FORM is not a macro call, it is returned unchanged.
@@ -1206,6 +1230,10 @@ definitions to shadow the loaded ones for use in file 
byte-compilation.  */)
              form = list2 (Qfunction, form);
              break;
            }
+         else
+         /* We must strip the positions from `defvar' and `defconst'
+            here, if any.  */
+           form = handle_defvar_defconst_positions (form);
          /* Look at its function definition.  */
          def = Fautoload_do_load (def, sym, Qmacro);
          if (!CONSP (def))
@@ -2496,6 +2524,8 @@ eval_sub (Lisp_Object form)
        xsignal1 (Qexcessive_lisp_nesting, make_fixnum (lisp_eval_depth));
     }
 
+  form = handle_defvar_defconst_positions (form);
+
   Lisp_Object original_fun = XCAR (form);
   Lisp_Object original_args = XCDR (form);
   CHECK_LIST (original_args);
@@ -4337,6 +4367,8 @@ before making `inhibit-quit' nil.  */);
   DEFSYM (Qdebug, "debug");
   DEFSYM (Qdebug_early, "debug-early");
   DEFSYM (Qdebug_early__handler, "debug-early--handler");
+  DEFSYM (Qbyte_run_posify_doc_string, "byte-run-posify-doc-string");
+  DEFSYM (Qbyte_run__early_defvar_const, "byte-run--early-defvar-const");
 
   DEFVAR_LISP ("inhibit-debugger", Vinhibit_debugger,
               doc: /* Non-nil means never enter the debugger.
@@ -4498,6 +4530,10 @@ alist of active lexical bindings.  */);
   defsubr (&Sdefault_toplevel_value);
   defsubr (&Sset_default_toplevel_value);
   defsubr (&Sdefvar);
+  DEFSYM (Qdefvar, "defvar");
+  Fput (Qdefvar, Qbyte_run_defined_form, make_fixnum (1));
+  DEFSYM (Qdefconst, "defconst");
+  Fput (Qdefconst, Qbyte_run_defined_form, make_fixnum (1));
   defsubr (&Sdefvar_bootstrap);
   defsubr (&Sdefvar_1);
   defsubr (&Sdefvaralias);
diff --git a/src/lread.c b/src/lread.c
index 0952b2b9fbb..f35463130a5 100644
--- a/src/lread.c
+++ b/src/lread.c
@@ -6262,8 +6262,8 @@ For internal use only.  */);
   DEFVAR_LISP ("early-lambda-lists", Vearly_lambda_lists,
               doc: /* List of details about early lambda forms.
 Each element is a triple, (FORM, LAMBDA, DEFINING-SYMBOL) where the latter two
-are (usually) symbols with position, with which the lambda a FORM will be
-later positioned.  */);
+are (usually) symbols with position, with which the lambda FORM will be later
+positioned.  */);
   Vearly_lambda_lists = Qnil;
 
   DEFSYM (Qdefalias, "defalias");



reply via email to

[Prev in Thread] Current Thread [Next in Thread]