Quintus
Prolog Manual
Quintus Prolog's source linked debugger allows you to see the source for the code you are running as you step through the debugging. It also provides convenient, window-based ways of debugging your code, and provides several optional continuously-updated views of your program's execution state as debugging proceeds.
+--------------------------------------------------------------------+---+ | - | Quintus Debugger: family.pl | o | +--------------------------------------------------------------------+---+ | File Options Debug Window Travel Help | +-----+----+----+---+----------+-----+----+--------+----------+----------+ |Creep|Skip|Leap|Zip|Quasi-skip|Retry|Fail|Frame Up|Frame Down|Frame Back| +-----+----+----+---+----------+-----+----+--------+----------+----------+ | Depth: Predicate: | +----------------------------------------------------------------------+-+ | % Family Relationships example | | | | | | % parent(?Parent, ?Child) | | | | | | parent(henry, peter). | | | parent(marie, peter). | | | parent(henry, judy). | | | parent(marie, judy). | | | parent(henry, henry2). | | | parent(marie, henry2). | | | parent(henry, susan). | | | parent(marie, susan). | | | parent(peter, peter2). | | +----------------------------------------------------------------------+-+ +----------------------------------------------------------------------+-+
This picture shows what the source-linked debugger looks like. At the top of the picture is the debugger window's title bar, which shows the name of the file currently being shown in the source code window. Below this is a menu bar showing names of the available menus. Next is a row of buttons that are used to travel between ports while debugging. Below this is a status panel that shows you useful information about the current debugging state. Finally, a scrolling window shows you where in your source code your current execution state is. All of these parts of the debugger are explained below.
The source-linked debugger is displayed either by selecting one of the first three options in the Debug pulldown in the menu bar of the QUI main window (see {manual(c-2-1-1)}), by selecting the Trace button in the interrupt dialogue (see {manual(c-2-4)}), or by turning on the debugger with the trace/0, debug/0, or prolog_flag/3 built-ins (see {manual(e-1-4-1)}).
The source linked debugger shows your place in your source code by positioning an arrow near the goal being executed or clause to be tried. The position of the arrow and the direction in which it points reflect which debugger port you are at ({manual(e-1-1)}).
The call port is shown by an arrow to the left of a goal, pointing toward it. This indicates the arrival at a goal.
descendant(X, Y) :-
---> parent(X, Y).
descendant(X, Z) :-
parent(X, Y),
descendant(Y, Z).
The exit and done ports are shown by an arrow to the right of a goal, pointing away from it. This indicates the successful completion of a goal. The exit port is distinguished from the done port by having a forked tail; this is meant to reflect the fact that this is only one of possibly many solutions to this goal. The done port signifies a determinate exit. This will help you find goals that are non-determinate and shouldn't be.
descendant(X, Y) :-
descendant(X, Y) :- parent(X, Y). --->
parent(X, Y). ===> descendant(X, Z) :-
descendant(X, Z) :- parent(X, Y),
parent(X, Y), descendant(Y, Z).
descendant(Y, Z).
The Done Port
The Exit Port
The redo port is shown by an arrow to the right of the goal, pointing toward it. This indicates that an alternate solution to a completed goal is being sought.
descendant(X, Y) :-
parent(X, Y). <---
descendant(X, Z) :-
parent(X, Y),
descendant(Y, Z).
The Redo Port
The fail port is shown by an arrow to the left of the goal, pointing away from it. This indicates that an no (more) solutions to this goal can be found.
descendant(X, Y) :-
<--- parent(X, Y).
descendant(X, Z) :-
parent(X, Y),
descendant(Y, Z).
The Fail Port
The head port is shown as an to the left of the clause, pointing toward it. This indicates which clause is about to be tried. If there are other clauses to be tried after this one, The tail of the arrow will be forked (suggesting that this is only one of possibly many clauses to be tried) and a smaller arrow will indicate the next clause to be tried. Note that indexing may mean that this is not the textually following clause.
parent(henry, peter).
parent(henry, peter). parent(marie, peter).
parent(marie, peter). parent(henry, judy).
===> parent(henry, judy). parent(marie, judy).
parent(marie, judy). parent(henry, henry2).
-> parent(henry, henry2). parent(marie, henry2).
parent(marie, henry2). ---> parent(henry, susan).
parent(henry, susan). parent(marie, susan).
parent(marie, susan).
Determinate Head Port
Nondeterminate Head Port
The exception port is shown as arrow an to the left of the goal, pointing away from it. The tail of this arrow is broken, suggesting that something may be wrong with the program or data.
descendant(X, Y, 1) :-
parent(X, Y).
descendant(X, Z, N) :-
parent(X, Y),
<- - descendant(Y, Z, N1),
N1 is N+1.
The Exception Port
Sometimes the debugger cannot find the source code for a predicate. This will happen when there is no source code, or when the correspondence between the compiled code and source code cannot be determined. For example, a dynamic predicate does not necessarily have source code, and so the debugger currently cannot show source. Similarly, a meta-call (executing a term with call/1) does not have any source code. The debugger also often cannot find the source code of clauses produced by term_expansion/2. Predicates that are compiled from "user" do not have source either!
When source linking is not possible, the debugger will show as much of the clause as it knows in place of the source file, with the appropriate arrows. At a head port, it will show the goal being called, followed by ":- ..." indicating that this goal will be matched with the head of a clause. For the head of a predicate descendent/2, it might look like this:
===> dynamic_pred(_743) :- ....
At a call port whose source code cannot be shown, the debugger will show "... :-" followed by the goal, indicating that this goal is in some unknown clause. The arrow will be as appropriate for that port. The call port for a call to descendant/2 might look like this:
... :- ---> descendant(peter, _749).
The source linked debugger provides a set of buttons to allow you to move from port to port while debugging. The debugger's travel commands are described in {manual(e-1-3)}; these buttons are labeled with the names of the commands, so using them should be straightforward.
+-----+----+----+---+----------+-----+----+- +----------+ |Creep|Skip|Leap|Zip|Quasi-skip|Retry|Fail| ... |Frame Back| +-----+----+----+---+----------+-----+----+- +----------+
The Traveling Buttons
When framed up, the skip, retry, and fail buttons operate relative to the invocation shown. Framing up is explained in {manual(e-2-4)}.
The source linked debugger also provides a set of buttons to allow you to view ancestor invocation frames.
-+--------+----------+----------+ |Frame Up|Frame Down|Frame Back| -+--------+----------+----------+
The Framing Buttons
The Frame Up button will show you the invocation before the one you are viewing. That means that the arrow will point to the place the invocation you are currently viewing was called from. Repeatedly hitting the Frame Up button will cause you to continue to traverse up through parent invocations, eventually stopping at the goal you typed at the top level prompt.
The Frame Down button may be used after you have framed up to take you back down toward the current invocation frame.
The Frame Back button will immediately take you back to the current invocation frame. This may also be used when you have framed up or scrolled the source window, and want to instantly scroll back to show the current invocation frame, or even if you are viewing another source file in the source window and want to get back.
In order to remind you when the goal you are viewing is not the current invocation frame, the arrow shown in the source window is hollow, or "ghosted", rather than the usual solid arrow.
|\
+-------+ \
| >
+-------+ /
|/
Ghost Arrow Shows Ancestor Frame
When you have framed up, certain travel buttons are interpreted relative to the frame you are currently viewing. Skip will skip over the invocation you are viewing (this is very handy if you have accidentally crept into a procedure you don't want to debug). Redo and Fail will take you to the call and fail ports of the selected invocation, respectively. All other travel buttons are disabled when you have framed up. You must either frame down or frame back in order to travel from the current invocation.
The source linked debugger has many options and commands that are invoked by menus. These are the menus available in the debugger window:
+---------------------------------------------------------+ | File Options Spypoints Window Travel Help | +---------------------------------------------------------+
Debugger Menus
Below is a description of each menu and what it is used for.
The File menu contains commands that affect the file that is being debugged, and the debugger as a whole. The file menu is selected by clicking its button in the dubber window. The commands in the File menu are:
+---------------+ | Open... | +---------------+ | Edit Source | +---------------+ |===============| +---------------+ | Nonstop | +---------------+ | Break | +---------------+ | Abort | +---------------+ |===============| +---------------+ | Quit Debugger | +---------------+
Selecting The File Menu
The Open command allows you to view another file in the source debugger window. This gives you a convenient way to set spypoints. When you select Open, the debugger pops up a dialogue which allows you to select the file to view. Note that only files that have been loaded into Prolog can be viewed. The Frame Back button, described above, provides a convenient way to return to the current debugging invocation frame.
The Edit Source command provides a quick and convenient way to begin editing the file in the debugger window. A Quintus User Interface editor window is opened on the file currently shown in the debugger window.
The Nonstop command turns off the debugger for the rest of the execution of the top-level goal. When the execution of this goal is completed, the debugger returns to its current mode (trace, debug, or zip). This option does not turn the debugger off; to turn the debugger off, you must use the Quit Debugger option, or type "nodebug." at the main Prolog prompt.
The Break command calls the built-in predicate break/0, thus suspending the execution so far and putting you at the equivalent of a new Prolog top level. (See the description of break/0 in {manual(g-11-1)}.) The new execution is separate from the suspended one, and invocation numbers will start again from 1. The debugger is turned off, and the debugger window is closed, when the break level is entered, although the spypoints and leashing of the suspended level are retained. When you end the break (by typing the end-of-file character), execution will resume and you will be prompted once again at the port which you left. Changes to leashing or to spypoints will remain in effect after the break has finished.
The Abort command aborts (abandons) the current execution. All the execution states built so far are destroyed, and execution restarts at the top level (or current break level).
The Quit Debugger command turns off the debugger altogether, just like the nodebug/0 command (see {manual(l-3)}). The debugger window is also closed at this time, since it is only open when debugging is on.
The Options menu allows you to change various aspects of the behavior of the source linked debugger. The Options menu is selected by clicking its button in the debugger window as shown.
+---------------------------+ | Print Format... | +---------------------------+ | Leashing... | +---------------------------+ |===========================| +---------------------------+ | * Creep Initially (Trace) | +---------------------------+ | o Leap Initially (Debug) | +---------------------------+ | o Zip Initially | +---------------------------+
Selecting The Options Menu
Beginning with the bottom part of the menu, the Creep, Leap, and Zip Initially toggles allow you to set the current debugging mode (see {manual(e-1-4-1)}).
The Print Format button brings up a dialogue that will allow you to change the way goals will be printed when source linkage is impossible (see {manual(e-2-2)}). This dialogue has a toggle button for each true/false write_term/[2,3] option (see Reference page), and a place to enter a print depth limit. Leaving the print depth empty (or setting it to 0) will mean that there is no depth limit; the goal will be printed in full.
+-------------------------------------------+ | * quoted * portrayed | | | | * character_escapes o number_vars | | +------+ | | o ignore_ops | 5 | max_depth | | +------+ | | +----+ +--------+ | | | Ok | | Cancel | | | +----+ +--------+ | +-------------------------------------------+
The Print Format Dialogue
The Leashing button brings up a dialogue that lets you set your leashing mode (see {manual(e-1-4-2)}).
+-----------------------------------+ | * Call * Redo | | | | * Head * Fail | | | | * Exit * Exception | | | | * Done | | | | +----+ +--------+ | | | Ok | | Cancel | | | +----+ +--------+ | +-----------------------------------+
The Leashing Dialogue
The Spypoint menu allows you to set spypoints in your code by selecting the goal to be spied with the mouse, thereby highlighting the goal, and then selecting a spy command (see {manual(e-1-3-2)} for an explanation of spypoints). You may add or remove spypoints from goals or predicates this way.
+-----------------+ | Spy Goal | +-----------------+ | Nospy Goal | +-----------------+ | Spy Predicate | +-----------------+ | Nospy Predicate | +-----------------+
Selecting The Spypoints Menu
Selecting the Spy Goal command will place a spypoint on the currently selected goal, and selecting Nospy Goal will remove the spypoint. Selecting the Spy Predicate command will place a spypoint on the predicate for which a goal (or clause head) is currently selected, and Nospy Predicate will remove the spypoint. The difference between goal and predicate spypoints is that a spypoint on a predicate will stop the debugger regardless of how that predicate is called, while a goal spypoint will only stop when the predicate is called from that particular goal.
When a spypoint is placed on a goal, a small stop-sign is placed before that goal in the debugger window, indicating that it is spied. Similarly, when a predicate is spied, a stop-sign is placed before the first clause for that predicate.
The Window menu allows you to pop up various windows which provide useful information not present in the debugger window. Selecting a window from this menu will open the specified window, or, if it is already open, cause it to pop to the front of any windows that might be covering it. This menu is available in all debugger windows.
+--------------------------+ | Debugger Window | +--------------------------+ | Bindings Window | +--------------------------+ | Standard Debugger Window | +--------------------------+ | Ancestors Window | +--------------------------+
The Windows Menu
Debugger Window refers to the main debugger window, and may be used when the debugger window is covered by other windows to bring it to the front. The other windows, the Variable Bindings Window, Standard Debugger Window, and Ancestors Window are discussed in depth below. (see {manual(e-2-7)})
The Travel Menu provides all the same commands as in the travel and framing panels, as described in {manual(e-2-3)}. They are provided in a menu for those who are more comfortable using menus, and also to document the keyboard shortcuts for the traveling and framing commands.
+----------------------+ | Creep C | | Skip S | | Leap L | | Zip Z | | Quasi-skip Q | | Retry R | | Fail F | +----------------------+ | Frame Up Ctrl + U | | Frame Down Ctrl + D | | Frame Back Ctrl + B | +----------------------+
The Travel Menu
The On This Window item opens up the help window viewing the documentation on this window. This menu is available in all debugger windows.
+----------------+ | On This Window | +----------------+
The Help Menu
The status panel is located just below the buttons in the debugger window, and shows the invocation depth of the current arrow, as well as information about the called predicate.
+-----------------------------------------------+ | Depth: 1 Predicate: descendant/2 | +-----------------------------------------------+
The Status Panel
Note that the depth shown is the depth of the frame currently being shown, so if you use the Frame Up button to show ancestors (see {manual(e-2-4)}), the depth will reflect the frame being shown.
The Predicate field first shows the module (if other than user), name, and arity of the predicate being called. Second is shown information about the predicate and the port, which is only shown when the there is something unusual or interesting to be noted about the predicate or port. The information about the predicate is one of the following:
Nothing is shown for ordinary user-defined static (compiled) procedures defined all in a single file. The debugger also gives information that may help you understand why it has stopped where it has. This information may be one of the following:
Of course, you will want to know more than just which predicate is being called or which clause is about to be tried. Other useful information includes the bindings of the variables in the goal being executed, the history of your debugging session, and the ancestors (the call stack) of the current goal. This information is available in separate windows which you may bring up using the window menu, as described in {manual(e-2-5-4)}.
The variable binding window shows the current bindings of the variables that appear in source code for the goal being called. This information is displayed in a format similar to that used when Prolog returns to the top level and shows the results of a user-typed goal.
For example, the variable bindings window might show the following:
+---+------------------------------------------------------------+ | - | Quintus Debugger Variable Bindings | +---+------------------------------------------------------------+ | File Options Window Help | +----------------------------------------------------------------+ | X = henry | | | Y = _749 | | | | | | | | +--------------------------------------------------------------+-+ +--------------------------------------------------------------+-+
The Variable Bindings Window
Unlike the other windows provided by the debugger, the variable bindings window changes its display depending on which frame is being shown in the main debugger window. This allows you to examine the current bindings for the arguments to any ancestor goal. See {manual(e-2-4)} for more information on the debugger's framing commands.
The standard debugger window shows what would be shown by the standard debugger (see {manual(e-3)}). This gives you a history of the debugging session from the time you opened the Standard Debugger window that you may scroll back through later to review what has happened. The standard debugger window might look like this:
+---+------------------------------------------------------------+ | - | Quintus Standard Debugger | +---+------------------------------------------------------------+ | File Options Window Help | +----------------------------------------------------------------+ | (2) 1 Exit: parent(henry,peter) | | | (1) 0 Exit: descendant(henry,peter) | | | (1) 0 Redo: descendant(henry,peter) | | | (2) 1 Redo: parent(henry,peter) | | | | | +--------------------------------------------------------------+-+ +--------------------------------------------------------------+-+
The Standard Debugger Window
The ancestors window shows the current invocation and all its ancestors, and is continuously updated. It can be a very powerful tool in debugging, as it lets you quickly see how variable bindings propagate to ancestor goals. The ancestors window might look like this:
+---+------------------------------------------------------------+ | - | Quintus Debugger Ancestor List | +---+------------------------------------------------------------+ | File Options Window Help | +----------------------------------------------------------------+ | (8) 3 : parent(peter2,_749) | | | (7) 2 : descendant(peter2,_749) | | | (4) 1 : descendant(peter,_749) | | | (1) 0 : descendant(henry,_749) | | | | | +--------------------------------------------------------------+-+ +--------------------------------------------------------------+-+
The Ancestors Window
Since the ancestors window is updated every time the debugger stops, when there are very many ancestors, you may notice some slowdown in the debugger. In this case, you may wish to close the ancestors window, and only open it when you really need to examine the ancestors. Usually, though, the slowdown caused by having the ancestors window open is small.
All of these extra windows have the same menus, with the same options. These menus are as follows:
+----------------------------------------------------------------+ | File Options Window Help | +----------------------------------------------------------------+
Extra Window Menus
The File menu contains only a close command, which simply closes that window:
+-------+ | Close | +-------+
The Extra Window File Menu
The Options menu contains only a Print Format command:
+-----------------+ | Print Format... | +-----------------+
The Extra Window Options Menu
Selecting Print Format will pop up a dialogue which allows you to control the printout of the information in that window. The operation of this dialogue is explained in {manual(e-2-5-2)}.
Note that changing the print format of the variable bindings window or the ancestors window will cause that window to be updated immediately, to reflect the new print format. However, changing the print format of the standard debugger window will only change the format of subsequent entries in the window; lines already written will not be changed.
contact: product
support sales information