aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGemini Lasswell2017-11-01 21:13:02 -0700
committerGemini Lasswell2017-11-26 13:44:15 -0800
commit0ded1b41a986229eaa4218095d9c78d1800c0b27 (patch)
treee7df79ca1383abc77d33d444e0998dacdfbce122
parent16358d4fcbad3fa60ff36167ae666b1ec7e7c02a (diff)
downloademacs-0ded1b41a986229eaa4218095d9c78d1800c0b27.tar.gz
emacs-0ded1b41a986229eaa4218095d9c78d1800c0b27.zip
Fix Edebug's handling of dotted specs (bug#6415)
* lisp/emacs-lisp/cl-macs.el (cl-destructuring-bind): Use cl-macro-list1 instead of cl-macro-list in Edebug spec. * lisp/emacs-lisp/edebug.el (edebug-after-dotted-spec): Delete unused variable. (edebug-dotted-spec): Add docstring. (edebug-match-specs): Allow &optional and &rest specs to match nothing at the tail of a dotted form. Handle matches of dotted form tails which return non-lists. * test/lisp/emacs-lisp/edebug-tests.el (edebug-tests-dotted-forms): New test. * test/lisp/emacs-lisp/edebug-resources/edebug-test-code.el: (edebug-test-code-use-destructuring-bind): New function.
-rw-r--r--lisp/emacs-lisp/cl-macs.el2
-rw-r--r--lisp/emacs-lisp/edebug.el67
-rw-r--r--test/lisp/emacs-lisp/edebug-resources/edebug-test-code.el4
-rw-r--r--test/lisp/emacs-lisp/edebug-tests.el14
4 files changed, 58 insertions, 29 deletions
diff --git a/lisp/emacs-lisp/cl-macs.el b/lisp/emacs-lisp/cl-macs.el
index e313af24975..5535100d4ae 100644
--- a/lisp/emacs-lisp/cl-macs.el
+++ b/lisp/emacs-lisp/cl-macs.el
@@ -684,7 +684,7 @@ its argument list allows full Common Lisp conventions."
684(defmacro cl-destructuring-bind (args expr &rest body) 684(defmacro cl-destructuring-bind (args expr &rest body)
685 "Bind the variables in ARGS to the result of EXPR and execute BODY." 685 "Bind the variables in ARGS to the result of EXPR and execute BODY."
686 (declare (indent 2) 686 (declare (indent 2)
687 (debug (&define cl-macro-list def-form cl-declarations def-body))) 687 (debug (&define cl-macro-list1 def-form cl-declarations def-body)))
688 (let* ((cl--bind-lets nil) (cl--bind-forms nil) 688 (let* ((cl--bind-lets nil) (cl--bind-forms nil)
689 (cl--bind-defs nil) (cl--bind-block 'cl-none) (cl--bind-enquote nil)) 689 (cl--bind-defs nil) (cl--bind-block 'cl-none) (cl--bind-enquote nil))
690 (cl--do-arglist (or args '(&aux)) expr) 690 (cl--do-arglist (or args '(&aux)) expr)
diff --git a/lisp/emacs-lisp/edebug.el b/lisp/emacs-lisp/edebug.el
index d00b14e803e..217bc2c906b 100644
--- a/lisp/emacs-lisp/edebug.el
+++ b/lisp/emacs-lisp/edebug.el
@@ -950,7 +950,8 @@ circular objects. Let `read' read everything else."
950 950
951;;; Cursors for traversal of list and vector elements with offsets. 951;;; Cursors for traversal of list and vector elements with offsets.
952 952
953(defvar edebug-dotted-spec nil) 953(defvar edebug-dotted-spec nil
954 "Set to t when matching after the dot in a dotted spec list.")
954 955
955(defun edebug-new-cursor (expressions offsets) 956(defun edebug-new-cursor (expressions offsets)
956 ;; Return a new cursor for EXPRESSIONS with OFFSETS. 957 ;; Return a new cursor for EXPRESSIONS with OFFSETS.
@@ -1494,8 +1495,6 @@ expressions; a `progn' form will be returned enclosing these forms."
1494 1495
1495;;; Matching of specs. 1496;;; Matching of specs.
1496 1497
1497(defvar edebug-after-dotted-spec nil)
1498
1499(defvar edebug-matching-depth 0) ;; initial value 1498(defvar edebug-matching-depth 0) ;; initial value
1500 1499
1501 1500
@@ -1556,36 +1555,48 @@ expressions; a `progn' form will be returned enclosing these forms."
1556 (let ((edebug-dotted-spec t));; Containing spec list was dotted. 1555 (let ((edebug-dotted-spec t));; Containing spec list was dotted.
1557 (edebug-match-specs cursor (list specs) remainder-handler))) 1556 (edebug-match-specs cursor (list specs) remainder-handler)))
1558 1557
1559 ;; Is the form dotted? 1558 ;; The reason for processing here &optional, &rest, and vectors
1560 ((not (listp (edebug-cursor-expressions cursor)));; allow nil 1559 ;; which might contain them even when the form is dotted is to
1560 ;; allow them to match nothing, so we can advance to the dotted
1561 ;; part of the spec.
1562 ((or (listp (edebug-cursor-expressions cursor))
1563 (vectorp (car specs))
1564 (memq (car specs) '(&optional &rest))) ; Process normally.
1565 ;; (message "%scursor=%s specs=%s"
1566 ;; (make-string edebug-matching-depth ?|) cursor (car specs))
1567 (let* ((spec (car specs))
1568 (rest)
1569 (first-char (and (symbolp spec) (aref (symbol-name spec) 0)))
1570 (match (cond
1571 ((eq ?& first-char);; "&" symbols take all following specs.
1572 (funcall (get-edebug-spec spec) cursor (cdr specs)))
1573 ((eq ?: first-char);; ":" symbols take one following spec.
1574 (setq rest (cdr (cdr specs)))
1575 (funcall (get-edebug-spec spec) cursor (car (cdr specs))))
1576 (t;; Any other normal spec.
1577 (setq rest (cdr specs))
1578 (edebug-match-one-spec cursor spec)))))
1579 ;; The first match result may not be a list, which can happen
1580 ;; when matching the tail of a dotted list. In that case
1581 ;; there is no remainder.
1582 (if (listp match)
1583 (nconc match
1584 (funcall remainder-handler cursor rest remainder-handler))
1585 match)))
1586
1587 ;; Must be a dotted form, with no remaining &rest or &optional specs to
1588 ;; match.
1589 (t
1561 (if (not edebug-dotted-spec) 1590 (if (not edebug-dotted-spec)
1562 (edebug-no-match cursor "Dotted spec required.")) 1591 (edebug-no-match cursor "Dotted spec required."))
1563 ;; Cancel dotted spec and dotted form. 1592 ;; Cancel dotted spec and dotted form.
1564 (let ((edebug-dotted-spec) 1593 (let ((edebug-dotted-spec)
1565 (this-form (edebug-cursor-expressions cursor)) 1594 (this-form (edebug-cursor-expressions cursor))
1566 (this-offset (edebug-cursor-offsets cursor))) 1595 (this-offset (edebug-cursor-offsets cursor)))
1567 ;; Wrap the form in a list, (by changing the cursor??)... 1596 ;; Wrap the form in a list, by changing the cursor.
1568 (edebug-set-cursor cursor (list this-form) this-offset) 1597 (edebug-set-cursor cursor (list this-form) this-offset)
1569 ;; and process normally, then unwrap the result. 1598 ;; Process normally, then unwrap the result.
1570 (car (edebug-match-specs cursor specs remainder-handler)))) 1599 (car (edebug-match-specs cursor specs remainder-handler)))))))
1571
1572 (t;; Process normally.
1573 (let* ((spec (car specs))
1574 (rest)
1575 (first-char (and (symbolp spec) (aref (symbol-name spec) 0))))
1576 ;;(message "spec = %s first char = %s" spec first-char) (sit-for 1)
1577 (nconc
1578 (cond
1579 ((eq ?& first-char);; "&" symbols take all following specs.
1580 (funcall (get-edebug-spec spec) cursor (cdr specs)))
1581 ((eq ?: first-char);; ":" symbols take one following spec.
1582 (setq rest (cdr (cdr specs)))
1583 (funcall (get-edebug-spec spec) cursor (car (cdr specs))))
1584 (t;; Any other normal spec.
1585 (setq rest (cdr specs))
1586 (edebug-match-one-spec cursor spec)))
1587 (funcall remainder-handler cursor rest remainder-handler)))))))
1588
1589 1600
1590;; Define specs for all the symbol specs with functions used to process them. 1601;; Define specs for all the symbol specs with functions used to process them.
1591;; Perhaps we shouldn't be doing this with edebug-form-specs since the 1602;; Perhaps we shouldn't be doing this with edebug-form-specs since the
diff --git a/test/lisp/emacs-lisp/edebug-resources/edebug-test-code.el b/test/lisp/emacs-lisp/edebug-resources/edebug-test-code.el
index f52a2b1896c..ca49dcd213d 100644
--- a/test/lisp/emacs-lisp/edebug-resources/edebug-test-code.el
+++ b/test/lisp/emacs-lisp/edebug-resources/edebug-test-code.el
@@ -126,5 +126,9 @@
126 !start!(with-current-buffer (get-buffer-create "*edebug-test-code-buffer*") 126 !start!(with-current-buffer (get-buffer-create "*edebug-test-code-buffer*")
127 !body!(format "current-buffer: %s" (current-buffer)))) 127 !body!(format "current-buffer: %s" (current-buffer))))
128 128
129(defun edebug-test-code-use-destructuring-bind ()
130 (let ((two 2) (three 3))
131 (cl-destructuring-bind (x . y) (cons two three) (+ x!x! y!y!))))
132
129(provide 'edebug-test-code) 133(provide 'edebug-test-code)
130;;; edebug-test-code.el ends here 134;;; edebug-test-code.el ends here
diff --git a/test/lisp/emacs-lisp/edebug-tests.el b/test/lisp/emacs-lisp/edebug-tests.el
index 02f4d1c5abe..f6c016cdf80 100644
--- a/test/lisp/emacs-lisp/edebug-tests.el
+++ b/test/lisp/emacs-lisp/edebug-tests.el
@@ -899,5 +899,19 @@ test and possibly others should be updated."
899 "@g" (should (equal edebug-tests-@-result 899 "@g" (should (equal edebug-tests-@-result
900 '(#("abcd" 1 3 (face italic)) 511)))))) 900 '(#("abcd" 1 3 (face italic)) 511))))))
901 901
902(ert-deftest edebug-tests-dotted-forms ()
903 "Edebug can instrument code matching the tail of a dotted spec (Bug#6415)."
904 (edebug-tests-with-normal-env
905 (edebug-tests-setup-@ "use-destructuring-bind" nil t)
906 (edebug-tests-run-kbd-macro
907 "@ SPC SPC SPC SPC SPC SPC"
908 (edebug-tests-should-be-at "use-destructuring-bind" "x")
909 (edebug-tests-should-match-result-in-messages "2 (#o2, #x2, ?\\C-b)")
910 "SPC"
911 (edebug-tests-should-be-at "use-destructuring-bind" "y")
912 (edebug-tests-should-match-result-in-messages "3 (#o3, #x3, ?\\C-c)")
913 "g"
914 (should (equal edebug-tests-@-result 5)))))
915
902(provide 'edebug-tests) 916(provide 'edebug-tests)
903;;; edebug-tests.el ends here 917;;; edebug-tests.el ends here