Amzi! Prolog includes a full source code debugger. It works on interpreted and compiled code that is running on the local or a remote machine. This makes it very easy to debug Prolog modules embedded in other languages (such as Java, C++, Delphi or VB) and Web servers (using JSP/Servlets or ASP.NET). The debugger is based on the Clocksin & Mellish box-model of Prolog execution that allows you to trace and interact with interpreted or compiled clauses as they are running.
The box model of Prolog execution is a conceptual tool that gives a procedural interpretation of flow-of-control through a Prolog program. As such it is useful for understanding the execution of a program. To use the box model envision each Prolog goal surrounded by a box:
Each box has four ports through which Prolog may enter (call and redo ports) or leave (exit or fail ports) the goal.
There is one box per goal in a program, and the boxes are linked from port to port. Ports that we stop at in the debugger are known as "debug ports."
You can single step through your program from port to port, stopping at each one. The debugger can stop at every CALL, REDO, FAIL and EXIT and ask what to do next. Alternatively, you can run until a breakpoint is reached. In this case, the intervening ports are not displayed.
When using 'Step Into' you can limit which of the ports are stopped at by selecting them from the pull-down debug menu (to the right of the step buttons). Then, when you Step Into, all the ports will be displayed, but the debugger will only break at the ones which are checked on the menu. For example, you might want to break only at CALLs and REDOs. By default, all ports are stepped into when the debugger is started.
The Eclipse Debugging Perspective looks like this:
If your screen does not look like the screen shot above, you can select Window / Reset Perspective to restore this arrangement of the views. The debugging perspective consists of the following views (starting from the top left):
In order to run or debug a Prolog component or program, the Amzi! IDE needs a 'Launch Configuration'. Launch Configurations define all the necessary parameters for the runtime or debug environment. For Prolog, these are the libraries and Logic Server extensions to load, the path to run from, source files or executable file. 'Launch Shortcuts' automatically build an appropriate Launch Configuration for the current project. See the Eclipse documentation for details.
There are four types of configurations/shortcuts for debugging: interpreted code run locally, single file interpreted code run locally, compiled code run locally and compiled code run 'remotely' (embedded in another application on the same or a different machine). The parameters for each launch configuration are:
Interpreted Project
Directory to Run From -- The directory where execution is started. This is usually the project folder because it contains the source files and the amzi.cfg configuration file.
Optional Pathname for Config File -- The full pathname of the .cfg file to use when running this project. If left blank, amzi.cfg in the run directory is used.
List of Source Files to Consult -- The files to consult into the Listener.
List of Libraries to Load -- The Amzi! libraries to load into the Listener. These are taken from the Project Properties.
List of Extensions to Load -- The Logic Server Extensions to load into the Listener. These are take from the Project Properties.
Interpreted Single File Project
Directory to Run From -- The directory where execution is started. This is usually the project folder because it contains the source files and the amzi.cfg configuration file.
Optional Pathname for Config File -- The full pathname of the .cfg file to use when running this project. If left blank, amzi.cfg in the run directory is used.
List of Source Files to Consult -- The files to consult into the Listener.
List of Libraries to Load -- The Amzi! libraries to load into the Listener. These are taken from the Project Properties.
List of Extensions to Load -- The Logic Server Extensions to load into the Listener. These are take from the Project Properties.
Compiled Project
Directory to Run From -- The directory where execution is started. This is usually the project folder because it contains the source files and the amzi.cfg configuration file.
Optional Pathname for Config File -- The full pathname of the .cfg file to use when running this project. If left blank, amzi.cfg in the run directory is used.
Compiled File to Run -- The xpl file to execute. (The libraries are linked into the xpl file). This file is usually in a bin subdirectory.
List of Extensions to Load -- The Logic Server Extensions to load into the Listener. These are take from the Project Properties.
Remote Prolog Application
Note you must set the Project Property to 'Debug' for executable file type in order to run the source code debugger on an xpl file. Do not ship files built in Debug mode as they have considerable overhead in terms of memory and CPU usage.Project Name -- The name of an open Eclipse project that corresponds to the remote Prolog application. (This is not checked, so you must ensure you have a project with source code that matches the source code used to build the remote application.)
Debug Port Number -- The port to connect to the Prolog engine on. This is set in the amzi.cfg file for the remote Prolog application.
To start the debugger select a Prolog Project in the Navigator View or an open source file editor (for a file that is in a Prolog Project), then:
Amzi! IDE |
Shortcuts Run / Debug As / Interpreted Project Run / Debug As / Compiled Project Run / Debug As / Interpreted Single File Run / Debug As / Remote Prolog Application To Create a Launch Configuration for the Selected Project Run / Debug ... New |
When debugging a remote application, you will be prompted to start it. Wait until you receive the prompt before starting the remote application. Note, you need to specify a debug_host and debug_port, and load the adebug.lsx file in your amzi.cfg file or program code before the remote debugger will operate. See Remote Debugging below.
To exit the debugger:
Amzi! IDE |
Interpreted Project Type 'quit.' in the Debug Listener or Press the 'Terminate' Button Remote Prolog Press the 'Terminate' or 'Disconnect' Button |
You can switch back to the Prolog Perspective by pressing on the Paw button on the left edge.
You can rerun your last debug session by selecting the launch configuration from either the Debug | Debug History menu or from the Debug command button.
The Amzi! Eclipse remote debugger is implemented using the TCP/IP protocol. There are two parts: the Amzi! Eclipse IDE and the LSX (adebug) that communicates on behalf of the compiled Prolog application with the IDE. The remote application must load adebug.lsx either explicitly by calling AddLSX in the host program or by specifying it in the amzi.cfg file.
You can control the port used for this communication. In the IDE this is done in the launch configuration (the default is port 8000). For the remote Prolog application, this is done in the amzi.cfg file (via debug_host and debug_port). If you are running through a firewall you will need to select a port that is open. Contact your network administrator.
Problems with the connection are reported by adebug.lsx by throwing errors to the host application. So we strongly recommend that you catch and display any errors from your calls to lsExec, lsExecStr, lsMain, lsCall, lsCallStr, lsRedo, etc.This is how you will find out if adebug.lsx is unable to connect to the Amzi! Eclipse IDE.
To initiate remote debugging, follow these steps:
The debugger works by displaying the list of active stack frames in the upper left Debug View. A stack frame includes the port name and term that execution passes through in the course of a computation. When you click on a stack frame the variable bindings are displayed in the Variables View to the right.
The stack frames take the following form:
PORT TERM VARIABLES
For example:
CALL append([a,b,c], [d,e,f], X)
Notice that variables are represented using the Hn notation.
PORT: is one of CALL, REDO, FAIL, or EXIT corresponding to the ports of the box model discussed above or blank for information-only.
TERM is the goal that caused entry to the call or redo port of the box.
VARIABLES is the list of variable bindings (you can also see these in the Variables View)
When the Debug Listener View is active you can type a goal (or other input required by your program). When it is dimmed, you can select one of the debugging actions from the Debug View tool bar. The options are:
Button | Name | Description |
Resume | Runs to the next breakpoint. | |
Suspend | Suspend the running program at the next port. | |
Terminate | Stops the debugger. | |
Step Into | Steps to the very next port. | |
Step Over | Steps over the current term to the next one. | |
Auto Step | When set, runs your code by automatically stepping into the next line at the speed set on the Debug View menu. | |
Disconnect | Disconnects a remote debugging session. | |
Listener | Opens a listener for user queries on the current debugging session. This is useful for examining or changing the dynamic database, running code and determining execution state. |
When the debugger is ready to stop at a line of code, it checks the leashing. Leashing tells the debugger which execution ports are to be displayed. The choices are the four standard ports, call, exit, redo, and fail, plus one additional pseudo-port, called info, which stops at the head of a clause. Leashing is set using the buttons. When a port is clicked, then the port will be displayed when execution stops at that line of code. The options shown are:
Button | Name | Description |
|
Display Call Ports | If not set, debugger skips call ports. |
|
Display Redo Ports | If not set, debugger skips redo ports. |
Display Fail Ports | If not set, debugger skips fail ports. | |
Display Exit Ports | If not set, debugger skips exit ports. | |
Display Clause Heads | If not set, debugger skips clause heads. |
There are also commands on the Debug View menu:
Command | Description |
Auto Step Speed
|
Select from Very Fast to Very Slow to set the speed for the Auto Step command button. |
Cut Display | Controls whether or not cut stack frames are displayed. When this feature is enabled, execution may require additional control stack space. You can increase the control stack size in the amzi.cfg file. |
DCG Variable Display |
Controls what difference list variables are displayed during execution:
|
Breakpoints are used to stop the debugger at particular predicates. Execution always pauses at a breakpoint regardless whether you are running or stepping.
Under the Amzi! IDE, you can double-click in the left margin of the Editor on the line you want to break at. A blue dot will appear. If you double-click again, the breakpoint is removed. You can also right-click in the left margin to set or clear breakpoints.
The list of all breakpoints is displayed in the Breakpoints View in the upper left. You can also clear one, some or all the breakpoints in this window.
Note that entering and exiting the IDE does not remove or otherwise alter the setting of breakpoints. The only way to remove breakpoints is to use one of the above.
As mentioned above we can either step or run to a port. When we run to a port, it is a port for a predicate that has a breakpoint set on it, and the debugger pauses to allow interaction.
Step into takes us to the ports of predicates in between the breakpoints. The debugger might pause at a port, or it may simply display it without giving you the opportunity to interact, as execution continues. The different behavior at ports is controlled by the Debug View pull-down menu.
Breaking at a specified port is not related to particular predicates, as breakpoints are, but is instead a characteristic of each of the four types of ports, CALL, REDO, FAIL and EXIT (and INFO). By default, the debugger will break at all ports, so all ports of predicates that are stepped into to are paused at. But port breaking can be turned off for the ports of these intermediate predicates so they display but don't require step-by-step interaction from you.
Let's look at an example of creeping, leaping and leashing using Duck World presented in A Quick Tutorial. First we consult our source code and enter the debugger.
Amzi! IDE |
File / Import / Existing Project into Workspace Browse to amzi/samples/prolog/duckworld Double-click on dw_rules.pro to edit it Select duckworld project folder Run / Debug As / Interpreted Project |
Next, we set connect as a breakpoint and break only the call port. Then we call main.
Amzi! IDE |
Click connect/2 in the Outline Double-click in the left margin next to the connect/2 clauses On the pull-down menu, uncheck Display Redo, Fail, Exit and Info Ports In the Debug Listener window type: ?- main. |
We start to step through the program by pressing the Step Into button. Note, we pause only on CALL ports. Notice after we step into:
write(` Welcome to Duck World `),nl,
the output appears in the Debug Listener View. Now press the Resume button. The Debug Listener View now reads:
Welcome to Duck World
... Go get an egg >> goto(yard).
Our run was interrupted for some user input, so we type "goto(yard)." We step onwards watching the variable bindings and backtracking. Every time we reach a predicate that is a breakpoint, we pause. Note that although we are only leashing CALLs, we pause at the other ports for connect/2.
When you reach a predicate that you are not interested in seeing, so press Step Over to go directly to the EXIT port. This is illustrated nicely by stepping over demons/0 in the go/0 predicate.
Finally, we end the debugger:
Amzi! IDE |
Press Terminate or type: >> quit. Quitter ?- quit. |
Copyright ©1987-2011 Amzi! inc. All Rights Reserved. Amzi! is a registered trademark and Logic Server is a trademark of Amzi! inc.