SICStus Prolog offers the user an interactive programming environment with tools for incrementally building programs, debugging programs by following their executions, and modifying parts of programs without having to start again from scratch.
The text of a Prolog program is normally created in a file or a number of files using one of the standard text editors. The Prolog interpreter can then be instructed to read in programs from these files; this is called consulting the file. Alternatively, the Prolog compiler can be used for compiling the file.
Under UNIX, SICStus Prolog is normally started from one of the shells. On other platforms, it is normally started by clicking on an icon. However, it is often convenient to run SICStus Prolog under GNU Emacs instead. A GNU Emacs mode for SICStus Prolog is described later (see section Emacs Interface). From a shell, SICStus Prolog is started by typing:
% sicstus [-f] [-i] [-B] [-l prolog-file] \ [-P[T] [num] [-F [num]]] [-a argument...]
where the flags have the following meaning:
-f
reinitialise/0
. If the flag is omitted,
SICStus Prolog will consult this file on startup and on
reinitialise/0
, if it exists.
-i
-B
-l prolog-file
reinitialise/0
.
-P [num]
-PT [num]
-F num
-a argument...
prolog_flag(argv, Args)
, which will unify Args with
argument... represented as a list of atoms.
To start SICStus Prolog from a saved state file, issue the shell command:
% file argument...
Notice that the flags are not available in this variant--all the command line arguments are treated as Prolog arguments. The above command is equivalent to:
% sicstus -r file [-a argument...]
The Development System responds with a message of identification and the prompt `| ?- ' as soon as it is ready to accept input, thus:
SICStus 3 #0: Wed Mar 15 12:29:29 MET 1995 | ?-
At this point the top-level is expecting input of a directive, i.e. a query or command. See section Directives: Queries and Commands. You cannot type in clauses immediately (see section Inserting Clauses at the Terminal). While typing in a directive, the prompt (on following lines) becomes ` '. That is, the `| ?- ' appears only for the first line of the directive, and subsequent lines are indented.
The following environment variables can be set before starting SICStus Prolog. Some of these override the default sizes of certain areas. The sizes are given in cells:
SP_PATH
sicstus -B ...
, the value
returned by the predicate user:library_directory/1
is derived from
this environment variable if set, and otherwise from the absolute path
name of the Development System, as far as it can be determined.
The path to the Runtime Library for a Runtime System is also derived from
SP_PATH
.
Finally, commands for building foreign resources, Development Systems
and Runtime Systems are placed in `$SP_PATH/bin'.
SP_CTYPE
euc
(for EUC) and iso_8859_1
(for ISO 8859/1).
The latter is the default.
TMPDIR
GLOBALSTKSIZE
LOCALSTKSIZE
CHOICESTKSIZE
TRAILSTKSIZE
Send bug reports to <sicstus-bug@sics.se>
. Bugs tend actually to
be fixed if they can be isolated, so it is in your interest to report
them in such a way that they can be easily reproduced.
The mailing list <sicstus-users@sics.se>
is a mailing list for
communication among users and implementors. To [un]subscribe, write to
<sicstus-users-request@sics.se>
.
A program is made up of a sequence of clauses, possibly interspersed with directives to the interpreter. The clauses of a predicate do not have to be immediately consecutive, but remember that their relative order may be important (see section Procedural Semantics).
To input a program from a file file, just type the filename inside list brackets (followed by . and RET), thus:
| ?- [file].
This instructs the interpreter to read in (consult) the program. Note that it may be necessary to surround the whole file specification file with single quotes to make it a legal Prolog atom; e.g.
| ?- ['myfile.pl']. | ?- ['/usr/prolog/somefile'].
The specified file is then read in. Clauses in the file are stored so that they can later be interpreted, while any directives are obeyed as they are encountered. When the end of the file is found, the interpreter displays on the standard error stream the time spent for read-in. This indicates the completion of the directive.
Predicates that expect the name of a Prolog source file as an argument use
absolute_file_name/2
(see section Stream I/O) to look up the file.
This predicate will first search for a file with the suffix `.pl' added
to the name given as an argument. If this fails it will look for a file
with no extra suffix added. There is also support for libraries.
In general, this directive can be any list of filenames, such as:
| ?- [myprog,extras,tests].
In this case all three files would be consulted.
The clauses for all the predicates in the consulted files will replace any existing clauses for those predicates, i.e. any such previously existing clauses in the database will be deleted.
Note that consult/1
in SICStus Prolog behaves like reconsult/1
in DEC-10 Prolog.
Clauses may also be typed in directly at the terminal, although this is only recommended if the clauses will not be needed permanently, and are few in number. To enter clauses at the terminal, you must give the special directive:
| ?- [user]. |
and the new prompt `| ' shows that the interpreter is now in a state where it expects input of clauses or directives. To return to interpreter top level, type ^D. The interpreter responds thus:
{user consulted, 20 msec 200 bytes}
Directives are either queries or commands. Both are ways of directing the system to execute some goal or goals.
In the following, suppose that list membership has been defined by loading the following clauses from a file:
member(X, [X|_]). member(X, [_|L]) :- member(X, L).
(Notice the use of anonymous variables written `_'.)
The full syntax of a query is `?-' followed by a sequence of goals. The interpreter top level expects queries. This is signaled by the initial prompt `| ?- '. Thus a query at top level looks like:
| ?- member(b, [a,b,c]).
Remember that Prolog terms must terminate with a full stop (., possibly followed by layout text), and that therefore Prolog will not execute anything until you have typed the full stop (and then RET) at the end of the query.
If the goal(s) specified in a query can be satisfied, and if there are no variables as in this example, then the system answers
yes
and execution of the query terminates.
If variables are included in the query, then the final value of each variable is displayed (except for variables whose names begin with _). Thus the query
| ?- member(X, [a,b,c]).
would be answered by
X = a
At this point the interpreter is waiting for input of either just a RET or else a ; followed by RET. Simply typing RET terminates the query; the interpreter responds with `yes'. However, typing ; causes the system to backtrack (see section Procedural Semantics) looking for alternative solutions. If no further solutions can be found it outputs `no'.
The outcome of some queries is shown below, where a number preceded by _ is a system-generated name for a variable.
| ?- member(X, [tom,dick,harry]). X = tom ; X = dick ; X = harry ; no | ?- member(X, [a,b,f(Y,c)]), member(X, [f(b,Z),d]). X = f(b,c), Y = b, Z = c yes | ?- member(X, [f(_),g]). X = f(_A) yes | ?-
Commands are like queries except that
Commands start with the symbol `:-'. Any required output must be programmed explicitly; e.g. the command:
:- member(3, [1,2,3]), write(ok).
directs the system to check whether 3
belongs to the list
[1,2,3]
. Execution of a command terminates when all the goals in
the command have been successfully executed. Other alternative solutions
are not sought. If no solution can be found, the system prints:
{Warning: Goal - goal failed}
as a warning.
The principal use for commands (as opposed to queries) is to allow files to contain directives which call various predicates, but for which you do not want to have the answers printed out. In such cases you only want to call the predicates for their effect, i.e. you don't want terminal interaction in the middle of consulting the file. A useful example would be the use of a directive in a file which consults a whole list of other files, e.g.
:- [ bits, bobs, main, tests, data, junk ].
If a command like this were contained in the file `myprog' then typing the following at top-level would be a quick way of reading in your entire program:
| ?- [myprog].
When simply interacting with the top-level of the Prolog interpreter this distinction between queries and commands is not normally very important. At top-level you should just type queries normally. In a file, queries are in fact treated as commands, i.e. if you wish to execute some goals then the directive in the file must be preceded by `:-' or `?-', otherwise it would be treated as a clause.
Syntax errors are detected during reading. Each clause, directive or in
general any term read in by the built-in predicate read/1
that
fails to comply with syntax requirements is displayed on the standard
error stream as soon as it is read, along with its position in the input
stream and a mark indicating the point in the string of symbols where
the parser has failed to continue analysis, e.g.:
| member(X, X$L). ** in lines 11-12 ** ** , or ) expected in arguments ** member ( X , X ** here ** $ L ) .
if $ has not been declared as an infix operator.
Note that any comments in the faulty line are not displayed with the error
message. If you are in doubt about which clause was wrong you can use the
listing/1
predicate to list all the clauses which were successfully
read-in, e.g.
| ?- listing(member/2).
Note: The built in predicates read/(1-2)
normaly raise an exception
on syntax errors (see section Error and Exception Handling). The behavior is controlled by the
flag syntax_errors
(see prolog_flag/3
).
There is a difference between predicates that have no definition and predicates that have no clauses. The latter case is meaningful e.g. for dynamic predicates (see section Declarations) that clauses are being added to or removed from. There are good reasons for treating calls to undefined predicates as errors, as such calls easily arise from typing errors.
The system can optionally catch calls to predicates that have no
definition. First the user defined predicate
user:unknown_predicate_handler/3
(see section Error and Exception Handling) is called. If
undefined or if the call fails the action is governed by the state of
the unknown/2
flag which can be:
trace
error
fail
Calls to predicates that have no clauses are not caught.
The built-in predicate unknown(?OldState, ?NewState)
unifies OldState with the current state and sets the state to
NewState. The built-in predicate debugging/0
prints the
value of this state along with its other information. This state is
also controlled by the flag unknown
(see prolog_flag/3
).
Execution of a program is started by giving the interpreter a directive which contains a call to one of the program's predicates.
Only when execution of one directive is complete does the interpreter become ready for another directive. However, one may interrupt the normal execution of a directive by typing ^C. This ^C interruption has the effect of suspending the execution, and the following message is displayed:
Prolog interruption (h or ? for help) ?
At this point, the Development System accepts one-letter commands corresponding to certain actions. To execute an action simply type the corresponding character (lower or upper case) followed by RET. The available commands in both Development Systems are:
The following commands are also available in the sequential Development System only:
If the standard input stream is not connected to the terminal, e.g. by redirecting standard input to a file or a pipe, the above ^C interrupt options are not available. Instead, typing ^C causes SICStus Prolog to exit, and no terminal prompts are printed.
To exit from the top-level and return to the shell, either type
^D at the top-level, or call the built-in predicate halt/0
,
or use the e (exit) command following a ^C interruption.
The Prolog system provides a way to suspend the execution of your program and to enter a new incarnation of the top level where you can issue directives to solve goals etc. This is achieved by issuing the directive (see section Program Execution And Interruption):
| ?- break.
This invokes a recursive top-level, indicated by the message:
{ Break level 1 }
You can now type queries just as if you were at top-level.
If another call of break/0
is encountered, it moves up to level 2,
and so on. To close the break and resume the execution which was
suspended, type ^D. The debugger state and current input and output
streams will be restored, and execution will be resumed at the predicate
call where it had been suspended after printing the message:
{ End break }
Alternatively, the suspended execution can be aborted by calling the
built-in predicate abort/0
.
A suspended execution can be aborted by issuing the directive:
| ?- abort.
within a break. In this case no ^D is needed to close the break;
all break levels are discarded and the system returns right back
to top-level. I/O streams remain open, but the debugger is switched off.
abort/0
may also be called from within a program.
Once a program has been read, the interpreter will have available all the information necessary for its execution. This information is called a program state.
The state of a program may be saved on disk for future execution. To save a program into a file File, type the directive:
| ?- save(File).
This predicate may be called at any time, for example it may be useful to call it in a break in order to save an intermediate execution state. The file File becomes an executable file. See section Getting Started.
Once a program has been saved into a file File, the following directive will restore the interpreter to the saved state:
| ?- restore(File).
After execution of this directive, which may be given in the same
session or at some future date, the interpreter will be in
exactly the same state as existed immediately prior to the call
to save/1
. Thus if you saved a program as follows:
| ?- save(myprog), write('myprog restored').
then on restoring you will get the message `myprog restored' printed out.
A partial program state, containing only the user defined predicates may also be saved with the directive:
| ?- save_program(File).
The file File becomes an executable file. See section Getting Started. After restoring a partial program state, the interpreter will reinitialize itself.
Note that when a new version of the Prolog system is installed, all program files saved with the old version become obsolete.
In the Muse Development System, the above predicates may only be called when the system has been adjusted to one worker; see section The Muse Model.
The save facility is not available in Runtime Systems and the predicates defined in this chapter are undefined; see section Runtime Systems.
Note: Foreign resources, see section Calling C from Prolog, are unloaded by
save/1
and save_program/1
. The names and paths of the
resources are however included in the saved state. After the save, and
after a restore of the saved state, this information is used to reload
the foreign resources again. The state of the foreign resource in terms
of global C variables and allocated memory is thus not
preserved. Foreign resources may define init and deinit
functions to take special action upon loading and unloading, see section Init and Deinit Functions.
This section explains how to use the GNU Emacs mode for SICStus Prolog, and how to customize your GNU Emacs environment for it.
The advantages of using SICStus in the Emacs environment are auto indentation, syntax highlighting, help on predefined predicates (requires the SICStus info files to be installed), consultation and compilation from inside Emacs, auto-fill mode, and more.
The mode was developed for GNU Emacs 19.34 but it works well for versions 19.31 through 20.2. Earlier versions may not be able to provide syntax highlighting. The mode is not guaranteed to work with GNU Emacs 18 or XEmacs.
The Emacs mode is not part of SICStus Prolog proper, but is included in the distribution for convenience. It was written by Emi l{@AA}str{@oe}m, Milan Zamazal and based on an earlier version of the mode written by Masanobu Umeda. Contributions has also been made by Johan Andersson, Peter Olin, Mats Carlsson, Johan Bevemyr, Stefan Andersson, and Per Danielsson (all at SICS), and Henrik B{@aa}kman at Uppsala University, Sweden. Some ideas and also a few lines of code have been borrowed (with permission) from Oz.el, the Emacs major mode for the Oz programming language, written by Ralf Scheidhauer and Michael Mehl.
Assuming the GNU Emacs mode for SICStus Prolog has been installed, inserting the following lines in your `~/.emacs' (or `_emacs' in case of Windows/DOS) will make Emacs use this mode automatically when editing files with a `.pl' extension:
(setq load-path (cons "/usr/local/lib/sicstus3" load-path)) (autoload 'run-prolog "prolog" "Start a Prolog sub-process." t) (autoload 'prolog-mode "prolog" "Major mode for editing Prolog programs." t) (setq prolog-system 'sicstus) (setq auto-mode-alist (cons '("\\.pl$" . prolog-mode) auto-mode-alist))
where the path in the first line is the file system path to prolog.el (the Emacs mode). For example `~/site-lisp' means that the file is in the user's home directory, under site-lisp. MSDOS paths can be written like `d:/programs/emacs-19.34/site-lisp'.
The last line above makes sure that files ending with `.pl' are
assumed to be Prolog files and not Perl, which is the default Emacs
setting. If this is not wanted, remove that line. It is then necessary
for the user to manually switch to prolog mode by typing M-x
prolog-mode
after opening a prolog file.
If the shell command `sicstus' is not available in the default path, then it is necessary to set the value of the environment variable `EPROLOG' to a shell command to invoke SICStus Prolog.
If the following lines are not present in `~/.emacs' we suggest they are added, so that the font-lock mode (syntax coloring support) is enabled for all major modes in Emacs that support it.
(global-font-lock-mode t) (setq font-lock-maximum-decoration t)
If one wants to add font-locking only to the prolog mode, the two lines above could be replaced by:
(add-hook 'prolog-mode-hook 'turn-on-font-lock)
If the background color of Emacs is dark and it is difficult to read the code because of the chosen colors, then it might be useful to add
(setq font-lock-background-mode 'dark)
A prolog process can be started by choosing Run Prolog from the menu, by
typing C-c RET
, or by typing M-x run-prolog
. It is however
not strictly necessary to start a prolog process manually since it is
automatically done when needed. The process can be restarted (i.e. the
old one is killed and a new one is created) by typing C-u C-c RET
.
Consultation and compilation is either done via the menu or with the following key-bindings:
The boundaries used when consulting and compiling predicates are the first and last clauses of the predicate the cursor is currently in.
Other useful key-bindings are:
comment-column
. This comment will always
stay at this position when the line is indented, regardless of changes
in the text earlier on the line, provided that
prolog-align-comments-flag
is set to `t'.
If working with an application split into several modules, it is recommended to let the source files begin with a "mode line":
%%% -*- Module: ModuleName; -*-
The Emacs interface will look for the mode line and notify the SICStus Prolog module system that the predicates being incrementally reconsulted or recompiled belong to the module ModuleName. If SICStus Prolog recognizes the file as one being loaded before, it will remember what module it belongs to. If the mode line is missing, and the file has not been loaded before, the predicates will go into the type-in module. Even if the file has been loaded earlier, its filename may have a slightly different appearance to Prolog via the Emacs interface, so it is safest to always include the mode line. A mode line can be inserted by choosing Insert/Module modeline in the prolog menu.
The behavior of the Emacs mode can be controlled by a set of user
configurable settings. Some of these can be changed on the fly, while
some require Emacs to be restarted. To set a variable on the fly, type
M-x set-variable RET VariableName RET Value RET
. Note that variable
names can be completed by typing a few characters and then pressing TAB.
To set a variable so that the setting is used every time Emacs is started, add lines of the following format to ~/.emacs:
(setq VariableName Value)
The available settings are:
prolog-indent-width
prolog-align-comments-flag
nil
to prevent single %
-comments to be automatically
aligned. Defaults to t
.
Note that comments with one %
are indented to comment-column, comments
with two %
to the code level, and that comments with three %
are
never changed when indenting.
prolog-indent-mline-comments-flag
nil
to prevent indentation of text inside /*
... */
comments. Defaults t
.
prolog-object-end-to-0-flag
}
of an object definition to
prolog-indent-width. Defaults to t
.
prolog-paren-indent
p :- ( q1 ; q2, q3 ).Note that the spaces between the parentheses and the code are automatically inserted.
prolog-keywords
:- <keyword>
). Defaults to
'("block" "dynamic" "mode" "module" "multifile" "meta_predicate"
"parallel" "public" "sequential")
.
prolog-electric-newline-flag
nil
to prevent Emacs to
automatically indent the next line when pressing RET. Defaults to t
.
prolog-hungry-delete-key-flag
t
to enable deletion of all white space before the cursor
when pressing the delete key (unless inside a string or quoted
atom). Defaults to nil
.
prolog-old-sicstus-keys-flag
t
to enable the key-bindings of the old Emacs mode. These
bindings are not used by default since they violate GNU Emacs
recommendations. Defaults to nil
.
prolog-use-prolog-tokenizer-flag
nil
to use builtin functions of Emacs for parsing the
source code when indenting. This is faster than the default but does not
handle some of the syntax peculiarities of Prolog. Defaults to t
.
Some general tips and tricks for using the SICStus mode and Emacs in general are given here.
When editing large files it might happen that font-locking is not done
because the file is too large. Typing M-x lazy-lock-mode
results in that
only the visible parts of the buffer is highlighted, which is much
quicker.
If the font-locking seems to be incorrect then choose Fontify Buffer from the Prolog menu.
Auto-fill mode is enabled by typing M-x auto-fill-mode
. This
enables automatic line breaking with some features. For example, the
following multiline comment was created by typing `M-;' followed by the
text. The second line was indented and a '%' was added automatically.
dynamics([]) % A list of pit furnace % dynamic instances
There are several things to do if speed is a problem:
M-x
byte-compile-file RET Path RET
, where Path
is the path to
`prolog.el'. Do not be alarmed if there are a few warning messages
as this is normal. If all went well, there should now be a compiled
file which is used the next time Emacs is started.
prolog-use-prolog-tokenizer-flag
to nil
. This means that Emacs uses
builtin functions for some of the source code parsing, thus speeding up
things. The problem is that it does not handle all peculiarities of the
Prolog syntax, so this is a trade-off between correctness and speed.
The prolog mode uses the default Emacs colors for font-locking as far as possible. The only custom settings are in the prolog process buffer. The default settings of the colors may not agree with your preferences, so here is how to change them.
First of all, list all available faces (a face is a combined setting of
foreground and background colors, font, boldness, etc.) by typing
M-x list-faces-display
.
There are several functions that change the appearance of a face, the ones you will most likely need are:
set-face-foreground
set-face-background
set-face-underline-p
make-face-bold
make-face-bold-italic
make-face-italic
make-face-unbold
make-face-unitalic
These can be tested interactively by typing M-x
<function-name>
. You will then be asked for the name of the face to
change and a value. If the buffers are not updated according to the new
settings, then refontify the buffer using the Fontify Buffer menu entry
in the Prolog menu.
Colors are specified by a name or by RGB values. Available color names
can be listed with M-x list-colors-display
.
To store the settings of the faces, a few lines must be added to `~/.emacs'. For example:
;; Customize font-lock faces (add-hook 'font-lock-mode-hook '(lambda () (set-face-foreground font-lock-variable-name-face "#00a000") (make-face-bold font-lock-keyword-face) (set-face-foreground font-lock-reference-face "Blue") ))