Node:Hooks Related to Breakpoints, Next:Programming Breakpoints, Previous:Storing User Information in the Backtrace, Up:Advanced Debugging
There are two hooks related to breakpoints.
The hook breakpoint_expansion(
Macro,
Body)
makes it
possible for the user to extend the set of allowed conditions. This hook
is called, at breakpoint addition time, with each simple test or action
within the breakpoint spec, as the Macro argument. If the hook
succeeds, then the term returned in the Body argument is
substituted for the original test or action. Note that Body can
not span both the test and the action part, i.e. it cannot contain the
- /2
operator. The whole Body will be interpreted either as
a test or as an action, depending on the context of the original
condition.
We now give a few examples for breakpoint macros. The last example defines a condition making a predicate invisible, a reformulation of the last example of the previous subsection.
:- multifile user:breakpoint_expansion/2. user:breakpoint_expansion( skip, [inv(I),skip(I)]). user:breakpoint_expansion( gpriv(Value), [goal_private(GP),true(memberchk(Value,GP))]). user:breakpoint_expansion( invisible, [silent,proceed, ( call -> get(mode(M)), gpriv(mymode(M)), skip ; exit -> gpriv(mymode(MM)), mode(MM) ; true )]). | ?- spy(foo/2, -invisible).
We first define the skip
macro, instructing the debugger to skip
the current invocation. This macro is only meaningful in the action
part.
The second clause defines the gpriv/2
macro, a generalization of
the earlier mode_memory/1
predicate. For example,
gpriv(mymode(M))
expands to
goal_private(GP),true(memberchk(mymode(M),GP))
. This
embodies the convention of using open-ended lists for the goal private
field.
Finally, the last clause implements the action macro invisible/0
,
which makes the predicate in question to disappear from the trace. The
last line shows how this macro can be used to make foo/2
invisible.
Below is an alternative implementation of the same macro. Here we use a Prolog predicate which returns the list of action variable settings to be applied at the given port. Notice that a variable can be used as a breakpoint condition, as long as this variable gets instantiated to a (simple or composite) breakpoint condition by the time it is reached in the process of breakpoint evaluation.
user:breakpoint_expansion(invisible, [true(invisible(Settings)),Settings]). invisible([proceed,silent,NewMode]) :- execution_state([mode(M),port(P),inv(Inv),goal_private(GP)]), memberchk(mymode(MM), GP), ( P == call -> MM = M, NewMode = skip(Inv) ; P = exit(_) -> NewMode = MM ; NewMode = M ).
The second hook related to breakpoints is
debugger_command_hook(
DCommand,
Actions)
. This hook
serves for customizing the behavior of the interactive debugger,
i.e. for introducing new interactive debugger commands. The hook is
called for each debugger command read in by the debugger. DCommand
contains the abstract format of the debugger command read in, as
returned by the query facility (see Query Processing). If the hook
succeeds, it should return in Actions an action part to be
evaluated as the result of the command.
If you want to redefine an existing debugger command, you should study
library('SU_messages')
to learn the abstract format of this
command, as returned by the query facility. If you want to add a new
command, it suffices to know that unrecognized debugger commands are
returned as unknown(Line,Warning)
. Here, Line
is the list
of character codes typed in, with any leading layout removed, and
Warning
is a warning message.
The following example defines the S
interactive debugger command to behave as skip at Call and Redo ports,
and as creep otherwise:
:- multifile user:debugger_command_hook/2. user:debugger_command_hook(unknown([0'S|_],_), Actions) :- execution_state([port(P),inv(I)]), Actions = [Mode,proceed,silent], ( P = call -> Mode = skip(I) ; P = redo -> Mode = skip(I) ; Mode = trace ).
Note that the silent
action is needed above; otherwise, the
trace message will be printed a second time, before continuing the
execution.
library(debugger_examples)
contains some of the above hooks, as
well as several others.