mirror of
https://git.savannah.gnu.org/git/guile.git
synced 2025-04-30 03:40:34 +02:00
* scheme-debugging.texi (Debug Last Error, Interactive Debugger):
Moved/merged to scheme-using.texi, as REPL features. (Examples): New. (Intro to Breakpoints): New introductory text here. Removed all subnodes except for Breakpoints Overview. * scheme-using.texi: New. * guile.texi (Programming in Scheme): Include new scheme-using.texi file. * Makefile.am (guile_TEXINFOS): Include new scheme-using.texi file.
This commit is contained in:
parent
b49123789f
commit
46f7666d7f
5 changed files with 608 additions and 709 deletions
|
@ -1,3 +1,19 @@
|
||||||
|
2006-08-01 Neil Jerram <neil@ossau.uklinux.net>
|
||||||
|
|
||||||
|
* scheme-debugging.texi (Debug Last Error, Interactive Debugger):
|
||||||
|
Moved/merged to scheme-using.texi, as REPL features.
|
||||||
|
(Examples): New.
|
||||||
|
(Intro to Breakpoints): New introductory text here. Removed all
|
||||||
|
subnodes except for Breakpoints Overview.
|
||||||
|
|
||||||
|
* scheme-using.texi: New.
|
||||||
|
|
||||||
|
* guile.texi (Programming in Scheme): Include new
|
||||||
|
scheme-using.texi file.
|
||||||
|
|
||||||
|
* Makefile.am (guile_TEXINFOS): Include new scheme-using.texi
|
||||||
|
file.
|
||||||
|
|
||||||
2006-06-16 Ludovic Courtès <ludovic.courtes@laas.fr>
|
2006-06-16 Ludovic Courtès <ludovic.courtes@laas.fr>
|
||||||
|
|
||||||
* api-utility.texi (Equality): Mentioned the behavior of `equal?'
|
* api-utility.texi (Equality): Mentioned the behavior of `equal?'
|
||||||
|
|
|
@ -56,6 +56,7 @@ guile_TEXINFOS = preface.texi \
|
||||||
gh.texi \
|
gh.texi \
|
||||||
api-overview.texi \
|
api-overview.texi \
|
||||||
scheme-debugging.texi \
|
scheme-debugging.texi \
|
||||||
|
scheme-using.texi \
|
||||||
indices.texi \
|
indices.texi \
|
||||||
script-getopt.texi \
|
script-getopt.texi \
|
||||||
data-rep.texi \
|
data-rep.texi \
|
||||||
|
|
|
@ -137,7 +137,7 @@ x
|
||||||
@comment The title is printed in a large font.
|
@comment The title is printed in a large font.
|
||||||
@title Guile Reference Manual
|
@title Guile Reference Manual
|
||||||
@subtitle Edition @value{MANUAL-EDITION}, for use with Guile @value{VERSION}
|
@subtitle Edition @value{MANUAL-EDITION}, for use with Guile @value{VERSION}
|
||||||
@c @subtitle $Id: guile.texi,v 1.44 2005-06-22 23:42:23 kryde Exp $
|
@c @subtitle $Id: guile.texi,v 1.45 2006-08-01 21:33:17 ossau Exp $
|
||||||
|
|
||||||
@c See preface.texi for the list of authors
|
@c See preface.texi for the list of authors
|
||||||
@author The Guile Developers
|
@author The Guile Developers
|
||||||
|
@ -219,6 +219,8 @@ etc. that make up Guile's application programming interface (API),
|
||||||
* Basic Ideas:: Basic ideas in Scheme.
|
* Basic Ideas:: Basic ideas in Scheme.
|
||||||
* Guile Scheme:: Guile's implementation of Scheme.
|
* Guile Scheme:: Guile's implementation of Scheme.
|
||||||
* Guile Scripting:: How to write Guile scripts.
|
* Guile Scripting:: How to write Guile scripts.
|
||||||
|
* Using Guile Interactively:: Guile's REPL features.
|
||||||
|
* Using Guile in Emacs:: Guile and Emacs.
|
||||||
* Debugging Features:: Features for finding errors.
|
* Debugging Features:: Features for finding errors.
|
||||||
* Further Reading:: Where to find out more about Scheme.
|
* Further Reading:: Where to find out more about Scheme.
|
||||||
@end menu
|
@end menu
|
||||||
|
@ -226,6 +228,7 @@ etc. that make up Guile's application programming interface (API),
|
||||||
@include scheme-ideas.texi
|
@include scheme-ideas.texi
|
||||||
@include scheme-intro.texi
|
@include scheme-intro.texi
|
||||||
@include scheme-scripts.texi
|
@include scheme-scripts.texi
|
||||||
|
@include scheme-using.texi
|
||||||
@include scheme-debugging.texi
|
@include scheme-debugging.texi
|
||||||
@include scheme-reading.texi
|
@include scheme-reading.texi
|
||||||
|
|
||||||
|
|
|
@ -28,135 +28,196 @@ execution context at a breakpoint, or when the last error occurred.
|
||||||
The details are more complex and more powerful @dots{}
|
The details are more complex and more powerful @dots{}
|
||||||
|
|
||||||
@menu
|
@menu
|
||||||
* Debug Last Error:: Debugging the most recent error.
|
* Examples::
|
||||||
* Intro to Breakpoints:: Setting and manipulating them.
|
* Intro to Breakpoints:: Setting and manipulating them.
|
||||||
* Interactive Debugger:: Using the interactive debugger.
|
|
||||||
* Tracing:: Tracing program execution.
|
* Tracing:: Tracing program execution.
|
||||||
@end menu
|
@end menu
|
||||||
|
|
||||||
|
|
||||||
@node Debug Last Error
|
@node Examples
|
||||||
@subsection Debugging the Most Recent Error
|
@subsection Examples
|
||||||
|
|
||||||
When an error is signalled, Guile remembers the execution context where
|
Before we dive into the details and reference documentation of
|
||||||
the error occurred. By default, Guile then displays only the most
|
guile-debugging's features, this chapter sets the scene by presenting a
|
||||||
immediate information about where and why the error occurred, for
|
few examples of what you can do with guile-debugging.
|
||||||
example:
|
|
||||||
|
|
||||||
@lisp
|
|
||||||
(make-string (* 4 (+ 3 #\s)) #\space)
|
|
||||||
@print{}
|
|
||||||
standard input:2:19: In procedure + in expression (+ 3 #\s):
|
|
||||||
standard input:2:19: Wrong type argument: #\s
|
|
||||||
ABORT: (wrong-type-arg)
|
|
||||||
|
|
||||||
Type "(backtrace)" to get more information or "(debug)" to enter the debugger.
|
|
||||||
@end lisp
|
|
||||||
|
|
||||||
@noindent
|
|
||||||
However, as the message above says, you can obtain much more
|
|
||||||
information about the context of the error by typing
|
|
||||||
@code{(backtrace)} or @code{(debug)}.
|
|
||||||
|
|
||||||
@code{(backtrace)} displays the Scheme call stack at the point where the
|
|
||||||
error occurred:
|
|
||||||
|
|
||||||
@lisp
|
|
||||||
(backtrace)
|
|
||||||
@print{}
|
|
||||||
Backtrace:
|
|
||||||
In standard input:
|
|
||||||
2: 0* [make-string ...
|
|
||||||
2: 1* [* 4 ...
|
|
||||||
2: 2* [+ 3 #\s]
|
|
||||||
|
|
||||||
Type "(debug-enable 'backtrace)" if you would like a backtrace
|
|
||||||
automatically if an error occurs in the future.
|
|
||||||
@end lisp
|
|
||||||
|
|
||||||
@noindent
|
|
||||||
In a more complex scenario than this one, this can be extremely useful
|
|
||||||
for understanding where and why the error occurred. For more on the
|
|
||||||
format of the displayed backtrace, see the subsection below.
|
|
||||||
|
|
||||||
@code{(debug)} takes you into Guile's interactive debugger, which
|
|
||||||
provides commands that allow you to
|
|
||||||
|
|
||||||
@itemize @bullet
|
|
||||||
@item
|
|
||||||
display the Scheme call stack at the point where the error occurred
|
|
||||||
(the @code{backtrace} command --- see @ref{Display Backtrace})
|
|
||||||
|
|
||||||
@item
|
|
||||||
move up and down the call stack, to see in detail the expression being
|
|
||||||
evaluated, or the procedure being applied, in each @dfn{frame} (the
|
|
||||||
@code{up}, @code{down}, @code{frame}, @code{position}, @code{info args}
|
|
||||||
and @code{info frame} commands --- see @ref{Frame Selection} and
|
|
||||||
@ref{Frame Information})
|
|
||||||
|
|
||||||
@item
|
|
||||||
examine the values of variables and expressions in the context of each
|
|
||||||
frame (the @code{evaluate} command --- see @ref{Frame Evaluation}).
|
|
||||||
@end itemize
|
|
||||||
|
|
||||||
Use of the interactive debugger, including these commands, is described
|
|
||||||
in @ref{Interactive Debugger}.
|
|
||||||
|
|
||||||
@menu
|
@menu
|
||||||
* Backtrace Format:: How to interpret a backtrace.
|
* Single Stepping through a Procedure's Code::
|
||||||
|
* Profiling or Tracing a Procedure's Code::
|
||||||
@end menu
|
@end menu
|
||||||
|
|
||||||
|
|
||||||
@node Backtrace Format
|
@node Single Stepping through a Procedure's Code
|
||||||
@subsubsection How to Interpret a Backtrace
|
@subsubsection Single Stepping through a Procedure's Code
|
||||||
|
|
||||||
|
A good way to explore in detail what a Scheme procedure does is to set a
|
||||||
|
breakpoint on it and then single step through what it does. To do this,
|
||||||
|
use the @code{break-in} procedure from the @code{(ice-9 debugging
|
||||||
|
breakpoints)} module 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 breakpoints))
|
||||||
|
guile> (load "matrix.scm")
|
||||||
|
guile> (break-in 'mkmatrix #:behaviour debug-trap)
|
||||||
|
#<<break-in> 808cb70>
|
||||||
|
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-debugging'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? In this case you set a breakpoint on the
|
||||||
|
procedure using @code{break-in} (the same as in the previous example),
|
||||||
|
but 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 breakpoints) (ice-9 debugging trace))
|
||||||
|
guile> (load "matrix.scm")
|
||||||
|
guile> (break-in 'mkmatrix #:behaviour (list trace-trap trace-until-exit))
|
||||||
|
#<<break-in> 808b430>
|
||||||
|
guile> (do-main 4)
|
||||||
|
| 2: [mkmatrix]
|
||||||
|
| 3: [define (define yy 23) ((()) #<eval-closure 4028db30>)]
|
||||||
|
| 3: [define (define yy 23) ((()) #<eval-closure 4028db30>)]
|
||||||
|
| 3: =>(#@@define yy 23)
|
||||||
|
| 3: [let (let # #) (# #)]
|
||||||
|
| 3: [let (let # #) (# #)]
|
||||||
|
| 3: =>(#@@let* (x 1) #@@let (quote this-is-a-matric))
|
||||||
|
| 2: (letrec ((yy 23)) (let ((x 1)) (quote this-is-a-matric)))
|
||||||
|
| 3: [let (let # #) (# # #)]
|
||||||
|
| 3: [let (let # #) (# # #)]
|
||||||
|
| 3: =>(#@@let* (x 1) #@@let (quote this-is-a-matric))
|
||||||
|
| 2: (let ((x 1)) (quote this-is-a-matric))
|
||||||
|
| 3: [quote (quote this-is-a-matric) ((x . 1) ((yy) 23) (()) ...)]
|
||||||
|
| 3: [quote (quote this-is-a-matric) ((x . 1) ((yy) 23) (()) ...)]
|
||||||
|
| 3: =>(#@@quote this-is-a-matric)
|
||||||
|
| 2: (quote this-is-a-matric)
|
||||||
|
| 2: =>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:20: (quote this-is-a-matric)
|
||||||
|
| matrix.scm:4:20: =>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.)
|
||||||
|
|
||||||
|
|
||||||
@node Intro to Breakpoints
|
@node Intro to Breakpoints
|
||||||
@subsection Intro to Breakpoints
|
@subsection Intro to Breakpoints
|
||||||
|
|
||||||
If you are not already familiar with the concept of breakpoints, the
|
Sometimes a piece of Scheme code isn't working and you'd like to go
|
||||||
first subsection below explains how they work are why they are useful.
|
through it step by step. You can do this in Guile by setting a
|
||||||
|
breakpoint at the start of the relevant code, and then using the command
|
||||||
|
line or Emacs interface to step through it.
|
||||||
|
|
||||||
Broadly speaking, Guile's breakpoint support consists of
|
A breakpoint can be specified by procedure name or by location -- the
|
||||||
|
relevant code's file name, line number and column number. For details
|
||||||
|
please see the full documentation for @code{break-in} and
|
||||||
|
@code{break-at} in @ref{Intro to Breakpoints}.
|
||||||
|
|
||||||
@itemize @bullet
|
When you set a breakpoint, you can specify any ``behaviour'' you like
|
||||||
@item
|
for what should happen when the breakpoint is hit; a breakpoint
|
||||||
type-specific features for @emph{creating} breakpoints of various types
|
``behaviour'' is just a Scheme procedure with the right signature.
|
||||||
|
|
||||||
@item
|
|
||||||
relatively generic features for @emph{manipulating} the behaviour of
|
|
||||||
breakpoints once they've been created.
|
|
||||||
@end itemize
|
|
||||||
|
|
||||||
Different breakpoint types are implemented as different classes in a
|
|
||||||
GOOPS hierarchy with common base class @code{<breakpoint>}. The magic
|
|
||||||
of generic functions then allows most of the manipulation functions to
|
|
||||||
be generic by default but specializable (by breakpoint class) if the
|
|
||||||
need arises.
|
|
||||||
|
|
||||||
Generic breakpoint support is provided by the @code{(ice-9 debugger
|
|
||||||
breakpoints)} module, so you will almost always need to use this module
|
|
||||||
in order to access the functionality described here:
|
|
||||||
|
|
||||||
@smalllisp
|
|
||||||
(use-modules (ice-9 debugger breakpoints))
|
|
||||||
@end smalllisp
|
|
||||||
|
|
||||||
@noindent
|
|
||||||
You may like to add this to your @file{.guile} file.
|
|
||||||
|
|
||||||
@menu
|
@menu
|
||||||
* Breakpoints Overview::
|
* Breakpoints Overview::
|
||||||
* Source Breakpoints::
|
|
||||||
* Procedural Breakpoints::
|
|
||||||
* Setting Breakpoints::
|
|
||||||
* break! trace! trace-subtree!::
|
|
||||||
* Accessing Breakpoints::
|
|
||||||
* Breakpoint Behaviours::
|
|
||||||
* Enabling and Disabling::
|
|
||||||
* Deleting Breakpoints::
|
|
||||||
* Breakpoint Information::
|
|
||||||
* Other Breakpoint Types::
|
|
||||||
@end menu
|
@end menu
|
||||||
|
|
||||||
|
|
||||||
|
@ -187,8 +248,9 @@ available:
|
||||||
|
|
||||||
@itemize @bullet
|
@itemize @bullet
|
||||||
@item
|
@item
|
||||||
all the commands as described for last error debugging (@pxref{Debug
|
all the commands as described for last error debugging
|
||||||
Last Error}), which allow you to explore the stack and so on
|
(@pxref{Interactive Debugger}), which allow you to explore the stack and
|
||||||
|
so on
|
||||||
|
|
||||||
@item
|
@item
|
||||||
additional commands for continuing program execution in various ways:
|
additional commands for continuing program execution in various ways:
|
||||||
|
@ -200,607 +262,13 @@ Use of the interactive debugger is described in @ref{Interactive
|
||||||
Debugger}.
|
Debugger}.
|
||||||
|
|
||||||
|
|
||||||
@node Source Breakpoints
|
|
||||||
@subsubsection Source Breakpoints
|
|
||||||
|
|
||||||
A source breakpoint is a breakpoint that triggers whenever program
|
|
||||||
execution hits a particular source location. A source breakpoint can be
|
|
||||||
conveniently set simply by evaluating code that has @code{##} inserted
|
|
||||||
into it at the position where you want the breakpoint to be.
|
|
||||||
|
|
||||||
For example, to set a breakpoint immediately before evaluation of
|
|
||||||
@code{(= n 0)} in the following procedure definition, evaluate:
|
|
||||||
|
|
||||||
@smalllisp
|
|
||||||
(define (fact1 n)
|
|
||||||
(if ##(= n 0)
|
|
||||||
1
|
|
||||||
(* n (fact1 (- n 1)))))
|
|
||||||
@print{}
|
|
||||||
Set breakpoint 1: standard input:4:9: (= n 0)
|
|
||||||
@end smalllisp
|
|
||||||
|
|
||||||
@noindent
|
|
||||||
Note the message confirming that you have set a breakpoint. If you
|
|
||||||
don't see this, something isn't working.
|
|
||||||
|
|
||||||
@code{##} is provided by the @code{(ice-9 debugger breakpoints source)} module,
|
|
||||||
so you must use this module before trying to set breakpoints in this
|
|
||||||
way:
|
|
||||||
|
|
||||||
@smalllisp
|
|
||||||
(use-modules (ice-9 debugger breakpoints source))
|
|
||||||
@end smalllisp
|
|
||||||
|
|
||||||
@noindent
|
|
||||||
You may like to add this to your @file{.guile} file.
|
|
||||||
|
|
||||||
The default behaviour for source breakpoints is @code{debug-here}
|
|
||||||
(@pxref{Breakpoint Behaviours}), which means to enter the command line
|
|
||||||
debugger when the breakpoint is hit. So, if you now use @code{fact1},
|
|
||||||
that is what happens.
|
|
||||||
|
|
||||||
@smalllisp
|
|
||||||
guile> (fact1 3)
|
|
||||||
Hit breakpoint 1: standard input:4:9: (= n 0)
|
|
||||||
Frame 3 at standard input:4:9
|
|
||||||
(= n 0)
|
|
||||||
debug>
|
|
||||||
@end smalllisp
|
|
||||||
|
|
||||||
|
|
||||||
@node Procedural Breakpoints
|
|
||||||
@subsubsection Procedural Breakpoints
|
|
||||||
|
|
||||||
A procedural breakpoint is a breakpoint that triggers whenever Guile is
|
|
||||||
about to apply a specified procedure to its (already evaluated)
|
|
||||||
arguments. To set a procedural breakpoint, call @code{break!} with the
|
|
||||||
target procedure as a single argument. For example:
|
|
||||||
|
|
||||||
@smalllisp
|
|
||||||
(define (fact1 n)
|
|
||||||
(if (= n 0)
|
|
||||||
1
|
|
||||||
(* n (fact1 (- n 1)))))
|
|
||||||
|
|
||||||
(break! fact1)
|
|
||||||
@print{}
|
|
||||||
Set breakpoint 1: [fact1]
|
|
||||||
@result{}
|
|
||||||
#<<procedure-breakpoint> 808b0b0>
|
|
||||||
@end smalllisp
|
|
||||||
|
|
||||||
Alternatives to @code{break!} are @code{trace!} and
|
|
||||||
@code{trace-subtree!}. The difference is that these three calls create
|
|
||||||
a breakpoint in the same place but with three different behaviours,
|
|
||||||
respectively @code{debug-here}, @code{trace-here} and
|
|
||||||
@code{trace-subtree}. Breakpoint behaviours are documented fully later
|
|
||||||
(@pxref{Breakpoint Behaviours}), but to give a quick taste, here's an
|
|
||||||
example of running code that includes a procedural breakpoint with the
|
|
||||||
@code{trace-here} behaviour.
|
|
||||||
|
|
||||||
@smalllisp
|
|
||||||
(trace! fact1)
|
|
||||||
@print{}
|
|
||||||
Set breakpoint 1: [fact1]
|
|
||||||
@result{}
|
|
||||||
#<<procedure-breakpoint> 808b0b0>
|
|
||||||
|
|
||||||
(fact1 4)
|
|
||||||
@print{}
|
|
||||||
| [fact1 4]
|
|
||||||
| | [fact1 3]
|
|
||||||
| | | [fact1 2]
|
|
||||||
| | | | [fact1 1]
|
|
||||||
| | | | | [fact1 0]
|
|
||||||
| | | | | 1
|
|
||||||
| | | | 2
|
|
||||||
| | | 6
|
|
||||||
| | 24
|
|
||||||
| 24
|
|
||||||
@result{}
|
|
||||||
24
|
|
||||||
@end smalllisp
|
|
||||||
|
|
||||||
To set and use procedural breakpoints, you will need to use the
|
|
||||||
@code{(ice-9 debugger breakpoints procedural)} module:
|
|
||||||
|
|
||||||
@smalllisp
|
|
||||||
(use-modules (ice-9 debugger breakpoints procedural))
|
|
||||||
@end smalllisp
|
|
||||||
|
|
||||||
@noindent
|
|
||||||
You may like to add this to your @file{.guile} file.
|
|
||||||
|
|
||||||
|
|
||||||
@node Setting Breakpoints
|
|
||||||
@subsubsection Setting Breakpoints
|
|
||||||
|
|
||||||
In general, that is. We've already seen how to set source and
|
|
||||||
procedural breakpoints conveniently in practice. This section explains
|
|
||||||
how those conveniences map onto a more general mechanism.
|
|
||||||
|
|
||||||
The general mechanism for setting breakpoints is the generic function
|
|
||||||
@code{set-breakpoint!}. Different kinds of breakpoints define
|
|
||||||
subclasses of the class @code{<breakpoint>} and provide their own
|
|
||||||
methods for @code{set-pbreakpoint!}.
|
|
||||||
|
|
||||||
For example, @code{(ice-9 debugger breakpoints procedural)} implements
|
|
||||||
the @code{<procedure-breakpoint>} subclass and provides a
|
|
||||||
@code{set-breakpoint!} method that takes a procedure argument:
|
|
||||||
|
|
||||||
@smalllisp
|
|
||||||
(set-breakpoint! @var{behavior} fact1)
|
|
||||||
@print{}
|
|
||||||
Set breakpoint 1: [fact1]
|
|
||||||
@result{}
|
|
||||||
#<<procedure-breakpoint> 808b0b0>
|
|
||||||
@end smalllisp
|
|
||||||
|
|
||||||
A non-type-specific @code{set-breakpoint!} method is provided by the
|
|
||||||
generic module @code{(ice-9 debugger breakpoints)}. It allows you to
|
|
||||||
change the behaviour of an existing breakpoint that is identified by
|
|
||||||
its breakpoint number.
|
|
||||||
|
|
||||||
@smalllisp
|
|
||||||
(set-breakpoint! @var{behavior} 1)
|
|
||||||
@end smalllisp
|
|
||||||
|
|
||||||
@node break! trace! trace-subtree!
|
|
||||||
@subsubsection break! trace! trace-subtree!
|
|
||||||
|
|
||||||
We have already talked above about the use of @code{break!},
|
|
||||||
@code{trace!} and @code{trace-subtree!} for setting procedural
|
|
||||||
breakpoints. Now that @code{set-breakpoint!} has been introduced, we
|
|
||||||
can reveal that @code{break!}, @code{trace!} and @code{trace-subtree!}
|
|
||||||
are in fact just wrappers for @code{set-breakpoint!} that specify
|
|
||||||
particular breakpoint behaviours, respectively @code{debug-here},
|
|
||||||
@code{trace-here} and @code{trace-subtree}.
|
|
||||||
|
|
||||||
@smalllisp
|
|
||||||
(break! . @var{args})
|
|
||||||
@equiv{} (set-breakpoint! debug-here . @var{args})
|
|
||||||
(trace! . @var{args})
|
|
||||||
@equiv{} (set-breakpoint! trace-here . @var{args})
|
|
||||||
(trace-subtree! . @var{args})
|
|
||||||
@equiv{} (set-breakpoint! trace-subtree . @var{args})
|
|
||||||
@end smalllisp
|
|
||||||
|
|
||||||
This means that these three procedures can be used to set the
|
|
||||||
corresponding behaviours for any type of breakpoint for which a
|
|
||||||
@code{set-breakpoint!} method exists, not just procedural ones.
|
|
||||||
|
|
||||||
|
|
||||||
@node Accessing Breakpoints
|
|
||||||
@subsubsection Accessing Breakpoints
|
|
||||||
|
|
||||||
Information about the state and behaviour of a breakpoint is stored in
|
|
||||||
an instance of the appropriate breakpoint class. To access and change
|
|
||||||
that information, therefore, you need to get hold of the desired
|
|
||||||
breakpoint instance.
|
|
||||||
|
|
||||||
The generic function @code{get-breakpoint} meets this need: For every
|
|
||||||
@code{set-breakpoint!} method there is a corresponding
|
|
||||||
@code{get-breakpoint} method. Note especially the useful
|
|
||||||
type-independent case:
|
|
||||||
|
|
||||||
@smalllisp
|
|
||||||
(get-breakpoint 1)
|
|
||||||
@result{}
|
|
||||||
#<<procedure-breakpoint> 808b0b0>
|
|
||||||
@end smalllisp
|
|
||||||
|
|
||||||
|
|
||||||
@node Breakpoint Behaviours
|
|
||||||
@subsubsection Breakpoint Behaviours
|
|
||||||
|
|
||||||
A breakpoint's @dfn{behaviour} determines what happens when that
|
|
||||||
breakpoint is hit. Several kinds of behaviour are generally useful.
|
|
||||||
|
|
||||||
@table @code
|
|
||||||
@item debug-here
|
|
||||||
Enter the command line debugger. This gives the opportunity to explore
|
|
||||||
the stack, evaluate expressions in any of the pending stack frames,
|
|
||||||
change breakpoint properties or set new breakpoints, and continue
|
|
||||||
program execution when you are done.
|
|
||||||
|
|
||||||
@item trace-here
|
|
||||||
Trace the current stack frame. For expressions being evaluated, this
|
|
||||||
shows the expression. For procedure applications, it shows the
|
|
||||||
procedure name and its arguments @emph{post-evaluation}. For both
|
|
||||||
expressions and applications, the indentation of the tracing indicates
|
|
||||||
whether the traced items are mutually tail recursive.
|
|
||||||
|
|
||||||
@item trace-subtree
|
|
||||||
Trace the current stack frame, and enable tracing for all future
|
|
||||||
evaluations and applications until the current stack frame is exited.
|
|
||||||
@code{trace-subtree} is a great preliminary exploration tool when all
|
|
||||||
you know is that there is a bug ``somewhere in XXX or in something that
|
|
||||||
XXX calls''.
|
|
||||||
|
|
||||||
@item (at-exit @var{thunk})
|
|
||||||
Don't do anything now, but arrange for @var{thunk} to be executed when
|
|
||||||
the current stack frame is exited. For example, the operation that most
|
|
||||||
debugging tools call ``finish'' is @code{(at-exit debug-here)}.
|
|
||||||
|
|
||||||
@item (at-next @var{count} @var{thunk})
|
|
||||||
@dots{} arrange for @var{thunk} to be executed when beginning the
|
|
||||||
@var{count}th next evaluation or application with source location in the
|
|
||||||
current file.
|
|
||||||
|
|
||||||
@item (at-entry @var{count} @var{thunk})
|
|
||||||
@dots{} arrange for @var{thunk} to be executed when beginning the
|
|
||||||
@var{count}th next evaluation (regardless of source location).
|
|
||||||
|
|
||||||
@item (at-apply @var{count} @var{thunk})
|
|
||||||
@dots{} arrange for @var{thunk} to be executed just before performing
|
|
||||||
the @var{count}th next application (regardless of source location).
|
|
||||||
|
|
||||||
@item (at-step @var{count} @var{thunk})
|
|
||||||
Synthesis of @code{at-entry} and @code{at-apply}; counts both
|
|
||||||
evaluations and applications.
|
|
||||||
@end table
|
|
||||||
|
|
||||||
Every breakpoint instance has a slot in which its behaviour is stored.
|
|
||||||
If you have a breakpoint instance in hand, you can change its behaviour
|
|
||||||
using the @code{bp-behaviour} accessor.
|
|
||||||
|
|
||||||
An @dfn{accessor} supports the setting of a property like this:
|
|
||||||
|
|
||||||
@smalllisp
|
|
||||||
(set! (bp-behaviour @var{breakpoint}) @var{new-behaviour})
|
|
||||||
@end smalllisp
|
|
||||||
|
|
||||||
@noindent
|
|
||||||
See the GOOPS manual for further information on accessors.
|
|
||||||
|
|
||||||
Alternatively, if you know how to specify the @var{location-args} for
|
|
||||||
the breakpoint in question, you can change its behaviour using
|
|
||||||
@code{set-breakpoint!}. For example:
|
|
||||||
|
|
||||||
@smalllisp
|
|
||||||
;; Change behaviour of breakpoint number 2.
|
|
||||||
(set-breakpoint! @var{new-behaviour} 2)
|
|
||||||
|
|
||||||
;; Change behaviour of procedural breakpoint on [fact1].
|
|
||||||
(set-breakpoint! @var{new-behaviour} fact1)
|
|
||||||
@end smalllisp
|
|
||||||
|
|
||||||
In all cases, the behaviour that you specify should be either a single
|
|
||||||
thunk, or a list of thunks, to be called when the breakpoint is hit.
|
|
||||||
|
|
||||||
The most common behaviours above are exported as thunks from the
|
|
||||||
@code{(ice-9 debugger behaviour)} module. So, if you use this module, you can
|
|
||||||
use those behaviours directly like this:
|
|
||||||
|
|
||||||
@smalllisp
|
|
||||||
(use-modules (ice-9 debugger behaviour))
|
|
||||||
(set-breakpoint! trace-subtree 2)
|
|
||||||
(set! (bp-behaviour (get-breakpoint 3)) debug-here)
|
|
||||||
@end smalllisp
|
|
||||||
|
|
||||||
@noindent
|
|
||||||
You can also use the list option to combine common behaviours:
|
|
||||||
|
|
||||||
@smalllisp
|
|
||||||
(set-breakpoint! (list trace-here debug-here) 2)
|
|
||||||
@end smalllisp
|
|
||||||
|
|
||||||
@noindent
|
|
||||||
Or, for more customized behaviour, you could build and use your own
|
|
||||||
thunk like this:
|
|
||||||
|
|
||||||
@smalllisp
|
|
||||||
(define (my-behaviour)
|
|
||||||
(trace-here)
|
|
||||||
(at-exit (lambda ()
|
|
||||||
(display "Exiting frame of my-behaviour bp\n")
|
|
||||||
... do something unusual ...)))
|
|
||||||
|
|
||||||
(set-breakpoint my-behaviour 2)
|
|
||||||
@end smalllisp
|
|
||||||
|
|
||||||
|
|
||||||
@node Enabling and Disabling
|
|
||||||
@subsubsection Enabling and Disabling
|
|
||||||
|
|
||||||
Independently of its behaviour, each breakpoint also keeps track of
|
|
||||||
whether it is currently enabled. This is a straightforward convenience
|
|
||||||
to allow breakpoints to be temporarily switched off without losing all
|
|
||||||
their carefully constructed properties.
|
|
||||||
|
|
||||||
If you have a breakpoint instance in hand, you can enable or disable it
|
|
||||||
using the @code{bp-enabled?} accessor.
|
|
||||||
|
|
||||||
Alternatively, you can enable or disable a breakpoint via its location
|
|
||||||
args by using @code{enable-breakpoint!} or @code{disable-breakpoint!}.
|
|
||||||
|
|
||||||
@smalllisp
|
|
||||||
(disable-breakpoint! fact1) ; disable the procedural breakpoint on fact1
|
|
||||||
(enable-breakpoint! 1) ; enable breakpoint 1
|
|
||||||
@end smalllisp
|
|
||||||
|
|
||||||
@code{enable-breakpoint!} and @code{disable-breakpoint!} are implemented
|
|
||||||
using @code{get-breakpoint} and @code{bp-enabled?}, so any
|
|
||||||
@var{location-args} that are valid for @code{get-breakpoint} will work
|
|
||||||
also for these procedures.
|
|
||||||
|
|
||||||
|
|
||||||
@node Deleting Breakpoints
|
|
||||||
@subsubsection Deleting Breakpoints
|
|
||||||
|
|
||||||
Given a breakpoint instance in hand, you can deactivate it and remove
|
|
||||||
it from the global list of current breakpoints by calling
|
|
||||||
@code{bp-delete!}.
|
|
||||||
|
|
||||||
Alternatively, you can delete a breakpoint by its location args:
|
|
||||||
|
|
||||||
@smalllisp
|
|
||||||
(delete-breakpoint! 1) ; delete breakpoint 1
|
|
||||||
@end smalllisp
|
|
||||||
|
|
||||||
@code{delete-breakpoint!} is implemented using @code{get-breakpoint} and
|
|
||||||
@code{bp-delete!}, so any @var{location-args} that are valid for
|
|
||||||
@code{get-breakpoint} will work also for @code{delete-breakpoint!}.
|
|
||||||
|
|
||||||
There is no way to reinstate a deleted breakpoint. Final destruction of
|
|
||||||
the breakpoint instance is determined by the usual garbage collection
|
|
||||||
rules.
|
|
||||||
|
|
||||||
|
|
||||||
@node Breakpoint Information
|
|
||||||
@subsubsection Breakpoint Information
|
|
||||||
|
|
||||||
To get Guile to print a description of a breakpoint instance, use
|
|
||||||
@code{bp-describe}:
|
|
||||||
|
|
||||||
@smalllisp
|
|
||||||
(bp-describe (get-breakpoint 1) #t) ; #t specifies standard output
|
|
||||||
@print{}
|
|
||||||
Breakpoint 1: [fact1]
|
|
||||||
enabled? = #t
|
|
||||||
behaviour = #<procedure trace-here ()>
|
|
||||||
@end smalllisp
|
|
||||||
|
|
||||||
Following the usual model, @code{describe-breakpoint} is also provided:
|
|
||||||
|
|
||||||
@smalllisp
|
|
||||||
(describe-breakpoint 1)
|
|
||||||
@print{}
|
|
||||||
Breakpoint 1: [fact1]
|
|
||||||
enabled? = #t
|
|
||||||
behaviour = #<procedure trace-here ()>
|
|
||||||
@end smalllisp
|
|
||||||
|
|
||||||
Finally, two stragglers. @code{all-breakpoints} returns a list of all
|
|
||||||
current breakpoints. @code{describe-all-breakpoints} combines
|
|
||||||
@code{bp-describe} and @code{all-breakpoints} by printing a description
|
|
||||||
of all current breakpoints to standard output.
|
|
||||||
|
|
||||||
@node Other Breakpoint Types
|
|
||||||
@subsubsection Other Breakpoint Types
|
|
||||||
|
|
||||||
Besides source and procedural breakpoints, Guile includes an early
|
|
||||||
implementation of a third class of breakpoints: @dfn{range} breakpoints.
|
|
||||||
These are breakpoints that trigger when program execution enters (or
|
|
||||||
perhaps exits) a defined range of source locations.
|
|
||||||
|
|
||||||
Sadly, these don't yet work well. The apparent problem is that the
|
|
||||||
extra methods for @code{set-breakpoint!} and @code{get-breakpoint} cause
|
|
||||||
some kind of explosion in the time taken by GOOPS to construct its
|
|
||||||
method cache and to dispatch calls involving these generic functions.
|
|
||||||
But we haven't really investigated enough to be sure that this is the
|
|
||||||
real issue.
|
|
||||||
|
|
||||||
If you're interested in looking and/or investigating anyway, please feel
|
|
||||||
free to check out and play with the @code{(ice-9 debugger breakpoints
|
|
||||||
range)} module.
|
|
||||||
|
|
||||||
The other kind of breakpoint that we'd like to have is watchpoints, but
|
|
||||||
this hasn't been implemented at all yet. Watchpoints may turn out to be
|
|
||||||
impractical for performance reasons.
|
|
||||||
|
|
||||||
|
|
||||||
@node Interactive Debugger
|
|
||||||
@subsection Using the Interactive Debugger
|
|
||||||
|
|
||||||
Guile's interactive debugger is a command line application that accepts
|
|
||||||
commands from you for examining the stack and, if at a breakpoint, for
|
|
||||||
continuing program execution in various ways. Unlike in the normal
|
|
||||||
Guile REPL, commands are typed mostly without parentheses.
|
|
||||||
|
|
||||||
When you first enter the debugger, it introduces itself with a message
|
|
||||||
like this:
|
|
||||||
|
|
||||||
@lisp
|
|
||||||
This is the Guile debugger -- for help, type `help'.
|
|
||||||
There are 3 frames on the stack.
|
|
||||||
|
|
||||||
Frame 2 at standard input:36:19
|
|
||||||
[+ 3 #\s]
|
|
||||||
debug>
|
|
||||||
@end lisp
|
|
||||||
|
|
||||||
@noindent
|
|
||||||
``debug>'' is the debugger's prompt, and a useful reminder that you are
|
|
||||||
not in the normal Guile REPL. The available commands are described in
|
|
||||||
detail in the following subsections.
|
|
||||||
|
|
||||||
@menu
|
|
||||||
* Display Backtrace:: backtrace.
|
|
||||||
* Frame Selection:: up, down, frame.
|
|
||||||
* Frame Information:: info args, info frame, position.
|
|
||||||
* Frame Evaluation:: evaluate.
|
|
||||||
* Single Stepping:: step, next.
|
|
||||||
* Run To Frame Exit:: finish, trace-finish.
|
|
||||||
* Continue Execution:: continue.
|
|
||||||
* Leave Debugger:: quit.
|
|
||||||
@end menu
|
|
||||||
|
|
||||||
|
|
||||||
@node Display Backtrace
|
|
||||||
@subsubsection Display Backtrace
|
|
||||||
|
|
||||||
The @code{backtrace} command, which can also be invoked as @code{bt} or
|
|
||||||
@code{where}, displays the call stack (aka backtrace) at the point where
|
|
||||||
the debugger was entered:
|
|
||||||
|
|
||||||
@lisp
|
|
||||||
debug> bt
|
|
||||||
In standard input:
|
|
||||||
36: 0* [make-string ...
|
|
||||||
36: 1* [* 4 ...
|
|
||||||
36: 2* [+ 3 #\s]
|
|
||||||
@end lisp
|
|
||||||
|
|
||||||
@deffn {Debugger Command} backtrace [count]
|
|
||||||
@deffnx {Debugger Command} bt [count]
|
|
||||||
@deffnx {Debugger Command} where [count]
|
|
||||||
Print backtrace of all stack frames, or of the innermost @var{count}
|
|
||||||
frames. With a negative argument, print the outermost -@var{count}
|
|
||||||
frames. If the number of frames isn't explicitly given, the debug
|
|
||||||
option @code{depth} determines the maximum number of frames printed.
|
|
||||||
@end deffn
|
|
||||||
|
|
||||||
The format of the displayed backtrace is the same as for the
|
|
||||||
@code{backtrace} procedure --- see @ref{Backtrace Format} for details.
|
|
||||||
|
|
||||||
|
|
||||||
@node Frame Selection
|
|
||||||
@subsubsection Frame Selection
|
|
||||||
|
|
||||||
A call stack consists of a sequence of stack @dfn{frames}, with each
|
|
||||||
frame describing one level of the nested evaluations and applications
|
|
||||||
that the program was executing when it hit a breakpoint or an error.
|
|
||||||
Frames are numbered such that frame 0 is the outermost --- i.e. the
|
|
||||||
operation on the call stack that began least recently --- and frame N-1
|
|
||||||
the innermost (where N is the total number of frames on the stack).
|
|
||||||
|
|
||||||
When you enter the debugger, the innermost frame is selected, which
|
|
||||||
means that the commands for getting information about the ``current''
|
|
||||||
frame, or for evaluating expressions in the context of the current
|
|
||||||
frame, will do so by default with respect to the innermost frame. To
|
|
||||||
select a different frame, so that these operations will apply to it
|
|
||||||
instead, use the @code{up}, @code{down} and @code{frame} commands like
|
|
||||||
this:
|
|
||||||
|
|
||||||
@lisp
|
|
||||||
debug> up
|
|
||||||
Frame 1 at standard input:36:14
|
|
||||||
[* 4 ...
|
|
||||||
debug> frame 0
|
|
||||||
Frame 0 at standard input:36:1
|
|
||||||
[make-string ...
|
|
||||||
debug> down
|
|
||||||
Frame 1 at standard input:36:14
|
|
||||||
[* 4 ...
|
|
||||||
@end lisp
|
|
||||||
|
|
||||||
@deffn {Debugger Command} up [n]
|
|
||||||
Move @var{n} frames up the stack. For positive @var{n}, this
|
|
||||||
advances toward the outermost frame, to higher frame numbers, to
|
|
||||||
frames that have existed longer. @var{n} defaults to one.
|
|
||||||
@end deffn
|
|
||||||
|
|
||||||
@deffn {Debugger Command} down [n]
|
|
||||||
Move @var{n} frames down the stack. For positive @var{n}, this
|
|
||||||
advances toward the innermost frame, to lower frame numbers, to frames
|
|
||||||
that were created more recently. @var{n} defaults to one.
|
|
||||||
@end deffn
|
|
||||||
|
|
||||||
@deffn {Debugger Command} frame [n]
|
|
||||||
Select and print a stack frame. With no argument, print the selected
|
|
||||||
stack frame. (See also ``info frame''.) An argument specifies the
|
|
||||||
frame to select; it must be a stack-frame number.
|
|
||||||
@end deffn
|
|
||||||
|
|
||||||
|
|
||||||
@node Frame Information
|
|
||||||
@subsubsection Frame Information
|
|
||||||
|
|
||||||
[to be completed]
|
|
||||||
|
|
||||||
@deffn {Debugger Command} {info frame}
|
|
||||||
All about selected stack frame.
|
|
||||||
@end deffn
|
|
||||||
|
|
||||||
@deffn {Debugger Command} {info args}
|
|
||||||
Argument variables of current stack frame.
|
|
||||||
@end deffn
|
|
||||||
|
|
||||||
@deffn {Debugger Command} position
|
|
||||||
Display the position of the current expression.
|
|
||||||
@end deffn
|
|
||||||
|
|
||||||
|
|
||||||
@node Frame Evaluation
|
|
||||||
@subsubsection Frame Evaluation
|
|
||||||
|
|
||||||
[to be completed]
|
|
||||||
|
|
||||||
@deffn {Debugger Command} evaluate expression
|
|
||||||
Evaluate an expression.
|
|
||||||
The expression must appear on the same line as the command,
|
|
||||||
however it may be continued over multiple lines.
|
|
||||||
@end deffn
|
|
||||||
|
|
||||||
|
|
||||||
@node Single Stepping
|
|
||||||
@subsubsection Single Stepping
|
|
||||||
|
|
||||||
[to be completed]
|
|
||||||
|
|
||||||
@deffn {Debugger Command} step [n]
|
|
||||||
Continue until entry to @var{n}th next frame.
|
|
||||||
@end deffn
|
|
||||||
|
|
||||||
@deffn {Debugger Command} next [n]
|
|
||||||
Continue until entry to @var{n}th next frame in same file.
|
|
||||||
@end deffn
|
|
||||||
|
|
||||||
|
|
||||||
@node Run To Frame Exit
|
|
||||||
@subsubsection Run To Frame Exit
|
|
||||||
|
|
||||||
[to be completed]
|
|
||||||
|
|
||||||
@deffn {Debugger Command} finish
|
|
||||||
Continue until evaluation of the current frame is complete, and
|
|
||||||
print the result obtained.
|
|
||||||
@end deffn
|
|
||||||
|
|
||||||
@deffn {Debugger Command} trace-finish
|
|
||||||
Trace until evaluation of the current frame is complete.
|
|
||||||
@end deffn
|
|
||||||
|
|
||||||
|
|
||||||
@node Continue Execution
|
|
||||||
@subsubsection Continue Execution
|
|
||||||
|
|
||||||
[to be completed]
|
|
||||||
|
|
||||||
@deffn {Debugger Command} continue
|
|
||||||
Continue program execution.
|
|
||||||
@end deffn
|
|
||||||
|
|
||||||
|
|
||||||
@node Leave Debugger
|
|
||||||
@subsubsection Leave Debugger
|
|
||||||
|
|
||||||
[to be completed]
|
|
||||||
|
|
||||||
@deffn {Debugger Command} quit
|
|
||||||
Exit the debugger.
|
|
||||||
@end deffn
|
|
||||||
|
|
||||||
|
|
||||||
@node Tracing
|
@node Tracing
|
||||||
@subsection Tracing
|
@subsection Tracing
|
||||||
|
|
||||||
Tracing has already been described as a breakpoint behaviour
|
Tracing has already been described as a breakpoint behaviour, but we
|
||||||
(@pxref{Breakpoint Behaviours}), but we mention it again here because it
|
mention it again here because it is so useful, and because Guile
|
||||||
is so useful, and because Guile actually now has @emph{two} mechanisms
|
actually now has @emph{two} mechanisms for tracing, and its worth
|
||||||
for tracing, and its worth clarifying the differences between them.
|
clarifying the differences between them.
|
||||||
|
|
||||||
@menu
|
@menu
|
||||||
* Old Tracing:: Tracing provided by (ice-9 debug).
|
* Old Tracing:: Tracing provided by (ice-9 debug).
|
||||||
|
|
411
doc/ref/scheme-using.texi
Normal file
411
doc/ref/scheme-using.texi
Normal file
|
@ -0,0 +1,411 @@
|
||||||
|
@c -*-texinfo-*-
|
||||||
|
@c This is part of the GNU Guile Reference Manual.
|
||||||
|
@c Copyright (C) 2006
|
||||||
|
@c Free Software Foundation, Inc.
|
||||||
|
@c See the file guile.texi for copying conditions.
|
||||||
|
|
||||||
|
@node Using Guile Interactively
|
||||||
|
@section Using Guile Interactively
|
||||||
|
|
||||||
|
When you start up Guile by typing just @code{guile}, without a
|
||||||
|
@code{-c} argument or the name of a script to execute, you get an
|
||||||
|
interactive interpreter where you can enter Scheme expressions, and
|
||||||
|
Guile will evaluate them and print the results for you. Here are some
|
||||||
|
simple examples.
|
||||||
|
|
||||||
|
@lisp
|
||||||
|
guile> (+ 3 4 5)
|
||||||
|
12
|
||||||
|
guile> (display "Hello world!\n")
|
||||||
|
Hello world!
|
||||||
|
guile> (values 'a 'b)
|
||||||
|
a
|
||||||
|
b
|
||||||
|
@end lisp
|
||||||
|
|
||||||
|
@noindent
|
||||||
|
This mode of use is called a @dfn{REPL}, which is short for
|
||||||
|
``Read-Eval-Print Loop'', because the Guile interpreter first reads the
|
||||||
|
expression that you have typed, then evaluates it, and then prints the
|
||||||
|
result.
|
||||||
|
|
||||||
|
@menu
|
||||||
|
* Readline::
|
||||||
|
* Value Historyx::
|
||||||
|
* Error Handling::
|
||||||
|
* Interactive Debugger:: Using the interactive debugger.
|
||||||
|
@end menu
|
||||||
|
|
||||||
|
|
||||||
|
@node Readline
|
||||||
|
@subsection Readline
|
||||||
|
|
||||||
|
To make it easier for you to repeat and vary previously entered
|
||||||
|
expressions, or to edit the expression that you're typing in, Guile
|
||||||
|
can use the GNU Readline library. This is not enabled by default
|
||||||
|
because of licensing reasons, but all you need to activate Readline is
|
||||||
|
the following pair of lines.
|
||||||
|
|
||||||
|
@lisp
|
||||||
|
guile> (use-modules (ice-9 readline))
|
||||||
|
guile> (activate-readline)
|
||||||
|
@end lisp
|
||||||
|
|
||||||
|
It's a good idea to put these two lines (without the ``guile>''
|
||||||
|
prompts) in your @file{.guile} file. Guile reads this file when it
|
||||||
|
starts up interactively, so anything in this file has the same effect
|
||||||
|
as if you type it in by hand at the ``guile>'' prompt.
|
||||||
|
|
||||||
|
|
||||||
|
@node Value Historyx
|
||||||
|
@subsection Value History
|
||||||
|
|
||||||
|
Just as Readline helps you to reuse a previous input line, @dfn{value
|
||||||
|
history} allows you to use the @emph{result} of a previous evaluation
|
||||||
|
in a new expression. When value history is enabled, each evaluation
|
||||||
|
result is automatically assigned to the next in the sequence of
|
||||||
|
variables @code{$1}, @code{$2}, @dots{}, and you can then use these
|
||||||
|
variables in subsequent expressions.
|
||||||
|
|
||||||
|
@lisp
|
||||||
|
guile> (iota 10)
|
||||||
|
$1 = (0 1 2 3 4 5 6 7 8 9)
|
||||||
|
guile> (apply * (cdr $1))
|
||||||
|
$2 = 362880
|
||||||
|
guile> (sqrt $2)
|
||||||
|
$3 = 602.3952191045344
|
||||||
|
guile> (cons $2 $1)
|
||||||
|
$4 = (362880 0 1 2 3 4 5 6 7 8 9)
|
||||||
|
@end lisp
|
||||||
|
|
||||||
|
To enable value history, type @code{(use-modules (ice-9 history))} at
|
||||||
|
the Guile prompt, or add this to your @file{.guile} file. (It is not
|
||||||
|
enabled by default, to avoid the possibility of conflicting with some
|
||||||
|
other use you may have for the variables @code{$1}, @code{$2},
|
||||||
|
@dots{}, and also because it prevents the stored evaluation results
|
||||||
|
from being garbage collected, which some people may not want.)
|
||||||
|
|
||||||
|
|
||||||
|
@node Error Handling
|
||||||
|
@subsection Error Handling
|
||||||
|
|
||||||
|
When code being evaluated from the REPL hits an error, Guile remembers
|
||||||
|
the execution context where the error occurred and can give you three
|
||||||
|
levels of information about what the error was and exactly where it
|
||||||
|
occurred.
|
||||||
|
|
||||||
|
By default, Guile then displays only the first level, which is the most
|
||||||
|
immediate information about where and why the error occurred, for
|
||||||
|
example:
|
||||||
|
|
||||||
|
@lisp
|
||||||
|
(make-string (* 4 (+ 3 #\s)) #\space)
|
||||||
|
@print{}
|
||||||
|
standard input:2:19: In procedure + in expression (+ 3 #\s):
|
||||||
|
standard input:2:19: Wrong type argument: #\s
|
||||||
|
ABORT: (wrong-type-arg)
|
||||||
|
|
||||||
|
Type "(backtrace)" to get more information or "(debug)" to enter the debugger.
|
||||||
|
@end lisp
|
||||||
|
|
||||||
|
@noindent
|
||||||
|
However, as the message above says, you can obtain more information
|
||||||
|
about the context of the error by typing @code{(backtrace)} or
|
||||||
|
@code{(debug)}.
|
||||||
|
|
||||||
|
@code{(backtrace)} displays the Scheme call stack at the point where the
|
||||||
|
error occurred:
|
||||||
|
|
||||||
|
@lisp
|
||||||
|
(backtrace)
|
||||||
|
@print{}
|
||||||
|
Backtrace:
|
||||||
|
In standard input:
|
||||||
|
2: 0* [make-string ...
|
||||||
|
2: 1* [* 4 ...
|
||||||
|
2: 2* [+ 3 #\s]
|
||||||
|
|
||||||
|
Type "(debug-enable 'backtrace)" if you would like a backtrace
|
||||||
|
automatically if an error occurs in the future.
|
||||||
|
@end lisp
|
||||||
|
|
||||||
|
@noindent
|
||||||
|
In a more complex scenario than this one, this can be extremely useful
|
||||||
|
for understanding where and why the error occurred. You can make Guile
|
||||||
|
show the backtrace automatically by adding @code{(debug-enable
|
||||||
|
'backtrace)} to your @file{.guile}.
|
||||||
|
|
||||||
|
@code{(debug)} takes you into Guile's interactive debugger, which
|
||||||
|
provides commands that allow you to
|
||||||
|
|
||||||
|
@itemize @bullet
|
||||||
|
@item
|
||||||
|
display the Scheme call stack at the point where the error occurred
|
||||||
|
(the @code{backtrace} command --- see @ref{Display Backtrace})
|
||||||
|
|
||||||
|
@item
|
||||||
|
move up and down the call stack, to see in detail the expression being
|
||||||
|
evaluated, or the procedure being applied, in each @dfn{frame} (the
|
||||||
|
@code{up}, @code{down}, @code{frame}, @code{position}, @code{info args}
|
||||||
|
and @code{info frame} commands --- see @ref{Frame Selection} and
|
||||||
|
@ref{Frame Information})
|
||||||
|
|
||||||
|
@item
|
||||||
|
examine the values of variables and expressions in the context of each
|
||||||
|
frame (the @code{evaluate} command --- see @ref{Frame Evaluation}).
|
||||||
|
@end itemize
|
||||||
|
|
||||||
|
@noindent
|
||||||
|
This is documented further in the following section.
|
||||||
|
|
||||||
|
|
||||||
|
@node Interactive Debugger
|
||||||
|
@subsection Using the Interactive Debugger
|
||||||
|
|
||||||
|
Guile's interactive debugger is a command line application that accepts
|
||||||
|
commands from you for examining the stack and, if at a breakpoint, for
|
||||||
|
continuing program execution in various ways. Unlike in the normal
|
||||||
|
Guile REPL, commands are typed mostly without parentheses.
|
||||||
|
|
||||||
|
When you first enter the debugger, it introduces itself with a message
|
||||||
|
like this:
|
||||||
|
|
||||||
|
@lisp
|
||||||
|
This is the Guile debugger -- for help, type `help'.
|
||||||
|
There are 3 frames on the stack.
|
||||||
|
|
||||||
|
Frame 2 at standard input:36:19
|
||||||
|
[+ 3 #\s]
|
||||||
|
debug>
|
||||||
|
@end lisp
|
||||||
|
|
||||||
|
@noindent
|
||||||
|
``debug>'' is the debugger's prompt, and a reminder that you are not in
|
||||||
|
the normal Guile REPL. The available commands are described in the
|
||||||
|
following subsections.
|
||||||
|
|
||||||
|
@menu
|
||||||
|
* Display Backtrace:: backtrace.
|
||||||
|
* Frame Selection:: up, down, frame.
|
||||||
|
* Frame Information:: info args, info frame, position.
|
||||||
|
* Frame Evaluation:: evaluate.
|
||||||
|
* Single Stepping:: step, next.
|
||||||
|
* Run To Frame Exit:: finish, trace-finish.
|
||||||
|
* Continue Execution:: continue.
|
||||||
|
* Leave Debugger:: quit.
|
||||||
|
@end menu
|
||||||
|
|
||||||
|
|
||||||
|
@node Display Backtrace
|
||||||
|
@subsubsection Display Backtrace
|
||||||
|
|
||||||
|
The @code{backtrace} command, which can also be invoked as @code{bt} or
|
||||||
|
@code{where}, displays the call stack (aka backtrace) at the point where
|
||||||
|
the debugger was entered:
|
||||||
|
|
||||||
|
@lisp
|
||||||
|
debug> bt
|
||||||
|
In standard input:
|
||||||
|
36: 0* [make-string ...
|
||||||
|
36: 1* [* 4 ...
|
||||||
|
36: 2* [+ 3 #\s]
|
||||||
|
@end lisp
|
||||||
|
|
||||||
|
@deffn {Debugger Command} backtrace [count]
|
||||||
|
@deffnx {Debugger Command} bt [count]
|
||||||
|
@deffnx {Debugger Command} where [count]
|
||||||
|
Print backtrace of all stack frames, or of the innermost @var{count}
|
||||||
|
frames. With a negative argument, print the outermost -@var{count}
|
||||||
|
frames. If the number of frames isn't explicitly given, the debug
|
||||||
|
option @code{depth} determines the maximum number of frames printed.
|
||||||
|
@end deffn
|
||||||
|
|
||||||
|
The format of the displayed backtrace is the same as for the
|
||||||
|
@code{backtrace} procedure.
|
||||||
|
|
||||||
|
|
||||||
|
@node Frame Selection
|
||||||
|
@subsubsection Frame Selection
|
||||||
|
|
||||||
|
A call stack consists of a sequence of stack @dfn{frames}, with each
|
||||||
|
frame describing one level of the nested evaluations and applications
|
||||||
|
that the program was executing when it hit a breakpoint or an error.
|
||||||
|
Frames are numbered such that frame 0 is the outermost --- i.e. the
|
||||||
|
operation on the call stack that began least recently --- and frame N-1
|
||||||
|
the innermost (where N is the total number of frames on the stack).
|
||||||
|
|
||||||
|
When you enter the debugger, the innermost frame is selected, which
|
||||||
|
means that the commands for getting information about the ``current''
|
||||||
|
frame, or for evaluating expressions in the context of the current
|
||||||
|
frame, will do so by default with respect to the innermost frame. To
|
||||||
|
select a different frame, so that these operations will apply to it
|
||||||
|
instead, use the @code{up}, @code{down} and @code{frame} commands like
|
||||||
|
this:
|
||||||
|
|
||||||
|
@lisp
|
||||||
|
debug> up
|
||||||
|
Frame 1 at standard input:36:14
|
||||||
|
[* 4 ...
|
||||||
|
debug> frame 0
|
||||||
|
Frame 0 at standard input:36:1
|
||||||
|
[make-string ...
|
||||||
|
debug> down
|
||||||
|
Frame 1 at standard input:36:14
|
||||||
|
[* 4 ...
|
||||||
|
@end lisp
|
||||||
|
|
||||||
|
@deffn {Debugger Command} up [n]
|
||||||
|
Move @var{n} frames up the stack. For positive @var{n}, this
|
||||||
|
advances toward the outermost frame, to higher frame numbers, to
|
||||||
|
frames that have existed longer. @var{n} defaults to one.
|
||||||
|
@end deffn
|
||||||
|
|
||||||
|
@deffn {Debugger Command} down [n]
|
||||||
|
Move @var{n} frames down the stack. For positive @var{n}, this
|
||||||
|
advances toward the innermost frame, to lower frame numbers, to frames
|
||||||
|
that were created more recently. @var{n} defaults to one.
|
||||||
|
@end deffn
|
||||||
|
|
||||||
|
@deffn {Debugger Command} frame [n]
|
||||||
|
Select and print a stack frame. With no argument, print the selected
|
||||||
|
stack frame. (See also ``info frame''.) An argument specifies the
|
||||||
|
frame to select; it must be a stack-frame number.
|
||||||
|
@end deffn
|
||||||
|
|
||||||
|
|
||||||
|
@node Frame Information
|
||||||
|
@subsubsection Frame Information
|
||||||
|
|
||||||
|
[to be completed]
|
||||||
|
|
||||||
|
@deffn {Debugger Command} {info frame}
|
||||||
|
All about selected stack frame.
|
||||||
|
@end deffn
|
||||||
|
|
||||||
|
@deffn {Debugger Command} {info args}
|
||||||
|
Argument variables of current stack frame.
|
||||||
|
@end deffn
|
||||||
|
|
||||||
|
@deffn {Debugger Command} position
|
||||||
|
Display the position of the current expression.
|
||||||
|
@end deffn
|
||||||
|
|
||||||
|
|
||||||
|
@node Frame Evaluation
|
||||||
|
@subsubsection Frame Evaluation
|
||||||
|
|
||||||
|
[to be completed]
|
||||||
|
|
||||||
|
@deffn {Debugger Command} evaluate expression
|
||||||
|
Evaluate an expression.
|
||||||
|
The expression must appear on the same line as the command,
|
||||||
|
however it may be continued over multiple lines.
|
||||||
|
@end deffn
|
||||||
|
|
||||||
|
|
||||||
|
@node Single Stepping
|
||||||
|
@subsubsection Single Stepping
|
||||||
|
|
||||||
|
[to be completed]
|
||||||
|
|
||||||
|
@deffn {Debugger Command} step [n]
|
||||||
|
Continue until entry to @var{n}th next frame.
|
||||||
|
@end deffn
|
||||||
|
|
||||||
|
@deffn {Debugger Command} next [n]
|
||||||
|
Continue until entry to @var{n}th next frame in same file.
|
||||||
|
@end deffn
|
||||||
|
|
||||||
|
|
||||||
|
@node Run To Frame Exit
|
||||||
|
@subsubsection Run To Frame Exit
|
||||||
|
|
||||||
|
[to be completed]
|
||||||
|
|
||||||
|
@deffn {Debugger Command} finish
|
||||||
|
Continue until evaluation of the current frame is complete, and
|
||||||
|
print the result obtained.
|
||||||
|
@end deffn
|
||||||
|
|
||||||
|
@deffn {Debugger Command} trace-finish
|
||||||
|
Trace until evaluation of the current frame is complete.
|
||||||
|
@end deffn
|
||||||
|
|
||||||
|
|
||||||
|
@node Continue Execution
|
||||||
|
@subsubsection Continue Execution
|
||||||
|
|
||||||
|
[to be completed]
|
||||||
|
|
||||||
|
@deffn {Debugger Command} continue
|
||||||
|
Continue program execution.
|
||||||
|
@end deffn
|
||||||
|
|
||||||
|
|
||||||
|
@node Leave Debugger
|
||||||
|
@subsubsection Leave Debugger
|
||||||
|
|
||||||
|
[to be completed]
|
||||||
|
|
||||||
|
@deffn {Debugger Command} quit
|
||||||
|
Exit the debugger.
|
||||||
|
@end deffn
|
||||||
|
|
||||||
|
|
||||||
|
@node Using Guile in Emacs
|
||||||
|
@section Using Guile in Emacs
|
||||||
|
|
||||||
|
The Guile distribution includes a rich environment for working on Guile
|
||||||
|
Scheme code within Emacs. The idea of this environment is to allow you
|
||||||
|
to work on Guile Scheme code in the same kind of way that Emacs allows
|
||||||
|
you to work on Emacs Lisp code: providing easy access to help,
|
||||||
|
evaluating arbitrary fragments of code, a nice debugging interface, and
|
||||||
|
so on.@footnote{You can also, of course, run a Guile session in Emacs
|
||||||
|
simply by typing ``guile'' in a @code{*shell*} buffer. The environment
|
||||||
|
described here provides a much better integration than that, though.}
|
||||||
|
|
||||||
|
The thinking behind this environment is that you will usually be doing
|
||||||
|
one of two things.
|
||||||
|
|
||||||
|
@enumerate
|
||||||
|
@item
|
||||||
|
Writing or editing code. The code will be in a normal Emacs Scheme
|
||||||
|
mode buffer, and the Guile/Emacs environment extends Scheme mode to
|
||||||
|
add keystrokes and menu items for the things that are likely to be
|
||||||
|
useful to you when working on code:
|
||||||
|
|
||||||
|
@itemize
|
||||||
|
@item
|
||||||
|
completing the identifier at point
|
||||||
|
@item
|
||||||
|
accessing Guile's built in help
|
||||||
|
@item
|
||||||
|
evaluating fragments of code to check what they do.
|
||||||
|
@end itemize
|
||||||
|
|
||||||
|
@item
|
||||||
|
Debugging a Guile Scheme program. When your program hits an error or
|
||||||
|
a breakpoint, the Guile/Emacs environment shows you the relevant code
|
||||||
|
and the Scheme stack, and makes it easy to
|
||||||
|
|
||||||
|
@itemize
|
||||||
|
@item
|
||||||
|
look at the values of local variables
|
||||||
|
@item
|
||||||
|
see what is happening at all levels of the Scheme stack
|
||||||
|
@item
|
||||||
|
continue execution, either normally or step by step.
|
||||||
|
@end itemize
|
||||||
|
@end enumerate
|
||||||
|
|
||||||
|
Combinations of these work well too. You can evaluate a fragment of
|
||||||
|
code (in a Scheme buffer) that contains a breakpoint, then use the
|
||||||
|
debugging interface to step through the code at the breakpoint. You
|
||||||
|
can also run a program until it hits a breakpoint, then examine,
|
||||||
|
modify and reevaluate some of the relevant code, and then tell the
|
||||||
|
program to continue running.
|
||||||
|
|
||||||
|
|
||||||
|
@c Local Variables:
|
||||||
|
@c TeX-master: "guile.texi"
|
||||||
|
@c End:
|
Loading…
Add table
Add a link
Reference in a new issue