diff options
| author | Alan Mackenzie | 2023-03-07 08:00:25 +0000 |
|---|---|---|
| committer | Alan Mackenzie | 2023-03-07 08:00:25 +0000 |
| commit | fa83b236111ea024b75a8bb33b78a99f437a9a67 (patch) | |
| tree | d288fbdbdfb57f173ffb06c6b832c3ce7b201a4d | |
| parent | 8179555730d23f43b3043df0bfecc9f9c4f36eda (diff) | |
| download | emacs-fa83b236111ea024b75a8bb33b78a99f437a9a67.tar.gz emacs-fa83b236111ea024b75a8bb33b78a99f437a9a67.zip | |
eval-and-compile: Strip symbol positions for eval but not for compile.
This fixes bug #61962.
* lisp/subr.el (safe-copy-tree): New function.
* lisp/emacs-lisp/bytecomp.el (byte-compile-initial-macro-environment): Amend
the entry for eval-and-compile to use safe-copy-tree and
byte-run-strip-symbol-positions for the eval part.
* doc/lispref/lists.texi (Building Lists): Document safe-copy-tree.
* etc/NEWS: Note the new function safe-copy-tree.
| -rw-r--r-- | doc/lispref/lists.texi | 14 | ||||
| -rw-r--r-- | etc/NEWS | 5 | ||||
| -rw-r--r-- | lisp/emacs-lisp/bytecomp.el | 13 | ||||
| -rw-r--r-- | lisp/subr.el | 53 |
4 files changed, 82 insertions, 3 deletions
diff --git a/doc/lispref/lists.texi b/doc/lispref/lists.texi index f3758f5ce60..911defbc211 100644 --- a/doc/lispref/lists.texi +++ b/doc/lispref/lists.texi | |||
| @@ -705,9 +705,21 @@ same way. | |||
| 705 | Normally, when @var{tree} is anything other than a cons cell, | 705 | Normally, when @var{tree} is anything other than a cons cell, |
| 706 | @code{copy-tree} simply returns @var{tree}. However, if @var{vecp} is | 706 | @code{copy-tree} simply returns @var{tree}. However, if @var{vecp} is |
| 707 | non-@code{nil}, it copies vectors too (and operates recursively on | 707 | non-@code{nil}, it copies vectors too (and operates recursively on |
| 708 | their elements). | 708 | their elements). This function cannot cope with circular lists. |
| 709 | @end defun | 709 | @end defun |
| 710 | 710 | ||
| 711 | @defun safe-copy-tree tree &optional vecp | ||
| 712 | This function returns a copy of the tree @var{tree}. If @var{tree} is | ||
| 713 | a cons cell, this make a new cons cell with the same @sc{car} and | ||
| 714 | @sc{cdr}, then recursively copies the @sc{car} and @sc{cdr} in the | ||
| 715 | same way. | ||
| 716 | |||
| 717 | Normally, when @var{tree} is anything other than a cons cell, | ||
| 718 | @code{copy-tree} simply returns @var{tree}. However, if @var{vecp} is | ||
| 719 | non-@code{nil}, it copies vectors and records too (and operates | ||
| 720 | recursively on their elements). This function handles circular lists | ||
| 721 | and vectors, and is thus slower than @code{copy-tree} for typical cases. | ||
| 722 | |||
| 711 | @defun flatten-tree tree | 723 | @defun flatten-tree tree |
| 712 | This function returns a ``flattened'' copy of @var{tree}, that is, | 724 | This function returns a ``flattened'' copy of @var{tree}, that is, |
| 713 | a list containing all the non-@code{nil} terminal nodes, or leaves, of | 725 | a list containing all the non-@code{nil} terminal nodes, or leaves, of |
| @@ -359,6 +359,11 @@ This warning can be suppressed using 'with-suppressed-warnings' with | |||
| 359 | the warning name 'suspicious'. | 359 | the warning name 'suspicious'. |
| 360 | 360 | ||
| 361 | +++ | 361 | +++ |
| 362 | ** New function 'safe-copy-tree' | ||
| 363 | This function is a version of copy-tree which handles circular lists | ||
| 364 | and circular vectors/records. | ||
| 365 | |||
| 366 | +++ | ||
| 362 | ** New function 'file-user-uid'. | 367 | ** New function 'file-user-uid'. |
| 363 | This function is like 'user-uid', but is aware of file name handlers, | 368 | This function is like 'user-uid', but is aware of file name handlers, |
| 364 | so it will return the remote UID for remote files (or -1 if the | 369 | so it will return the remote UID for remote files (or -1 if the |
diff --git a/lisp/emacs-lisp/bytecomp.el b/lisp/emacs-lisp/bytecomp.el index 6f3d7a70903..243d4b11b5f 100644 --- a/lisp/emacs-lisp/bytecomp.el +++ b/lisp/emacs-lisp/bytecomp.el | |||
| @@ -533,7 +533,9 @@ Return the compile-time value of FORM." | |||
| 533 | (macroexpand--all-toplevel | 533 | (macroexpand--all-toplevel |
| 534 | form | 534 | form |
| 535 | macroexpand-all-environment))) | 535 | macroexpand-all-environment))) |
| 536 | (eval expanded lexical-binding) | 536 | (eval (byte-run-strip-symbol-positions |
| 537 | (safe-copy-tree expanded)) | ||
| 538 | lexical-binding) | ||
| 537 | expanded))))) | 539 | expanded))))) |
| 538 | (with-suppressed-warnings | 540 | (with-suppressed-warnings |
| 539 | . ,(lambda (warnings &rest body) | 541 | . ,(lambda (warnings &rest body) |
| @@ -2292,12 +2294,19 @@ With argument ARG, insert value in current buffer after the form." | |||
| 2292 | (symbols-with-pos-enabled t) | 2294 | (symbols-with-pos-enabled t) |
| 2293 | (value (eval | 2295 | (value (eval |
| 2294 | (displaying-byte-compile-warnings | 2296 | (displaying-byte-compile-warnings |
| 2297 | ;;;; NEW STOUGH, 2023-03-05 | ||
| 2298 | (byte-run-strip-symbol-positions | ||
| 2299 | ;;;; END OF NEW STOUGH | ||
| 2295 | (byte-compile-sexp | 2300 | (byte-compile-sexp |
| 2296 | (let ((form (read-positioning-symbols (current-buffer)))) | 2301 | (let ((form (read-positioning-symbols (current-buffer)))) |
| 2297 | (push form byte-compile-form-stack) | 2302 | (push form byte-compile-form-stack) |
| 2298 | (eval-sexp-add-defvars | 2303 | (eval-sexp-add-defvars |
| 2299 | form | 2304 | form |
| 2300 | start-read-position)))) | 2305 | start-read-position))) |
| 2306 | ;;;; NEW STOUGH, 2023-03-05 | ||
| 2307 | ) | ||
| 2308 | ;;;; END OF NEW STOUGH | ||
| 2309 | ) | ||
| 2301 | lexical-binding))) | 2310 | lexical-binding))) |
| 2302 | (cond (arg | 2311 | (cond (arg |
| 2303 | (message "Compiling from buffer... done.") | 2312 | (message "Compiling from buffer... done.") |
diff --git a/lisp/subr.el b/lisp/subr.el index 8ff3b868fab..2066be581d1 100644 --- a/lisp/subr.el +++ b/lisp/subr.el | |||
| @@ -845,6 +845,59 @@ argument VECP, this copies vectors as well as conses." | |||
| 845 | (aset tree i (copy-tree (aref tree i) vecp))) | 845 | (aset tree i (copy-tree (aref tree i) vecp))) |
| 846 | tree) | 846 | tree) |
| 847 | tree))) | 847 | tree))) |
| 848 | |||
| 849 | (defvar safe-copy-tree--seen nil | ||
| 850 | "A hash table for conses/vectors/records already seen by safe-copy-tree-1. | ||
| 851 | It's key is a cons or vector/record seen by the algorithm, and its value is | ||
| 852 | the corresponding cons/vector/record in the copy.") | ||
| 853 | |||
| 854 | (defun safe-copy-tree--1 (tree &optional vecp) | ||
| 855 | "Make a copy of TREE, taking circular structure into account. | ||
| 856 | If TREE is a cons cell, this recursively copies both its car and its cdr. | ||
| 857 | Contrast to `copy-sequence', which copies only along the cdrs. With second | ||
| 858 | argument VECP, this copies vectors and records as well as conses." | ||
| 859 | (cond | ||
| 860 | ((gethash tree safe-copy-tree--seen)) | ||
| 861 | ((consp tree) | ||
| 862 | (let* ((result (cons (car tree) (cdr tree))) | ||
| 863 | (newcons result) | ||
| 864 | hash) | ||
| 865 | (while (and (not hash) (consp tree)) | ||
| 866 | (if (setq hash (gethash tree safe-copy-tree--seen)) | ||
| 867 | (setq newcons hash) | ||
| 868 | (puthash tree newcons safe-copy-tree--seen)) | ||
| 869 | (setq tree newcons) | ||
| 870 | (unless hash | ||
| 871 | (if (or (consp (car tree)) | ||
| 872 | (and vecp (or (vectorp (car tree)) (recordp (car tree))))) | ||
| 873 | (let ((newcar (safe-copy-tree--1 (car tree) vecp))) | ||
| 874 | (setcar tree newcar))) | ||
| 875 | (setq newcons (if (consp (cdr tree)) | ||
| 876 | (cons (cadr tree) (cddr tree)) | ||
| 877 | (cdr tree))) | ||
| 878 | (setcdr tree newcons) | ||
| 879 | (setq tree (cdr tree)))) | ||
| 880 | (nconc result | ||
| 881 | (if (and vecp (or (vectorp tree) (recordp tree))) | ||
| 882 | (safe-copy-tree--1 tree vecp) tree)))) | ||
| 883 | ((and vecp (or (vectorp tree) (recordp tree))) | ||
| 884 | (let* ((newvec (copy-sequence tree)) | ||
| 885 | (i (length newvec))) | ||
| 886 | (puthash tree newvec safe-copy-tree--seen) | ||
| 887 | (setq tree newvec) | ||
| 888 | (while (>= (setq i (1- i)) 0) | ||
| 889 | (aset tree i (safe-copy-tree--1 (aref tree i) vecp))) | ||
| 890 | tree)) | ||
| 891 | (t tree))) | ||
| 892 | |||
| 893 | (defun safe-copy-tree (tree &optional vecp) | ||
| 894 | "Make a copy of TREE, taking circular structure into account. | ||
| 895 | If TREE is a cons cell, this recursively copies both its car and its cdr. | ||
| 896 | Contrast to `copy-sequence', which copies only along the cdrs. With second | ||
| 897 | argument VECP, this copies vectors and records as well as conses." | ||
| 898 | (setq safe-copy-tree--seen (make-hash-table :test #'eq)) | ||
| 899 | (safe-copy-tree--1 tree vecp)) | ||
| 900 | |||
| 848 | 901 | ||
| 849 | ;;;; Various list-search functions. | 902 | ;;;; Various list-search functions. |
| 850 | 903 | ||