U S I N G P R O L O G ======================= ======================= All this stuff is a quotation from http://www.cs.sunysb.edu:80/~sbprolog/xsb-page.html Some minor changes have been included. Iluju Kiringa Getting Started with XSB ======================== Invoking XSB ------------ XSB can be invoked by the command: qew.cs> xsb -i and you will find yourself in the top level interpreter. qew.cs> xsb XSB Version 1.7.1 (7/10/97) [Solaris, optimal mode] | ?- Most of the ``standard'' Prolog predicates are supported by XSB, so those of you who consideryourselves champion entomologists, can try to test them for bugs now. Compiling XSB programs ---------------------- All source programs should be in files whose names have the suffix .P. One of the ways tocompile a program from a file in the current directory and load it into memory, is to type the query: [my_file]. where my_file is the name of the file. If you are eccentric (or you don't know how to use an editor) you can also compile and loadpredicates input directly from the terminal by using the command: [user]. A CTRL-d or the atom end_of_file followed by a period terminates the input stream. Exiting XSB ----------- If you want to exit XSB, issue the command halt. or simply type CTRL-d at the XSB prompt. To exit XSB while it is executing queries, strike CTRL-c a number of times. More on Running and Compiling ----------------------------- (IMPORTANT NOTE: Just for you to know, but not important for now) There are several command line options for the system. The general synopsis is: xsb gen_opts [-l] [-i] xsb gen_opts -n xsb gen_opts bcf_basename xsb gen_opts -f bcf_path [-a bcf_path] xsb gen_opts -f bcf_path -d The order in which these options appear makes no difference. -i Brings up the XSB interpreter. This is the normal use. -l Forces the interpreter to print unbound variables as letters, as opposed to the default setting which prints variables as memory locations prefixed with an underscore. For example, starting XSB's interpreter with this option will print the following: | ?- Y = X, Z = 3, W = foo(X,Z). Y = A X = A Z = 3 W = foo(A,3) as opposed to something like the following: | ?- Y = X, Z = 3, W = foo(X,Z). Y = _10073976 X = _10073976 Z = 3 W = foo(_10073976,3); -n used in conjunction with the -i option, to indicate that the usual read-eval-print top-loop is not to be entered, but instead to interface to a calling C program. -d Produces a disassembled dump of byte_code_file to stdout and exits. -c size Allocates initial size Kbytes of space to the trail/choice-point stack area. The trail stack grows upward from the bottom of the region, and the choice point stack grows downward from the top of the region. Because this region is expanded automatically from Version 1.6.0 onward, this option should rarely need to be used. Default initial size: 768 Kbytes. -m size Allocates size Kbytes of space to the local/global stack area. The global stack grows upward from the bottom of the region, and the local stack grows downward from the top of the region. Default: 768 Kbytes. -o size Allocates size Kbytes of space to thecompletion stack area. Because this region is expanded automatically from Version 1.6.0 onward, this option should rarely need to be used. Default initial size 64 Kbytes. -u size Allocates size Kbytes of space to the unification (and table copy) stack. Default 64 Kbytes. (This option should rarely need to be used). -D path changes the definition of XSB_DIR (which is set at installation time) to path. This option can be used when the system has been moved to a different place in your file system but not re-installed. It is also useful when you have developed your own libraries and want to use them as the default system libraries. -E filename changes the definition of the currently executing XSB executable file to filename. The name of this executable is needed by the foreign language interface. It can be used if the XSB executable is moved from where it was originally installed, or if XSB is being called from another C routine. -r Turns off automatic stack expansion. -s Maintains information on the size of program stacks for the predicate statistics/0. This option may be expected to slow execution by around 10%. Default: off. -T Generates a trace at entry to each called predicate (both system and user-defined). This option is available mainly for people who want to modify and/or extend XSB, and it is not the normal way to trace XSB programs. For the latter, the builtin predicates trace/0 or debug/0 should be used. Note: This option is not available when the system is being used at the non-tracing mode -t Traces through code at SLG-WAM instruction level. This option is for internal debugging and is not fully supported. It is also not available when the system is being used at the non-debug mode. As an example, a program which uses more heap than common might be run with the command. xsb -m 2000 -i Version 1.7.1 of XSB can also directly execute object code files from the command line interface. Suppose you have a top-level routine go in a file foo.P that you would like to run from the UNIX or DOS/Windows command line. As long as foo.P contains a directive :- go., and foo has been compiled to an object file (foo.O), then qew.cs> xsb foo will execute go, loading the appropriate files as needed. Debugging --------- There are two ways to trace programs: high-level or low-level tracing. (IMPORTANT: The high-level tracing facility is VERY USEFULL !) High-Level Tracing ------------------ To turn on tracing, use trace/0. To turn tracing off, use notrace/0. When tracing is on, thesystem will print a message each time a predicate is: 1.initially entered (Call), 2.successfully returned from (Exit), 3.failed back into (Redo), and 4.completely failed out of (Fail). At each port, a message is printed and the tracer stops and prompts for input. (See the predicatesshow/1 and leash/1 described below to modify what is traced and when the user is prompted.) In addition to single-step tracing, the user can set spy points to influence how thetracing/debugging works. A spy point is set using spy/1. Spy points can be used to cause the system to enter the tracer when a particular predicate is entered. Also the tracer allows ``leaping'' from spy point to spy point during the debugging process. When the tracer prompts for input, the user may enter a return, or a single character followed by a return, with the following meanings: c, : Creep Causes the system to single-step to the next port (i.e. either the entry to a traced predicate called by the executed clause, or the success or failure exit from that clause). a: Abort Causes execution to abort and control to return to the top level interpreter. b: Break Calls the evaluable predicate break, thus invoking recursively a new incarnation of the system interpreter. The command prompt at break level n is n: ?- The user may return to the previous break level by entering the system end-of-file character (e.g. ctrl-D), or typing in the atom end_of_file; or to the top level interpreter by typing in abort. f: Fail Causes execution to fail, thus transferring control to the Fail port of the current execution. h: Help Displays the table of debugging options. l: Leap Causes the system to resume running the program, only stopping when a spy-point is reached or the program terminates. This allows the user to follow the execution at a higher level than exhaustive tracing. n: Nodebug Turns off debug mode. q: Quasi-skip This is like Skip except that it does not mask out spy points. r: Retry (fail) Transfers to the Call port of the current goal. Note, however, that side effects, such as database modifications etc., are not undone. s: Skip Causes tracing to be turned off for the entire execution of the procedure. Thus, nothing is seen until control comes back to that procedure, either at the Success or the Failure port. e: Exit Causes immediate exit from XSB back to the operating system. Low-Level Tracing ----------------- XSB also provides a facility for low-level tracing of execution. This can be activated by invoking the emulator with the -T option, or through the predicate trace/0. It causes trace information to be printed out at every call (including those to system trap handlers). Thevolume of such trace information can very become large very quickly, so this method of tracing isnot recommended in general. Other Debugging Predicates -------------------------- debug Turns on debugging mode. This causes subsequent execution of predicates with trace or spy points to be traced, and is a no-op if there are no such predicates. The predicates trace/1 and spy/1 cause debugging mode to be turned on automatically. nodebug Turns off debugging mode. This causes trace and spy points to be ignored. Examples -------- Here are some very simple old functions of mine. Note that comments in Prolog begin with a %. % within(+ Variable, + VarList) % % Test whether Variable is in VarList. within(_,[]):-fail. within(Var,[HeadOne|_]):- Var==HeadOne. within(Var,[_|VarList]):- within(Var,VarList). % nth(+Number, +ListOfElements, -Element) % % Element is the Number-th element in the list ListOfElements. nth(N, List, Element):- N1 is N - 1, length(Head, N1), append(Head, [Element|_Rest], List). I stored them in the file test2 You can also have stored them in "test2.P". Now, I had the following session. The examples are self-explanatory. For that, keep the above subsection on "trace" in mind. Take a look on some example from Clocksin & Melish and trace it to see how to single step through the program, how to skip, to abort, ... . As you see in the examples below, your variables X, Y, Z, ... are replaced by internaly generated variables _196, _149, _70, ... . This does not matter for you to follow the calculation of your program; just do a mapping from your original variables in the new ones to grasp what is going on. qew.cs> xsb XSB Version 1.7.1 (7/10/97) [Solaris, optimal mode] | ?- [test2]. [test2 loaded] yes | ?- trace. %%%% Here I am invoking trace/0. yes [trace] | ?- within("X",[Y,Z,T,V,X,P]). [ load module hilogsym ] [ load module string ] (0) Call: within([88],[_150,_64,_78,_92,_106,_120]) ? (1) Call: within([88],[_64,_78,_92,_106,_120]) ? (2) Call: within([88],[_78,_92,_106,_120]) ? (3) Call: within([88],[_92,_106,_120]) ? (4) Call: within([88],[_106,_120]) ? (5) Call: within([88],[_120]) ? (6) Call: within([88],[]) ? (6) Fail: within([88],[]) ? (5) Fail: within([88],[_120]) ? (4) Fail: within([88],[_106,_120]) ? (3) Fail: within([88],[_92,_106,_120]) ? (2) Fail: within([88],[_78,_92,_106,_120]) ? (1) Fail: within([88],[_64,_78,_92,_106,_120]) ? (0) Fail: within([88],[_150,_64,_78,_92,_106,_120]) ? no [trace] | ?- within("X",[Y,Z,T,V,X,P]). (0) Call: within([88],[_147,_64,_78,_92,_106,_120]) ? s (0) Fail: within([88],[_147,_64,_78,_92,_106,_120]) ? no [trace] | ?- within(X,[Y,Z,T,V,X,P]). (0) Call: within(_151,[_149,_70,_84,_98,_151,_124]) ? c (1) Call: within(_182,[_70,_84,_98,_182,_124]) ? c (2) Call: within(_188,[_84,_98,_188,_124]) ? a | ?- within(X,[Y,Z,T,V,X,P]). X = _149 Y = _147 Z = _68 T = _82 V = _96 P = _122 yes | ?- within(X,[Y,Z,T,V,X,P]). X = _149 Y = _147 Z = _68 T = _82 V = _96 P = _122 yes | ?- trace. yes [trace] | ?- within(X,[Y,Z,T,V,X,P]). (0) Call: within(_151,[_149,_70,_84,_98,_151,_124]) ? c (1) Call: within(_182,[_70,_84,_98,_182,_124]) ? h creep a abort c creep f fail r retry (fail) h help n nodebug e exit b break s skip q quasi-skip l leap ? q (1) Exit: within(_196,[_70,_84,_98,_196,_124]) ? (0) Exit: within(_196,[_149,_70,_84,_98,_196,_124]) ? X = _196 Y = _149 Z = _70 T = _84 V = _98 P = _124 yes [trace] |?- notrace. %%%% Here I exit from trace. yes