14.7 Extending the Debugger
14.7.1 User-defined Ports
The standard set of ports in the debugger's box model can be extended by
the programmer. This facility is not so much intended for applications,
but rather for libraries that want to allow debugging in terms of
concepts of the library. Specific ports can be used to identify the
interesting events during execution of the library code (while the standard
tracing of the library internals can be suppressed by compiling the
library in nodebug-mode).
The system provides 4 primitives that can generate 4 kinds of box model ports.
When inserted into the code, and when the debugger is on,
they will cause execution to stop and enter the debugger,
displaying a trace line with the user-defined port and data:
For example, trace_call_port/3 and trace_exit_port/0 can be used to
create a more readable trace in the presence of source
transformations. Imagine that the goal Y is X*X-1
has been flattened into the goal sequence *(X,X,T),-(T,1,Y).
By inserting the trace primitives the debugger can still show the
original source before transformation:
trace_call_port(+Port, ?Invoc, ?Term)
is used to create new ports similar to CALL ports, but the port name
can be chosen freely. Such a port creates a new box. There must be
a corresponding trace_exit_port/0 to exit the box on success.
is used in conjunction with trace_call_port/3 to exit a box
- trace_point_port(+Port, ?Invoc, ?Term)
is used to create a standalone port, i.e. a port that causes the
tracer to create a trace line, but does not create, enter or leave
is used to create an additional port for the parent box, but does
not enter or leave the box.
The trace then looks like this:
trace_call_port(call,_, Y is X*X-1),
Another example is the insertion of additional ports for existing boxes,
in particular the current parent box:
[eclipse 8]: p(3,Y).
(1) 1 CALL p(3, Y) %> creep
(2) 2 CALL Y is 3 * 3 - 1 %> skip
(2) 2 EXIT 8 is 3 * 3 - 1 %> creep
(1) 1 EXIT p(3, 8) %> creep
Y = 8
This gives rise to the following trace:
Note that the additional ports share the parent's invocation number,
so the i command can be used to skip from one to the other.
(1) 1 CALL p %> creep
(1) 1 CLAUSE1 p %> creep
S (2) 2 CALL writeln(hello) %> creep
S (2) 2 EXIT writeln(hello) %> creep
(3) 2 CALL fail %> creep
(3) 2 FAIL fail %> creep
(1) 1 NEXT p %> creep
(1) 1 CLAUSE2 p %> creep
S (4) 2 CALL writeln(world) %> creep
S (4) 2 EXIT writeln(world) %> creep
(1) 1 EXIT p %> creep
Yes (0.00s cpu)
14.7.2 Attaching a Different User Interface
The tracer consists of a trace generation component (which is part of the
ECLiPSe runtime kernel), and a user interface (which is part of the
development system). The standard ECLiPSe distribution contains two
user interfaces, a console-based one, and a graphical one which is part
of tkeclipse. A programmable tracer interface (OPIUM/LSD) is under
development in the group of Mireille Ducasse at IRISA/Rennes.
Connecting new interfaces is relatively easy, for more detailed
information contact the ECLiPSe development team.