1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686
|
\chapter{Hackers corner} \label{sec:hack}
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.
\section{Examining the Environment Stack} \label{sec:manipstack}
\begin{description}
\predicate[det]{prolog_current_frame}{1}{-Frame}
Unify \arg{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.
\predicate[semidet]{prolog_current_choice}{1}{-Choice}
Unify \arg{Choice} with an integer provided a reference to the last
choice point. Fails if the current environment has no choice points.
See also prolog_choice_attribute/3.
\predicate{prolog_frame_attribute}{3}{+Frame, +Key, :Value}
Obtain information about the local stack frame \arg{Frame}. \arg{Frame}
is a frame reference as obtained through prolog_current_frame/1,
prolog_trace_interception/4 or this predicate. The key values are
described below.
\begin{description}
\termitem{alternative}{}
\arg{Value} is unified with an integer reference to the local stack
frame in which execution is resumed if the goal associated with
\arg{Frame} fails. Fails if the frame has no alternative frame.
\termitem{has_alternatives}{}
\arg{Value} is unified with \const{true} if \arg{Frame} still is a
candidate for backtracking; \const{false} otherwise.
\termitem{goal}{}
\arg{Value} is unified with the goal associated with \arg{Frame}. If the
definition module of the active predicate is not the calling context,
the goal is represented as \mbox{\tt <module>:<goal>}. Do not instantiate
variables in this goal unless you {\bf know} what you are doing!
Note that the returned term may contain references to the frame and
should be discarded before the frame terminates.%
\footnote{The returned term is actually an illegal Prolog term
that may hold references from the global to the local
stack to preserve the variable names.}
\termitem{parent_goal}{}
If \arg{Value} is instantiated to a callable term, find a frame
executing the predicate described by \arg{Value} and unify the arguments
of \arg{Value} to the goal arguments associated with the frame. This is
intended to check the current execution context. The user must ensure
the checked parent goal is not removed from the stack due to last-call
optimisation and be aware of the slow operation on deeply nested calls.
\termitem{predicate_indicator}{}
Similar to \const{goal}, but only returning the
[<module>:]<name>/<arity> term describing the term, not the actual
arguments. It avoids creating an illegal term as \const{goal} and
is used by the library \pllib{prolog_stack}.
\termitem{clause}{}
\arg{Value} is unified with a reference to the currently running clause.
Fails if the current goal is associated with a foreign (C) defined
predicate. See also nth_clause/3 and clause_property/2.
\termitem{level}{}
\arg{Value} is unified with the recursion level of \arg{Frame}. The top
level frame is at level `0'.
\termitem{parent}{}
\arg{Value} is unified with an integer reference to the parent local
stack frame of \arg{Frame}. Fails if \arg{Frame} is the top frame.
\termitem{context_module}{}
\arg{Value} is unified with the name of the context module of the
environment.
\termitem{top}{}
\arg{Value} is unified with \const{true} if \arg{Frame} is the top Prolog
goal from a recursive call back from the foreign language; \const{false}
otherwise.
\termitem{hidden}{}
\arg{Value} is unified with \const{true} if the frame is hidden from the
user, either because a parent has the hide-childs attribute (all system
predicates), or the system has no trace-me attribute.
\termitem{skipped}{}
\arg{Value} is \const{true} if this frame was skipped in the debugger.
\termitem{pc}{}
\arg{Value} is unified with the program pointer saved on behalf of the
parent goal if the parent goal is not owned by a foreign predicate or
belongs to a compound meta-call (e.g., call((a,b))).
\termitem{argument}{N}
\arg{Value} is unified with the \arg{N}-th slot of the frame. Argument
1 is the first argument of the goal. Arguments above the arity
refer to local variables. Fails silently if \arg{N} is out of range.
\end{description}
\predicate{prolog_choice_attribute}{3}{+ChoicePoint, +Key, -Value}
Extract attributes of a choice point. \arg{ChoicePoint} is a reference
to a choice point as passed to prolog_trace_interception/4 on the 3rd
argument or obtained using prolog_current_choice/1. \arg{Key} specifies
the requested information:
\begin{description}
\termitem{parent}{}
Requests a reference to the first older choice point.
\termitem{frame}{}
Requests a reference to the frame to which the choice point refers.
\termitem{type}{}
Requests the type. Defined values are \const{clause} (the goal has
alternative clauses), \const{foreign} (non-deterministic foreign
predicate), \const{jump} (clause internal choice point), \const{top}
(first dummy choice point), \const{catch} (catch/3 to allow for undo),
\const{debug} (help the debugger), or \const{none} (has been deleted).
\end{description}
This predicate is used for the graphical debugger to show the
choice point stack.
\predicate{deterministic}{1}{-Boolean}
Unifies its argument with \const{true} if no choice point exists that is
more recent than the entry of the clause in which it appears. There are
few realistic situations for using this predicate. It is used by the
prolog/0 top level to check whether Prolog should prompt the user for
alternatives. Similar results can be achieved in a more portable fashion
using call_cleanup/2.
\end{description}
\section{Ancestral cuts} \label{sec:ancestral-cut}
\begin{description}
\predicate{prolog_cut_to}{1}{+Choice}
Prunes all choice points created since \arg{Choice}. Can be used
together with prolog_current_choice/1 to implement \jargon{ancestral} cuts.
This predicate is in the hackers corner because it should not be used
in normal Prolog code. It may be used to create new high level control
structures, particularly for compatibility purposes.
Note that in the current implementation, the pruned choice points and
environment frames are \emph{not} reclaimed. As a consequence, where
predicates that are deterministic due to clause indexing, normal cuts or
\verb$(if->then;else)$ and and tail recursive run in bounded local
stack space, predicates using prolog_cut_to/1 will run out of stack.
\end{description}
\section{Intercepting the Tracer} \label{sec:tracehook}
\begin{description}
\predicate{prolog_trace_interception}{4}{+Port, +Frame, +Choice, -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 that the trace action has been taken
care of and continues execution as described by \arg{Action}. Otherwise
the normal Prolog debugger actions are performed.
\arg{Port} denotes the reason to activate the tracer (`port' in the
4/5-port, but with some additions):
\begin{description}
\termitem{call}{}
Normal entry through the call port of the 4-port debugger.
\termitem{redo}{PC}
Normal entry through the redo port of the 4-port debugger. The
\const{redo} port signals resuming a predicate to generate alternative
solutions. If \arg{PC} is 0 (zero), clause indexing has found another
clause that will be tried next. Otherwise, \arg{PC} is the program
counter in the current clause where execution continues. This implies we
are dealing with an in-clause choice point left by, e.g., \predref{;}{2}.
Note that non-determinism in foreign predicates are also handled using
an in-clause choice point.
\termitem{unify}{}
The unify port represents the \jargon{neck} instruction, signalling the
end of the head-matching process. This port is normally invisible. See
leash/1 and visible/1.
\termitem{exit}{}
The exit port signals the goal is proved. It is possible for the goal
to have alternatives. See prolog_frame_attribute/3 to examine the
goal stack.
\termitem{fail}{}
The fail port signals final failure of the goal.
\termitem{exception}{Except}
An exception is raised and still pending. This port is activated on
each parent frame of the frame generating the exception until the
exception is caught or the user restarts normal computation using
\const{retry}. \arg{Except} is the pending exception term.
\termitem{break}{PC}
A \const{break} instruction is executed. \arg{PC} is program counter.
This port is used by the graphical debugger.
\termitem{cut_call}{PC}
A cut is encountered at \arg{PC}. This port is used by the graphical
debugger to visualise the effect of the cut.
\termitem{cut_exit}{PC}
A cut has been executed. See \term{cut_call}{PC} for more information.
\end{description}
\arg{Frame} is a reference to the current local stack frame, which can
be examined using prolog_frame_attribute/3. \arg{Choice} is a reference
to the last choice point and can be examined using
prolog_choice_attribute/3. \arg{Action} must be unified with a term that
specifies how execution must continue. The following actions are
defined:
\begin{description}
\termitem{abort}{}
Abort execution. See abort/0.
\termitem{continue}{}
Continue (i.e., \jargon{creep} in the command line debugger).
\termitem{fail}{}
Make the current goal fail.
\termitem{ignore}{}
Step over the current goal without executing it.
\termitem{nodebug}{}
Continue execution in normal nodebugging mode. See nodebug/0.
\termitem{retry}{}
Retry the current frame.
\termitem{retry}{Frame}
Retry the given frame. This must be a parent of the current
frame.
\termitem{skip}{}
Skip over the current goal (i.e., \jargon{skip} in the command line debugger).
\termitem{up}{}
Skip to the parent goal (i.e., \jargon{up} in the command line debugger).
\end{description}
Together with the predicates described in \secref{debugger}
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 to monitor the execution of a program. The
example below records all goals trapped by the tracer in the database.
\begin{code}
prolog_trace_interception(Port, Frame, _PC, continue) :-
prolog_frame_attribute(Frame, goal, Goal),
prolog_frame_attribute(Frame, level, Level),
recordz(trace, trace(Port, Level, Goal)).
\end{code}
To trace the execution of `go' this way the following query should be
given:
\begin{code}
?- trace, go, notrace.
\end{code}
\predicate{prolog_skip_frame}{1}{-Frame}
Indicate \arg{Frame} as a skipped frame and set the `skip level' (see
prolog_skip_level/2 to the recursion depth of \arg{Frame}. The effect
of the skipped flag is that a redo on a child of this frame is handled
differently. First, a \const{redo} trace is called for the child, where
the skip level is set to \const{redo_in_skip}. Next, the skip level is
set to skip level of the skipped frame.
\predicate{prolog_skip_level}{2}{-Old, +New}
Unify \arg{Old} with the old value of `skip level' and then set this
level according to \arg{New}. \arg{New} is an integer, the atom
\const{very_deep} (meaning don't skip) or the atom \const{skip_in_redo}
(see prolog_skip_frame/1). The `skip level' is a setting of each
Prolog thread that disables the debugger on all recursion levels deeper
than the level of the variable. See also prolog_skip_frame/1.
\end{description}
\section{Breakpoint and watchpoint handling}
\label{sec:breakpoint}
SWI-Prolog support \jargon{breakpoints}. Breakpoints can be manipulated
with the library \pllib{prolog_breakpoints}. Setting a breakpoint
replaces a virtual machine instruction with the \const{D_BREAK}
instruction. If the virtual machine executes a \const{D_BREAK}, it
performs a callback to decide on the action to perform. This section
describes this callback, called prolog:break_hook/6.
\begin{description}
\predicate[hook,semidet]{prolog:break_hook}{6}{+Clause, +PC, +FR,
+BFR, +Expression, -Action}
\emph{Experimental}
This hook is called if the virtual machine executes a \const{D_BREAK},
set using set_breakpoint/4. \arg{Clause} and \arg{PC} identify the
breakpoint. \arg{FR} and \arg{BFR} provide the environment frame and
current choicepoint. \arg{Expression} identifies the action that is
interrupted, and is one of the following:
\begin{description}
\termitem{call}{Goal}
The instruction will call \arg{Goal}. This is generated for nearly
all instructions. Note that \arg{Goal} is semantically
equivalent to the compiled body term, but might differ
syntactically. This is notably the case when arithmetic expressions
are compiled in optimized mode (see \prologflag{optimise}). In
particular, the arguments of arithmetic expressions have already
been evaluated. Thus, \arg{A} is 3*\arg{B}, where \arg{B} equals
3 results in a term \exam{call(A is 9)} if the clause was compiled
with optimization enabled.
\termitem{!}{}
The instruction will call the cut. Because the semantics of
metacalling the cut differs from executing the cut in its
original context we do not wrap the cut in \functor{call}{1}.
\termitem{:-}{}
The breakpoint is on the \jargon{neck} instruction, i.e., after
performing the head unifications.
\termitem{exit}{}
The breakpoint is on the \jargon{exit} instruction, i.e., at the
end of the clause. Note that the exit instruction may not be reached
due to last-call optimisation.
\termitem{unify_exit}{}
The breakpoint is on the completion of an in-lined unification while
the system is not in debug mode. If the system is in debug mode,
inlined unification is returned as call(Var=Term).\footnote{This
hack will disappear if we find a good solution for applying D_BREAK
to inlined unification. Only option might be to place the break on
both the unification start and end instructions.}
\end{description}
If prolog:break_hook/6 succeeds, it must unify \arg{Action} with a value
that describes how execution must continue. Possible values for
\arg{Action} are:
\begin{description}
\termitem{continue}{}
Just continue as if no breakpoint was present.
\termitem{debug}{}
Continue in \jargon{debug mode}. See debug/0.
\termitem{trace}{}
Continue in \jargon{trace mode}. See trace/0.
\termitem{call}{Goal}
Execute \arg{Goal} instead of the goal that would be executed.
\arg{Goal} is executed as call/1, preserving (non-)determinism
and exceptions.
\end{description}
If this hook throws an exception, the exception is propagated normally.
If this hook is not defined or fails, the default action is executed.
This implies that, if the thread is in debug mode, the tracer will be
enabled (\const{trace}) and otherwise the breakpoint is ignored
(\const{continue}).
This hook allows for injecting various debugging scenarios into the
executable without recompiling. The hook can access variables of the
calling context using the frame inspection predicates. Here are some
examples.
\begin{itemize}
\item Create \jargon{conditional} breakpoints by imposing
conditions before deciding the return \const{trace}.
\item Watch variables at a specific point in the execution.
Note that binding of these variables can be monitored
using \jargon{attributed variables}, see \secref{attvar}.
\item Dynamically add \jargon{assertions} on variables
using assertion/1.
\item Wrap the \arg{Goal} into a meta-call that traces
progress of the \arg{Goal}.
\end{itemize}
\end{description}
\section{Adding context to errors: prolog_exception_hook}
\label{sec:excepthook}
The hook prolog_exception_hook/4 has been introduced in SWI-Prolog 5.6.5
to provide dedicated exception handling facilities for application
frameworks, for example non-interactive server applications that
wish to provide extensive context for exceptions for offline debugging.
\begin{description}
\predicate{prolog_exception_hook}{4}{+ExceptionIn, -ExceptionOut,
+Frame, +CatcherFrame}
This hook predicate, if defined in the module \const{user}, is between
raising an exception and handling it. It is intended to allow a program
adding additional context to an exception to simplify diagnosing the
problem. \arg{ExceptionIn} is the exception term as raised by throw/1 or
one of the built-in predicates. The output argument \arg{ExceptionOut}
describes the exception that is actually raised. \arg{Frame} is the
innermost frame. See prolog_frame_attribute/3 and the library
\pllib{prolog_stack} for getting information from this.
\arg{CatcherFrame} is a reference to the frame calling the matching
catch/3, \const{none} if the exception is not caught or \const{'C'}
if the exception is caught in C calling Prolog using the flag
\const{PL_Q_CATCH_EXCEPTION}.
The hook is run in `nodebug' mode. If it succeeds, \arg{ExceptionOut} is
considered the current exception. If it fails, \arg{ExceptionIn} is used
for further processing. The hook is \emph{never} called recursively.
The hook is \emph{not} allowed to modify \arg{ExceptionOut} in such
a way that it no longer unifies with the catching frame.
Typically, prolog_exception_hook/4 is used to fill the second argument
of \term{error}{Formal, Context} exceptions. \arg{Formal} is
defined by the ISO standard, while SWI-Prolog defines \arg{Context}
as a term \term{context}{Location, Message}. \arg{Location} is bound
to a term <name>/<arity> by the kernel. This hook can be used to add
more information on the calling context, such as a full stack trace.
Applications that use exceptions as part of normal processing must
do a quick test of the environment before starting expensive gathering
information on the state of the program.
The hook can call trace/0 to enter trace mode immediately. For example,
imagine an application performing an unwanted division by zero while all
other errors are expected and handled. We can force the debugger using
the hook definition below. Run the program in debug mode (see debug/0)
to preserve as much as possible of the error context.
\begin{code}
user:prolog_exception_hook(
error(evaluation_error(zero_divisor), _),
_, _, _) :-
trace, fail.
\end{code}
\end{description}
\section{Hooks using the exception predicate} \label{sec:exception3}
This section describes the predicate exception/3, which can be defined
by the user in the module \module{user} as a multifile predicate. Unlike
the name suggests, this is actually a \jargon{hook} predicate that has
no relation to Prolog exceptions as defined by the ISO predicates
catch/3 and throw/1.
The predicate exception/3 is called by the kernel on a couple of events,
allowing the user to `fix' errors just-in-time. The mechanism allows for
\jargon{lazy} creation of objects such as predicates.
\begin{description}
\predicate{exception}{3}{+Exception, +Context, -Action}
Dynamic predicate, normally not defined. Called by the Prolog system on
run-time exceptions that can be repaired `just-in-time'. The values
for \arg{Exception} are described below. See also catch/3 and throw/1.
If this hook predicate succeeds it must instantiate the \arg{Action}
argument to the atom \const{fail} to make the operation fail silently,
\const{retry} to tell Prolog to retry the operation or \const{error} to
make the system generate an exception. The action \const{retry} only
makes sense if this hook modified the environment such that the
operation can now succeed without error.
\begin{description}
\termitem{undefined_predicate}{}
\arg{Context} is instantiated to a predicate indicator
([module]:<name>/<arity>). If the predicate fails, Prolog will generate
an \except{existence_error} exception. The hook is intended to implement
alternatives to the built-in autoloader, such as autoloading code from
a database. Do \emph{not} use this hook to suppress existence errors on
predicates. See also \prologflag{unknown} and \secref{autoload}.
\termitem{undefined_global_variable}{}
\arg{Context} is instantiated to the name of the missing global
variable. The hook must call nb_setval/2 or b_setval/2 before returning
with the action \const{retry}.
\end{description}
\end{description}
\section{Prolog events} \label{sec:prolog-event}
Version 8.1.9 introduces a uniform mechanism to listen to events that
happen in the Prolog engine. It replaces and generalises
\nopredref{prolog_event_hook}{1}, a hook that was introduced to support
the graphical debugger. The current implementation deals with debug,
thread and dynamic database events. We expect this mechanism to deal
with more hooks in the future.
\begin{description}
\predicate{prolog_listen}{2}{+Channel, :Closure}
\nodescription
\predicate{prolog_listen}{3}{+Channel, :Closure, +Options}
Call \arg{Closure} if an event that matches \arg{Channel} happens inside
Prolog. Possible choice points are pruned as by once/1. Possible failure
is ignored, but exceptions are propagated into the environment. Multiple
closures can be associated with the same channel. Execution of the list
of closures may be terminated by an exception. Options:
\begin{description}
\termitem{as}{Location}
\arg{Location} is one of \const{first} (default) or \const{last} and
determines whether the new handler is expected as first or last.
\end{description}
Defined channels are described below. The \arg{Channel} argument is the
name of the term listed below. The arguments are added as additional
arguments to the given \arg{Closure}.
\begin{description}
\termitem{abort}{}
Called by abort/0.
\termitem{erase}{DbRef}
Called on an erased recorded database reference or clause. Note that a
retracted clauses is not immediately removed. Clauses are reclaimed by
garbage_collect_clauses/0, which is normally executed automatially in
the \const{gc} thread. This specific channel is used by clause_info/5 to
reclaim source layout of reclaimed clauses. User applications should
typically use the \arg{PredicateIndicator} channel.
\termitem{break}{Action, ClauseRef, PCOffset}
Traps events related to Prolog break points. See library
\pllib{prolog_breakpoints}
\termitem{frame_finished}{FrameRef}
Indicates that a stack frame that has been examined using
prolog_current_frame/1, prolog_frame_attribute/3 and friends has
been deleted. Used by the source level debugger to avoid that
the stack view references non-existing frames.
\termitem{thread_exit}{Thread}
Globally registered channel that is called by any thread just
before the thread is terminated.
\termitem{this_thread_exit}{}
Thread local version of the \const{thread_exit} channel that
is also used by the \term{at_exit}{Closure} option of
thread_create/3.
\termitem{PredicateIndicator}{Action, ClauseRef}
Track changes to a (dynamic) predicate. For example:
\begin{code}
:- dynamic p/1.
:- prolog_listen(p/1, updated(p/1)).
updated(Pred, Action, Context) :-
format('Updated ~p: ~p ~p~n', [Pred, Action, Context]).
\end{code}
\begin{code}
?- assert(p(a)).
Updated p/1: assertz <clause>(0x55db261709d0)
?- retractall(p(_)).
Updated p/1: retractall start(user:p(_12294))
Updated p/1: retract <clause>(0x55db261719c0)
Updated p/1: retractall end(user:p(_12294))
\end{code}
\begin{description}
\termitem{asserta}{}
\termitem{assertz}{}
A new clauses has been added as first (last) for the given
predicate.
\termitem{retract}{}
A clause was retracted from the given predicate using either
retract/1, erase/1 or retractall/1.
\termitem{retractall}{}
The begining and end of retractall/1 is indicated with
the \arg{Action} \const{retractall}. The context argument
is \term{start}{Head} or \term{end}{Head}.
\end{description}
\end{description}
\predicate{prolog_unlisten}{2}{+Channel, :Closure}
Remove matching closures registered with prolog_listen/3.
\end{description}
\section{Hooks for integrating libraries} \label{sec:intlibs}
Some libraries realise an entirely new programming paradigm on top of
Prolog. An example is XPCE which adds an object system to Prolog as
well as an extensive set of graphical primitives. SWI-Prolog provides
several hooks to improve the integration of such libraries. See also
\secref{listing} for editing hooks and \secref{printmsg} for hooking
into the message system.
\begin{description}
\predicate{prolog_list_goal}{1}{:Goal}
Hook, normally not defined. This hook is called by the 'L' command of
the tracer in the module \module{user} to list the currently called
predicate. This hook may be defined to list only relevant clauses of the
indicated \arg{Goal} and/or show the actual source code in an editor.
See also portray/1 and multifile/1.
\predicate{prolog:debug_control_hook}{1}{:Action}
Hook for the debugger control predicates that allows the creator of
more high-level programming languages to use the common front-end
predicates to control the debugger. For example, XPCE uses these hooks
to allow for spying methods rather than predicates. \arg{Action} is one
of:
\begin{description}
\termitem{spy}{Spec}
Hook in spy/1. If the hook succeeds spy/1 takes no further action.
\termitem{nospy}{Spec}
Hook in nospy/1. If the hook succeeds nospy/1 takes no further action.
If spy/1 is hooked, it is advised to place a complementary hook for
nospy/1.
\termitem{nospyall}{}
Hook in nospyall/0. Should remove all spy points. This hook is
called in a failure-driven loop.
\termitem{debugging}{}
Hook in debugging/0. It can be used in two ways. It can report
the status of the additional debug points controlled by the above
hooks and fail to let the system report the others, or it succeeds,
overruling the entire behaviour of debugging/0.
\end{description}
\predicate{prolog:help_hook}{1}{+Action}
Hook into help/0 and help/1. If the hook succeeds, the built-in actions
are not executed. For example, \exam{?- help(picture).} is caught by the
XPCE help hook to give help on the class {\em picture}. Defined actions
are:
\begin{description}
\termitem{help}{}
User entered plain help/0 to give default help. The default performs
\exam{help(help/1)}, giving help on help.
\termitem{help}{What}
Hook in help/1 on the topic \arg{What}.
\termitem{apropos}{What}
Hook in apropos/1 on the topic \arg{What}.
\end{description}
\end{description}
\section{Hooks for loading files} \label{sec:loadfilehook}
All loading of source files is achieved by load_files/2. The hook
prolog_load_file/2 can be used to load Prolog code from non-files
or even load entirely different information, such as foreign files.
\begin{description}
\predicate{prolog_load_file}{2}{+Spec, +Options}
Load a single object. If this call succeeds, load_files/2 assumes the
action has been taken care of. This hook is only called if \arg{Options}
does not contain the \term{stream}{Input} option. The hook must be
defined in the module \const{user}.
This can be used to load from unusual places as well as dealing with
Prolog code that is not represented as a Prolog source text (for example
some binary representation). For example, library \pllib{http/http_load}
loads Prolog directly from an HTTP server. See also
prolog:open_source_hook/3, which merely allows for changing how a
physical file is opened.
\predicate{prolog:open_source_hook}{3}{+Path, -Stream, +Options}
This hooks is called by the compiler to overrule the default open/3 call
\term{open}{Path, read, Stream}. \arg{Options} provide the options as
provided to load_files/2. If the hook succeeds compilation continues by
loading from the returned (input) stream. This hook is particularly
suited to support running the code to a preprocessor. See also
prolog_load_file/2.
\predicate{prolog:comment_hook}{3}{+Comments, +Pos, +Term}
This hook allows for processing comments encountered by the compiler. If
this hook is defined, the compiler calls read_term/2 with the option
\term{comments}{Comments}. If the list of comments returned by
read_term/2 is not empty it calls this comment hook with the
following arguments.
\begin{itemize}
\item \arg{Comments} is the non-empty list of comments. Each
comment is a pair \arg{Position}-\arg{String}, where
\arg{String} is a string object (see \secref{strings})
that contains the comment \emph{including} delimiters.
Consecutive line comments are returned as a single
comment.
\item \arg{Pos} is a stream-position term that describes the
starting position of \arg{Term}
\item \arg{Term} is the term read.
\end{itemize}
This hook is exploited by the documentation system. See
stream_position_data/3. See also read_term/3.
\end{description}
|