@c -*-texinfo-*-
@c This is part of the GNU Guile Reference Manual.
-@c Copyright (C) 1996, 1997, 2000, 2001, 2002, 2003, 2004, 2007, 2010
+@c Copyright (C) 1996, 1997, 2000, 2001, 2002, 2003, 2004, 2007, 2010, 2011, 2012, 2013
@c Free Software Foundation, Inc.
@c See the file guile.texi for copying conditions.
* 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
Use @code{start-stack} to limit the stack extent captured by future
@code{make-stack} calls.
-@deffn {Scheme Procedure} make-stack obj . args
+@deffn {Scheme Procedure} make-stack obj arg @dots{}
@deffnx {C Function} scm_make_stack (obj, args)
Create a new stack. If @var{obj} is @code{#t}, the current
evaluation stack is used for creating the stack frames,
otherwise the frames are taken from @var{obj} (which must be
a continuation or a frame object).
-@var{args} should be a list containing any combination of
-integer, procedure, prompt tag and @code{#t} values.
+@var{arg} @dots{} can be any combination of integer, procedure, prompt
+tag and @code{#t} values.
These values specify various ways of cutting away uninteresting
stack frames from the top and bottom of the stack that
@code{(@var{inner_cut_1} @var{outer_cut_1} @var{inner_cut_2}
@var{outer_cut_2} @dots{})}.
-Each @var{inner_cut_N} can be @code{#t}, an integer, a prompt
+Each @var{inner_cut_i} can be @code{#t}, an integer, a prompt
tag, or a procedure. @code{#t} means to cut away all frames up
to but excluding the first user module frame. An integer means
to cut away exactly that number of frames. A prompt tag means
excluding the application frame whose procedure matches the
specified one.
-Each @var{outer_cut_N} can be an integer, a prompt tag, or a
+Each @var{outer_cut_i} can be an integer, a prompt tag, or a
procedure. An integer means to cut away that number of frames.
A prompt tag means to cut away all frames that are outside a
prompt with the given tag. A procedure means to cut away
frames down to but excluding the application frame whose
procedure matches the specified one.
-If the @var{outer_cut_N} of the last pair is missing, it is
+If the @var{outer_cut_i} of the last pair is missing, it is
taken as 0.
@end deffn
Guile's debugger can point back to the file and location where the
expression originated.
-The way that source properties are stored means that Guile can only
-associate source properties with parenthesized expressions, and not, for
-example, with individual symbols, numbers or strings. The difference
-can be seen by typing @code{(xxx)} and @code{xxx} at the Guile prompt
-(where the variable @code{xxx} has not been defined):
+The way that source properties are stored means that Guile cannot
+associate source properties with individual symbols, keywords,
+characters, booleans, or small integers. This can be seen by typing
+@code{(xxx)} and @code{xxx} at the Guile prompt (where the variable
+@code{xxx} has not been defined):
@example
scheme@@(guile-user)> (xxx)
In the latter case, no source properties were stored, so the error
doesn't have any source information.
+@deffn {Scheme Procedure} supports-source-properties? obj
+@deffnx {C Function} scm_supports_source_properties_p (obj)
+Return #t if source properties can be associated with @var{obj},
+otherwise return #f.
+@end deffn
+
The recording of source properties is controlled by the read option
named ``positions'' (@pxref{Scheme Read}). This option is switched
@emph{on} by default.
properties.
@end deffn
-If the @code{positions} reader option is enabled, each parenthesized
-expression will have values set for the @code{filename}, @code{line} and
+If the @code{positions} reader option is enabled, supported expressions
+will have values set for the @code{filename}, @code{line} and
@code{column} properties.
+Source properties are also associated with syntax objects. Procedural
+macros can get at the source location of their input using the
+@code{syntax-source} accessor. @xref{Syntax Transformer Helpers}, for
+more.
+
+Guile also defines a couple of convenience macros built on
+@code{syntax-source}:
+
+@deffn {Scheme Syntax} current-source-location
+Expands to the source properties corresponding to the location of the
+@code{(current-source-location)} form.
+@end deffn
+
+@deffn {Scheme Syntax} current-filename
+Expands to the current filename: the filename that the
+@code{(current-filename)} form appears in. Expands to @code{#f} if this
+information is unavailable.
+@end deffn
+
If you're stuck with defmacros (@pxref{Defmacros}), and want to preserve
source information, the following helper function might be useful to
you:
@deffn {Scheme Procedure} debug-enable option-name
@deffnx {Scheme Procedure} debug-disable option-name
-@deffnx {Scheme Procedure} debug-set! option-name value
+@deffnx {Scheme Syntax} debug-set! option-name value
Modify the debug options. @code{debug-enable} should be used with boolean
options and switches them on, @code{debug-disable} switches them off.
-@code{debug-set!} can be used to set an option to a specific value.
+
+@code{debug-set!} can be used to set an option to a specific value. Due
+to historical oddities, it is a macro that expects an unquoted option
+name.
@end deffn
@subsubheading Stack overflow
@lisp
scheme@@(guile-user)> (use-modules (system vm vm))
scheme@@(guile-user)> (debug-set! stack 10000)
-scheme@@(guile-user)> (let lp () (call-with-vm (the-vm) lp))
+scheme@@(guile-user)> (let lp () (call-with-vm lp))
ERROR: In procedure call-with-vm:
ERROR: Stack overflow
@end lisp
* Low-Level Traps:: The various kinds of low-level traps.
* Tracing Traps:: Traps to trace procedure calls and returns.
* Trap States:: One state (per thread) to bind them.
-* Trap Handlers:: What to do when a trap in a trap state fires.
-* Setting Traps:: The highest-level trap interface. Use this.
+* High-Level Traps:: The highest-level trap interface. Use this.
@end menu
fired at different times, which may be accessed with the following
procedures.
-All hooks are called with one argument, the frame in
-question. @xref{Frames}. Since these hooks may be fired very
-frequently, Guile does a terrible thing: it allocates the frames on the
-C stack instead of the garbage-collected heap.
+The first argument of calls to these hooks is the frame in question.
+@xref{Frames}. Some hooks may call their procedures with more
+arguments. Since these hooks may be fired very frequently, Guile does a
+terrible thing: it allocates the frames on the C stack instead of the
+garbage-collected heap.
The upshot here is that the frames are only valid within the dynamic
extent of the call to the hook. If a hook procedure keeps a reference to
@end example
@noindent
-The result of calling @code{the-vm} is usually passed as the @var{vm}
-argument to all of these procedures.
+All of these functions implicitly act on the VM for the current thread
+only.
-@deffn {Scheme Procedure} vm-next-hook vm
+@deffn {Scheme Procedure} vm-next-hook
The hook that will be fired before an instruction is retired (and
executed).
@end deffn
-@deffn {Scheme Procedure} vm-push-continuation-hook vm
+@deffn {Scheme Procedure} vm-push-continuation-hook
The hook that will be fired after preparing a new frame. Fires just
before applying a procedure in a non-tail context, just before the
corresponding apply-hook.
@end deffn
-@deffn {Scheme Procedure} vm-pop-continuation-hook vm
+@deffn {Scheme Procedure} vm-pop-continuation-hook
The hook that will be fired before returning from a frame.
-This hook is a bit trickier than the rest, in that there is a particular
-interpretation of the values on the stack. Specifically, the top value
-on the stack is the number of values being returned, and the next
-@var{n} values are the actual values being returned, with the last value
-highest on the stack.
+This hook fires with a variable number of arguments, corresponding to
+the values that the frame returns to its continuation.
@end deffn
-@deffn {Scheme Procedure} vm-apply-hook vm
+@deffn {Scheme Procedure} vm-apply-hook
The hook that will be fired before a procedure is applied. The frame's
procedure will have already been set to the new procedure.
hook.
@end deffn
-@deffn {Scheme Procedure} vm-abort-continuation-hook vm
+@deffn {Scheme Procedure} vm-abort-continuation-hook
The hook that will be called after aborting to a
-prompt. @xref{Prompts}. The stack will be in the same state as for
-@code{vm-pop-continuation-hook}.
+prompt. @xref{Prompts}.
+
+Like the pop-continuation hook, this hook fires with a variable number
+of arguments, corresponding to the values that returned to the
+continuation.
@end deffn
-@deffn {Scheme Procedure} vm-restore-continuation-hook vm
+@deffn {Scheme Procedure} vm-restore-continuation-hook
The hook that will be called after restoring an undelimited
continuation. Unfortunately it's not currently possible to introspect on
the values that were given to the continuation.
handling a hook. The trace level is restored to whatever it was once the hook
procedure finishes.
-@deffn {Scheme Procedure} vm-trace-level vm
+@deffn {Scheme Procedure} vm-trace-level
Retrieve the ``trace level'' of the VM. If positive, the trace hooks
associated with @var{vm} will be run. The initial trace level is 0.
@end deffn
-@deffn {Scheme Procedure} set-vm-trace-level! vm level
+@deffn {Scheme Procedure} set-vm-trace-level! level
Set the ``trace level'' of the VM.
@end deffn
Defaults to @code{#f}.
@end table
+To have access to these procedures, you'll need to have imported the
+@code{(system vm traps)} module:
+
+@lisp
+(use-modules (system vm traps))
+@end lisp
+
@deffn {Scheme Procedure} trap-at-procedure-call proc handler @
[#:vm] [#:closure?]
A trap that calls @var{handler} when @var{proc} is applied.
@deffn {Scheme Procedure} trap-instructions-in-dynamic-extent proc @
next-handler [#:current-frame] [#:vm] [#:closure?]
-A trap that calls @var{next-handler} for all retired intructions within
+A trap that calls @var{next-handler} for all retired instructions within
the dynamic extent of a call to @var{proc}.
@end deffn
trace: 24
@end lisp
-@deffn {Scheme Procedure} trace-calls-to-procedure proc #:key (width 80) (vm (the-vm)) (prefix "trace: "))
+The low-level traps below (@pxref{Low-Level Traps}) share some common
+options:
+
+@table @code
+@item #:width
+The maximum width of trace output. Trace printouts will try not to
+exceed this column, but for highly nested procedure calls, it may be
+unavoidable. Defaults to 80.
+@item #:vm
+The VM on which to add the traps. Defaults to the current thread's VM.
+@item #:prefix
+A string to print out before each trace line. As seen above in the
+examples, defaults to @code{"trace: "}.
+@end table
+
+To have access to these procedures, you'll need to have imported the
+@code{(system vm trace)} module:
+
+@lisp
+(use-modules (system vm trace))
+@end lisp
+
+@deffn {Scheme Procedure} trace-calls-to-procedure proc @
+ [#:width] [#:vm] [#:prefix]
+Print a trace at applications of and returns from @var{proc}.
@end deffn
-@deffn {Scheme Procedure} trace-calls-in-procedure proc #:key (width 80) (vm (the-vm)) (prefix "trace: "))
+@deffn {Scheme Procedure} trace-calls-in-procedure proc @
+ [#:width] [#:vm] [#:prefix]
+Print a trace at all applications and returns within the dynamic extent
+of calls to @var{proc}.
@end deffn
-@deffn {Scheme Procedure} trace-instructions-in-procedure proc #:key (width 80) (vm (the-vm))
+@deffn {Scheme Procedure} trace-instructions-in-procedure proc [#:width] [#:vm]
+Print a trace at all instructions executed in the dynamic extent of
+calls to @var{proc}.
@end deffn
In addition, Guile defines a procedure to call a thunk, tracing all
procedure calls and returns within the thunk.
-@deffn {Scheme Procedure} call-with-trace thunk #:key (calls? #t) (instructions? #f) (width 80) (vm (the-vm))
+@deffn {Scheme Procedure} call-with-trace thunk [#:calls?=#t] @
+ [#:instructions?=#f] @
+ [#:width=80]
Call @var{thunk}, tracing all execution within its dynamic extent.
If @var{calls?} is true, Guile will print a brief report at each
@node Trap States
@subsubsection Trap States
-@deffn {Scheme Procedure} list-traps
-@end deffn
+When multiple traps are present in a system, we begin to have a
+bookkeeping problem. How are they named? How does one disable, enable,
+or delete them?
-@deffn {Scheme Procedure} trap-name idx
-@end deffn
+Guile's answer to this is to keep an implicit per-thread @dfn{trap
+state}. The trap state object is not exposed to the user; rather, API
+that works on trap states fetches the current trap state from the
+dynamic environment.
-@deffn {Scheme Procedure} trap-enabled? idx
-@end deffn
+Traps are identified by integers. A trap can be enabled, disabled, or
+removed, and can have an associated user-visible name.
-@deffn {Scheme Procedure} enable-trap! idx
-@end deffn
+These procedures have their own module:
-@deffn {Scheme Procedure} disable-trap! idx
-@end deffn
-
-@deffn {Scheme Procedure} delete-trap! idx
-@end deffn
-
-@node Trap Handlers
-@subsubsection Trap Handlers
+@lisp
+(use-modules (system vm trap-state))
+@end lisp
-Trap Handlers What to do when a trap in a trap state fires.
+@deffn {Scheme Procedure} add-trap! trap name
+Add a trap to the current trap state, associating the given @var{name}
+with it. Returns a fresh trap identifier (an integer).
-@deffn {Scheme Procedure} with-default-trap-handler handler thunk
+Note that usually the more specific functions detailed in
+@ref{High-Level Traps} are used in preference to this one.
@end deffn
-@deffn {Scheme Procedure} install-trap-handler! handler
+@deffn {Scheme Procedure} list-traps
+List the current set of traps, both enabled and disabled. Returns a list
+of integers.
@end deffn
-@node Setting Traps
-@subsubsection Setting Traps
-
-@cindex Setting traps
-@cindex Installing and uninstalling traps
-Setting Traps The highest-level trap interface. Use this.
-
-@deffn {Scheme Procedure} add-trap-at-procedure-call! proc
+@deffn {Scheme Procedure} trap-name idx
+Returns the name associated with trap @var{idx}, or @code{#f} if there
+is no such trap.
@end deffn
-@deffn {Scheme Procedure} add-trace-at-procedure-call! proc
+@deffn {Scheme Procedure} trap-enabled? idx
+Returns @code{#t} if trap @var{idx} is present and enabled, or @code{#f}
+otherwise.
@end deffn
-@deffn {Scheme Procedure} add-trap-at-source-location! file user-line
+@deffn {Scheme Procedure} enable-trap! idx
+Enables trap @var{idx}.
@end deffn
-;; handler := frame -> nothing
-@deffn {Scheme Procedure} add-ephemeral-trap-at-frame-finish! frame handler
+@deffn {Scheme Procedure} disable-trap! idx
+Disables trap @var{idx}.
@end deffn
-@deffn {Scheme Procedure} add-ephemeral-stepping-trap! frame handler #:key (into? #t) (instruction? #f)
+@deffn {Scheme Procedure} delete-trap! idx
+Removes trap @var{idx}, disabling it first, if necessary.
@end deffn
+@node High-Level Traps
+@subsubsection High-Level Traps
-@node Debugging Examples
-@subsection Debugging Examples
-
-@c @node Tracing Examples
-@subsubheading Tracing Examples
+The low-level trap API allows one to make traps that call procedures,
+and the trap state API allows one to keep track of what traps are
+there. But neither of these APIs directly helps you when you want to
+set a breakpoint, because it's unclear what to do when the trap fires.
+Do you enter a debugger, or mail a summary of the situation to your
+great-aunt, or what?
-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.
+So for the common case in which you just want to install breakpoints,
+and then have them all result in calls to one parameterizable procedure,
+we have the high-level trap interface.
-@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.
+Perhaps we should have started this section with this interface, as it's
+clearly the one most people should use. But as its capabilities and
+limitations proceed from the lower layers, we felt that the
+character-building exercise of building a mental model might be helpful.
-In the next example, we probe the @emph{internal} workings of
-@code{rev} in more detail by using the @code{trace-until-exit}
-behaviour.
+These procedures share a module with trap states:
@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)
+(use-modules (system vm trap-state))
@end lisp
-@noindent
-The output in this case shows every step that the evaluator performs
-in evaluating @code{(rev '(a b))}.
+@deffn {Scheme Procedure} with-default-trap-handler handler thunk
+Call @var{thunk} in a dynamic context in which @var{handler} is the
+current trap handler.
+Additionally, during the execution of @var{thunk}, the VM trace level
+(@pxref{VM Hooks}) is set to the number of enabled traps. This ensures
+that traps will in fact fire.
-Here we present some examples of what you can do with the debugging
-facilities just described.
+@var{handler} may be @code{#f}, in which case VM hooks are not enabled
+as they otherwise would be, as there is nothing to handle the traps.
+@end deffn
-@subsubheading Single Stepping through a Procedure's Code
+The trace-level-setting behavior of @code{with-default-trap-handler} is
+one of its more useful aspects, but if you are willing to forgo that,
+and just want to install a global trap handler, there's a function for
+that too:
-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)}.
+@deffn {Scheme Procedure} install-trap-handler! handler
+Set the current thread's trap handler to @var{handler}.
+@end deffn
-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}.
+Trap handlers are called when traps installed by procedures from this
+module fire. The current ``consumer'' of this API is Guile's REPL, but
+one might easily imagine other trap handlers being used to integrate
+with other debugging tools.
-@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
+@cindex Breakpoints
+@cindex Setting breakpoints
+@deffn {Scheme Procedure} add-trap-at-procedure-call! proc
+Install a trap that will fire when @var{proc} is called.
-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.
+This is a breakpoint.
+@end deffn
+@cindex Tracepoints
+@cindex Setting tracepoints
+@deffn {Scheme Procedure} add-trace-at-procedure-call! proc
+Install a trap that will print a tracing message when @var{proc} is
+called. @xref{Tracing Traps}, for more information.
-@subsubheading Profiling or Tracing a Procedure's Code
+This is a tracepoint.
+@end deffn
-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.
+@deffn {Scheme Procedure} add-trap-at-source-location! file user-line
+Install a trap that will fire when control reaches the given source
+location. @var{user-line} is one-indexed, as users count lines, instead
+of zero-indexed, as Guile counts lines.
-@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 is a source breakpoint.
+@end deffn
-This example shows the default configuration for how each line of trace
-output is formatted, which is:
+@deffn {Scheme Procedure} add-ephemeral-trap-at-frame-finish! frame handler
+Install a trap that will call @var{handler} when @var{frame} finishes
+executing. The trap will be removed from the trap state after firing, or
+on nonlocal exit.
-@itemize
-@item
-the character @code{|}, a visual clue that the line is a line of trace
-output, followed by
+This is a finish trap, used to implement the ``finish'' REPL command.
+@end deffn
-@item
-a number indicating the real evaluator stack depth (where ``real'' means
-not counting tail-calls), followed by
+@deffn {Scheme Procedure} add-ephemeral-stepping-trap! frame handler [#:into?] [#:instruction?]
+Install a trap that will call @var{handler} after stepping to a
+different source line or instruction. The trap will be removed from the
+trap state after firing, or on nonlocal exit.
-@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
+If @var{instruction?} is false (the default), the trap will fire when
+control reaches a new source line. Otherwise it will fire when control
+reaches a new instruction.
-@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.
+Additionally, if @var{into?} is false (not the default), the trap will
+only fire for frames at or prior to the given frame. If @var{into?} is
+true (the default), the trap may step into nested procedure
+invocations.
+
+This is a stepping trap, used to implement the ``step'', ``next'',
+``step-instruction'', and ``next-instruction'' REPL commands.
+@end deffn
-@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"