Hackers corner

This appendix describes a number of predicates which enable the Prolog user to inspect the Prolog environment and manipulate (or even redefine) the debugger. They can be used as entry points for experiments with debugging tools for Prolog. The predicates described here should be handled with some care as it is easy to corrupt the consistency of the Prolog system by misusing them.

.S Examining the Environment Stack

.BD .C prolog_current_frame 1 -Frame Unify Frame with an integer providing a reference to the parent of the current local stack frame. A pointer to the current local frame cannot be provided as the predicate succeeds deterministically and therefore its frame is destroyed immediately after succeeding. .C prolog_frame_attribute 3 +Frame, +Key, -Value Obtain information about the local stack frame Frame. Frame is a frame reference as obtained through prolog_current_frame/1, prolog_trace_interception/3 or this predicate. The key values are described in table [*].


Table: Key values of prolog_current_frame/1
Key Value
alternative Value is unified with an integer reference to the local stack frame in which execution is resumed if the goal associated with Frame fails. Fails if the frame has no alternative frame.
has_alternatives Value is unified with `1' if Frame still is a candidate for backtracking. `0' otherwise.
goal Value is unified with the goal associated with Frame. If the definition module of the active predicate is not user the goal is represented as module:goal. Do not instantiate variables in this goal unless you know what you are doing!
level Value is unified with the recursion level of Frame. The top level frame is at level `0'.
parent Value is unified with an integer reference to the parent local stack frame of Frame. Fails if Frame is the top frame.
context_module Value is unified with the name of the context module of the environment.
top Value is unified with `1' if Frame is the top Prolog goal from a recursive call back from the foreign language. `0' otherwise.


.ED

.S Intercepting the Tracer

.BD .C prolog_trace_interception 3 +Port, +Frame, -Action Dynamic predicate, normally not defined. This predicate is called from the SWI-Prolog debugger just before it would show a port. If this predicate succeeds the debugger assumes the trace action has been taken care of and continues execution as described by Action. Otherwise the normal Prolog debugger actions are performed.

Port is one of call, redo, exit, fail or unify. Frame is an integer reference to the current local stack frame. Action should be unified with one of the atoms continue (just continue execution), retry (retry the current goal) or fail (force the current goal to fail). Leaving it a variable is identical to continue.

Together with the predicates described in section [*] and the other predicates of this chapter this predicate enables the Prolog user to define a complete new debugger in Prolog. Besides this it enables the Prolog programmer monitor the execution of a program. The example shown in figure [*] records all goals trapped by the tracer in the database. To trace the execution of `go' this way the following query should be given:
\begin{code}
?- trace, go, notrace.
\end{code}

Figure: Record a trace in the database
\begin{figure}\begin{quote}
\begin{boxed}
\begin{code}
prolog_trace_interception...
...trace, trace(Port, Level, Goal)).
\end{code}\end{boxed}\end{quote}
\end{figure}
.C prolog_skip_level 2 -Old, +New Unify Old with the old value of `skip level' and than set this level according to New. New is an integer, or the special atom very_deep (meaning don't skip). The `skip level' is a global variable of the Prolog system that disables the debugger on all recursion levels deeper than the level of the variable. Used to implement the trace options `skip' (sets skip level to the level of the frame) and `up' (sets skip level to the level of the parent frame (i.e. the level of this frame minus 1). .ED

.S Exception Handling

A start has been made to make exception handling available to the Prolog user. On exceptions a dynamic and multifile defined predicate exception/3 is called. If this user defined predicate succeeds Prolog assumes the exception has been taken care of. Otherwise the system default exception handler is called.

.BD .C exception 3 +Exception, +Context, -Action Dynamic predicate, normally not defined. Called by the Prolog system on run-time exceptions. Currently exception/3 is only used for trapping undefined predicates. Future versions might handle signal handling, floating exceptions and other runtime errors via this mechanism. The values for Exception are described below.

undefined_predicate

If Exception is undefined_predicate Context is instantiated to a term Name/Arity. Name refers to the name and Arity to the arity of the undefined predicate. If the definition module of the predicate is not user Context will be of the form Module:Name/Arity. If the predicate fails Prolog will print the default error warning and start the tracer. If the predicate succeeds it should instantiate the last argument either to the atom fail to tell Prolog to fail the predicate or the atom retry to tell Prolog to retry the predicate. This only makes sense if the exception handler has defined the predicate. Otherwise it will lead to a loop.
warning

If prolog wants to give a warning while reading a file, it will first raise the exception warning. The context argument is a term of the form warning(Path, LineNo, Message), where Path is the absolute filename of the file prolog is reading; LineNo is an extimate of the line number where the error occurred and Message is a Prolog string indicating the message. The Action argument is ignored. The error is supposed to be presented to the user if the exception handler succeeds. Otherwise the standard Prolog warning message is printed.

This exception is used by the library emacs_interface, that integrates error handling with GNU-Emacs.

.ED