Node:Breakpoint Tests, Next:Specific and Generic Breakpoints, Previous:Processing Breakpoints, Up:Advanced Debugging
This section gives a tour of the most important simple breakpoint
tests. In all examples here, the action part will be empty. Note
that the examples are independent, so if you want to try out these, you
should get rid of the old breakpoints (e.g. using ?- nospyall.
)
before you enter a new one.
The goal(...)
test is a generalization of the
pred(...)
test, as it allows us to check the arguments of
the invocation. For example:
| ?- add_breakpoint(goal(foo(1,_)), _). % Conditional spypoint for user:foo/2 added, BID=1
The goal(G)
breakpoint test specifies that the breakpoint
should be applied only if it unifies with G
. Thus in the above
example the debugger will stop if foo/2
is called with
1
as its first argument, but not if the first argument is, say,
2
.
Note that the above breakpoint can only be used safely if the first
argument of foo/2
is input, i.e. it is never
uninstantiated at the Call port. This is because the debugger actually
unifies the term given within the goal
test with the current
goal. If foo/2
is called with a variable first argument, then the
above breakpoint instantiates the variable to 1
, which is
probably not what you intended to do!
If you have a predicate foo/2
which sometimes is called with a
variable first argument, and you want the debugger to stop when the first
argument is a specific constant (say 1
), here is what you should
do:
| ?- add_breakpoint([goal(foo(X,_)),true(X==1)], _). % Conditional spypoint for user:foo/2 added, BID=1
Here the first test, goal
, specifies that we are only interested
in invocations of foo/2
, and names the first argument of the goal
as X
. The second, the true/1
test specifies a further
condition stated as a Prolog goal: X
is identical to
1
. Thus this breakpoint will be applicable if and only if the
first argument of foo/2
is identical to
1
. Generally, an arbitrary Prolog goal can be placed inside the
true
test: the test will succeed iff the goal completes
successfully.
Both the pred
and the goal
tests may include a module
name. In fact, the first argument of add_breakpoint
is module
name expanded, and the (explicit or implicit) module name of this
argument is then inherited by default by the pred
, goal
,
and true
tests. Notice the module names inserted in the
breakpoint spec of the last example, as shown in the output of the
debugging
built-in predicate:
| ?- debugging. (...) Breakpoints: 1 * user:foo/2 if [goal(user:foo(A,B)),true(user:(A==1))]
For exported predicates, a pred
or goal
test will be
found applicable for all invocations of the predicate, irrespective of
the module they occur in. When you add the breakpoint you can use the
defining or an importing module name, but this information is not
remembered: the module name is "normalized", i.e. it is changed to
the defining module. For example:
| ?- use_module(library(lists)). (...) % module lists imported into user (...) | ?- spy user:append. % Plain spypoint for lists:append/3 added, BID=1 yes | ?- debugging. (...) Breakpoints: 1 + lists:append/3
If you would like to restrict a breakpoint to calls from within a
particular module, then you should use the module
test, e.g.
| ?- add_breakpoint([pred(append/3),module(user)], _). % Conditional spypoint for lists:append/3 added, BID=1 yes % zip | ?- append([1,2], [3,4], L). * 1 1 Call: append([1,2],[3,4],_458) ? z * 1 1 Exit: append([1,2],[3,4],[1,2,3,4]) ? L = [1,2,3,4] ? yes
With this spypoint, the debugger will only stop at the invocations of
append/3
from the user
module. In the above example the
debugger does not stop at the recursive calls to append/3
(from
within the lists
module), as would be the case with a plain
spypoint.
Note that calling module information is not kept by the compiler for the
built-in predicates, therefore the module
test will always unify
its argument with prolog
in case of compiled calls to built-ins.
There are two further interesting breakpoint tests related to
invocations: inv(Inv)
and depth(Depth)
. These unify they
arguments with the invocation number and the depth, respectively (the
two numbers shown at the beginning of each trace message). Such tests
are most often used in more complex breakpoints, but there may be some
simple cases when they are useful.
Assume you put a plain spypoint on foo/2
, and start leaping
through your program. After some time, you notice some inconsistency at
an Exit port, but you cannot go back to the Call port for retrying this
invocation, because of side effects. So you would like to restart the
whole top-level goal and get back to the Call port of the suspicious
goal as fast as possible. Here is what you can do:
| ?- spy foo/2. % Plain spypoint for user:foo/2 added, BID=1 yes | ?- debug, foo(23, X). % The debugger will first leap -- showing spypoints (debug) + 1 1 Call: foo(23,_414) ? l (...) + 81 17 Call: foo(7,_9151) ? l + 86 18 Call: foo(6,_9651) ? l + 86 18 Exit: foo(6,8) ? - % Plain spypoint for user:foo/2, BID=1, removed (last) 86 18 Exit: foo(6,8) ? * Placing spypoint on user:foo/2 with conditions: inv(86). % Conditional spypoint for user:foo/2 added, BID=1 * 86 18 Exit: foo(6,8) ? a % Execution aborted % source_info | ?- debug, foo(23, X). % The debugger will first leap -- showing spypoints (debug) * 86 18 Call: foo(6,_2480) ?
When you reach the Exit port of the suspicious invocation (number 86),
you remove the plain spypoint, and add a conditional one using the
*
debugger command. This automatically includes
pred(foo/2)
among the conditions and displays the prompt
Placing spypoint ... with conditions:
, requesting further ones.
You enter here the inv
test with the invocation number in
question, resulting in a breakpoint with the
[pred(foo/2),inv(86)]
conditions. If you restart the original
top-level goal in debug mode, the debugger immediately positions you at
the invocation with the specified number.
Note that when the debugger executes a skip or a zip command, no
procedure boxes are built. Consequently, the invocation and depth
counters are not incremented. If skip and/or zip commands were used
during the first execution, then the suspicious invocation gets an
invocation number higher than 86 in the second run. Therefore it is
better to supply the inv(I),true(I>=86)
condition to the *
debugger command, which will bring you to the first call of foo/2
at, or after invocation number 86 (which still might not be the
suspicious invocation).
In the examples, the inv
test was used both with a numeric
and a variable argument (inv(86)
and inv(I)
). This is
possible because the debugger unifies the given feature with the
argument of the test. This holds for most tests, we will
mention the exceptions.
Another similar example: if you suspect that a given predicate goes into
an infinite recursion, and would like the execution to stop when
entering this predicate somewhere inside the recursion, then you can do
the following:
| ?- add_breakpoint([pred(foo/2),depth(_D),true(_D>=100)], _). % Conditional spypoint for user:foo/2 added, BID=1 yes % zip,source_info | ?- debug, foo(200, X). % The debugger will first leap -- showing spypoints (debug) * 496 100 Call: foo(101,_12156) ?
The above breakpoint spec will cause the debugger to stop at
the first invocation of foo/2
at depth 100 or greater. Note again
that debug mode has to be entered for this to work (in zip mode no
debugging information is kept, so the depth does not change).
We now continue with tests which restrict the breakpoint to an invocation at a specific place in the code.
Assume file /home/bob/myprog.pl
contains the following Prolog
program:
p(X, U) :- % line 1 q(X, Y), % line 2 q(Y, Z), % line 3 ( \+ q(Z, _) % line 4 -> q(Z+1, U) % line 5 ; q(Z+2, U) % line 6 ). % ... q(X, Y) :- X < 10, !, Y is X+1. % line 10 q(X, Y) :- Y is X+2. % line 12
If you are interested only in the last invocation of q/2
within p/2
, you can use the following breakpoint:
| ?- add_breakpoint([pred(q/2),line('/home/bob/myprog.pl',6)], _). % Conditional spypoint for user:q/2 added, BID=1
Generally, the test line(File,Line)
holds, if the current
invocation was in line number Line
of a file whose absolute name
is File
. This test (as well as the line/1
and
file/1
tests) require the presence of source information:
the file in question had to be consulted or compiled with the
source_info
prolog flag switched on (i.e. set to on
or
emacs
).
If e.g. q/2
is called only from a single file, then the file
name need not be mentioned and a line/1
test suffices:
line(6)
. On the other hand, if we are interested in all invocations
of a predicate within a file, then we can omit the line number and use
the file(File)
test.
For Prolog programs which are interpreted (consulted or asserted),
further positioning information can be obtained, even in the absence of
source information. The test parent_pred(Pred)
unifies
Pred
with a predicate spec (of form
Module:PredName/Arity
) identifying the
predicate in which the current invocation resides, while the test
parent_pred(Pred,N)
will additionally unify N
with the
serial number of the clause containing the current goal.
For example, assuming the above myprog.pl
file is consulted, the
breakpoint below will stop when execution reaches the call of
is/2
in the second clause of q/2
:
| ?- add_breakpoint([pred(is/2),parent_pred(user:q/2,2)], _). % Conditional spypoint for prolog:is/2 added, BID=1 * Predicate prolog:is/2 compiled inline, breakable only in interpreted code yes % zip,source_info | ?- p(20, X). in scope of a goal at line 12 in /home/bob/myprog.pl * 1 1 Call: _579 is 20+2 ?
Note that one has to include an explicit module name prefix in the first
argument of parent_pred
, for the unification of the predicate
spec to succeed. Also notice the warning issued by
add_breakpoint/2
: there are some built-ins (e.g. arithmetic,
functor/3
, arg/3
, etc.), for which the compiler generates
specific inline translation, rather than the generic predicate
invocation code. Therefore compiled calls to such predicates are not
visible to the debugger.
More exact positioning information can be obtained for interpreted
programs by using the parent_clause(Cl,Sel,I)
test. This
unifies Cl
with the clause containing the current invocation,
while Sel
and I
both identify the current invocation
within the body of this clause. Sel
is unified with a
subterm selector, while I
with the serial number of the
call. This test has variants parent_clause/[1,2]
, in which only
the Cl
argument, or the Cl,Sel
arguments are present.
As an example, two further alternatives of putting a breakpoint on the
last call of q/2
within myprog.pl
(line 6) are shown
below, together with a listing showing the selectors and call serial
numbers for the body of p/2
:
| ?- add_breakpoint([pred(q/2),parent_clause((p(_,_):-_),[2,2,2])],_). | ?- add_breakpoint([pred(q/2),parent_clause((p(_,_):-_),_,5)],_). p(X, U) :- % line % call no. % subterm selector q(X, Y), % 2 1 [1] q(Y, Z), % 3 2 [2,1] ( \+ q(Z, _) % 4 3 [2,2,1,1,1] -> q(Z+1, U) % 5 4 [2,2,1,2] ; q(Z+2, U) % 6 5 [2,2,2] ). % 7
Here, the first argument of the parent_clause
test
ensures that the current invocation is in (the only clause of)
p/2
. If p/2
had more clauses, we would have to use an
additional test, say parent_pred(user:p/2,1)
, and then the
first argument of parent_clause
could be an anonymous variable.
In the examples so far the breakpoint tests referred only to the
goal in question. Therefore, the breakpoint was found applicable at all
ports of the procedure box of the predicate. We can distinguish between
ports using the port
breakpoint test:
| ?- add_breakpoint([pred(foo/2),port(call)], _).
With this breakpoint, the debugger will stop at the Call port of
foo/2
, but not at other ports. Note that the port(call)
test can be simplified to call
-- add_breakpoint/2
will recognize this as a port name, and treat it as if it were enclosed
in a port/1
functor.
Here are two equivalent formulations for a breakpoint which will cause
the debugger to stop only at the Call and Exit ports of foo/2
:
| ?- add_breakpoint([pred(foo/2),(call;exit)], _). | ?- add_breakpoint([pred(foo/2),port(P),true((P=call;P=exit(_)))], _).
In both cases we have to use disjunction. In the first example we have a
disjunctive breakpoint condition of the two simple tests
port(call)
and port(exit)
(with the port
functor
omitted). In the second case the disjunction is inside the Prolog test
within the true
test.
Notice that the two examples refer to the Exit port differently. When
you use port(P)
, where P
is a variable, then, at an exit
port, P
will be unified with either exit(nondet)
or
exit(det)
, depending on the determinacy of the exited
procedure. However, for convenience, the test port(exit)
will also succeed at Exit ports.
So in the first example above, exit
can be replaced by
exit(_)
, but the exit(_)
in the second can not be replaced
by exit
.
Finally, there is a subtle point to note with respect to activating the
debugger at non Call ports. Let us look at the following breakpoint:
| ?- add_breakpoint([pred(foo/2),fail], _).
The intention here is to have the debugger stop at only the Fail port of
foo/2
. This is very useful if foo/2
is not supposed to
fail, but we suspect that it does. The above breakpoint will behave as
expected when the debugger is leaping, but not while zipping. This is
because for the debugger to be able to stop at a non Call port, a
procedure box has to be built at the Call port of the given
invocation. However, no debugging information is collected in zip mode
by default, i.e. procedure boxes are not built. Later we will show how
to achieve the required effect, even in zip mode.