next up previous index
Next: Using Libraries Up: Getting started with ECLiPSe Previous: Interaction with the Toplevel   Index

Subsections

More about compilation

Optimised Compilation

Note that the code above was compiled as traceable, which means that it can be traced using the built-in debugger or using the programmable debugger OPIUM. To obtain maximum efficiency, the directive nodbgcomp should be used, which will set some flags to produce a more efficient and shorter code
[eclipse 2]: nodbgcomp.

yes.
[eclipse 3]: [user].
 father(abraham, isaac).
 father(isaac, jacob).
 father(jacob, joseph).
 ancestor(X, Y) :- father(X, Y).
 ancestor(X, Y) :- ancestor(X, Z), ancestor(Z, Y).
  user       compiled optimized 396 bytes in 0.02 seconds

yes.
[eclipse 4]:


Compiling from a File

The square brackets [...] or compile/1 are also used to compile Prolog source from a file. If the goal
compile(myfile).
or the short-hand notation:
[myfile].
is called, either as a query at the top level or within another goal, the system looks for the file myfile or for a file called myfile.pl and compiles it into the Prolog database. The short-hand notation may also be used to compile several files in sequence
[ file_1, file_2, ...   file_n ]
The compile/2 predicate may be used to compile a file or list of files into a module specified in the second argument.

It is a recommended programming practice to give the Prolog source programs the suffix .pl or .ecl if it contains ECLiPSe specific code. It is not enforced by the system, but it simplifies managing the source programs. The compile/1 predicate automatically adds the suffix to the filename, so that it does not need to be specified; only if the literal filename can not be found, the system appends one of the valid suffixes and tries to find the resulting filename. The system's list of valid Prolog suffixes is in the global flag prolog_suffix and can be examined and modified using get_flag/2 and set_flag/2. For example, to add the new suffix ``.pro'' use:

get_flag(prolog_suffix, Old), set_flag(prolog_suffix, [".pro"|Old]).

File Queries and Directives

A file being compiled may contain queries. These are goals preceded by either the symbol ``?-'' or the symbol ``:-''. As soon as a query or command is encountered in the compilation of a file, the ECLiPSe system will try to satisfy it. In this way, in particular, a file can contain a directive to the system to compile another file, and so large programs can be split between files. When this happens, ECLiPSe interprets the pathnames of the nested compiled files relative to the directory of the parent compiled file; if e.g. the user calls
[eclipse 1]: compile('src/pl/prog').
and the file src/pl/prog.pl contains a query
:- [part1, part2].
then the system searches for the files part1.pl and part2.pl in the directory src/pl and not in the current directory. Usually larger Prolog programs have one main file which contains only commands to compile all the subfiles. In ECLiPSe it is possible to compile this main file from any directory, whereas in other Prolog systems it might be necessary to make the directory of the main file the current one, or to specify in the main file the full pathnames for all compiled subfiles.

If the compile/1 predicate is called and the system is unable to find or open the required file, it will issue an error:

[eclipse 1]: [file].
File does not exist in compile('/user/lp/eclipse/src/file')
yes.
[eclipse 2]:

If in compilation of a file file_a the compiler is directed to open or find a file file_b, but cannot do so, it will raise an exception whose default action is to write an error message and continue to compile file_a.


Compiling Procedures as Dynamic or Static

If it is intended that a procedure be altered through the use of assert/1 and retract/1, the system should be informed that the procedure will be dynamic, since these predicates are designed to work on dynamic procedures. If assert/1 is applied on a non-existing procedure, an error is raised, however the default error handler for this error only declares the procedure as dynamic and then makes the assertion.

A procedure is by default static unless it has been specifically declared as dynamic. Clauses of static procedures must always be consecutive, they may not be separated in one or more source files or by the user from the top level. If the static procedure clauses are not consecutive, each of the consecutive parts is taken as a separate procedure which redefines the previous occurrence of that procedure, and so only the last one will remain. However, whenever the compiler encounters nonconsecutive clauses of a static procedure in one file, it raises an exception whose default handler prints a warning but it continues to compile the rest of the file.

If a procedure is to be dynamic the ECLiPSe system should be given a specific dynamic declaration A dynamic declaration takes the form

:- dynamic SpecList.
The predicate is_dynamic/1 may be used to check if a procedure is dynamic:
is_dynamic(Name/Arity).
When the goal
compile(Somefile)
is executed and Somefile contains clauses for procedures that have already been defined in the Prolog database, those procedures are treated in one of two ways: If such a procedure is dynamic, its clauses compiled from Somefile are added to the database (just as would happen if they were asserted), and the existing clauses are not affected. For example, if the following clauses have already been compiled:
:- dynamic city/1.

city(london).
city(paris).
and the file Somefile contains the following Prolog code:
city(munich).
city(tokyo).
then compiling Somefile will cause adding the clauses for city/1 to those already compiled, as city/1 has been declared dynamic. Thus the query city(X) will give:
[eclipse 5]: city(X).
X = london    More? (;)

X = paris    More? (;)

X = munich    More? (;)

X = tokyo
yes.

If, however, the compiled procedure is static, the new clauses in Somefile replace the old procedure. Thus, if the following clauses have been compiled:

city(london).
city(paris).
and the file Somefile contains the following Prolog code:
city(munich).
city(tokyo).
when Somefile is compiled, then the procedure city/1 is redefined. Thus the query city(X) will give:
[eclipse 5]: city(X).
X = munich    More? (;)

X = tokyo
yes.

When the dynamic/1 declaration is used on a procedure that is already dynamic, which may happen for instance by recompiling a file with this declaration inside, the system raises the error 64, 'procedure already dynamic'. The default handler for this error, however, will only erase all existing clauses for the specified procedure, so that when such a file is recompiled several times during its debugging, the system behaves as expected, the existing clauses are always replaced. The handler for this error can of course be changed if required. If it is set to true/0, for instance, the dynamic/1 declaration is be just silently accepted without erasing any clauses and without printing an error message.

Altering Programs

The Prolog database can be updated during the execution of a program. ECLiPSe allows the user to modify procedures dynamically by adding new clauses via assert/1 and by removing some clauses via retract/1. These predicates operate on dynamic procedures; if it is required that the definition of a procedure be altered through assertion and retraction, the procedure should therefore first be declared dynamic (see the previous section). The effect of assert/1 and retract/1 on static procedures is explained below.

The effect of the goal

assert(ProcClause)
where ProcClause3.1is a clause of the procedure Proc, is as follows.
1.
If Proc has not been previously defined, the assertion raises an exception, however the default handler for this exception just declares the given procedure silently as dynamic and executes the assertion.

2.
If Proc is already defined as a dynamic procedure, the assertion adds ProcClause to the database after any clauses already existing for Proc.

3.
If Proc is already defined as a static procedure, then the assertion raises an exception.

The goal

retract(Clause)
will unify Clause with a clause on the dynamic database and remove it. If Clause does not specify a dynamic procedure, an exception is raised.

ECLiPSe's dynamic database features the so-called logical update semantics. This means that any change in the database that occurs as a result of executing one of the builtins of the abolish, assert or retract family affects only those goals that start executing afterwards. For every call to a dynamic procedure, the procedure is virtually frozen at call time.


next up previous index
Next: Using Libraries Up: Getting started with ECLiPSe Previous: Interaction with the Toplevel   Index

1999-08-06