Node:Built-in Predicates for Breakpoint Handling, Next:Accessing Past Debugger States, Previous:Advice-points, Up:Advanced Debugging
This section introduces built-in predicates for evaluating breakpoint conditions, and for retrieving, deleting, disabling and enabling breakpoints.
The breakpoint spec of the last advice-point example was quite
complex. And, 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)
, and use it instead of the
assert(line_reached(F,L))
condition.
Because of the complexity of the breakpoint spec, it looks like a good
idea to move the if-then-else condition into Prolog code. This requires
that we test the line(F,L)
condition from Prolog. The built-in
predicate execution_state/1
serves for this purpose. It 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,call]-[true(assert_line_reached),flit], _).
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,
Type)
enumerates all breakpoints present in the
debugger. For example, if we call current_breakpoint
before the
invocation of foo/2
in the last example, we get this:
| ?- current_breakpoint(Spec, BID, Status, Kind, Type). Spec = [pred(user:foo/2)]-[bid(_A),true(remove_breakpoints(_A)),leash], BID = 1, Status = on, Kind = conditional(user:foo/2), Type = debugger ?
Here Spec is the breakpoint spec of the breakpoint with
identifier BID. Status is on
for enabled breakpoints
and off
for disabled ones. Kind is one of
plain(
MFunc)
, conditional(
MFunc)
or
generic
, where MFunc is the module qualified functor of the
specific breakpoint. Finally Type is the breakpoint type:
debugger
or advice
.
The Spec returned by current_breakpoint/5
is exactly the
same as the one given in add_breakpoint/2
. If the breakpoint was
created by spy/2
, then the test part is extended by a pred
condition, as exemplified above. Earlier we described some
pre-processing steps that the spec goes through, such as moving the
module qualification of the spec to certain conditions. These
transformations are performed on the copy of the breakpoint used for
testing. Independently of this, the debugger also stores the original
breakpoint which is returned by current_breakpoint/5
.