X-Git-Url: http://git.hcoop.net/bpt/guile.git/blobdiff_plain/5db7c0bf4ae6266415b464f8e011209e7a7f55fd..1df515a077f26d59510e48fad3d45a33d2c90e0f:/doc/ref/api-debug.texi diff --git a/doc/ref/api-debug.texi b/doc/ref/api-debug.texi index f6342b021..32f32caba 100644 --- a/doc/ref/api-debug.texi +++ b/doc/ref/api-debug.texi @@ -1,6 +1,6 @@ @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. @@ -18,8 +18,7 @@ infrastructure that builds on top of those calls. * Evaluation Model:: Evaluation and the Scheme stack. * Source Properties:: From expressions to source locations. * Programmatic Error Handling:: Debugging when an error occurs. -* Traps:: -* Debugging Examples:: +* Traps:: Breakpoints, tracepoints, oh my! @end menu @node Evaluation Model @@ -81,15 +80,15 @@ describes the Scheme stack at that point. 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 @@ -97,7 +96,7 @@ 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 @@ -106,14 +105,14 @@ tag. A procedure means to cut away all frames up to but 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 @@ -239,11 +238,11 @@ that, if an error occurs when evaluating the transformed expression, 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) @@ -259,6 +258,12 @@ ERROR: Unbound variable: 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. @@ -289,10 +294,29 @@ Return the property specified by @var{key} from @var{obj}'s source 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: @@ -646,10 +670,13 @@ using @code{debug-set!}. @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 @@ -689,7 +716,7 @@ a thunk, gives us the following: @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 @@ -747,8 +774,7 @@ understanding how the interface hangs together. * 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 @@ -773,10 +799,11 @@ To digress, Guile's VM has 6 different hooks (@pxref{Hooks}) that can be 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 @@ -789,31 +816,28 @@ The interface to hooks is provided by the @code{(system vm vm)} module: @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. @@ -824,13 +848,16 @@ whereas a tail call will run without having fired a push-continuation 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. @@ -848,12 +875,12 @@ level temporarily set to 0. That way the hooks don't fire while you're 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 @@ -945,6 +972,13 @@ this argument gives the current frame that the trap is running in. 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. @@ -1025,7 +1059,7 @@ of an application of @var{proc}. @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 @@ -1101,19 +1135,50 @@ trace: (facti 24 0) 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 @@ -1132,347 +1197,161 @@ directly, it doesn't compose well with traps at the REPL. @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 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 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{} 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 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 mkmatrix - #:behaviour (list trace-trap trace-until-exit))) -guile> (do-main 4) -| 2: [mkmatrix] -| 3: [# # define #f] -| 3: [# # define #f] -| 4: (and (memq sym bindings) (let ...)) -| 5: (memq sym bindings) -| 5: [memq define (debug)] -| 5: =>#f -| 3: [# # define #f] -| 3: [# # define #f] -| 4: (and (memq sym bindings) (let ...)) -| 5: (memq sym bindings) -| 5: [memq define (debug)] -| 5: =>#f -| 3: [# # let #f] -| 3: [# # let #f] -| 4: (and (memq sym bindings) (let ...)) -| 5: (memq sym bindings) -| 5: [memq let (debug)] -| 5: =>#f -| 3: [# # let #f] -| 3: [# # let #f] -| 4: (and (memq sym bindings) (let ...)) -| 5: (memq sym bindings) -| 5: [memq let (debug)] -| 5: =>#f -| 3: [# # let #f] -| 3: [# # 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: [# # let #f] -| 3: [# # let #f] -| 4: (and (memq sym bindings) (let ...)) -| 5: (memq sym bindings) -| 5: [memq let (debug)] -| 5: =>#f -| 3: [# # let #f] -| 3: [# # let #f] -| 4: (and (memq sym bindings) (let ...)) -| 5: (memq sym bindings) -| 5: [memq let (debug)] -| 5: =>#f -| 3: [# # let #f] -| 3: [# # 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: [# # let #f] -| 3: [# # 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"