summaryrefslogtreecommitdiff
path: root/doc/ref/scheme-using.texi
diff options
context:
space:
mode:
Diffstat (limited to 'doc/ref/scheme-using.texi')
-rw-r--r--doc/ref/scheme-using.texi399
1 files changed, 248 insertions, 151 deletions
diff --git a/doc/ref/scheme-using.texi b/doc/ref/scheme-using.texi
index c19823683..93d0949f8 100644
--- a/doc/ref/scheme-using.texi
+++ b/doc/ref/scheme-using.texi
@@ -449,11 +449,9 @@ section.
* GDS Introduction::
* GDS Architecture::
* GDS Getting Started::
+* Working with GDS in Scheme Buffers::
* Displaying the Scheme Stack::
* Continuing Execution::
-* Evaluating Scheme Code::
-* Setting and Managing Breakpoints::
-* Access to Guile Help and Completion::
* Associating Buffers with Clients::
* An Example GDS Session::
@end menu
@@ -501,7 +499,6 @@ existing ones
@item
continue execution, either normally or step by step.
@end itemize
-@end enumerate
The presentation makes it very easy to move up and down the stack,
showing whenever possible the source code for each frame in another
@@ -509,11 +506,12 @@ Emacs buffer. It also provides convenient keystrokes for telling Guile
what to do next; for example, you can select a stack frame and tell
Guile to run until that frame completes, at which point GDS will display
the frame's return value.
+@end enumerate
-Combinations of the above work well too. You can evaluate a fragment of
-code (in a Scheme buffer) that contains a breakpoint, then use the
-debugging interface to step through the code at the breakpoint. You can
-also run a program until it hits a breakpoint, then examine, modify and
+Combinations of these well too. You can evaluate a fragment of code (in
+a Scheme buffer) that contains a breakpoint, then use the debugging
+interface to step through the code at the breakpoint. You can also run
+a program until it hits a breakpoint, then examine, modify and
reevaluate some of the relevant code, and then tell the program to
continue running.
@@ -642,7 +640,6 @@ files or modules by sending it @code{load} or @code{use-modules}
expressions. You can set breakpoints and evaluate code which hits those
breakpoints, and GDS will pop up the stack at the breakpoint so you can
explore your code by single-stepping and evaluating test expressions.
-
For a hands-on, tutorial introduction to using GDS in this way, use
Emacs to open the file @file{gds-tutorial.txt} (which should have been
installed as part of Guile, perhaps under @file{/usr/share/doc/guile}),
@@ -655,21 +652,33 @@ following subsections describe the various ways of doing this.
@subsubsection Setting Specific Breakpoints
+The first option is to use @code{break-in} or @code{break-at} to set
+specific breakpoints in the application's code. This requires code like
+the following.
+
@lisp
(use-modules (ice-9 debugging breakpoints)
(ice-9 gds-client))
(break-in 'fact2 "ice-9/debugging/example-fns"
#:behaviour gds-debug-trap)
+(break-in 'facti "ice-9/debugging/example-fns"
+ #:behaviour gds-debug-trap)
@end lisp
-In this example, the program chooses to define its breakpoint explicitly
-in its code, rather than downloading definitions from GDS, but it still
-uses GDS to control what happens when the breakpoint is hit, by
-specifying @code{gds-debug-trap} as the breakpoint behaviour.
+@noindent
+The @code{#:behaviour gds-debug-trap} clauses mean to use GDS to display
+the stack when one of these breakpoints is hit. For more on
+breakpoints, @code{break-in} and @code{break-at}, see @ref{Intro to
+Breakpoints}.
@subsubsection Setting GDS-managed Breakpoints
+Instead of listing specific breakpoints in application code, you can use
+GDS to manage the set of breakpoints that you want from Emacs, and tell
+the application to download the breakpoints that it should set from
+GDS. The code for this is:
+
@lisp
(use-modules (ice-9 gds-client))
(set-gds-breakpoints)
@@ -680,11 +689,52 @@ a set of breakpoint definitions. The program sets those breakpoints in
its code, then continues running.
When the program later hits one of the breakpoints, it will use GDS to
-display the stack and wait for instruction on what to do next, as
-described above.
+display the stack and wait for instruction on what to do next.
@subsubsection Invoking GDS when an Exception Occurs
+Another option is to use GDS to catch and display any exceptions that
+are thrown by the application's code. If you already have a
+@code{lazy-catch} or @code{with-throw-handler} around the area of code
+that you want to monitor, you just need to add the following to the
+handler code:
+
+@lisp
+(gds-debug-trap (throw->trap-context key args))
+@end lisp
+
+@noindent
+where @code{key} and @code{args} are the first and rest arguments that
+Guile passes to the handler. (In other words, they assume the handler
+signature @code{(lambda (key . args) @dots{})}.) With Guile 1.8 or
+later, you can also do this with a @code{catch}, by adding this same
+code to the catch's pre-unwind handler.
+
+If you don't already have any of these, insert a whole
+@code{with-throw-handler} expression (or @code{lazy-catch} if your Guile
+is pre-1.8) around the code of interest like this:
+
+@lisp
+(with-throw-handler #t
+ (lambda ()
+ ;; Protected code here.
+ )
+ (lambda (key . args)
+ (gds-debug-trap (throw->trap-context key args))))
+@end lisp
+
+In all cases you will need to use the @code{(ice-9 gds-client)} and
+@code{(ice-9 debugging traps)} modules.
+
+Two special cases of this are the lazy-catch that the Guile REPL code
+uses to catch exceptions in user code, and the lazy-catch inside the
+@code{stack-catch} utility procedure that is provided by the
+@code{(ice-9 stack-catch)} module. Both of these use a handler called
+@code{lazy-handler-dispatch} (defined in @file{boot-9.scm}), which you
+can hook into such that it calls GDS to display the stack when an
+exception occurs. To do this, use the @code{on-lazy-handler-dispatch}
+procedure as follows.
+
@lisp
(use-modules (ice-9 gds-client)
(ice-9 debugging traps))
@@ -692,18 +742,10 @@ described above.
(on-lazy-handler-dispatch gds-debug-trap)
@end lisp
-This means that the program will use GDS to display the stack whenever
-it hits an exception that is protected by a @code{lazy-catch} using
-Guile's standard @code{lazy-catch-handler} (defined in
-@file{boot-9.scm}).
-
-@code{lazy-catch-handler} is used by the @code{stack-catch} procedure,
-provided by the @code{(ice-9 stack-catch)} module, so this will include
-exceptions within a @code{stack-catch}. @code{lazy-catch-handler} is
-also used by the standard Guile REPL, when you run Guile interactively,
-so you can add the above lines to your @file{.guile} file if you want to
-use GDS whenever something that you type into the REPL throws an
-exception.
+@noindent
+After this the program will use GDS to display the stack whenever it
+hits an exception that is protected by a @code{lazy-catch} using
+@code{lazy-handler-dispatch}.
@subsubsection Accepting GDS Instructions at Any Time
@@ -745,14 +787,11 @@ This approach is not yet implemented, though.
@subsubsection Utility Guile Implementation
-We bring this subsection full circle by noting that the ``utility'' Guile
-client, which GDS starts automatically when you use GDS as described
-under approach 1 above, is really just a special case of ``a Guile
-program or script which is started independently'' (approach 2), and
-provides the services that the GDS front end needs by a simple
-combination of some of the code fragments just described.
+We conclude this subsection with an aside, by noting that the
+``utility'' Guile client described above is nothing more than a
+combination of the previous options.
-To be precise, the code for the utility Guile client is essentially
+To be precise, the code for the utility Guile client is essentially just
this:
@lisp
@@ -765,12 +804,11 @@ this:
@code{set-gds-breakpoints} works as already described. The
@code{named-module-use!} line ensures that the client can process
-@code{help} and @code{apropos} expressions, which is what the front end
-sends to implement lookups in Guile's online help. The @code{#f}
-parameter to @code{gds-accept-input} means that the @code{continue}
-instruction will not cause the instruction loop to exit, which makes
-sense here because the utility client has nothing to do except to
-process GDS instructions.
+@code{help} and @code{apropos} expressions, to implement lookups in
+Guile's online help. The @code{#f} parameter to @code{gds-accept-input}
+means that the @code{continue} instruction will not cause the
+instruction loop to exit, which makes sense here because the utility
+client has nothing to do except to process GDS instructions.
(The utility client does not use @code{on-lazy-handler-dispatch},
because it has its own mechanism for catching and reporting exceptions
@@ -780,6 +818,176 @@ stack, so the end result is very similar to what
@code{on-lazy-handler-dispatch} provides.)
+@node Working with GDS in Scheme Buffers
+@subsection Working with GDS in Scheme Buffers
+
+The following subsections describe the facilities and key sequences that
+GDS provides for working on code in @code{scheme-mode} buffers.
+
+@menu
+* Access to Guile Help and Completion::
+* Setting and Managing Breakpoints::
+* Listing and Deleting Breakpoints::
+* Moving and Losing Breakpoints::
+* Evaluating Scheme Code::
+@end menu
+
+
+@node Access to Guile Help and Completion
+@subsubsection Access to Guile Help and Completion
+
+The following keystrokes provide fast and convenient access to Guile's
+built in help, and to completion with respect to the set of defined and
+accessible symbols.
+
+@table @kbd
+@item C-h g
+@findex gds-help-symbol
+Get Guile help for a particular symbol, with the same results as if
+you had typed @code{(help SYMBOL)} into the Guile REPL
+(@code{gds-help-symbol}). The symbol to query defaults to the word at
+or before the cursor but can also be entered or edited in the
+minibuffer. The available help is popped up in a temporary Emacs
+window.
+
+@item C-h C-g
+@findex gds-apropos
+List all accessible Guile symbols matching a given regular expression,
+with the same results as if you had typed @code{(apropos REGEXP)} into
+the Guile REPL (@code{gds-apropos}). The regexp to query defaults to
+the word at or before the cursor but can also be entered or edited in
+the minibuffer. The list of matching symbols is popped up in a
+temporary Emacs window.
+
+@item M-@key{TAB}
+@findex gds-complete-symbol
+Try to complete the symbol at the cursor by matching it against the
+set of all defined and accessible bindings in the associated Guile
+process (@code{gds-complete-symbol}). If there are any extra
+characters that can be definitively added to the symbol at point, they
+are inserted. Otherwise, if there are any completions available, they
+are popped up in a temporary Emacs window, where one of them can be
+selected using either @kbd{@key{RET}} or the mouse.
+@end table
+
+
+@node Setting and Managing Breakpoints
+@subsubsection Setting and Managing Breakpoints
+
+You can create a breakpoint in GDS by typing @kbd{C-x @key{SPC}} in a
+Scheme mode buffer. To create a breakpoint on calls to a procedure ---
+i.e. the equivalent of calling @code{break-in} --- place the cursor
+anywhere within the procedure's definition, make sure that the region is
+unset, and type @kbd{C-x @key{SPC}}. To create breakpoints on a
+particular expression, or on the series of expressions in a particular
+region --- i.e. as with @code{break-at} --- select a region containing
+the open parentheses of the expressions where you want breakpoints, and
+type @kbd{C-x @key{SPC}}. In other words, GDS assumes that you want a
+@code{break-at} breakpoint if there is an active region, and a
+@code{break-in} breakpoint otherwise.
+
+There are three supported breakpoint behaviours, known as @code{debug},
+@code{trace} and @code{trace-subtree}. @code{debug} means that GDS will
+display the stack and wait for instruction when the breakpoint is hit.
+@code{trace} means that a line will be written to the trace output
+buffer (@code{*GDS Trace*}) when the breakpoint is hit, and when the
+relevant expression or procedure call returns. @code{trace-subtree}
+means that a line is written to the trace output buffer for every
+evaluation step between when the breakpoint is hit and when the
+expression or procedure returns.
+
+@kbd{C-x @key{SPC}} creates a breakpoint with behaviour according to the
+@code{gds-default-breakpoint-type} variable, which by default is
+@code{debug}; you can customize this if you prefer a different default.
+You can also create a breakpoint with behaviour other than the current
+default by using the alternative key sequences @kbd{C-c C-b d} (for
+@code{debug}), @kbd{C-c C-b t} (for @code{trace}) and @kbd{C-c C-b T}
+(for @code{trace-subtree}).
+
+GDS keeps all the breakpoints that you create in a single list, and
+tries to set them in every Guile program that connects to GDS and calls
+@code{set-gds-breakpoints}. That may sound surprising, because you are
+probably thinking of one particular program when you create a
+breakpoint; but GDS assumes that you would want the breakpoint to continue
+taking effect if you stop and restart that program, and this is
+currently achieved by giving all breakpoints to every program that asks
+for them. In practice it doesn't matter if a program gets a breakpoint
+definition --- such as ``break in procedure @code{foo}'' --- that it
+can't actually map to any of its code.
+
+If there are already Guile programs connected to GDS when you create a
+new breakpoint, GDS also tries to set the new breakpoint in each of
+those programs at the earliest opportunity, which is usually when they
+decide to stop and talk to GDS for some other reason.
+
+
+@node Listing and Deleting Breakpoints
+@subsubsection Listing and Deleting Breakpoints
+
+To see a list of all breakpoints, type @kbd{C-c C-b ?} (or @kbd{M-x
+gds-describe-breakpoints}). GDS will then pop up a buffer that
+describes each breakpoint and reports whether it is actually set in each
+of the Guile programs connected to GDS.
+
+To delete a breakpoint, type @kbd{C-c C-b @key{backspace}}. If the
+region is active when you do this, GDS will delete all of the
+breakpoints in the region. If the region is not active, GDS tries to
+delete a ``break-in'' breakpoint for the procedure whose definition
+contains point (the Emacs cursor). In either case, deletion means that
+the breakpoint is removed both from GDS's global list and from all of
+the connected Guile programs that had previously managed to set it.
+
+
+@node Moving and Losing Breakpoints
+@subsubsection Moving and Losing Breakpoints
+
+Imagine that you set a breakpoint at line 80 of a Scheme code file, and
+execute some code that hits this breakpoint; then you add some new code
+at line 40, or delete some code that is no longer needed, and save the
+file. Now the breakpoint will have moved up or down from line 80, and
+any attached Guile program needs to be told about the new line number.
+Otherwise, when a program loads this file again, it will try incorrectly
+to set a breakpoint on whatever code is now at line 80, and will
+@emph{not} set a breakpoint on the code where you want it.
+
+For this reason, GDS checks all breakpoint positions whenever you save a
+Scheme file, and sends the new position to connected Guile programs for
+any breakpoints that have moved. @dots{} [to be continued]
+
+
+@node Evaluating Scheme Code
+@subsubsection Evaluating Scheme Code
+
+The following keystrokes and commands provide various ways of sending
+code to a Guile client process for evaluation.
+
+@table @kbd
+@item M-C-x
+@findex gds-eval-defun
+Evaluate the ``top level defun'' that the cursor is in, in other words
+the smallest balanced expression which includes the cursor and whose
+opening parenthesis is in column 0 (@code{gds-eval-defun}).
+
+@item C-x C-e
+@findex gds-eval-last-sexp
+Evaluate the expression that ends just before the cursor
+(@code{gds-eval-last-sexp}). This is designed so that it is easy to
+evaluate an expression that you have just finished typing.
+
+@item C-c C-e
+@findex gds-eval-expression
+Read a Scheme expression using the minibuffer, and evaluate that
+expression (@code{gds-eval-expression}).
+
+@item C-c C-r
+@findex gds-eval-region
+Evaluate the Scheme code in the marked region of the current buffer
+(@code{gds-eval-region}). Note that GDS does not check whether the
+region contains a balanced expression, or try to expand the region so
+that it does; it uses the region exactly as it is.
+@end table
+
+
@node Displaying the Scheme Stack
@subsection Displaying the Scheme Stack
@@ -902,117 +1110,6 @@ remains in place and so will still fire at the appropriate point.
@end table
-@node Evaluating Scheme Code
-@subsection Evaluating Scheme Code
-
-The following keystrokes and commands provide various ways of sending
-code to a Guile client process for evaluation.
-
-@table @kbd
-@item M-C-x
-@findex gds-eval-defun
-Evaluate the ``top level defun'' that the cursor is in, in other words
-the smallest balanced expression which includes the cursor and whose
-opening parenthesis is in column 0 (@code{gds-eval-defun}).
-
-@item C-x C-e
-@findex gds-eval-last-sexp
-Evaluate the expression that ends just before the cursor
-(@code{gds-eval-last-sexp}). This is designed so that it is easy to
-evaluate an expression that you have just finished typing.
-
-@item C-c C-e
-@findex gds-eval-expression
-Read a Scheme expression using the minibuffer, and evaluate that
-expression (@code{gds-eval-expression}).
-
-@item C-c C-r
-@findex gds-eval-region
-Evaluate the Scheme code in the marked region of the current buffer
-(@code{gds-eval-region}). Note that GDS does not check whether the
-region contains a balanced expression, or try to expand the region so
-that it does; it uses the region exactly as it is.
-@end table
-
-
-@node Setting and Managing Breakpoints
-@subsection Setting and Managing Breakpoints
-
-You can create a breakpoint in GDS by typing @kbd{C-x @key{SPC}} in a
-Scheme mode buffer. To create a breakpoint on calls to a procedure
---- i.e. the equivalent of calling @code{break-in} --- place the
-cursor on the procedure's name and type @kbd{C-x @key{SPC}}. To
-create breakpoints on a particular expression, or on the series of
-expressions in a particular region --- i.e. as with @code{break-at}
---- select the expression or region in the usual way and type @kbd{C-x
-@key{SPC}}. In general, GDS assumes that you want a @code{break-at}
-breakpoint if there is an active region, and a @code{break-in}
-breakpoint otherwise.
-
-When you create a breakpoint like this, two things happen. Firstly,
-if the current buffer is associated with a Guile client program, the
-new breakpoint definition is immediately sent to that client (or, if
-the client cannot accept input immediately, it is held in readiness to
-pass to the client at the next possible opportunity). This allows the
-new breakpoint to take effect as soon as possible in the relevant
-client program.
-
-Secondly, it is added to GDS's @emph{global} list of all breakpoints.
-This list holds the breakpoint information that will be given to any
-client program that asks for it by calling @code{set-gds-breakpoints}.
-The fact that this list is global, rather than client-specific, means
-that the breakpoints you have set will automatically be recreated if
-the program you are debugging has to be stopped and restarted ---
-which in my experience happens often.@footnote{An important point here
-is that there is nothing that unambiguously relates two subsequent
-runs of the same client program, which might allow GDS to pass on
-breakpoint settings more precisely.}
-
-(The only possible downside of this last point is that if you are
-debugging two programs in parallel, which have some code in common,
-you might not want a common code breakpoint in one program to be set
-in the other program as well. But this feels like a small concern in
-comparison to the benefit of breakpoints persisting as just described.)
-
-
-@node Access to Guile Help and Completion
-@subsection Access to Guile Help and Completion
-
-The following keystrokes provide fast and convenient access to Guile's
-built in help, and to completion with respect to the set of defined and
-accessible symbols.
-
-@table @kbd
-@item C-h g
-@findex gds-help-symbol
-Get Guile help for a particular symbol, with the same results as if
-you had typed @code{(help SYMBOL)} into the Guile REPL
-(@code{gds-help-symbol}). The symbol to query defaults to the word at
-or before the cursor but can also be entered or edited in the
-minibuffer. The available help is popped up in a temporary Emacs
-window.
-
-@item C-h C-g
-@findex gds-apropos
-List all accessible Guile symbols matching a given regular expression,
-with the same results as if you had typed @code{(apropos REGEXP)} into
-the Guile REPL (@code{gds-apropos}). The regexp to query defaults to
-the word at or before the cursor but can also be entered or edited in
-the minibuffer. The list of matching symbols is popped up in a
-temporary Emacs window.
-
-@item M-@key{TAB}
-@findex gds-complete-symbol
-Try to complete the symbol at the cursor by matching it against the
-set of all defined and accessible bindings in the associated Guile
-process (@code{gds-complete-symbol}). If there are any extra
-characters that can be definitively added to the symbol at point, they
-are inserted. Otherwise, if there are any completions available, they
-are popped up in a temporary Emacs window, where one of them can be
-selected using either @kbd{@key{RET}} or the mouse.
-@end table
-
-
@node Associating Buffers with Clients
@subsection Associating Buffers with Clients