mirror of
https://git.savannah.gnu.org/git/guile.git
synced 2025-05-01 12:20:26 +02:00
181 lines
4.8 KiB
Text
181 lines
4.8 KiB
Text
@page
|
|
@node Debugger User Interface
|
|
@chapter Debugger User Interface
|
|
|
|
@c --- The title and introduction of this appendix need to
|
|
@c distinguish this clearly from the chapter on the internal
|
|
@c debugging interface.
|
|
|
|
When debugging a program, programmers often find it helpful to examine
|
|
the program's internal status while it runs: the values of internal
|
|
variables, the choices made in @code{if} and @code{cond} statements, and
|
|
so forth. Guile Scheme provides a debugging interface that programmers
|
|
can use to single-step through Scheme functions and examine symbol
|
|
bindings. This is different from the @ref{Debugging}, which permits
|
|
programmers to debug the Guile interpreter itself. Most programmers
|
|
will be more interested in debugging their own Scheme programs than the
|
|
interpreter which evaluates them.
|
|
|
|
[FIXME: should we include examples of traditional debuggers
|
|
and explain why they can't be used to debug interpreted Scheme or Lisp?]
|
|
|
|
@menu
|
|
* Single-Step:: Execute a program or function one step at a time.
|
|
* Trace:: Print a report each time a given function is called.
|
|
* Backtrace:: See a list of the statements that caused an error.
|
|
* Stacks and Frames:: Examine the state of an interrupted program.
|
|
@end menu
|
|
|
|
|
|
@node Single-Step
|
|
@section Single-Step
|
|
|
|
|
|
@node Trace
|
|
@section Trace
|
|
|
|
When a function is @dfn{traced}, it means that every call to that
|
|
function is reported to the user during a program run. This can help a
|
|
programmer determine whether a function is being called at the wrong
|
|
time or with the wrong set of arguments.
|
|
|
|
@defun trace function
|
|
Enable debug tracing on @code{function}. While a program is being run, Guile
|
|
will print a brief report at each call to a traced function,
|
|
advising the user which function was called and the arguments that were
|
|
passed to it.
|
|
@end defun
|
|
|
|
@defun untrace function
|
|
Disable debug tracing for @code{function}.
|
|
@end defun
|
|
|
|
Example:
|
|
|
|
@lisp
|
|
(define (rev ls)
|
|
(if (null? ls)
|
|
'()
|
|
(append (rev (cdr ls))
|
|
(cons (car ls) '())))) @result{} rev
|
|
|
|
(trace rev) @result{} (rev)
|
|
|
|
(rev '(a b c d e))
|
|
@result{} [rev (a b c d e)]
|
|
| [rev (b c d e)]
|
|
| | [rev (c d e)]
|
|
| | | [rev (d e)]
|
|
| | | | [rev (e)]
|
|
| | | | | [rev ()]
|
|
| | | | | ()
|
|
| | | | (e)
|
|
| | | (e d)
|
|
| | (e d c)
|
|
| (e d c b)
|
|
(e d c b a)
|
|
(e d c b a)
|
|
@end lisp
|
|
|
|
Note the way Guile indents the output, illustrating the depth of
|
|
execution at each function call. This can be used to demonstrate, for
|
|
example, that Guile implements self-tail-recursion properly:
|
|
|
|
@lisp
|
|
(define (rev ls sl)
|
|
(if (null? ls)
|
|
sl
|
|
(rev (cdr ls)
|
|
(cons (car ls) sl)))) @result{} rev
|
|
|
|
(trace rev) @result{} (rev)
|
|
|
|
(rev '(a b c d e) '())
|
|
@result{} [rev (a b c d e) ()]
|
|
[rev (b c d e) (a)]
|
|
[rev (c d e) (b a)]
|
|
[rev (d e) (c b a)]
|
|
[rev (e) (d c b a)]
|
|
[rev () (e d c b a)]
|
|
(e d c b a)
|
|
(e d c b a)
|
|
@end lisp
|
|
|
|
Since the tail call is effectively optimized to a @code{goto} statement,
|
|
there is no need for Guile to create a new stack frame for each
|
|
iteration. Using @code{trace} here helps us see why this is so.
|
|
|
|
|
|
@node Backtrace
|
|
@section Backtrace
|
|
|
|
|
|
@node Stacks and Frames
|
|
@section Stacks and Frames
|
|
|
|
When a running program is interrupted, usually upon reaching an error or
|
|
breakpoint, its state is represented by a @dfn{stack} of suspended
|
|
function calls, each of which is called a @dfn{frame}. The programmer
|
|
can learn more about the program's state at the point of interruption by
|
|
inspecting and modifying these frames.
|
|
|
|
@deffn {Scheme Procedure} stack? obj
|
|
Return @code{#t} if @var{obj} is a calling stack.
|
|
@end deffn
|
|
|
|
@deffn {Scheme Procedure} make-stack
|
|
@end deffn
|
|
|
|
@deffn syntax start-stack id exp
|
|
Evaluate @var{exp} on a new calling stack with identity @var{id}. If
|
|
@var{exp} is interrupted during evaluation, backtraces will not display
|
|
frames farther back than @var{exp}'s top-level form. This macro is a
|
|
way of artificially limiting backtraces and stack procedures, largely as
|
|
a convenience to the user.
|
|
@end deffn
|
|
|
|
@deffn {Scheme Procedure} stack-id stack
|
|
Return the identifier given to @var{stack} by @code{start-stack}.
|
|
@end deffn
|
|
|
|
@deffn {Scheme Procedure} stack-ref
|
|
@end deffn
|
|
|
|
@deffn {Scheme Procedure} stack-length
|
|
@end deffn
|
|
|
|
@deffn {Scheme Procedure} frame?
|
|
@end deffn
|
|
|
|
@deffn {Scheme Procedure} last-stack-frame
|
|
@end deffn
|
|
|
|
@deffn {Scheme Procedure} frame-number
|
|
@end deffn
|
|
|
|
@deffn {Scheme Procedure} frame-source
|
|
@end deffn
|
|
|
|
@deffn {Scheme Procedure} frame-procedure
|
|
@end deffn
|
|
|
|
@deffn {Scheme Procedure} frame-arguments
|
|
@end deffn
|
|
|
|
@deffn {Scheme Procedure} frame-previous
|
|
@end deffn
|
|
|
|
@deffn {Scheme Procedure} frame-next
|
|
@end deffn
|
|
|
|
@deffn {Scheme Procedure} frame-real?
|
|
@end deffn
|
|
|
|
@deffn {Scheme Procedure} frame-procedure?
|
|
@end deffn
|
|
|
|
@deffn {Scheme Procedure} frame-evaluating-args?
|
|
@end deffn
|
|
|
|
@deffn {Scheme Procedure} frame-overflow
|
|
@end deffn
|