The function edebug-instrument-for-tracing
as defined in the following Elisp snippet works similar to edebug-defun
.
But, instead of instrumenting stuff for edebug
it prepares it for tracing into the buffer *edebug-trace*
.
(defun edebug-untrace (form)
"Remove tracing instructions from FORM."
(if (consp form)
(if (eq (car form) 'edebug-tracing)
(edebug-untrace (caddr form))
(cons (edebug-untrace (car form))
(edebug-untrace (cdr form))))
form))
(defcustom edebug-trace-print-level 3
"`print-level' for `edebug-make-trace-form'."
:type 'integer
:group 'edebug)
(defcustom edebug-trace-print-length 5
"`print-length' for `edebug-make-trace-form'."
:type 'integer
:group 'edebug)
(defun edebug-make-trace-form (form)
"Prepare FORM for tracing."
`(edebug-tracing ,(let ((print-level edebug-trace-print-level)
(print-length edebug-trace-print-length))
(prin1-to-string (edebug-untrace form)))
,form))
(defun edebug-make-trace-enter-wrapper (forms)
"Prepare function with FORMS for tracing."
(if edebug-def-name
`(edebug-tracing ,(format "%S%S"
edebug-def-name
(nreverse edebug-def-args))
,@forms)
`(progn ,@forms)))
(defun edebug-instrument-for-tracing ()
"Like `edebug-defun' but instruments for tracing."
(interactive)
(cl-letf (((symbol-function 'edebug-make-enter-wrapper)
(lambda (forms)
(edebug-make-trace-enter-wrapper forms)))
((symbol-function 'edebug-make-before-and-after-form)
(lambda (before-index form after-index)
(edebug-make-trace-form form)))
((symbol-function 'edebug-make-after-form)
(lambda (form after-index)
(edebug-make-trace-form form))))
(edebug-defun)))
For testing, put point into the following form and run M-x edebug-instrument-for-tracing
.
(let ((i 0))
(while (< i 2)
(message "i=%d" i)
(setq i (1+ i))))
You get an *edebug-trace*
buffer with the following output.
Each form is printed before and after its evaluation.
The result of the evaluation of the form is also printed.
{ (let ((i 0)) (while (< i 2) (message "i=%d" i) (setq i ...)))
:{ (while (< i 2) (message "i=%d" i) (setq i (1+ i)))
::{ (< i 2)
:::{ i
:::} i result: 0
::} (< i 2) result: t
::{ (message "i=%d" i)
:::{ i
:::} i result: 0
::} (message "i=%d" i) result: i=0
::{ (setq i (1+ i))
:::{ (1+ i)
::::{ i
::::} i result: 0
:::} (1+ i) result: 1
::} (setq i (1+ i)) result: 1
::{ (< i 2)
:::{ i
:::} i result: 1
::} (< i 2) result: t
::{ (message "i=%d" i)
:::{ i
:::} i result: 1
::} (message "i=%d" i) result: i=1
::{ (setq i (1+ i))
:::{ (1+ i)
::::{ i
::::} i result: 1
:::} (1+ i) result: 2
::} (setq i (1+ i)) result: 2
::{ (< i 2)
:::{ i
:::} i result: 2
::} (< i 2) result: nil
:} (while (< i 2) (message "i=%d" i) (setq i (1+ i))) result: nil
} (let ((i 0)) (while (< i 2) (message "i=%d" i) (setq i ...))) result: nil
Note that this is a kind of simple prototype-implementation. It is not very efficient. It may be that tracing becomes a bit slow on deeply nested functions.
M-x trace-function
. See also "Debugging lisp programs" in the elisp manual.