Node:Breakpoint Processing, Next:Breakpoint Conditions, Previous:Breakpoint Predicates, Up:Debug Intro
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:
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 non-exported 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 breakpoint search is carried
out as follows. The debugger considers all breakpoints of the given
type, most recent first. The first breakpoint, for which the evaluation
of the test part succeeds is selected. Next, the action part of the
selected breakpoint is evaluated, normally setting some debugger action
variables. If the action part succeeds, then the breakpoint search is
said to complete successfully. If the action part fails, then the
breakpoint search is still considered successful. As a side effect,
however, it is ensured that a procedure box is built (if the
command
action variable is flit
, it is changed to
proceed
). If none of the test parts evaluated successfully then
the search is said to have failed.
Now 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, command
to proceed
and show
to silent
. Next, advice-point search takes place.
If this fails, command
is set to flit
, otherwise its value
is unchanged.
Having completed the advice-point search, the command
variable is
examined. If its value is divertive, i.e. different from
proceed
and flit
, then the spypoint search stage is
omitted, and the debugger continues with the third stage. Otherwise, it
is noted if 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 (mode
is off
or
skip(_)
). First the the show
and command
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 silent
and 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 print
and
ask
for leashed ports, and print
and proceed
for
unleashed ports. In debug mode, the variables are set to silent
and proceed
, while in zip mode to silent
and flit
(Breakpoint Actions contains a tabulated listing of these
initialization values).
Having initialized the debugger action variables, spypoint search is
performed. If an empty action part has been selected in a successful
search, then show
and command
are set to print
and
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 value of
command
is checked: if it is other than ask
, then the
interactive stage ends. Otherwise, (it is ask
), the variable
show
is re-initialized to print
, or 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
repeated.
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
or
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
proceed
and proceed(Old,New)
, respectively.
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.