This section describes in detail how the debugger handles the breakpoints. For the purpose of this section disabled breakpoints are not taken into account: whenever we refer to the existence of some breakpoint(s), we always mean the existence of enabled breakpoint(s).
The Prolog engine can be in one of the following three states with respect to the debugger:
if there are no advice-points and the debugger is either switched off, or doing a skip;
if the debugger is in trace or debug mode (creeping or leaping), or there are any generic breakpoints;
in all other cases.
In the selective debugging state only those predicate invocations are examined, for which there exists a specific breakpoint. In the full debugging state all invocations are examined, except those calling a predicate of a hidden module (but even these will be examined, if there is a specific breakpoint for them). In the no debugging state the debugger is not entered at predicate invocations.
Now we describe what the debugger does when examining an invocation of a predicate, i.e. executing its Call port. The debugger activities can be divided into three stages: advice-point processing, spypoint processing and interaction with the user. The last stage may be repeated several times before program execution continues.
The first two stages are similar, as they both search for an applicable breakpoint (spypoint or advice-point). This common breakpoint search is carried out as follows. The debugger considers all breakpoints of the given type, most recent first. For each breakpoint, the test part of the spec is evaluated, until one successful is found. Any variable bindings created in this successful evaluation are then discarded (this is implemented by enclosing it in double negation). The first breakpoint, for which the evaluation of the test part succeeds is selected. If such a breakpoint can be found, then the breakpoint search is said to have completed successfully, otherwise it is said to have failed.
If a breakpoint has been selected, then its action part is
evaluated, normally setting some debugger action variables. If the
action part fails, then as a side-effect, it is ensured that a
procedure box will be built. This is achieved by changing the
value of the
command action variable from
Having described the common breakpoint search, let us look at the
details of the first stage, advice-point processing. This stage is
executed only if there are any advice-points set. First, the
debugger action variables are initialized:
mode is set to the
current debugger mode,
silent. Next, advice-point search takes place. If this
command is set to
flit, otherwise its value is
After completing the advice-point search the
variable is examined. If its value is divertive, i.e. different from
flit, then the spypoint search stage is
omitted, and the debugger continues with the third stage. Otherwise, it
is noted that the advice-point processing has requested the building
of a procedure box (i.e.
command = proceed), and the
debugger continues with the second stage.
The second stage is spypoint processing. This stage is skipped if
the debugger is switched off or doing a skip (
skip(_)). First the
variables are re-assigned, based on the hiddenness of the
predicate being invoked, the debugger mode, and the leashing
status of the port. If the predicate is both defined in, and
called from a hidden module, then their values will be
flit. An example of this is when a
built-in predicate is called from a hidden module, e.g.
from a library. Otherwise, in trace mode, their values are
ask for leashed ports, and
proceed for unleashed ports. In
debug mode, the variables are set to
proceed, while in zip mode to
(Breakpoint Actions contains a tabulated listing of these
Having initialized the debugger action variables, the spypoint
search phase is performed. If an empty action part has been selected in
a successful search, then
command are set to
ask. The failure of the search is ignored.
The third stage is the interactive part. First, the goal in
question is displayed according to the value of
show. Next, the
command is checked: if it is other than
the interactive stage ends. Otherwise, (it is
ask), the variable
show is re-initialized to
print-Sel, if its value was of form
Method-Sel. Next, the debugger prompts the user for a
command, which is interpreted either in the standard way, or through
user:debugger_command_hook/2. In both cases the debugger action
variables are modified as requested, and the interactive part is
After the debugger went through all the three stages, it decides whether
to build a procedure box. This will happen if either the
advice-point stage or the other two stages require it. The latter
is decided by checking the
command variable: if that is
flit(Old,New), then no procedure
box is required by the spypoint part. If the advice-point
does require the building of a procedure box, then the above
command values are replaced by
At the end of the process the value of
mode will be the new
debugging mode, and
command will determine what the debugger will
do; see Action Variables.
A similar three-stage process is carried out when the debugger arrives
at a non-Call port of a predicate. The only difference is
that the building of a procedure box is not considered
flit is equivalent to
proceed), and the hiddenness of the
predicate is not taken into account.
While the Prolog system is executing the above three-stage process for any of the ports, it is said to be inside the debugger. This is relevant, because some of the conditions can only be evaluated in this context.