aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlan Mackenzie2023-03-07 08:00:25 +0000
committerAlan Mackenzie2023-03-07 08:00:25 +0000
commitfa83b236111ea024b75a8bb33b78a99f437a9a67 (patch)
treed288fbdbdfb57f173ffb06c6b832c3ce7b201a4d
parent8179555730d23f43b3043df0bfecc9f9c4f36eda (diff)
downloademacs-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.texi14
-rw-r--r--etc/NEWS5
-rw-r--r--lisp/emacs-lisp/bytecomp.el13
-rw-r--r--lisp/subr.el53
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.
705Normally, when @var{tree} is anything other than a cons cell, 705Normally, 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
707non-@code{nil}, it copies vectors too (and operates recursively on 707non-@code{nil}, it copies vectors too (and operates recursively on
708their elements). 708their elements). This function cannot cope with circular lists.
709@end defun 709@end defun
710 710
711@defun safe-copy-tree tree &optional vecp
712This function returns a copy of the tree @var{tree}. If @var{tree} is
713a 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
715same way.
716
717Normally, when @var{tree} is anything other than a cons cell,
718@code{copy-tree} simply returns @var{tree}. However, if @var{vecp} is
719non-@code{nil}, it copies vectors and records too (and operates
720recursively on their elements). This function handles circular lists
721and vectors, and is thus slower than @code{copy-tree} for typical cases.
722
711@defun flatten-tree tree 723@defun flatten-tree tree
712This function returns a ``flattened'' copy of @var{tree}, that is, 724This function returns a ``flattened'' copy of @var{tree}, that is,
713a list containing all the non-@code{nil} terminal nodes, or leaves, of 725a list containing all the non-@code{nil} terminal nodes, or leaves, of
diff --git a/etc/NEWS b/etc/NEWS
index 7e0454b3b9e..540b59a628f 100644
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -359,6 +359,11 @@ This warning can be suppressed using 'with-suppressed-warnings' with
359the warning name 'suspicious'. 359the warning name 'suspicious'.
360 360
361+++ 361+++
362** New function 'safe-copy-tree'
363This function is a version of copy-tree which handles circular lists
364and circular vectors/records.
365
366+++
362** New function 'file-user-uid'. 367** New function 'file-user-uid'.
363This function is like 'user-uid', but is aware of file name handlers, 368This function is like 'user-uid', but is aware of file name handlers,
364so it will return the remote UID for remote files (or -1 if the 369so 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.
851It's key is a cons or vector/record seen by the algorithm, and its value is
852the 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.
856If TREE is a cons cell, this recursively copies both its car and its cdr.
857Contrast to `copy-sequence', which copies only along the cdrs. With second
858argument 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.
895If TREE is a cons cell, this recursively copies both its car and its cdr.
896Contrast to `copy-sequence', which copies only along the cdrs. With second
897argument 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