aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGemini Lasswell2017-02-16 22:08:03 -0800
committerNoam Postavsky2017-02-23 20:21:11 -0500
commit8b912ab47bc91f54565f127abf24c97e5d46a1ba (patch)
tree107d90118764ae7df4fe0957bb01846ad1a5c858
parentba6c382404a9fe598be72e64beb21a90161ebb91 (diff)
downloademacs-8b912ab47bc91f54565f127abf24c97e5d46a1ba.tar.gz
emacs-8b912ab47bc91f54565f127abf24c97e5d46a1ba.zip
Support read syntax for circular objects in Edebug (Bug#23660)
* lisp/emacs-lisp/edebug.el (edebug-read-special): New name for edebug-read-function. Handle the read syntax for circular objects. (edebug-read-objects): New variable. (edebug-read-and-maybe-wrap-form1): Reset edebug-read-objects. * src/lread.c (Fsubstitute_object_in_subtree): Make substitute_object_in_subtree into a Lisp primitive.
-rw-r--r--lisp/emacs-lisp/edebug.el60
-rw-r--r--src/lread.c12
2 files changed, 55 insertions, 17 deletions
diff --git a/lisp/emacs-lisp/edebug.el b/lisp/emacs-lisp/edebug.el
index a8838046a4d..267fc573d3a 100644
--- a/lisp/emacs-lisp/edebug.el
+++ b/lisp/emacs-lisp/edebug.el
@@ -755,6 +755,11 @@ Maybe clear the markers and delete the symbol's edebug property?"
755(defvar edebug-offsets-stack nil) 755(defvar edebug-offsets-stack nil)
756(defvar edebug-current-offset nil) ; Top of the stack, for convenience. 756(defvar edebug-current-offset nil) ; Top of the stack, for convenience.
757 757
758;; The association list of objects read with the #n=object form.
759;; Each member of the list has the form (n . object), and is used to
760;; look up the object for the corresponding #n# construct.
761(defvar edebug-read-objects nil)
762
758;; We must store whether we just read a list with a dotted form that 763;; We must store whether we just read a list with a dotted form that
759;; is itself a list. This structure will be condensed, so the offsets 764;; is itself a list. This structure will be condensed, so the offsets
760;; must also be condensed. 765;; must also be condensed.
@@ -826,7 +831,7 @@ Maybe clear the markers and delete the symbol's edebug property?"
826 (backquote . edebug-read-backquote) 831 (backquote . edebug-read-backquote)
827 (comma . edebug-read-comma) 832 (comma . edebug-read-comma)
828 (lbracket . edebug-read-vector) 833 (lbracket . edebug-read-vector)
829 (hash . edebug-read-function) 834 (hash . edebug-read-special)
830 )) 835 ))
831 836
832(defun edebug-read-storing-offsets (stream) 837(defun edebug-read-storing-offsets (stream)
@@ -872,17 +877,47 @@ Maybe clear the markers and delete the symbol's edebug property?"
872 (edebug-storing-offsets opoint symbol) 877 (edebug-storing-offsets opoint symbol)
873 (edebug-read-storing-offsets stream))))) 878 (edebug-read-storing-offsets stream)))))
874 879
875(defun edebug-read-function (stream) 880(defun edebug-read-special (stream)
876 ;; Turn #'thing into (function thing) 881 "Read from STREAM a Lisp object beginning with #.
877 (forward-char 1) 882Turn #'thing into (function thing) and handle the read syntax for
878 (cond ((eq ?\' (following-char)) 883circular objects. Let `read' read everything else."
879 (forward-char 1) 884 (catch 'return
880 (list 885 (forward-char 1)
881 (edebug-storing-offsets (- (point) 2) 'function) 886 (let ((start (point)))
882 (edebug-read-storing-offsets stream))) 887 (cond
883 (t 888 ((eq ?\' (following-char))
884 (backward-char 1) 889 (forward-char 1)
885 (read stream)))) 890 (throw 'return
891 (list
892 (edebug-storing-offsets (- (point) 2) 'function)
893 (edebug-read-storing-offsets stream))))
894 ((and (>= (following-char) ?0) (<= (following-char) ?9))
895 (while (and (>= (following-char) ?0) (<= (following-char) ?9))
896 (forward-char 1))
897 (let ((n (string-to-number (buffer-substring start (point)))))
898 (when (and read-circle
899 (<= n most-positive-fixnum))
900 (cond
901 ((eq ?= (following-char))
902 ;; Make a placeholder for #n# to use temporarily.
903 (let* ((placeholder (cons nil nil))
904 (elem (cons n placeholder)))
905 (push elem edebug-read-objects)
906 ;; Read the object and then replace the placeholder
907 ;; with the object itself, wherever it occurs.
908 (forward-char 1)
909 (let ((obj (edebug-read-storing-offsets stream)))
910 (substitute-object-in-subtree obj placeholder)
911 (throw 'return (setf (cdr elem) obj)))))
912 ((eq ?# (following-char))
913 ;; #n# returns a previously read object.
914 (let ((elem (assq n edebug-read-objects)))
915 (when (consp elem)
916 (forward-char 1)
917 (throw 'return (cdr elem))))))))))
918 ;; Let read handle errors, radix notation, and anything else.
919 (goto-char (1- start))
920 (read stream))))
886 921
887(defun edebug-read-list (stream) 922(defun edebug-read-list (stream)
888 (forward-char 1) ; skip \( 923 (forward-char 1) ; skip \(
@@ -1074,6 +1109,7 @@ Maybe clear the markers and delete the symbol's edebug property?"
1074 edebug-offsets 1109 edebug-offsets
1075 edebug-offsets-stack 1110 edebug-offsets-stack
1076 edebug-current-offset ; reset to nil 1111 edebug-current-offset ; reset to nil
1112 edebug-read-objects
1077 ) 1113 )
1078 (save-excursion 1114 (save-excursion
1079 (if (and (eq 'lparen (edebug-next-token-class)) 1115 (if (and (eq 'lparen (edebug-next-token-class))
diff --git a/src/lread.c b/src/lread.c
index 094aa628eec..1b154b7326e 100644
--- a/src/lread.c
+++ b/src/lread.c
@@ -558,8 +558,6 @@ static Lisp_Object read_vector (Lisp_Object, bool);
558 558
559static Lisp_Object substitute_object_recurse (Lisp_Object, Lisp_Object, 559static Lisp_Object substitute_object_recurse (Lisp_Object, Lisp_Object,
560 Lisp_Object); 560 Lisp_Object);
561static void substitute_object_in_subtree (Lisp_Object,
562 Lisp_Object);
563static void substitute_in_interval (INTERVAL, Lisp_Object); 561static void substitute_in_interval (INTERVAL, Lisp_Object);
564 562
565 563
@@ -2957,7 +2955,7 @@ read1 (Lisp_Object readcharfun, int *pch, bool first_in_list)
2957 tem = read0 (readcharfun); 2955 tem = read0 (readcharfun);
2958 2956
2959 /* Now put it everywhere the placeholder was... */ 2957 /* Now put it everywhere the placeholder was... */
2960 substitute_object_in_subtree (tem, placeholder); 2958 Fsubstitute_object_in_subtree (tem, placeholder);
2961 2959
2962 /* ...and #n# will use the real value from now on. */ 2960 /* ...and #n# will use the real value from now on. */
2963 Fsetcdr (cell, tem); 2961 Fsetcdr (cell, tem);
@@ -3326,8 +3324,10 @@ read1 (Lisp_Object readcharfun, int *pch, bool first_in_list)
3326/* List of nodes we've seen during substitute_object_in_subtree. */ 3324/* List of nodes we've seen during substitute_object_in_subtree. */
3327static Lisp_Object seen_list; 3325static Lisp_Object seen_list;
3328 3326
3329static void 3327DEFUN ("substitute-object-in-subtree", Fsubstitute_object_in_subtree,
3330substitute_object_in_subtree (Lisp_Object object, Lisp_Object placeholder) 3328 Ssubstitute_object_in_subtree, 2, 2, 0,
3329 doc: /* Replace every reference to PLACEHOLDER in OBJECT with OBJECT. */)
3330 (Lisp_Object object, Lisp_Object placeholder)
3331{ 3331{
3332 Lisp_Object check_object; 3332 Lisp_Object check_object;
3333 3333
@@ -3345,6 +3345,7 @@ substitute_object_in_subtree (Lisp_Object object, Lisp_Object placeholder)
3345 original. */ 3345 original. */
3346 if (!EQ (check_object, object)) 3346 if (!EQ (check_object, object))
3347 error ("Unexpected mutation error in reader"); 3347 error ("Unexpected mutation error in reader");
3348 return Qnil;
3348} 3349}
3349 3350
3350/* Feval doesn't get called from here, so no gc protection is needed. */ 3351/* Feval doesn't get called from here, so no gc protection is needed. */
@@ -4548,6 +4549,7 @@ syms_of_lread (void)
4548{ 4549{
4549 defsubr (&Sread); 4550 defsubr (&Sread);
4550 defsubr (&Sread_from_string); 4551 defsubr (&Sread_from_string);
4552 defsubr (&Ssubstitute_object_in_subtree);
4551 defsubr (&Sintern); 4553 defsubr (&Sintern);
4552 defsubr (&Sintern_soft); 4554 defsubr (&Sintern_soft);
4553 defsubr (&Sunintern); 4555 defsubr (&Sunintern);