mirror of
https://git.savannah.gnu.org/git/guile.git
synced 2025-04-30 03:40:34 +02:00
remove old debugging examples from api-debug
* doc/ref/api-debug.texi (Debugging Examples): Remove section, as the tracing bits are adequately covered in tracing, and the breakpoints and such will get covered in the debugging meta-commands section.
This commit is contained in:
parent
de03880abe
commit
3b541ca244
1 changed files with 1 additions and 291 deletions
|
@ -18,8 +18,7 @@ infrastructure that builds on top of those calls.
|
|||
* Evaluation Model:: Evaluation and the Scheme stack.
|
||||
* Source Properties:: From expressions to source locations.
|
||||
* Programmatic Error Handling:: Debugging when an error occurs.
|
||||
* Traps::
|
||||
* Debugging Examples::
|
||||
* Traps:: Breakpoints, tracepoints, oh my!
|
||||
@end menu
|
||||
|
||||
@node Evaluation Model
|
||||
|
@ -1236,295 +1235,6 @@ Setting Traps The highest-level trap interface. Use this.
|
|||
@end deffn
|
||||
|
||||
|
||||
@node Debugging Examples
|
||||
@subsection Debugging Examples
|
||||
|
||||
@c @node Tracing Examples
|
||||
@subsubheading Tracing Examples
|
||||
|
||||
The following examples show what tracing is and the kind of output that
|
||||
it generates. In the first example, we define a recursive function for
|
||||
reversing a list, then watch the effect of the recursive calls by
|
||||
tracing each call and return value.
|
||||
|
||||
@lisp
|
||||
guile> (define (rev ls)
|
||||
(if (null? ls)
|
||||
ls
|
||||
(append (rev (cdr ls))
|
||||
(list (car ls)))))
|
||||
guile> (use-modules (ice-9 debugging traps) (ice-9 debugging trace))
|
||||
guile> (define t1 (make <procedure-trap>
|
||||
#:procedure rev
|
||||
#:behaviour (list trace-trap
|
||||
trace-at-exit)))
|
||||
guile> (install-trap t1)
|
||||
guile> (rev '(a b c))
|
||||
| 2: [rev (a b c)]
|
||||
| 3: [rev (b c)]
|
||||
| 4: [rev (c)]
|
||||
| 5: [rev ()]
|
||||
| 5: =>()
|
||||
| 4: =>(c)
|
||||
| 3: =>(c b)
|
||||
| 2: =>(c b a)
|
||||
(c b a)
|
||||
@end lisp
|
||||
|
||||
@noindent
|
||||
The number before the colon in this output (which follows @code{(ice-9
|
||||
debugging trace)}'s default output format) is the number of real frames
|
||||
on the stack. The fact that this number increases for each recursive
|
||||
call confirms that the implementation above of @code{rev} is not
|
||||
tail-recursive.
|
||||
|
||||
In the next example, we probe the @emph{internal} workings of
|
||||
@code{rev} in more detail by using the @code{trace-until-exit}
|
||||
behaviour.
|
||||
|
||||
@lisp
|
||||
guile> (uninstall-trap t1)
|
||||
guile> (define t2 (make <procedure-trap>
|
||||
#:procedure rev
|
||||
#:behaviour (list trace-trap
|
||||
trace-until-exit)))
|
||||
guile> (install-trap t2)
|
||||
guile> (rev '(a b))
|
||||
| 2: [rev (a b)]
|
||||
| 2: (if (null? ls) ls (append (rev (cdr ls)) (list (car ls))))
|
||||
| 3: (null? ls)
|
||||
| 3: [null? (a b)]
|
||||
| 3: =>#f
|
||||
| 2: (append (rev (cdr ls)) (list (car ls)))
|
||||
| 3: (rev (cdr ls))
|
||||
| 4: (cdr ls)
|
||||
| 4: [cdr (a b)]
|
||||
| 4: =>(b)
|
||||
| 3: [rev (b)]
|
||||
| 3: (if (null? ls) ls (append (rev (cdr ls)) (list (car ls))))
|
||||
| 4: (null? ls)
|
||||
| 4: [null? (b)]
|
||||
| 4: =>#f
|
||||
| 3: (append (rev (cdr ls)) (list (car ls)))
|
||||
| 4: (rev (cdr ls))
|
||||
| 5: (cdr ls)
|
||||
| 5: [cdr (b)]
|
||||
| 5: =>()
|
||||
| 4: [rev ()]
|
||||
| 4: (if (null? ls) ls (append (rev (cdr ls)) (list (car ls))))
|
||||
| 5: (null? ls)
|
||||
| 5: [null? ()]
|
||||
| 5: =>#t
|
||||
| 4: (list (car ls))
|
||||
| 5: (car ls)
|
||||
| 5: [car (b)]
|
||||
| 5: =>b
|
||||
| 4: [list b]
|
||||
| 4: =>(b)
|
||||
| 3: [append () (b)]
|
||||
| 3: =>(b)
|
||||
| 3: (list (car ls))
|
||||
| 4: (car ls)
|
||||
| 4: [car (a b)]
|
||||
| 4: =>a
|
||||
| 3: [list a]
|
||||
| 3: =>(a)
|
||||
| 2: [append (b) (a)]
|
||||
| 2: =>(b a)
|
||||
(b a)
|
||||
@end lisp
|
||||
|
||||
@noindent
|
||||
The output in this case shows every step that the evaluator performs
|
||||
in evaluating @code{(rev '(a b))}.
|
||||
|
||||
|
||||
Here we present some examples of what you can do with the debugging
|
||||
facilities just described.
|
||||
|
||||
@subsubheading 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 debugger)}.
|
||||
|
||||
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 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 hi!))
|
||||
debug> info frame
|
||||
Stack frame: 3
|
||||
This frame is an evaluation.
|
||||
The expression being evaluated is:
|
||||
matrix.scm:4:3:
|
||||
(let ((x 1)) (quote hi!))
|
||||
debug> next
|
||||
Frame 3 at matrix.scm:5:21
|
||||
(quote hi!)
|
||||
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 hi!)
|
||||
debug> quit
|
||||
hi!
|
||||
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
|
||||
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.
|
||||
|
||||
|
||||
@subsubheading 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 hi!)))
|
||||
| 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 hi!))
|
||||
| 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 hi!))
|
||||
hi!
|
||||
guile> (do-main 4)
|
||||
| 2: [mkmatrix]
|
||||
| 2: (letrec ((yy 23)) (let* ((x 1)) (quote hi!)))
|
||||
| 2: (let* ((x 1)) (quote hi!))
|
||||
| 2: (quote hi!)
|
||||
| 2: =>hi!
|
||||
hi!
|
||||
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 hi!)))
|
||||
| matrix.scm:3:2: (let* ((x 1)) (quote hi!))
|
||||
| matrix.scm:4:4: (quote hi!)
|
||||
| matrix.scm:4:4: =>hi!
|
||||
hi!
|
||||
guile>
|
||||
@end lisp
|
||||
|
||||
@c Local Variables:
|
||||
@c TeX-master: "guile.texi"
|
||||
@c End:
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue