[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Fri, 29 Apr 2005 19:32:08 +0100
Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.7) Gecko/20050420 Debian/1.7.7-2
In case it triggers some feedback, here is some
specification-masquerading-as-documentation in my continuing mission to
implement a useful breakpoint facility for Guile. (The starting point
for this is the trap documentation at
4.5 Setting and Managing Breakpoints
While they are an important piece of infrastructure, and directly
usable in some scenarios, traps are still too low level to meet some of
the requirements of interactive development.
For example, in my experience a very common scenario is that a newly
written procedure is not working properly, and so you'd like to be able
to step or trace through its code to find out why. Ideally this should
be possible from the IDE and without having to modify the source code.
There are two problems with using traps directly in this scenario.
1. They are too detailed: constructing and installing a trap requires
you to say what kind of trap you want and to specify fairly low
level options for it, whereas what you really want is just to say
"break here using the most efficient means possible."
2. The most efficient kinds of trap -- that is, `<procedure-trap>'
and `<source-trap>' -- can only be specified and installed _after_
the code that they refer to has been loaded. This is an
inconvenient detail for the user to deal with, and in some
applications it might be very difficult to effect an instruction to
install the required trap in between when the code is loaded and
when the procedure concerned is first called. It would be better
to be able to tell Guile about the requirement upfront, and for it
to deal with installing the trap when possible.
We solve these problems by introducing breakpoints. A breakpoint is
something which says "I want to break at location X, or in procedure P
-- just make it happen", and can be set regardless of whether the
relevant code has already been loaded. Breakpoints use traps to do
their work, but that is a detail that the user will usually not have to
Breakpoints are provided by a combination of Scheme code in the client
program, and facilities for setting and managing breakpoints in the GDS
front end. On the Scheme side the entry points are as follows.
-- Getter with Setter: default-breakpoint-behaviour
A "getter with setter" procedure that can be used to get or set the
default behaviour for new breakpoints. When a new default
behaviour is set, by calling
(set! (default-breakpoint-behaviour) NEW-BEHAVIOUR)
the new behaviour applies to all following `break-in' and
`break-at' calls, but does not affect breakpoints which have
already been set. NEW-BEHAVIOUR should be a behaviour procedure
with the signature
(lambda (trap-context) ...)
as described in *Note Specifying Trap Behaviour::.
-- Procedure: break-in procedure-name [options]
Set a breakpoint on entry to the procedure named PROCEDURE-NAME,
which should be a symbol. The available options are:
Specifies the name of the module that the target procedure is
Specifies a behaviour for this breakpoint other than the
-- Procedure: break-at file-regexp line [options]
-- Procedure: break-at file-regexp from-line to-line [options]
-- Procedure: break-at file-regexp line from-column to-column [options]
-- Procedure: break-at file-regexp from-line from-column to-line
Set a breakpoint in the file matching FILE-REGEXP on all code
expressions that begin in the specified range of lines and/or
columns. FROM-COLUMN and all line numbers are inclusive;
TO-COLUMN is exclusive. The available options are:
Specifies a behaviour for this breakpoint other than the
-- Procedure: set-gds-breakpoints
Ask the GDS front end for a list of breakpoints to set, and set
these using `break-in' and `break-at' as appropriate.
`default-breakpoint-behaviour', `break-in' and `break-at' allow an
application's startup code to specify any breakpoints that it needs
inline in that code. For example, to trace calls and arguments to a
group of procedures to handle HTTP requests, one might write something
(use-modules (ossau breakpoints) (ossau trace))
(set! (default-breakpoint-behaviour) trace-trap)
(break-in 'handle-http-request #:module '(web http))
(break-in 'read-http-request #:module '(web http))
(break-in 'decode-form-data #:module '(web http))
(break-in 'send-http-response #:module '(web http))
`set-gds-breakpoints' can be used as well as or instead of the above,
and is intended to be the most practical option if you are using GDS.
The idea is that you only need to add this one call somewhere in your
application's startup code, like this:
(use-modules (ossau breakpoints))
and then all the details of the breakpoints that you want to set can be
managed through GDS.
4.5.1 Managing Breakpoints in GDS
You can create a breakpoint in GDS by typing `C-x <SPC>' in a Scheme
mode buffer. To create a breakpoint on calls to a procedure -- i.e.
the equivalent of calling `break-in' -- place the cursor on the
procedure's name and type `C-x <SPC>'. To create breakpoints on a
particular expression, or on the series of expressions in a particular
region -- i.e. as with `break-at' -- select the expression or region in
the usual way and type `C-x <SPC>'. In general, GDS assumes that you
want a `break-at' breakpoint if there is an active region, and a
`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
Secondly, it is added to GDS's _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 `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.(1)
(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.)
---------- Footnotes ----------
(1) 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.
|[Prev in Thread]
||[Next in Thread]|
- Breakpoint doc,
Neil Jerram <=