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 that
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 % 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/1
, 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/5
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
.