Node:Built-in Predicates for Breakpoint Handling, Next:Accessing Past Debugger States, Previous:Advice-points, Up:Advanced Debugging
For the last advice-point example to be practical, it should be improved
to assert only line numbers not recorded so far. For this you will
write a Prolog predicate for the conditional assertion of file/line
information, assert_line_reached(File,Line)
. The breakpoint spec will
then look as follows:
| ?- add_breakpoint([advice,goal(_:_),call,line(F,L)] -[true(assert_line_reached(F,L)),flit], _).
The above breakpoint spec can be simplified by moving the
line(F,L)
query into the Prolog goal called within the
true/1
condition. To achieve this, the built-in predicate
execution_state/1
can be used. This predicate takes a simple or a
composite breakpoint condition as its argument and evaluates it, as if
in the test part of a breakpoint spec. The predicate will succeed iff
the breakpoint condition evaluates successfully. Thus
execution_state/1
allows you to access debugging information from
within Prolog code. For example, you can write a Prolog predicate,
assert_line_reached/0
, which queries the debugger for the current
line information and then processes the line number:
assert_line_reached :- ( execution_state(line(F,L)) -> assert_line_reached(F,L). ; true ). | ?- add_breakpoint([advice,goal(_:_),call] -[true(assert_line_reached),flit], _).
Note that assert_line_reached/0
succeeds even if no source
information is available. This is to avoid the creation of procedure
boxes (if the action part fails, a procedure box is created).
Arbitrary tests can be used in execution_state/1
, if it is called
from within a true
condition. It can also be called from outside
the debugger, but then only a subset of conditions is available.
Furthermore, the built-in predicate execution_state/2
allows
accessing information from past debugger states (see Accessing Past Debugger States.
The built-in predicates remove_breakpoints(BIDs)
,
disable_breakpoints(BIDs)
and enable_breakpoints(BIDs)
serve for removing, disabling and enabling the given breakpoints. Here
BIDs can be a single breakpoint identifier, a list of these, or
one of the atoms all
, advice
, debugger
.
We now show an application of remove_breakpoints/1
for
implementing one-off breakpoints, i.e. breakpoints which are removed
when first activated.
For this we need to get hold of the currently selected breakpoint
identifier. The bid(BID)
condition serves for this purpose: it
unifies its argument with the identifier of the breakpoint being
processed. The following is an example of a one-off breakpoint.
| ?- spy(foo/2, -[bid(BID),true(remove_breakpoints(BID)),leash]). % Conditional spypoint for user:foo/2 added, BID=1 true ? yes % zip | ?- foo(2, X). % Conditional spypoint for user:foo/2, BID=1, removed (last) 1 1 Call: foo(2,_402) ? z X = 1 ?
The action part of the above breakpoint calls the bid
test to
obtain the breakpoint identifier. It then uses this number as the
argument to the built-in predicate remove_breakpoints
, which
removes the activated breakpoint.
The built-in predicate current_breakpoint(Spec, BID,
Status, Kind)
enumerates all breakpoints present in the
debugger. Here Spec is the breakpoint spec of the breakpoint with
identifier BID, Status is on
for enabled breakpoints
and off
for disabled ones, while Kind is one of
plain
, conditional
or generic
. The Spec
returned by current_breakpoint/4
is not necessarily the same as
the one given in add_breakpoint/2
, as the breakpoint spec
is subject to some normalization, see Breakpoint Predicates.