From b0f07fa20c0f033a1a9ba35983fb00dea15bd960 Mon Sep 17 00:00:00 2001 From: Neil Jerram Date: Wed, 12 Mar 2008 00:57:41 +0000 Subject: [PATCH] Merge GDS (except for breakpoints) from CVS HEAD: * debugger/commands.scm (evaluate, info-args, info-frame, position, up, down): Improve/fix doc strings. * Makefile.am (SUBDIRS): Add debugging. (ice9_sources): Add gds-client.scm and gds-server.scm. * scheme-debugging.texi: Remove lots of text that is now duplicated (exactly) elsewhere, leaving only the `Tracing' node. * guile.texi: Replace `Debugging Features' (scheme-debugging.texi) by `Using Guile Interactively' and `Using Guile in Emacs' (scheme-using.texi). Move the `Tracing' content of scheme-debugging.texi to the Modules section. * api-options.texi (Evaluator trap options): Move doc for with-traps and debug-object? to here. * api-modules.texi (Included Guile Modules): Change reference from `Debugging Features' to `Tracing'. * api-evaluation.texi (Evaluator Behaviour): Add reference to `Evaluator trap options'. * api-debug.texi (Examining the Stack): Minor improvements to display-backtrace doc. * api-debug.texi (Debug on Error): New text on how to catch errors and the error stack. * api-debug.texi (High Level Traps): New. * api-debug.texi (Debugging): New intro text. New subsection "Evaluation Model". Moved existing subsections "Capturing the Stack or Innermost Stack Frame", "Examining the Stack", "Examining Stack Frames", "Source Properties", "Decoding Memoized Source Expressions" and "Starting a New Stack" under "Evaluation Model". (Capturing the Stack or Innermost Stack Frame): Some new text, and correction to doc for last-stack-frame. (Debug on Error): Renamed from "Interactive Debugging". * configure.in (AC_CONFIG_FILES): Add emacs/Makefile and ice-9/debugging/Makefile. * Makefile.am (SUBDIRS): Add emacs. --- ChangeLog | 7 + Makefile.am | 2 +- configure.in | 2 + doc/ref/ChangeLog | 36 + doc/ref/Makefile.am | 1 + doc/ref/api-debug.texi | 1731 +++++++++++++++++++++++++++++---- doc/ref/api-evaluation.texi | 3 + doc/ref/api-modules.texi | 2 +- doc/ref/api-options.texi | 10 + doc/ref/guile.texi | 11 +- doc/ref/scheme-debugging.texi | 245 +---- ice-9/ChangeLog | 6 + ice-9/Makefile.am | 5 +- ice-9/debugger/commands.scm | 24 +- 14 files changed, 1638 insertions(+), 447 deletions(-) diff --git a/ChangeLog b/ChangeLog index bfdc42f9d..20fe5eb79 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,10 @@ +2008-03-12 Neil Jerram + + * configure.in (AC_CONFIG_FILES): Add emacs/Makefile and + ice-9/debugging/Makefile. + + * Makefile.am (SUBDIRS): Add emacs. + 2008-02-23 Neil Jerram * FAQ: New file. diff --git a/Makefile.am b/Makefile.am index 540653d2f..384ec5c6e 100644 --- a/Makefile.am +++ b/Makefile.am @@ -24,7 +24,7 @@ # AUTOMAKE_OPTIONS = 1.10 -SUBDIRS = oop libguile ice-9 guile-config guile-readline \ +SUBDIRS = oop libguile ice-9 guile-config guile-readline emacs \ scripts srfi doc examples test-suite benchmark-suite lang am bin_SCRIPTS = guile-tools diff --git a/configure.in b/configure.in index e48f0d478..5dc280ae0 100644 --- a/configure.in +++ b/configure.in @@ -1442,6 +1442,7 @@ AC_CONFIG_FILES([ doc/r5rs/Makefile doc/ref/Makefile doc/tutorial/Makefile + emacs/Makefile examples/Makefile examples/box-dynamic-module/Makefile examples/box-dynamic/Makefile @@ -1453,6 +1454,7 @@ AC_CONFIG_FILES([ guile-config/Makefile ice-9/Makefile ice-9/debugger/Makefile + ice-9/debugging/Makefile lang/Makefile lang/elisp/Makefile lang/elisp/internals/Makefile diff --git a/doc/ref/ChangeLog b/doc/ref/ChangeLog index 7039a5584..87396d395 100644 --- a/doc/ref/ChangeLog +++ b/doc/ref/ChangeLog @@ -1,5 +1,41 @@ 2008-03-12 Neil Jerram + * scheme-debugging.texi: Remove lots of text that is now + duplicated (exactly) elsewhere, leaving only the `Tracing' node. + + * guile.texi: Replace `Debugging Features' (scheme-debugging.texi) + by `Using Guile Interactively' and `Using Guile in Emacs' + (scheme-using.texi). Move the `Tracing' content of + scheme-debugging.texi to the Modules section. + + * api-options.texi (Evaluator trap options): Move doc for + with-traps and debug-object? to here. + + * api-modules.texi (Included Guile Modules): Change reference from + `Debugging Features' to `Tracing'. + + * api-evaluation.texi (Evaluator Behaviour): Add reference to + `Evaluator trap options'. + + * api-debug.texi (Examining the Stack): Minor improvements to + display-backtrace doc. + + * api-debug.texi (Debug on Error): New text on how to catch errors + and the error stack. + + * api-debug.texi (High Level Traps): New. + + * api-debug.texi (Debugging): New intro text. New subsection + "Evaluation Model". Moved existing subsections "Capturing the + Stack or Innermost Stack Frame", "Examining the Stack", "Examining + Stack Frames", "Source Properties", "Decoding Memoized Source + Expressions" and "Starting a New Stack" under "Evaluation Model". + (Capturing the Stack or Innermost Stack Frame): Some new text, and + correction to doc for last-stack-frame. + (Debug on Error): Renamed from "Interactive Debugging". + + * Makefile (guile_TEXINFOS): Add scheme-using.texi. + * scheme-using.texi: New (merged with modifications from CVS HEAD). diff --git a/doc/ref/Makefile.am b/doc/ref/Makefile.am index 1e4f3cfee..76a66f0c9 100644 --- a/doc/ref/Makefile.am +++ b/doc/ref/Makefile.am @@ -56,6 +56,7 @@ guile_TEXINFOS = preface.texi \ gh.texi \ api-overview.texi \ scheme-debugging.texi \ + scheme-using.texi \ indices.texi \ script-getopt.texi \ data-rep.texi \ diff --git a/doc/ref/api-debug.texi b/doc/ref/api-debug.texi index 036065921..54c8c1fb0 100644 --- a/doc/ref/api-debug.texi +++ b/doc/ref/api-debug.texi @@ -8,36 +8,234 @@ @node Debugging @section Debugging Infrastructure +In order to understand Guile's debugging facilities, you first need to +understand a little about how the evaluator works and what the Scheme +stack is. With that in place we explain the low level trap calls that +the evaluator can be configured to make, and the trap and breakpoint +infrastructure that builds on top of those calls. + +@menu +* Evaluation Model:: Evaluation and the Scheme stack. +* Debug on Error:: Debugging when an error occurs. +* High Level Traps:: +@end menu + +@node Evaluation Model +@subsection Evaluation and the Scheme Stack + +The idea of the Scheme stack is central to a lot of debugging. It +always exists implicitly, as a result of the way that the Guile +evaluator works, and can be summoned into concrete existence as a +first-class Scheme value by the @code{make-stack} call, so that an +introspective Scheme program -- such as a debugger -- can present it in +some way and allow the user to query its details. The first thing to +understand, therefore, is how the workings of the evaluator build up the +stack. + +@cindex Evaluations +@cindex Applications +Broadly speaking, the evaluator performs @dfn{evaluations} and +@dfn{applications}. An evaluation means that it is looking at a source +code expression like @code{(+ x 5)} or @code{(if msg (loop))}, deciding +whether the top level of the expression is a procedure call, macro, +builtin syntax, or whatever, and doing some appropriate processing in +each case. (In the examples here, @code{(+ x 5)} would normally be a +procedure call, and @code{(if msg (loop))} builtin syntax.) For a +procedure call, ``appropriate processing'' includes evaluating the +procedure's arguments, as that must happen before the procedure itself +can be called. An application means calling a procedure once its +arguments have been calculated. + +@cindex Stack +@cindex Frames +@cindex Stack frames +Typically evaluations and applications alternate with each other, and +together they form a @dfn{stack} of operations pending completion. This +is because, on the one hand, evaluation of an expression like @code{(+ x +5)} requires --- once its arguments have been calculated --- an +application (in this case, of the procedure @code{+}) before it can +complete and return a result, and, on the other hand, the application of +a procedure written in Scheme involves evaluating the sequence of +expressions that constitute that procedure's code. Each level on this +stack is called a @dfn{frame}. + +Therefore, when an error occurs in a running program, or the program +hits a breakpoint, or in fact at any point that the programmer chooses, +its state at that point can be represented by a @dfn{stack} of all the +evaluations and procedure applications that are logically in progress at +that time, each of which is known as a @dfn{frame}. The programmer can +learn more about the program's state at that point by inspecting the +stack and its frames. + @menu -* Interactive Debugging:: Functions intended for interactive use. -* Source Properties:: Remembering the source of an expression. -* Using Traps:: * Capturing the Stack or Innermost Stack Frame:: * Examining the Stack:: * Examining Stack Frames:: +* Source Properties:: Remembering the source of an expression. * Decoding Memoized Source Expressions:: * Starting a New Stack:: @end menu -@node Interactive Debugging -@subsection Interactive Debugging +@node Capturing the Stack or Innermost Stack Frame +@subsubsection Capturing the Stack or Innermost Stack Frame -@deffn {Scheme Procedure} backtrace [highlights] -@deffnx {C Function} scm_backtrace_with_highlights (highlights) -@deffnx {C Function} scm_backtrace () -Display a backtrace of the stack saved by the last error -to the current output port. When @var{highlights} is given, -it should be a list and all members of it are highligthed in -the backtrace. +A Scheme program can use the @code{make-stack} primitive anywhere in its +code, with first arg @code{#t}, to construct a Scheme value that +describes the Scheme stack at that point. + +@lisp +(make-stack #t) +@result{} +# +@end lisp + +@deffn {Scheme Procedure} make-stack obj . args +@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 +either a debug object or a continuation). + +@var{args} should be a list containing any combination of +integer, procedure 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{make-stack} returns. They come in pairs like this: +@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, 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 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 or a procedure. An +integer means to cut away that number of frames. 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 +taken as 0. @end deffn -@deffn {Scheme Procedure} debug -Invoke the Guile debugger to explore the context of the last error. +@deffn {Scheme Procedure} last-stack-frame obj +@deffnx {C Function} scm_last_stack_frame (obj) +Return the last (innermost) frame of @var{obj}, which must be +either a debug object or a continuation. +@end deffn + + +@node Examining the Stack +@subsubsection Examining the Stack + +@deffn {Scheme Procedure} stack? obj +@deffnx {C Function} scm_stack_p (obj) +Return @code{#t} if @var{obj} is a calling stack. +@end deffn + +@deffn {Scheme Procedure} stack-id stack +@deffnx {C Function} scm_stack_id (stack) +Return the identifier given to @var{stack} by @code{start-stack}. +@end deffn + +@deffn {Scheme Procedure} stack-length stack +@deffnx {C Function} scm_stack_length (stack) +Return the length of @var{stack}. +@end deffn + +@deffn {Scheme Procedure} stack-ref stack index +@deffnx {C Function} scm_stack_ref (stack, index) +Return the @var{index}'th frame from @var{stack}. +@end deffn + +@deffn {Scheme Procedure} display-backtrace stack port [first [depth [highlights]]] +@deffnx {C Function} scm_display_backtrace_with_highlights (stack, port, first, depth, highlights) +@deffnx {C Function} scm_display_backtrace (stack, port, first, depth) +Display a backtrace to the output port @var{port}. @var{stack} +is the stack to take the backtrace from, @var{first} specifies +where in the stack to start and @var{depth} how many frames +to display. @var{first} and @var{depth} can be @code{#f}, +which means that default values will be used. +If @var{highlights} is given it should be a list; the elements +of this list will be highlighted wherever they appear in the +backtrace. +@end deffn + + +@node Examining Stack Frames +@subsubsection Examining Stack Frames + +@deffn {Scheme Procedure} frame? obj +@deffnx {C Function} scm_frame_p (obj) +Return @code{#t} if @var{obj} is a stack frame. +@end deffn + +@deffn {Scheme Procedure} frame-number frame +@deffnx {C Function} scm_frame_number (frame) +Return the frame number of @var{frame}. +@end deffn + +@deffn {Scheme Procedure} frame-previous frame +@deffnx {C Function} scm_frame_previous (frame) +Return the previous frame of @var{frame}, or @code{#f} if +@var{frame} is the first frame in its stack. +@end deffn + +@deffn {Scheme Procedure} frame-next frame +@deffnx {C Function} scm_frame_next (frame) +Return the next frame of @var{frame}, or @code{#f} if +@var{frame} is the last frame in its stack. +@end deffn + +@deffn {Scheme Procedure} frame-source frame +@deffnx {C Function} scm_frame_source (frame) +Return the source of @var{frame}. +@end deffn + +@deffn {Scheme Procedure} frame-procedure? frame +@deffnx {C Function} scm_frame_procedure_p (frame) +Return @code{#t} if a procedure is associated with @var{frame}. +@end deffn + +@deffn {Scheme Procedure} frame-procedure frame +@deffnx {C Function} scm_frame_procedure (frame) +Return the procedure for @var{frame}, or @code{#f} if no +procedure is associated with @var{frame}. +@end deffn + +@deffn {Scheme Procedure} frame-arguments frame +@deffnx {C Function} scm_frame_arguments (frame) +Return the arguments of @var{frame}. +@end deffn + +@deffn {Scheme Procedure} frame-evaluating-args? frame +@deffnx {C Function} scm_frame_evaluating_args_p (frame) +Return @code{#t} if @var{frame} contains evaluated arguments. +@end deffn + +@deffn {Scheme Procedure} frame-overflow? frame +@deffnx {C Function} scm_frame_overflow_p (frame) +Return @code{#t} if @var{frame} is an overflow frame. +@end deffn + +@deffn {Scheme Procedure} frame-real? frame +@deffnx {C Function} scm_frame_real_p (frame) +Return @code{#t} if @var{frame} is a real frame. +@end deffn + +@deffn {Scheme Procedure} display-application frame [port [indent]] +@deffnx {C Function} scm_display_application (frame, port, indent) +Display a procedure application @var{frame} to the output port +@var{port}. @var{indent} specifies the indentation of the +output. @end deffn @node Source Properties -@subsection Source Properties +@subsubsection Source Properties @cindex source properties As Guile reads in Scheme code from file or from standard input, it @@ -135,178 +333,8 @@ that will avoid bloating the source property hash table, which is really only intended for the specific purposes described in this section. -@node Using Traps -@subsection Using Traps - -@deffn {Scheme Procedure} with-traps thunk -@deffnx {C Function} scm_with_traps (thunk) -Call @var{thunk} with traps enabled. -@end deffn - -@deffn {Scheme Procedure} debug-object? obj -@deffnx {C Function} scm_debug_object_p (obj) -Return @code{#t} if @var{obj} is a debug object. -@end deffn - - -@node Capturing the Stack or Innermost Stack Frame -@subsection Capturing the Stack or Innermost Stack Frame - -When an error occurs in a running program, or the program hits a -breakpoint, its state at that point can be represented by a @dfn{stack} -of all the evaluations and procedure applications that are logically in -progress at that time, each of which is known as a @dfn{frame}. The -programmer can learn more about the program's state at the point of -interruption or error by inspecting the stack and its frames. - -@deffn {Scheme Procedure} make-stack obj . args -@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 -either a debug object or a continuation). - -@var{args} should be a list containing any combination of -integer, procedure 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{make-stack} returns. They come in pairs like this: -@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, 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 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 or a procedure. An -integer means to cut away that number of frames. 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 -taken as 0. -@end deffn - -@deffn {Scheme Procedure} last-stack-frame obj -@deffnx {C Function} scm_last_stack_frame (obj) -Return a stack which consists of a single frame, which is the -last stack frame for @var{obj}. @var{obj} must be either a -debug object or a continuation. -@end deffn - - -@node Examining the Stack -@subsection Examining the Stack - -@deffn {Scheme Procedure} stack? obj -@deffnx {C Function} scm_stack_p (obj) -Return @code{#t} if @var{obj} is a calling stack. -@end deffn - -@deffn {Scheme Procedure} stack-id stack -@deffnx {C Function} scm_stack_id (stack) -Return the identifier given to @var{stack} by @code{start-stack}. -@end deffn - -@deffn {Scheme Procedure} stack-length stack -@deffnx {C Function} scm_stack_length (stack) -Return the length of @var{stack}. -@end deffn - -@deffn {Scheme Procedure} stack-ref stack index -@deffnx {C Function} scm_stack_ref (stack, index) -Return the @var{index}'th frame from @var{stack}. -@end deffn - -@deffn {Scheme Procedure} display-backtrace stack port [first [depth [highlights]]] -@deffnx {C Function} scm_display_backtrace_with_highlights (stack, port, first, depth, highlights) -@deffnx {C Function} scm_display_backtrace (stack, port, first, depth) -Display a backtrace to the output port @var{port}. @var{stack} -is the stack to take the backtrace from, @var{first} specifies -where in the stack to start and @var{depth} how much frames -to display. Both @var{first} and @var{depth} can be @code{#f}, -which means that default values will be used. -When @var{highlights} is given, -it should be a list and all members of it are highligthed in -the backtrace. -@end deffn - - -@node Examining Stack Frames -@subsection Examining Stack Frames - -@deffn {Scheme Procedure} frame? obj -@deffnx {C Function} scm_frame_p (obj) -Return @code{#t} if @var{obj} is a stack frame. -@end deffn - -@deffn {Scheme Procedure} frame-number frame -@deffnx {C Function} scm_frame_number (frame) -Return the frame number of @var{frame}. -@end deffn - -@deffn {Scheme Procedure} frame-previous frame -@deffnx {C Function} scm_frame_previous (frame) -Return the previous frame of @var{frame}, or @code{#f} if -@var{frame} is the first frame in its stack. -@end deffn - -@deffn {Scheme Procedure} frame-next frame -@deffnx {C Function} scm_frame_next (frame) -Return the next frame of @var{frame}, or @code{#f} if -@var{frame} is the last frame in its stack. -@end deffn - -@deffn {Scheme Procedure} frame-source frame -@deffnx {C Function} scm_frame_source (frame) -Return the source of @var{frame}. -@end deffn - -@deffn {Scheme Procedure} frame-procedure? frame -@deffnx {C Function} scm_frame_procedure_p (frame) -Return @code{#t} if a procedure is associated with @var{frame}. -@end deffn - -@deffn {Scheme Procedure} frame-procedure frame -@deffnx {C Function} scm_frame_procedure (frame) -Return the procedure for @var{frame}, or @code{#f} if no -procedure is associated with @var{frame}. -@end deffn - -@deffn {Scheme Procedure} frame-arguments frame -@deffnx {C Function} scm_frame_arguments (frame) -Return the arguments of @var{frame}. -@end deffn - -@deffn {Scheme Procedure} frame-evaluating-args? frame -@deffnx {C Function} scm_frame_evaluating_args_p (frame) -Return @code{#t} if @var{frame} contains evaluated arguments. -@end deffn - -@deffn {Scheme Procedure} frame-overflow? frame -@deffnx {C Function} scm_frame_overflow_p (frame) -Return @code{#t} if @var{frame} is an overflow frame. -@end deffn - -@deffn {Scheme Procedure} frame-real? frame -@deffnx {C Function} scm_frame_real_p (frame) -Return @code{#t} if @var{frame} is a real frame. -@end deffn - -@deffn {Scheme Procedure} display-application frame [port [indent]] -@deffnx {C Function} scm_display_application (frame, port, indent) -Display a procedure application @var{frame} to the output port -@var{port}. @var{indent} specifies the indentation of the -output. -@end deffn - - @node Decoding Memoized Source Expressions -@subsection Decoding Memoized Source Expressions +@subsubsection Decoding Memoized Source Expressions @deffn {Scheme Procedure} memoized? obj @deffnx {C Function} scm_memoized_p (obj) @@ -325,7 +353,7 @@ Return the environment of the memoized expression @var{m}. @node Starting a New Stack -@subsection Starting a New Stack +@subsubsection Starting a New Stack @deffn {Scheme Syntax} start-stack id exp Evaluate @var{exp} on a new calling stack with identity @var{id}. If @@ -336,6 +364,1335 @@ a convenience to the user. @end deffn +@node Debug on Error +@subsection Debugging when an error occurs + +A common requirement is to be able to show as much useful context as +possible when a Scheme program hits an error. The most immediate +information about an error is the kind of error that it is -- such as +``division by zero'' -- and any parameters that the code which signalled +the error chose explicitly to provide. This information originates with +the @code{error} or @code{throw} call (or their C code equivalents, if +the error is detected by C code) that signals the error, and is passed +automatically to the handler procedure of the innermost applicable +@code{catch}, @code{lazy-catch} or @code{with-throw-handler} expression. + +@subsubsection Intercepting basic error information + +Therefore, to catch errors that occur within a chunk of Scheme code, and +to intercept basic information about those errors, you need to execute +that code inside the dynamic context of a @code{catch}, +@code{lazy-catch} or @code{with-throw-handler} expression, or the +equivalent in C. In Scheme, this means you need something like this: + +@lisp +(catch #t + (lambda () + ;; Execute the code in which + ;; you want to catch errors here. + ...) + (lambda (key . parameters) + ;; Put the code which you want + ;; to handle an error here. + ...)) +@end lisp + +@noindent +The @code{catch} here can also be @code{lazy-catch} or +@code{with-throw-handler}; see @ref{Throw Handlers} and @ref{Lazy Catch} +for the details of how these differ from @code{catch}. The @code{#t} +means that the catch is applicable to all kinds of error; if you want to +restrict your catch to just one kind of error, you can put the symbol +for that kind of error instead of @code{#t}. The equivalent to this in +C would be something like this: + +@lisp +SCM my_body_proc (void *body_data) +@{ + /* Execute the code in which + you want to catch errors here. */ + ... +@} + +SCM my_handler_proc (void *handler_data, + SCM key, + SCM parameters) +@{ + /* Put the code which you want + to handle an error here. */ + ... +@} + +@{ + ... + scm_c_catch (SCM_BOOL_T, + my_body_proc, body_data, + my_handler_proc, handler_data, + NULL, NULL); + ... +@} +@end lisp + +@noindent +Again, as with the Scheme version, @code{scm_c_catch} could be replaced +by @code{scm_internal_lazy_catch} or @code{scm_c_with_throw_handler}, +and @code{SCM_BOOL_T} could instead be the symbol for a particular kind +of error. + +@subsubsection Capturing the full error stack + +The other interesting information about an error is the full Scheme +stack at the point where the error occurred; in other words what +innermost expression was being evaluated, what was the expression that +called that one, and so on. If you want to write your code so that it +captures and can display this information as well, there are three +important things to understand. + +Firstly, the code in question must be executed using the debugging +version of the evaluator, because information about the Scheme stack is +only available at all from the debugging evaluator. Using the debugging +evaluator means that the debugger option (@pxref{Debugger options}) +called @code{debug} must be enabled; this can be done by running +@code{(debug-enable 'debug)} or @code{(turn-on-debugging)} at the top +level of your program; or by running guile with the @code{--debug} +command line option, if your program begins life as a Scheme script. + +Secondly, the stack at the point of the error needs to be explicitly +captured by a @code{make-stack} call (or the C equivalent +@code{scm_make_stack}). The Guile library does not do this +``automatically'' for you, so you will need to write code with a +@code{make-stack} or @code{scm_make_stack} call yourself. (We emphasise +this point because some people are misled by the fact that the Guile +interactive REPL code @emph{does} capture and display the stack +automatically. But the Guile interactive REPL is itself a Scheme +program@footnote{In effect, it is the default program which is run when +no commands or script file are specified on the Guile command line.} +running on top of the Guile library, and which uses @code{catch} and +@code{make-stack} in the way we are about to describe to capture the +stack when an error occurs.) + +Thirdly, in order to capture the stack effectively at the point where +the error occurred, the @code{make-stack} call must be made before Guile +unwinds the stack back to the location of the prevailing catch +expression. This means that the @code{make-stack} call must be made +within the handler of a @code{lazy-catch} or @code{with-throw-handler} +expression, or the optional "pre-unwind" handler of a @code{catch}. +(For the full story of how these alternatives differ from each other, +see @ref{Exceptions}. The main difference is that @code{catch} +terminates the error, whereas @code{lazy-catch} and +@code{with-throw-handler} only intercept it temporarily and then allow +it to continue propagating up to the next innermost handler.) + +So, here are some examples of how to do all this in Scheme and in C. +For the purpose of these examples we assume that the captured stack +should be stored in a variable, so that it can be displayed or +arbitrarily processed later on. In Scheme: + +@lisp +(let ((captured-stack #f)) + (catch #t + (lambda () + ;; Execute the code in which + ;; you want to catch errors here. + ...) + (lambda (key . parameters) + ;; Put the code which you want + ;; to handle an error after the + ;; stack has been unwound here. + ...) + (lambda (key . parameters) + ;; Capture the stack here: + (set! captured-stack (make-stack #t)))) + ... + (if captured-stack + (begin + ;; Display or process the captured stack. + ...)) + ...) +@end lisp + +@noindent +And in C: + +@lisp +SCM my_body_proc (void *body_data) +@{ + /* Execute the code in which + you want to catch errors here. */ + ... +@} + +SCM my_handler_proc (void *handler_data, + SCM key, + SCM parameters) +@{ + /* Put the code which you want + to handle an error after the + stack has been unwound here. */ + ... +@} + +SCM my_preunwind_proc (void *handler_data, + SCM key, + SCM parameters) +@{ + /* Capture the stack here: */ + *(SCM *)handler_data = scm_make_stack (SCM_BOOL_T, SCM_EOL); +@} + +@{ + SCM captured_stack = SCM_BOOL_F; + ... + scm_c_catch (SCM_BOOL_T, + my_body_proc, body_data, + my_handler_proc, handler_data, + my_preunwind_proc, &captured_stack); + ... + if (captured_stack != SCM_BOOL_F) + @{ + /* Display or process the captured stack. */ + ... + @} + ... +@} +@end lisp + +@noindent +Note that you don't have to wait until after the @code{catch} or +@code{scm_c_catch} has returned. You can also do whatever you like with +the stack immediately after it has been captured in the pre-unwind +handler, or in the normal (post-unwind) handler. (Except that for the +latter case in C you will need to change @code{handler_data} in the +@code{scm_c_catch(@dots{})} call to @code{&captured_stack}, so that +@code{my_handler_proc} has access to the captured stack.) + +@subsubsection Displaying or interrogating the captured stack + +Once you have a captured stack, you can interrogate and display its +details in any way that you want, using the @code{stack-@dots{}} and +@code{frame-@dots{}} API described in @ref{Examining the Stack} and +@ref{Examining Stack Frames}. + +If you want to print out a backtrace in the same format that the Guile +REPL does, you can use the @code{display-backtrace} procedure to do so. +You can also use @code{display-application} to display an individual +application frame -- that is, a frame that satisfies the +@code{frame-procedure?} predicate -- in the Guile REPL format. + +@subsubsection What the Guile REPL does + +The Guile REPL code (in @file{ice-9/boot-9.scm}) uses a @code{catch} +with a pre-unwind handler to capture the stack when an error occurs in +an expression that was typed into the REPL, and saves the captured stack +in a fluid (@pxref{Fluids and Dynamic States}) called +@code{the-last-stack}. You can then use the @code{(backtrace)} command, +which is basically equivalent to @code{(display-backtrace (fluid-ref +the-last-stack))}, to print out this stack at any time until it is +overwritten by the next error that occurs. + +@deffn {Scheme Procedure} backtrace [highlights] +@deffnx {C Function} scm_backtrace_with_highlights (highlights) +@deffnx {C Function} scm_backtrace () +Display a backtrace of the stack saved by the last error +to the current output port. If @var{highlights} is given +it should be a list; the elements of this list will be +highlighted wherever they appear in the backtrace. +@end deffn + +You can also use the @code{(debug)} command to explore the saved stack +using an interactive command-line-driven debugger. See @ref{Interactive +Debugger} for more information about this. + +@deffn {Scheme Procedure} debug +Invoke the Guile debugger to explore the context of the last error. +@end deffn + + +@node High Level Traps +@subsection High Level Traps + +@cindex Traps +@cindex Evaluator trap calls +@cindex Breakpoints +@cindex Trace +@cindex Tracing +@cindex Code coverage +@cindex Profiling +The low level C code of Guile's evaluator can be configured to call +out at key points to arbitrary user-specified procedures. These +procedures, and the circumstances under which the evaluator calls +them, are configured by the ``evaluator trap options'' interface +(@pxref{Evaluator trap options}), and by the @code{trace} and +@code{breakpoints} fields of the ``debug options'' interface +(@pxref{Debugger options}). In principle this allows Scheme code to +implement any model it chooses for examining the evaluation stack as +program execution proceeds, and for suspending execution to be resumed +later. Possible applications of this feature include breakpoints, +runtime tracing, code coverage, and profiling. + +@cindex Trap classes +@cindex Trap objects +Based on these low level trap calls, Guile provides a higher level, +object-oriented interface for the manipulation of traps. Different +kinds of trap are represented as GOOPS classes; for example, the +@code{} class describes traps that are triggered by +invocation of a specified procedure. A particular instance of a trap +class --- or @dfn{trap object} --- describes the condition under which +a single trap will be triggered, and what will happen then; for +example, an instance of @code{} whose @code{procedure} +and @code{behaviour} slots contain @code{my-factorial} and +@code{debug-trap} would be a trap that enters the command line +debugger when the @code{my-factorial} procedure is invoked. + +The following subsubsections describe all this in greater detail, for both +the user wanting to use traps, and the developer interested in +understanding how the interface hangs together. + + +@subsubsection A Quick Note on Terminology + +@cindex Trap terminology +It feels natural to use the word ``trap'' in some form for all levels +of the structure just described, so we need to be clear on the +terminology we use to describe each particular level. The terminology +used in this subsection is as follows. + +@itemize @bullet +@item +@cindex Evaluator trap calls +@cindex Low level trap calls +``Low level trap calls'', or ``low level traps'', are the calls made +directly from the C code of the Guile evaluator. + +@item +@cindex Trap classes +``Trap classes'' are self-explanatory. + +@item +@cindex Trap objects +``Trap objects'', ``trap instances'', or just ``traps'', are instances +of a trap class, and each describe a single logical trap condition +plus behaviour as specified by the user of this interface. +@end itemize + +A good example of when it is important to be clear, is when we talk +below of behaviours that should only happen once per low level trap. +A single low level trap call will typically map onto the processing of +several trap objects, so ``once per low level trap'' is significantly +different from ``once per trap''. + + +@menu +* How to Set a Trap:: +* Specifying Trap Behaviour:: +* Trap Context:: +* Tracing Examples:: +* Tracing Configuration:: +* Tracing and (ice-9 debug):: +* Traps Installing More Traps:: +* Common Trap Options:: +* Procedure Traps:: +* Exit Traps:: +* Entry Traps:: +* Apply Traps:: +* Step Traps:: +* Source Traps:: +* Location Traps:: +* Trap Shorthands:: +* Trap Utilities:: +@end menu + + +@node How to Set a Trap +@subsubsection How to Set a Trap + +@cindex Setting traps +@cindex Installing and uninstalling traps +Setting a trap is done in two parts. First the trap is defined by +creating an instance of the appropriate trap class, with slot values +specifying the condition under which the trap will fire and the action +to take when it fires. Secondly the trap object thus created must be +@dfn{installed}. + +To make this immediately concrete, here is an example that sets a trap +to fire on the next application of the @code{facti} procedure, and to +handle the trap by entering the command line debugger. + +@lisp +(install-trap (make + #:procedure facti + #:single-shot #t + #:behaviour debug-trap)) +@end lisp + +@noindent +Briefly, the elements of this incantation are as follows. (All of +these are described more fully in the following subsubsections.) + +@itemize @bullet +@item +@code{} is the trap class for trapping on invocation +of a specific procedure. + +@item +@code{#:procedure facti} says that the specific procedure to trap on for this +trap object is @code{facti}. + +@item +@code{#:single-shot #t} says that this trap should only fire on the +@emph{next} invocation of @code{facti}, not on all future invocations +(which is the default if the @code{#:single-shot} option is not +specified). + +@item +@code{#:behaviour debug-trap} says that the trap infrastructure should +call the procedure @code{debug-trap} when this trap fires. + +@item +Finally, the @code{install-trap} call installs the trap immediately. +@end itemize + +@noindent +It is of course possible for the user to define more convenient +shorthands for setting common kinds of traps. @xref{Trap Shorthands}, +for some examples. + +The ability to install, uninstall and reinstall a trap without losing +its definition is Guile's equivalent of the disable/enable commands +provided by debuggers like GDB. + +@deffn {Generic Function} install-trap trap +Install the trap object @var{trap}, so that its behaviour will be +executed when the conditions for the trap firing are met. +@end deffn + +@deffn {Generic Function} uninstall-trap trap +Uninstall the trap object @var{trap}, so that its behaviour will +@emph{not} be executed even if the conditions for the trap firing are +met. +@end deffn + + +@node Specifying Trap Behaviour +@subsubsection Specifying Trap Behaviour + +@cindex Trap behaviour +Guile provides several ``out-of-the-box'' behaviours for common needs. +All of the following can be used directly as the value of the +@code{#:behaviour} option when creating a trap object. + +@deffn {Procedure} debug-trap trap-context +Enter Guile's command line debugger to explore the stack at +@var{trap-context}, and to single-step or continue program execution +from that point. +@end deffn + +@deffn {Procedure} gds-debug-trap trap-context +Use the GDS debugging interface, which displays the stack and +corresponding source code via Emacs, to explore the stack at +@var{trap-context} and to single-step or continue program execution +from that point. +@end deffn + +@cindex Trace +@cindex Tracing +@deffn {Procedure} trace-trap trap-context +Display trace information to summarize the current @var{trap-context}. +@end deffn + +@deffn {Procedure} trace-at-exit trap-context +Install a further trap to cause the return value of the application or +evaluation just starting (as described by @var{trap-context}) to be +traced using @code{trace-trap}, when this application or evaluation +completes. The extra trap is automatically uninstalled after the +return value has been traced. +@end deffn + +@deffn {Procedure} trace-until-exit trap-context +Install a further trap so that every step that the evaluator performs +as part of the application or evaluation just starting (as described +by @var{trap-context}) is traced using @code{trace-trap}. The extra +trap is automatically uninstalled when the application or evaluation +is complete. @code{trace-until-exit} can be very useful as a first +step when all you know is that there is a bug ``somewhere in XXX or in +something that XXX calls''. +@end deffn + +@noindent +@code{debug-trap} and @code{gds-debug-trap} are provided by the modules +@code{(ice-9 debugger)} and @code{(ice-9 gds-client)} respectively, and +their behaviours are fairly self-explanatory. For more information on +the operation of the GDS interface via Emacs, see @ref{Using Guile in +Emacs}. The tracing behaviours are explained more fully below. + +@cindex Trap context +More generally, the @dfn{behaviour} specified for a trap can be any +procedure that expects to be called with one @dfn{trap context} +argument. A trivial example would be: + +@lisp +(define (report-stack-depth trap-context) + (display "Stack depth at the trap is: ") + (display (tc:depth trap-context)) + (newline)) +@end lisp + + +@node Trap Context +@subsubsection Trap Context + +The @dfn{trap context} is an object that caches information about the +low level trap call and the stack at the point of the trap, and is +passed as the only argument to all behaviour procedures. The +information in the trap context can be accessed through the procedures +beginning @code{tc:} that are exported by the @code{(ice-9 debugging +traps)} module@footnote{Plus of course any procedures that build on +these, such as the @code{trace/@dots{}} procedures exported by +@code{(ice-9 debugging trace)} (@pxref{Tracing Configuration}).}; the +most useful of these are as follows. + +@deffn {Generic Function} tc:type trap-context +Indicates the type of the low level trap by returning one of the +keywords @code{#:application}, @code{#:evaluation}, @code{#:return} or +@code{#:error}. +@end deffn + +@deffn {Generic Function} tc:return-value trap-context +When @code{tc:type} gives @code{#:return}, this provides the value +that is being returned. +@end deffn + +@deffn {Generic Function} tc:stack trap-context +Provides the stack at the point of the trap (as computed by +@code{make-stack}, but cached so that the lengthy @code{make-stack} +operation is not performed more than once for the same low level +trap). +@end deffn + +@deffn {Generic Function} tc:frame trap-context +The innermost frame of the stack at the point of the trap. +@end deffn + +@deffn {Generic Function} tc:depth trap-context +The number of frames (including tail recursive non-real frames) in the +stack at the point of the trap. +@end deffn + +@deffn {Generic Function} tc:real-depth trap-context +The number of real frames (that is, excluding the non-real frames that +describe tail recursive calls) in the stack at the point of the trap. +@end deffn + + +@node Tracing Examples +@subsubsection Tracing Examples + +The following examples show what tracing is and the kind of output that +it generates. In the first example, we define a recursive function for +reversing a list, then watch the effect of the recursive calls by +tracing each call and return value. + +@lisp +guile> (define (rev ls) + (if (null? ls) + ls + (append (rev (cdr ls)) + (list (car ls))))) +guile> (use-modules (ice-9 debugging traps) (ice-9 debugging trace)) +guile> (define t1 (make + #:procedure rev + #:behaviour (list trace-trap + trace-at-exit))) +guile> (install-trap t1) +guile> (rev '(a b c)) +| 2: [rev (a b c)] +| 3: [rev (b c)] +| 4: [rev (c)] +| 5: [rev ()] +| 5: =>() +| 4: =>(c) +| 3: =>(c b) +| 2: =>(c b a) +(c b a) +@end lisp + +@noindent +The number before the colon in this output (which follows @code{(ice-9 +debugging trace)}'s default output format) is the number of real frames +on the stack. The fact that this number increases for each recursive +call confirms that the implementation above of @code{rev} is not +tail-recursive. + +In the next example, we probe the @emph{internal} workings of +@code{rev} in more detail by using the @code{trace-until-exit} +behaviour. + +@lisp +guile> (uninstall-trap t1) +guile> (define t2 (make + #:procedure rev + #:behaviour (list trace-trap + trace-until-exit))) +guile> (install-trap t2) +guile> (rev '(a b)) +| 2: [rev (a b)] +| 2: (if (null? ls) ls (append (rev (cdr ls)) (list (car ls)))) +| 3: (null? ls) +| 3: [null? (a b)] +| 3: =>#f +| 2: (append (rev (cdr ls)) (list (car ls))) +| 3: (rev (cdr ls)) +| 4: (cdr ls) +| 4: [cdr (a b)] +| 4: =>(b) +| 3: [rev (b)] +| 3: (if (null? ls) ls (append (rev (cdr ls)) (list (car ls)))) +| 4: (null? ls) +| 4: [null? (b)] +| 4: =>#f +| 3: (append (rev (cdr ls)) (list (car ls))) +| 4: (rev (cdr ls)) +| 5: (cdr ls) +| 5: [cdr (b)] +| 5: =>() +| 4: [rev ()] +| 4: (if (null? ls) ls (append (rev (cdr ls)) (list (car ls)))) +| 5: (null? ls) +| 5: [null? ()] +| 5: =>#t +| 4: (list (car ls)) +| 5: (car ls) +| 5: [car (b)] +| 5: =>b +| 4: [list b] +| 4: =>(b) +| 3: [append () (b)] +| 3: =>(b) +| 3: (list (car ls)) +| 4: (car ls) +| 4: [car (a b)] +| 4: =>a +| 3: [list a] +| 3: =>(a) +| 2: [append (b) (a)] +| 2: =>(b a) +(b a) +@end lisp + +@noindent +The output in this case shows every step that the evaluator performs +in evaluating @code{(rev '(a b))}. + + +@node Tracing Configuration +@subsubsection Tracing Configuration + +The detail of what gets printed in each trace line, and the port to +which tracing is written, can be configured by the procedures +@code{set-trace-layout} and @code{trace-port}, both exported by the +@code{(ice-9 debugging trace)} module. + +@deffn {Procedure with Setter} trace-port +Get or set the port to which tracing is printed. The default is the +value of @code{(current-output-port)} when the @code{(ice-9 debugging +trace)} module is first loaded. +@end deffn + +@deffn {Procedure} set-trace-layout format-string . arg-procs +Layout each trace line using @var{format-string} and @var{arg-procs}. +For each trace line, the list of values to be printed is obtained by +calling all the @var{arg-procs}, passing the trap context as the only +parameter to each one. This list of values is then formatted using +the specified @var{format-string}. +@end deffn + +@noindent +The @code{(ice-9 debugging trace)} module exports a set of arg-proc +procedures to cover most common needs, with names beginning +@code{trace/}. These are all implemented on top of the @code{tc:} trap +context accessor procedures documented in @ref{Trap Context}, and if any +trace output not provided by the following is needed, it should be +possible to implement based on a combination of the @code{tc:} +procedures. + +@deffn {Procedure} trace/pid trap-context +An arg-proc that returns the current process ID. +@end deffn + +@deffn {Procedure} trace/stack-id trap-context +An arg-proc that returns the stack ID of the stack in which the +current trap occurred. +@end deffn + +@deffn {Procedure} trace/stack-depth trap-context +An arg-proc that returns the length (including non-real frames) of the +stack at the point of the current trap. +@end deffn + +@deffn {Procedure} trace/stack-real-depth trap-context +An arg-proc that returns the length excluding non-real frames of the +stack at the point of the current trap. +@end deffn + +@deffn {Procedure} trace/stack trap-context +An arg-proc that returns a string summarizing stack information. This +string includes the stack ID, real depth, and count of additional +non-real frames, with the format @code{"~a:~a+~a"}. +@end deffn + +@deffn {Procedure} trace/source-file-name trap-context +An arg-proc that returns the name of the source file for the innermost +stack frame, or an empty string if source is not available for the +innermost frame. +@end deffn + +@deffn {Procedure} trace/source-line trap-context +An arg-proc that returns the line number of the source code for the +innermost stack frame, or zero if source is not available for the +innermost frame. +@end deffn + +@deffn {Procedure} trace/source-column trap-context +An arg-proc that returns the column number of the start of the source +code for the innermost stack frame, or zero if source is not available +for the innermost frame. +@end deffn + +@deffn {Procedure} trace/source trap-context +An arg-proc that returns the source location for the innermost stack +frame. This is a string composed of file name, line and column number +with the format @code{"~a:~a:~a"}, or an empty string if source is not +available for the innermost frame. +@end deffn + +@deffn {Procedure} trace/type trap-context +An arg-proc that returns a three letter abbreviation indicating the +type of the current trap: @code{"APP"} for an application frame, +@code{"EVA"} for an evaluation, @code{"RET"} for an exit trap, or +@code{"ERR"} for an error (pseudo-)trap. +@end deffn + +@deffn {Procedure} trace/real? trap-context +An arg-proc that returns @code{" "} if the innermost stack frame is a +real frame, or @code{"t"} if it is not. +@end deffn + +@deffn {Procedure} trace/info trap-context +An arg-proc that returns a string describing the expression being +evaluated, application being performed, or return value, according to +the current trap type. +@end deffn + +@noindent +@code{trace/stack-depth} and @code{trace/stack-real-depth} are identical +to the trap context methods @code{tc:depth} and @code{tc:real-depth} +described before (@pxref{Trap Context}), but renamed here for +convenience. + +The default trace layout, as exhibited by the examples of the previous +subsubsubsection, is set by this line of code from the @code{(ice-9 debugging +traps)} module: + +@lisp +(set-trace-layout "|~3@@a: ~a\n" trace/stack-real-depth trace/info) +@end lisp + +@noindent +If we rerun the first of those examples, but with trace layout +configured to show source location and trap type in addition, the +output looks like this: + +@lisp +guile> (set-trace-layout "| ~25a ~3@@a: ~a ~a\n" + trace/source + trace/stack-real-depth + trace/type + trace/info) +guile> (rev '(a b c)) +| standard input:29:0 2: APP [rev (a b c)] +| standard input:4:21 3: APP [rev (b c)] +| standard input:4:21 4: APP [rev (c)] +| standard input:4:21 5: APP [rev ()] +| standard input:2:9 5: RET =>() +| standard input:4:13 4: RET =>(c) +| standard input:4:13 3: RET =>(c b) +| standard input:4:13 2: RET =>(c b a) +(c b a) +@end lisp + + +@node Tracing and (ice-9 debug) +@subsubsection Tracing and (ice-9 debug) + +The @code{(ice-9 debug)} module provides a tracing facility +(@pxref{Tracing}) that is roughly similar to that described here, but +there are important differences. + +@itemize @bullet +@item +The @code{(ice-9 debug)} trace gives a nice pictorial view of changes +in stack depth, by using indentation like this: + +@lisp +[fact1 4] +| [fact1 3] +| | [fact1 2] +| | | [fact1 1] +| | | | [fact1 0] +| | | | 1 +| | | 1 +| | 2 +| 6 +24 +@end lisp + +However its output can @emph{only} show the information seen here, +which corresponds to @code{(ice-9 debugging trace)}'s +@code{trace/info} procedure; it cannot be configured to show other +pieces of information about the trap context in the way that the +@code{(ice-9 debugging trace)} implementation can. + +@item +The @code{(ice-9 debug)} trace only allows the tracing of procedure +applications and their return values, whereas the @code{(ice-9 debugging +trace)} implementation allows any kind of trap to be traced. + +It's interesting to note that @code{(ice-9 debug)}'s restriction here, +which might initially appear to be just a straightforward consequence +of its implementation, is also somewhat dictated by its pictorial +display. The use of indentation in the output relies on hooking into +the low level trap calls in such a way that the trapped application +entries and exits exactly balance each other. The @code{ice-9 +debugging trace} implementation allows traps to be installed such that +entry and exit traps don't necessarily balance, which means that, in +general, indentation diagrams like the one above don't work. +@end itemize + +It isn't currently possible to use both @code{(ice-9 debug)} trace and +@code{(ice-9 debugging trace)} in the same Guile session, because +their settings of the low level trap options conflict with each other. + + +@node Traps Installing More Traps +@subsubsection Traps Installing More Traps + +Sometimes it is desirable for the behaviour at one trap to install +further traps. In other words, the behaviour is something like +``Don't do much right now, but set things up to stop after two or +three more steps'', or ``@dots{} when this frame completes''. This is +absolutely fine. For example, it is easy to code a generic ``do +so-and-so when the current frame exits'' procedure, which can be used +wherever a trap context is available, as follows. + +@lisp +(define (at-exit trap-context behaviour) + (install-trap (make + #:depth (tc:depth trap-context) + #:single-shot #t + #:behaviour behaviour))) +@end lisp + +To continue and pin down the example, this could then be used as part +of a behaviour whose purpose was to measure the accumulated time spent +in and below a specified procedure. + +@lisp +(define calls 0) +(define total 0) + +(define accumulate-time + (lambda (trap-context) + (set! calls (+ calls 1)) + (let ((entry (current-time))) + (at-exit trap-context + (lambda (ignored) + (set! total + (+ total (- (current-time) + entry)))))))) + +(install-trap (make + #:procedure my-proc + #:behaviour accumulate-time)) +@end lisp + + +@node Common Trap Options +@subsubsection Common Trap Options + +When creating any kind of trap object, settings for the trap being +created are specified as options on the @code{make} call using syntax +like this: + +@lisp +(make <@var{trap-class}> + #:@var{option-keyword} @var{setting} + @dots{}) +@end lisp + +The following common options are provided by the base class +@code{}, and so can be specified for any kind of trap. + +@deffn {Class} +Base class for trap objects. +@end deffn + +@deffn {Trap Option} #:condition thunk +If not @code{#f}, this is a thunk which is called when the trap fires, +to determine whether trap processing should proceed any further. If +the thunk returns @code{#f}, the trap is basically suppressed. +Otherwise processing continues normally. (Default value @code{#f}.) +@end deffn + +@deffn {Trap Option} #:skip-count count +A count of valid (after @code{#:condition} processing) firings of this +trap to skip. (Default value 0.) +@end deffn + +@deffn {Trap Option} #:single-shot boolean +If not @code{#f}, this indicates that the trap should be automatically +uninstalled after it has successfully fired (after @code{#:condition} +and @code{#:skip-count} processing) for the first time. (Default +value @code{#f}.) +@end deffn + +@deffn {Trap Option} #:behaviour behaviour-proc +A trap behaviour procedure --- as discussed in the preceding subsubsection +--- or a list of such procedures, in which case each procedure is +called in turn when the trap fires. (Default value @code{'()}.) +@end deffn + +@deffn {Trap Option} #:repeat-identical-behaviour boolean +Normally, if multiple trap objects are triggered by the same low level +trap, and they request the same behaviour, it's only actually useful +to do that behaviour once (per low level trap); so by default multiple +requests for the same behaviour are coalesced. If this option is set +other than @code{#f}, the contents of the @code{#:behaviour} option +are uniquified so that they avoid being coalesced in this way. +(Default value @code{#f}.) +@end deffn + + +@node Procedure Traps +@subsubsection Procedure Traps + +The @code{} class implements traps that are triggered +upon application of a specified procedure. Instances of this class +should use the @code{#:procedure} option to specify the procedure to +trap on. + +@deffn {Class} +Class for traps triggered by application of a specified procedure. +@end deffn + +@deffn {Trap Option} #:procedure procedure +Specifies the procedure to trap on. +@end deffn + +@noindent +Example: + +@lisp +(install-trap (make + #:procedure my-proc + #:behaviour (list trace-trap + trace-until-exit))) +@end lisp + + +@node Exit Traps +@subsubsection Exit Traps + +The @code{} class implements traps that are triggered upon +stack frame exit past a specified stack depth. Instances of this +class should use the @code{#:depth} option to specify the target stack +depth. + +@deffn {Class} +Class for traps triggered by exit past a specified stack depth. +@end deffn + +@deffn {Trap Option} #:depth depth +Specifies the reference depth for the trap. +@end deffn + +@noindent +Example: + +@lisp +(define (trace-at-exit trap-context) + (install-trap (make + #:depth (tc:depth trap-context) + #:single-shot #t + #:behaviour trace-trap))) +@end lisp + +@noindent +(This is the actual definition of the @code{trace-at-exit} behaviour.) + + +@node Entry Traps +@subsubsection Entry Traps + +The @code{} class implements traps that are triggered upon +any stack frame entry. No further parameters are needed to specify an +instance of this class, so there are no class-specific trap options. +Note that it remains possible to use the common trap options +(@pxref{Common Trap Options}), for example to set a trap for the +@var{n}th next frame entry. + +@deffn {Class} +Class for traps triggered by any stack frame entry. +@end deffn + +@noindent +Example: + +@lisp +(install-trap (make + #:skip-count 5 + #:behaviour gds-debug-trap)) +@end lisp + + +@node Apply Traps +@subsubsection Apply Traps + +The @code{} class implements traps that are triggered upon +any procedure application. No further parameters are needed to +specify an instance of this class, so there are no class-specific trap +options. Note that it remains possible to use the common trap options +(@pxref{Common Trap Options}), for example to set a trap for the next +application where some condition is true. + +@deffn {Class} +Class for traps triggered by any procedure application. +@end deffn + +@noindent +Example: + +@lisp +(install-trap (make + #:condition my-condition + #:behaviour gds-debug-trap)) +@end lisp + + +@node Step Traps +@subsubsection Step Traps + +The @code{} class implements traps that do single-stepping +through a program's execution. They come in two flavours, with and +without a specified file name. If a file name is specified, the trap +is triggered by the next evaluation, application or frame exit +pertaining to source code from the specified file. If a file name is +not specified, the trap is triggered by the next evaluation, +application or frame exit from any file (or for code whose source +location was not recorded), in other words by the next evaluator step +of any kind. + +The design goal of the @code{} class is to match what a +user would intuitively think of as single-stepping through their code, +either through code in general (roughly corresponding to GDB's +@code{step} command, for example), or through code from a particular +source file (roughly corresponding to GDB's @code{next}). Therefore +if you are using a step trap to single-step through code and finding +its behaviour counter-intuitive, please report that so we can improve +it. + +The implementation and options of the @code{} class are +complicated by the fact that it is unreliable to determine whether a +low level frame exit trap is applicable to a specified file by +examining the details of the reported frame. This is a consequence of +tail recursion, which has the effect that many frames can be removed +from the stack at once, with only the outermost frame being reported +by the low level trap call. The effects of this on the +@code{} class are such as to require the introduction of +the strange-looking @code{#:exit-depth} option, for the following +reasons. + +@itemize @bullet +@item +When stopped at the start of an application or evaluation frame, and +it is desired to continue execution until the next ``step'' in the same +source file, that next step could be the start of a nested application +or evaluation frame, or --- if the procedure definition is in a +different file, for example --- it could be the exit from the current +frame. + +@item +Because of the effects of tail recursion noted above, the current +frame exit possibility must be expressed as frame exit past a +specified stack depth. When an instance of the @code{} +class is installed from the context of an application or evaluation +frame entry, the @code{#:exit-depth} option should be used to specify +this stack depth. + +@item +When stopped at a frame exit, on the other hand, we know that the next +step must be an application or evaluation frame entry. In this +context the @code{#:exit-depth} option is not needed and should be +omitted or set to @code{#f}. +@end itemize + +@noindent +When a step trap is installed without @code{#:single-shot #t}, such +that it keeps firing, the @code{} code automatically +updates its idea of the @code{#:exit-depth} setting each time, so that +the trap always fires correctly for the following step. + +@deffn {Class} +Class for single-stepping traps. +@end deffn + +@deffn {Trap Option} #:file-name name +If not @code{#f}, this is a string containing the name of a source +file, and restricts the step trap to evaluation steps within that +source file. (Default value @code{#f}.) +@end deffn + +@deffn {Trap Option} #:exit-depth depth +If not @code{#f}, this is a positive integer implying that the next +step may be frame exit past the stack depth @var{depth}. See the +discussion above for more details. (Default value @code{#f}.) +@end deffn + +@noindent +Example: + +@lisp +(install-trap (make + #:file-name (frame-file-name + (stack-ref stack index)) + #:exit-depth (- (stack-length stack) + (stack-ref stack index)) + #:single-shot #t + #:behaviour debug-trap)) +@end lisp + + +@node Source Traps +@subsubsection Source Traps + +The @code{} class implements traps that are attached to a +precise source code expression, as read by the reader, and which fire +each time that that expression is evaluated. These traps use a low +level Guile feature which can mark individual expressions for +trapping, and are relatively efficient. But it can be tricky to get +at the source expression in the first place, and these traps are +liable to become irrelevant if the procedure containing the expression +is reevaluated; these issues are discussed further below. + +@deffn {Class} +Class for traps triggered by evaluation of a specific Scheme +expression. +@end deffn + +@deffn {Trap Option} #:expression expr +Specifies the Scheme expression to trap on. +@end deffn + +@noindent +Example: + +@lisp +(display "Enter an expression: ") +(let ((x (read))) + (install-trap (make + #:expression x + #:behaviour (list trace-trap + trace-at-exit))) + (primitive-eval x)) +@print{} +Enter an expression: (+ 1 2 3 4 5 6) +| 3: (+ 1 2 3 4 5 6) +| 3: =>21 +21 +@end lisp + +The key point here is that the expression specified by the +@code{#:expression} option must be @emph{exactly} (i.e. @code{eq?} to) +what is going to be evaluated later. It doesn't work, for example, to +say @code{#:expression '(+ x 3)}, with the expectation that the trap +will fire whenever evaluating any expression @code{(+ x 3)}. + +The @code{trap-here} macro can be used in source code to create and +install a source trap correctly. Take for example the factorial +function defined in the @code{(ice-9 debugging example-fns)} module: + +@lisp +(define (fact1 n) + (if (= n 0) + 1 + (* n (fact1 (- n 1))))) +@end lisp + +@noindent +To set a source trap on a particular expression --- let's say the +expression @code{(= n 0)} --- edit the code so that the expression is +enclosed in a @code{trap-here} macro call like this: + +@lisp +(define (fact1 n) + (if (trap-here (= n 0) #:behaviour debug-trap) + 1 + (* n (fact1 (- n 1))))) +@end lisp + +@deffn {Macro} trap-here expression . trap-options +Install a source trap with options @var{trap-options} on +@var{expression}, then return with the whole call transformed to +@code{(begin @var{expression})}. +@end deffn + +Note that if the @code{trap-here} incantation is removed, and +@code{fact1} then redefined by reloading its source file, the effect +of the source trap is lost, because the text ``(= n 0)'' is read again +from scratch and becomes a new expression @code{(= n 0)} which does +not have the ``trap here'' mark on it. + +If the semantics and setting of source traps seem unwieldy, location +traps may meet your need more closely; these are described in the +following subsubsection. + + +@node Location Traps +@subsubsection Location Traps + +The @code{} class implements traps that are triggered +by evaluation of code at a specific source location or within a +specified range of source locations. When compared with source traps, +they are easier to set, and do not become irrelevant when the relevant +code is reloaded; but unfortunately they are considerably less +efficient, as they require running some ``are we in the right place +for a trap'' code on every low level frame entry trap call. + +@deffn {Class} +Class for traps triggered by evaluation of code at a specific source +location or in a specified range of source locations. +@end deffn + +@deffn {Trap Option} #:file-regexp regexp +A regular expression specifying the filenames that will match this +trap. This option must be specified when creating a location trap. +@end deffn + +@deffn {Trap Option} #:line line-spec +If specified, @var{line-spec} describes either a single line, in which +case it is a single integer, or a range of lines, in which case it is +a pair of the form @code{(@var{min-line} . @var{max-line})}. All line +numbers are 0-based, and the range form is inclusive-inclusive. If +@code{#f} or not specified, the trap is not restricted by line number. +(Default value @code{#f}.) +@end deffn + +@deffn {Trap Option} #:column column-spec +If specified, @var{column-spec} describes either a single column, in +which case it is a single integer, or a range of columns, in which +case it is a pair of the form @code{(@var{min-column} +. @var{max-column})}. All column numbers are 0-based, and the range +form is inclusive-inclusive. If @code{#f} or not specified, the trap +is not restricted by column number. (Default value @code{#f}.) +@end deffn + +@noindent +Example: + +@lisp +(install-trap (make + #:file-regexp "example-fns.scm" + #:line '(11 . 13) + #:behaviour gds-debug-trap)) +@end lisp + + +@node Trap Shorthands +@subsubsection Trap Shorthands + +If the code described in the preceding subsubsections for creating and +manipulating traps seems a little long-winded, it is of course +possible to define more convenient shorthand forms for typical usage +patterns. For example, my own @file{.guile} file contains the +following definitions for setting breakpoints and for tracing. + +@lisp +(define (break! proc) + (install-trap (make + #:procedure proc + #:behaviour gds-debug-trap))) + +(define (trace! proc) + (install-trap (make + #:procedure proc + #:behaviour (list trace-trap + trace-at-exit)))) + +(define (trace-subtree! proc) + (install-trap (make + #:procedure proc + #:behaviour (list trace-trap + trace-until-exit)))) +@end lisp + +Definitions like these are not provided out-of-the-box by Guile, +because different users will have different ideas about what their +default debugger should be, or, for example, which of the common trap +options (@pxref{Common Trap Options}) it might be useful to expose +through such shorthand procedures. + + +@node Trap Utilities +@subsubsection Trap Utilities + +@code{list-traps} can be used to print a description of all known trap +objects. This uses a weak value hash table, keyed by a trap index +number. Each trap object has its index number assigned, and is added +to the hash table, when it is created by a @code{make @var{trap-class} +@dots{}} call. When a trap object is GC'd, it is automatically +removed from the hash table, and so no longer appears in the output +from @code{list-traps}. + +@deffn {Variable} all-traps +Weak value hash table containing all known trap objects. +@end deffn + +@deffn {Procedure} list-traps +Print a description of all known trap objects. +@end deffn + +The following example shows a single trap that traces applications of +the procedure @code{facti}. + +@lisp +guile> (list-traps) +#< 100d2e30> is an instance of class +Slots are: + number = 1 + installed = #t + condition = #f + skip-count = 0 + single-shot = #f + behaviour = (#) + repeat-identical-behaviour = #f + procedure = # +@end lisp + +When @code{all-traps} or @code{list-traps} reveals a trap that you +want to modify but no longer have a reference to, you can retrieve the +trap object by calling @code{get-trap} with the trap's number. For +example, here's how you could change the behaviour of the trap listed +just above. + +@lisp +(slot-set! (get-trap 1) 'behaviour (list debug-trap)) +@end lisp + +@deffn {Procedure} get-trap number +Return the trap object with the specified @var{number}, or @code{#f} +if there isn't one. +@end deffn + + @c Local Variables: @c TeX-master: "guile.texi" @c End: diff --git a/doc/ref/api-evaluation.texi b/doc/ref/api-evaluation.texi index 1da13de43..6fd363df2 100644 --- a/doc/ref/api-evaluation.texi +++ b/doc/ref/api-evaluation.texi @@ -629,6 +629,9 @@ Like @code{help}, but also print programmer options. Modify the evaluator options. @code{trap-enable} should be used with boolean options and switches them on, @code{trap-disable} switches them off. @code{trap-set!} can be used to set an option to a specific value. + +See @ref{Evaluator trap options} for more information on the available +trap handlers. @end deffn @deffn {Scheme Procedure} evaluator-traps-interface [setting] diff --git a/doc/ref/api-modules.texi b/doc/ref/api-modules.texi index 415c9cba6..94b93bdc1 100644 --- a/doc/ref/api-modules.texi +++ b/doc/ref/api-modules.texi @@ -679,7 +679,7 @@ Guile starts up. @item (ice-9 debug) Mikael Djurfeldt's source-level debugging support for Guile -(@pxref{Debugging Features}). +(@pxref{Tracing}). @item (ice-9 expect) Actions based on matching input from a port (@pxref{Expect}). diff --git a/doc/ref/api-options.texi b/doc/ref/api-options.texi index 6dbc37062..ed1c42d01 100644 --- a/doc/ref/api-options.texi +++ b/doc/ref/api-options.texi @@ -612,6 +612,16 @@ way. @var{retval} is the return value. @end deffn +@deffn {Scheme Procedure} with-traps thunk +@deffnx {C Function} scm_with_traps (thunk) +Call @var{thunk} with traps enabled. +@end deffn + +@deffn {Scheme Procedure} debug-object? obj +@deffnx {C Function} scm_debug_object_p (obj) +Return @code{#t} if @var{obj} is a debug object. +@end deffn + @node Debugger options @subsubsection Debugger options diff --git a/doc/ref/guile.texi b/doc/ref/guile.texi index 0487dccb5..9e742f436 100644 --- a/doc/ref/guile.texi +++ b/doc/ref/guile.texi @@ -137,7 +137,7 @@ x @comment The title is printed in a large font. @title Guile Reference Manual @subtitle Edition @value{MANUAL-EDITION}, for use with Guile @value{VERSION} -@c @subtitle $Id: guile.texi,v 1.44.2.1 2006-10-04 21:40:24 kryde Exp $ +@c @subtitle $Id: guile.texi,v 1.44.2.2 2008-03-12 00:57:40 ossau Exp $ @c See preface.texi for the list of authors @author The Guile Developers @@ -219,14 +219,15 @@ etc. that make up Guile's application programming interface (API), * Basic Ideas:: Basic ideas in Scheme. * Guile Scheme:: Guile's implementation of Scheme. * Guile Scripting:: How to write Guile scripts. -* Debugging Features:: Features for finding errors. +* Using Guile Interactively:: Guile's REPL features. +* Using Guile in Emacs:: Guile and Emacs. * Further Reading:: Where to find out more about Scheme. @end menu @include scheme-ideas.texi @include scheme-intro.texi @include scheme-scripts.texi -@include scheme-debugging.texi +@include scheme-using.texi @include scheme-reading.texi @node Programming in C @@ -302,7 +303,7 @@ available through both Scheme and C interfaces. * Options and Config:: Configuration, features and runtime options. * Translation:: Support for translating other languages. * Internationalization:: Support for gettext, etc. -* Debugging:: Internal debugging interface. +* Debugging:: Debugging infrastructure and Scheme interface. * GH:: The deprecated GH interface. @end menu @@ -347,6 +348,7 @@ available through both Scheme and C interfaces. * Buffered Input:: Ports made from a reader function. * Expect:: Controlling interactive programs with Guile. * The Scheme shell (scsh):: Using scsh interfaces in Guile. +* Tracing:: Tracing program execution. @end menu @include slib.texi @@ -357,6 +359,7 @@ available through both Scheme and C interfaces. @include misc-modules.texi @include expect.texi @include scsh.texi +@include scheme-debugging.texi @include data-rep.texi @include fdl.texi diff --git a/doc/ref/scheme-debugging.texi b/doc/ref/scheme-debugging.texi index df0234d47..6166b2448 100644 --- a/doc/ref/scheme-debugging.texi +++ b/doc/ref/scheme-debugging.texi @@ -5,251 +5,8 @@ @c See the file guile.texi for copying conditions. @page -@node Debugging Features -@section Debugging Features - -Guile includes debugging tools to help you work out what is going wrong -when a program signals an error or behaves differently to how you would -expect. This chapter describes how to use these tools. - -@menu -* Debug Last Error:: Debugging the most recent error. -* Interactive Debugger:: Using the interactive debugger. -* Tracing:: Tracing program execution. -@end menu - - -@node Debug Last Error -@subsection Debugging the Most Recent Error - -When an error is signalled, Guile remembers the execution context where -the error occurred. By default, Guile then displays only the most -immediate information about where and why the error occurred, for -example: - -@c Note: line break in "enter the debugger" to avoid an over-long -@c line in both info and DVI. -@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}. - - -@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. In case you find yourself in the debugger by -mistake, the @code{quit} command will return you to the REPL. - -@deffn {Debugger Command} quit -Exit the debugger. -@end deffn - -The other 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. -@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 lower 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 higher 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 - -The following commands return detailed information about the currently -selected frame. - -@deffn {Debugger Command} {info frame} -Display a verbose description of the selected frame. The information -that this command provides is equivalent to what can be deduced from the -one line summary for the frame that appears in a backtrace, but is -presented and explained more clearly. -@end deffn - -@deffn {Debugger Command} {info args} -Display the argument variables of the current stack frame. Arguments -can also be seen in the backtrace, but are presented more clearly by -this command. -@end deffn - -@deffn {Debugger Command} position -Display the name of the source file that the current expression comes -from, and the line and column number of the expression's opening -parenthesis within that file. This information is only available when -the @code{positions} read option is enabled (@pxref{Reader options}). -@end deffn - - -@node Frame Evaluation -@subsubsection Frame Evaluation - -The @code{evaluate} command is most useful for querying the value of a -variable, either global or local, in the environment of the selected -stack frame, but it can be used more generally to evaluate any -expression. - -@deffn {Debugger Command} evaluate expression -Evaluate an expression in the environment of the selected stack frame. -The expression must appear on the same line as the command, however it -may be continued over multiple lines. -@end deffn - - @node Tracing -@subsection Tracing +@section Tracing The @code{(ice-9 debug)} module implements tracing of procedure applications. When a procedure is @dfn{traced}, it means that every diff --git a/ice-9/ChangeLog b/ice-9/ChangeLog index 3f3deccef..4f0f9fd5e 100644 --- a/ice-9/ChangeLog +++ b/ice-9/ChangeLog @@ -1,5 +1,11 @@ 2008-03-12 Neil Jerram + * debugger/commands.scm (evaluate, info-args, info-frame, + position, up, down): Improve/fix doc strings. + + * Makefile.am (SUBDIRS): Add debugging. + (ice9_sources): Add gds-client.scm and gds-server.scm. + * debugging/Makefile.am, debugging/example-fns.scm, debugging/ice-9-debugger-extensions.scm, debugging/steps.scm, debugging/trace.scm, debugging/traps.scm, debugging/trc.scm: New diff --git a/ice-9/Makefile.am b/ice-9/Makefile.am index 734185570..87a39e51c 100644 --- a/ice-9/Makefile.am +++ b/ice-9/Makefile.am @@ -21,7 +21,7 @@ AUTOMAKE_OPTIONS = gnu -SUBDIRS = debugger +SUBDIRS = debugger debugging # These should be installed and distributed. ice9_sources = \ @@ -35,7 +35,8 @@ ice9_sources = \ streams.scm string-fun.scm syncase.scm threads.scm \ buffered-input.scm time.scm history.scm channel.scm \ pretty-print.scm ftw.scm gap-buffer.scm occam-channel.scm \ - weak-vector.scm deprecated.scm list.scm serialize.scm + weak-vector.scm deprecated.scm list.scm serialize.scm \ + gds-client.scm gds-server.scm subpkgdatadir = $(pkgdatadir)/${GUILE_EFFECTIVE_VERSION}/ice-9 subpkgdata_DATA = $(ice9_sources) diff --git a/ice-9/debugger/commands.scm b/ice-9/debugger/commands.scm index 1d716e2bb..ef6f79026 100644 --- a/ice-9/debugger/commands.scm +++ b/ice-9/debugger/commands.scm @@ -67,9 +67,9 @@ If the number of frames isn't explicitly given, the debug option (throw 'continue)) (define (evaluate state expression) - "Evaluate an expression. -The expression must appear on the same line as the command, -however it may be continued over multiple lines." + "Evaluate an expression in the environment of the selected stack frame. +The expression must appear on the same line as the command, however it +may be continued over multiple lines." (let ((source (frame-source (stack-ref (state-stack state) (state-index state))))) (if (not source) @@ -100,18 +100,26 @@ however it may be continued over multiple lines." (lambda args args))))) (define (info-args state) - "Argument variables of current stack frame." + "Display the argument variables of the current stack frame. +Arguments can also be seen in the backtrace, but are presented more +clearly by this command." (let ((index (state-index state))) (let ((frame (stack-ref (state-stack state) index))) (write-frame-index-long frame) (write-frame-args-long frame)))) (define (info-frame state) - "All about selected stack frame." + "Display a verbose description of the selected frame. The +information that this command provides is equivalent to what can be +deduced from the one line summary for the frame that appears in a +backtrace, but is presented and explained more clearly." (write-state-long state)) (define (position state) - "Display the position of the current expression." + "Display the name of the source file that the current expression +comes from, and the line and column number of the expression's opening +parenthesis within that file. This information is only available when +the 'positions read option is enabled." (let* ((frame (stack-ref (state-stack state) (state-index state))) (source (frame-source frame))) (if (not source) @@ -124,14 +132,14 @@ however it may be continued over multiple lines." (define (up state n) "Move @var{n} frames up the stack. For positive @var{n}, this -advances toward the outermost frame, to higher frame numbers, to +advances toward the outermost frame, to lower frame numbers, to frames that have existed longer. @var{n} defaults to one." (set-stack-index! state (+ (state-index state) (or n 1))) (write-state-short state)) (define (down state n) "Move @var{n} frames down the stack. For positive @var{n}, this -advances toward the innermost frame, to lower frame numbers, to frames +advances toward the innermost frame, to higher frame numbers, to frames that were created more recently. @var{n} defaults to one." (set-stack-index! state (- (state-index state) (or n 1))) (write-state-short state))