1
Fork 0
mirror of https://git.savannah.gnu.org/git/guile.git synced 2025-05-20 11:40:18 +02:00

* api-debug.texi (Debugging Examples): New (from CVS HEAD).

This commit is contained in:
Neil Jerram 2008-03-19 23:06:52 +00:00
parent 3913785b73
commit 8c16237dc3
2 changed files with 213 additions and 0 deletions

View file

@ -1,5 +1,7 @@
2008-03-19 Neil Jerram <neil@ossau.uklinux.net>
* api-debug.texi (Debugging Examples): New (from CVS HEAD).
* scheme-using.texi (Interactive Debugger): Cover continuing
execution.
(Stepping and Continuing): New (from CVS HEAD).

View file

@ -18,6 +18,7 @@ infrastructure that builds on top of those calls.
* Evaluation Model:: Evaluation and the Scheme stack.
* Debug on Error:: Debugging when an error occurs.
* Traps::
* Debugging Examples::
@end menu
@node Evaluation Model
@ -1688,6 +1689,216 @@ if there isn't one.
@end deffn
@node Debugging Examples
@subsection Debugging Examples
Here we present some examples of what you can do with the debugging
facilities just described.
@menu
* Single Stepping through a Procedure's Code::
* Profiling or Tracing a Procedure's Code::
@end menu
@node Single Stepping through a Procedure's Code
@subsubsection Single Stepping through a Procedure's Code
A good way to explore in detail what a Scheme procedure does is to set
a trap on it and then single step through what it does. To do this,
make and install a @code{<procedure-trap>} with the @code{debug-trap}
behaviour from @code{(ice-9 debugging ice-9-debugger-extensions)}.
The following sample session illustrates this. It assumes that the
file @file{matrix.scm} defines a procedure @code{mkmatrix}, which is
the one we want to explore, and another procedure @code{do-main} which
calls @code{mkmatrix}.
@lisp
$ /usr/bin/guile -q
guile> (use-modules (ice-9 debugger)
(ice-9 debugging ice-9-debugger-extensions)
(ice-9 debugging traps))
guile> (load "matrix.scm")
guile> (install-trap (make <procedure-trap>
#:procedure mkmatrix
#:behaviour debug-trap))
guile> (do-main 4)
This is the Guile debugger -- for help, type `help'.
There are 3 frames on the stack.
Frame 2 at matrix.scm:8:3
[mkmatrix]
debug> next
Frame 3 at matrix.scm:4:3
(let ((x 1)) (quote this-is-a-matric))
debug> info frame
Stack frame: 3
This frame is an evaluation.
The expression being evaluated is:
matrix.scm:4:3:
(let ((x 1)) (quote this-is-a-matric))
debug> next
Frame 3 at matrix.scm:5:21
(quote this-is-a-matric)
debug> bt
In unknown file:
?: 0* [primitive-eval (do-main 4)]
In standard input:
4: 1* [do-main 4]
In matrix.scm:
8: 2 [mkmatrix]
...
5: 3 (quote this-is-a-matric)
debug> quit
this-is-a-matric
guile>
@end lisp
Or you can use Guile's Emacs interface (GDS), by using the module
@code{(ice-9 gds-client)} instead of @code{(ice-9 debugger)} and
@code{(ice-9 debugging ice-9-debugger-extensions)}, and changing
@code{debug-trap} to @code{gds-debug-trap}. Then the stack and
corresponding source locations are displayed in Emacs instead of on
the Guile command line.
@node Profiling or Tracing a Procedure's Code
@subsubsection Profiling or Tracing a Procedure's Code
What if you wanted to get a trace of everything that the Guile
evaluator does within a given procedure, but without Guile stopping
and waiting for your input at every step? For this requirement you
can install a trap on the procedure, as in the previous example, but
instead of @code{debug-trap} or @code{gds-debug-trap}, use the
@code{trace-trap} and @code{trace-until-exit} behaviours provided by
the @code{(ice-9 debugging trace)} module.
@lisp
guile> (use-modules (ice-9 debugging traps) (ice-9 debugging trace))
guile> (load "matrix.scm")
guile> (install-trap (make <procedure-trap>
#:procedure mkmatrix
#:behaviour (list trace-trap trace-until-exit)))
guile> (do-main 4)
| 2: [mkmatrix]
| 3: [#<procedure #f (a sym definep)> #<autoload # b7c93870> define #f]
| 3: [#<procedure #f (a sym definep)> #<autoload # b7c93870> define #f]
| 4: (and (memq sym bindings) (let ...))
| 5: (memq sym bindings)
| 5: [memq define (debug)]
| 5: =>#f
| 3: [#<procedure #f (a sym definep)> #<autoload # b7c93870> define #f]
| 3: [#<procedure #f (a sym definep)> #<autoload # b7c93870> define #f]
| 4: (and (memq sym bindings) (let ...))
| 5: (memq sym bindings)
| 5: [memq define (debug)]
| 5: =>#f
| 3: [#<procedure #f (a sym definep)> #<autoload # b7c93870> let #f]
| 3: [#<procedure #f (a sym definep)> #<autoload # b7c93870> let #f]
| 4: (and (memq sym bindings) (let ...))
| 5: (memq sym bindings)
| 5: [memq let (debug)]
| 5: =>#f
| 3: [#<procedure #f (a sym definep)> #<autoload # b7c93870> let #f]
| 3: [#<procedure #f (a sym definep)> #<autoload # b7c93870> let #f]
| 4: (and (memq sym bindings) (let ...))
| 5: (memq sym bindings)
| 5: [memq let (debug)]
| 5: =>#f
| 3: [#<procedure #f (a sym definep)> #<autoload # b7c93870> let #f]
| 3: [#<procedure #f (a sym definep)> #<autoload # b7c93870> let #f]
| 4: (and (memq sym bindings) (let ...))
| 5: (memq sym bindings)
| 5: [memq let (debug)]
| 5: =>#f
| 2: (letrec ((yy 23)) (let ((x 1)) (quote this-is-a-matric)))
| 3: [#<procedure #f (a sym definep)> #<autoload # b7c93870> let #f]
| 3: [#<procedure #f (a sym definep)> #<autoload # b7c93870> let #f]
| 4: (and (memq sym bindings) (let ...))
| 5: (memq sym bindings)
| 5: [memq let (debug)]
| 5: =>#f
| 3: [#<procedure #f (a sym definep)> #<autoload # b7c93870> let #f]
| 3: [#<procedure #f (a sym definep)> #<autoload # b7c93870> let #f]
| 4: (and (memq sym bindings) (let ...))
| 5: (memq sym bindings)
| 5: [memq let (debug)]
| 5: =>#f
| 3: [#<procedure #f (a sym definep)> #<autoload # b7c93870> let #f]
| 3: [#<procedure #f (a sym definep)> #<autoload # b7c93870> let #f]
| 4: (and (memq sym bindings) (let ...))
| 5: (memq sym bindings)
| 5: [memq let (debug)]
| 5: =>#f
| 2: (let ((x 1)) (quote this-is-a-matric))
| 3: [#<procedure #f (a sym definep)> #<autoload # b7c93870> let #f]
| 3: [#<procedure #f (a sym definep)> #<autoload # b7c93870> let #f]
| 4: (and (memq sym bindings) (let ...))
| 5: (memq sym bindings)
| 5: [memq let (debug)]
| 5: =>#f
| 2: [let (let # #) (# # #)]
| 2: [let (let # #) (# # #)]
| 2: =>(#@@let* (x 1) #@@let (quote this-is-a-matric))
this-is-a-matric
guile> (do-main 4)
| 2: [mkmatrix]
| 2: (letrec ((yy 23)) (let* ((x 1)) (quote this-is-a-matric)))
| 2: (let* ((x 1)) (quote this-is-a-matric))
| 2: (quote this-is-a-matric)
| 2: =>this-is-a-matric
this-is-a-matric
guile>
@end lisp
This example shows the default configuration for how each line of trace
output is formatted, which is:
@itemize
@item
the character @code{|}, a visual clue that the line is a line of trace
output, followed by
@item
a number indicating the real evaluator stack depth (where ``real'' means
not counting tail-calls), followed by
@item
a summary of the expression being evaluated (@code{(@dots{})}), the
procedure being called (@code{[@dots{}]}), or the value being returned
from an evaluation or procedure call (@code{=>@dots{}}).
@end itemize
@noindent
You can customize @code{(ice-9 debugging trace)} to show different
information in each trace line using the @code{set-trace-layout}
procedure. The next example shows how to get the source location in
each trace line instead of the stack depth.
@lisp
guile> (set-trace-layout "|~16@@a: ~a\n" trace/source trace/info)
guile> (do-main 4)
| matrix.scm:7:2: [mkmatrix]
| : (letrec ((yy 23)) (let* ((x 1)) (quote this-is-a-matric)))
| matrix.scm:3:2: (let* ((x 1)) (quote this-is-a-matric))
| matrix.scm:4:4: (quote this-is-a-matric)
| matrix.scm:4:4: =>this-is-a-matric
this-is-a-matric
guile>
@end lisp
(For anyone wondering why the first @code{(do-main 4)} call above
generates lots more trace lines than the subsequent calls: these
examples also demonstrate how the Guile evaluator ``memoizes'' code.
When Guile evaluates a source code expression for the first time, it
changes some parts of the expression so that they will be quicker to
evaluate when that expression is evaluated again; this is called
memoization. The trace output from the first @code{(do-main 4)} call
shows memoization steps, such as an internal define being transformed to
a letrec.)
@c Local Variables:
@c TeX-master: "guile.texi"
@c End: