Subject: Re: bug#21920: 25.0.50; describe-symbols cannot be debugged with Edebug

From: Johan Bockgård <[email-masked]>
Date: Sun, 15 Nov 2015 17:09:54 +0100

Eli Zaretskii <[email-masked]> writes:

> M-x load-file RET lisp/help-fns.el
> C-x C-f lisp/help-fns.el RET
>
> Go to the describe-symbol function and type:
>
> M-x edebug-defun RET
>
> This signals an error:
>
>   pcase--macroexpand: Unknown edebug-enter pattern: (edebug-enter (quote describe-symbol) nil (function (lambda nil (edebug-after 0 80 descfn))))

That last part (pcase-QPAT) of the patch in

    http://lists.gnu.org/archive/html/emacs-devel/2015-10/msg02285.html

should fix this.

The patch also contains code to step through SYMBOL bindings as was
suggested in that thread, i.e. it will make Edebug pause after x and y
in

    (pcase '(0 1) (`(,x 2) 3) (y 4))

This may make pcase a little more easy to understand—which branches it
tried and where it backtracked. On the other hand it may be illogical
since it would be a bit like stepping through the ARGS of lambda or
destructuring-bind.

Finally, here's a second patch that adds full support for stepping of
`pred' and `app' patterns. It instruments each ARG (x) of FUN (+) as
well as the result of FUN itself (including the hidden argument):

    (pcase '(1 2) (`(,x ,(pred (+ x))) t))

This completes the edebug support for pcase.

diff --git a/lisp/emacs-lisp/pcase.el b/lisp/emacs-lisp/pcase.el
index 3ea519c..adac2d9 100644
--- a/lisp/emacs-lisp/pcase.el
+++ b/lisp/emacs-lisp/pcase.el
@@ -94,12 +94,21 @@ (defun pcase--edebug-match-macro (cursor)
 		 specs)))))
     (edebug-match cursor (cons '&or specs))))
 
-(def-edebug-spec
-  pcase-FUN
-  (&or lambda-expr
-       ;; Punt on macros/special forms.
-       (functionp &rest form)
-       sexp))
+(def-edebug-spec pcase-FUN pcase--edebug-match-fun)
+(defun pcase--edebug-match-fun (cursor)
+  (let ((sexp (edebug-top-element-required cursor "Expected" '(pcase-FUN))))
+    ;; FUN = (lambda ...) | (F ...) | F
+    (if (eq 'lambda (car-safe sexp))
+        (list (edebug-match cursor '(lambda-expr)))
+      (let* ((x (make-symbol "x"))
+             (f (car (edebug-match cursor '(form))))
+             ;; Hack edebug instrumented form.
+             (g (let ((e (nthcdr 3 f)))
+                  (if (consp (car e))
+                      (setcdr (last (car e)) (list x))
+                    (setcar e (cons (car e) (list x))))
+                  f)))
+        (list `(lambda (,x) ,g))))))
 
 (def-edebug-spec
   pcase-PAT