diff options
| author | Gemini Lasswell | 2017-11-01 21:13:02 -0700 |
|---|---|---|
| committer | Gemini Lasswell | 2017-11-26 13:44:15 -0800 |
| commit | 0ded1b41a986229eaa4218095d9c78d1800c0b27 (patch) | |
| tree | e7df79ca1383abc77d33d444e0998dacdfbce122 | |
| parent | 16358d4fcbad3fa60ff36167ae666b1ec7e7c02a (diff) | |
| download | emacs-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.el | 2 | ||||
| -rw-r--r-- | lisp/emacs-lisp/edebug.el | 67 | ||||
| -rw-r--r-- | test/lisp/emacs-lisp/edebug-resources/edebug-test-code.el | 4 | ||||
| -rw-r--r-- | test/lisp/emacs-lisp/edebug-tests.el | 14 |
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 |