You may use
an extension other than .pro for your source files, but then you must type
it in each time, rather than using the default.
The net result of all of this work is that compiled code can run twenty or thirty times faster than equivalent interpreted code, occupies less space in memory and consumes much less space to execute.
We strongly
recommend that as much code as possible be compiled once it has been developed.
The compiler
does not unintentional (no discontiguous or multifile specified) split
definitions of predicates. When you try to load the compiled program, however,
you will get an error message indicating you have attempted to redefine
a compiled predicate.
To compile a single file, select Build / Compile. The standard "file open" dialog box is displayed that allows you to select a source file to compile.
The compiler output and messages are displayed in a scrolling window for your perusal when compilation is completed.
acmp [source], [object], [listing] [source] the name of the source file (.pro) [object] the name of the object file to be created (.plm) [listing] the name of the optional listing file (PAL)To use compile in prompting mode, do not specify any arguments.
c> acmp source file [.PRO] : object file [.PLM] : listing file [.PAL] :For example:
c> acmp Amzi! Prolog Compiler Copyright (c) 1987-2000 Amzi! inc. All Rights Reserved. Source Code [.PRO]: duck2 Object Code [duck2.PLM]: Listing File [NULL.PAL]: duck2 Compiling duck2.pro |- main / 0 |- go / 0 |- go / 0 |- go / 0 [CodeSize 410 Bytes, Compile time 11 seconds.]or
c> acmp duck1 ...
|- Name / Arity_Pred_1_Clause_1 |- Name / Arity_Pred_2_Clause_2 |- ...If an error occurs a message will be printed to the screen and the error handler will be invoked. Most errors will be syntax errors. In the case of a syntax error, the offending term will be listed along with the error message.
Note that
when the compiler reads in clauses it does so by reading in all clauses
for a given predicate and the first clause of the following predicate.
Thus it is possible for a read error to occur in a clause which is not
in the predicate being compiled but is in the next predicate to be compiled.
Errors in a clause will cause the compilation of that clause to be skipped; compilation continues with the next clause.
The compiler
output is especially useful for tracking down errors due to unintentional
split-definition clauses, or "missing" predicates lost by a misplaced period.
By viewing the listing you can see if all the clause definitions are contiguous,
and if all the predicates you thought were in the file actually were.
You might also run into difficulties loading programs that contain predicates with large numbers of clauses. The .cfg file parameters maxclauses, destbuf and srcbuf can all be used to increase the capacity of the Prolog engine when loading a compiled program.
The compiler optimizes its processing of clauses with only one or zero goals in the body. This permits such clauses to be compiled more quickly. This optimization has no effect on the resulting compiled code (it just arrives at it sooner).
The downside of this is a slight chance that such a clause will cause a stack to overflow on compilation. This is usually due to having very complex clauses, e.g.,
options( [option1, ..], [option2, ..], ... [option30, ..] ).To resolve this problem, cast the clause in the following form:
options(X1, X2, .., X30) :- X1 = [option1,..], ... X30 = [option30,..].By forcing the clause to have a more complex body (and a simpler head) the optimization technique described above will not be used by the compiler.
Where it is a problem try dividing predicates into two or more predicates, e.g.,
head1 :- body1. head1 :- body2. .. head1 :- body100.can be replaced with a slight performance penalty by:
head1 :- body1. .. head1 :- body50. head1 :- head2. % New link to remaining clauses head2 :- body51. .. head2 :- body100.
It's syntax is:
:- dynamic f1/a1, f2/a2, ... fn/an.You can have multiple dynamic directives if you prefer.
For example, in this code fragment the loc/2 predicate will be interpreted while the other predicates are compiled:
:- dynamic loc/2. main :- ... loc(you, house). loc(egg, pen). goto(...
It's syntax is:
:- multifile f1/a1, f2/a2, ... fn/an.You can have multiple multifile directives if you prefer.
It's syntax is:
:- discontiguous f1/a1, f2/a2, ... fn/an.You can have multiple discontiguous directives if you prefer.
For example consider:
:- write('Starting loading the file\n'). a :- b. :- write('Half way through\n'). b :- c. :- write('All done').This file is compiled. When it is loaded (either as part of an application or as a single Prolog Object file) it will print out three lines at the terminal:
Starting loading the file Half way through All donewhile loading the two clauses. Then the listener will be entered.
The one exception to this treatment is if the body of :- is the single term op/3. In this case not only is latent expression latent_exp :- op(..) produced but op(..) is also executed as a compiler directive. This function is provided as a convenience (see above).
main :- run_user_program.Then when the application loads it will immediately try to prove the user-written predicate run_user_program.
A module is a compiled file which contains at least one of the following declarations in the source code:
:- export Name1/Arity1,... NameN/ArityN. :- import Name1/Arity1,... NameN/ArityN.We refer to these declarations as import and export lists. There may be any number of import and export lists in one module.
Modules are an optional feature of Amzi! Prolog. If there are no import/export lists then all predicates in the file are 'visible' to predicates in all other files.
:- import Name1/Arity1,.. Namen/Arityn.in a compiled file indicates that the predicates listed are defined externally to this file but are used in the body of some clauses within this file. The file is made into a module upon compilation.
It is not
necessary to explicitly import any predicate contained in the Prolog runtime
and consequently documented in this manual, although declaring such a predicate
to be imported causes no harm.
:- export Name1/Arity1,.. Namen/Arityn.in a compiled file indicates that the predicates listed are defined internally in the file but are to be made visible externally. A module which wishes to use any of the predicates would have to, in turn, import them. The occurrence of the export declaration causes the file to be made into a module upon compilation.
There is
no difference between import and export. Both directives make predicates
visible to other modules. Both names are provided for clarity and readability.
Note, this
is not the case when the source file is loaded into the interpreter. The
predicates only stay hidden in the compiled version of the file.
This allows you to construct library modules and link or load them together in applications without having to worry about support-predicates hidden inside each module colliding. Typical offenders in this regard are append/3 and member/2 which are often needed to accomplish some goal within the definition of a "bigger" predicate, but are not required outside of these definitions.
It is an error for a goal to appear in the body of a clause in a module where the predicate of that goal is neither imported (explicitly or implicitly) nor defined within the module. Attempting to load such a module (or run an application containing this module) will cause an error to occur at load timea message will be printed out and you will be returned to the operating system.
There
are some predicates which should always be exported even if they are used
only inside a compiled module. These are any predicates which are arguments
to call/1 (the interpreter), bagof/3, findall/3 or setof/3 in the
file.
:- export a1/0. a1 :- b. b :- write('First file\n'). |
:- export a2/0, b/0. a2 :- b. b :- write('Second file\n'). |
:- export doit. :- import a1/0, a2/0, b/0. doit :- a1, a2, b. |
Compile all three files and load then into the runtime system. Now give the goal:
?- doit. First file Second file Second file yesNotice that there are two definitions for b/0; however that definition in the first file is visible only in the first file (since it is not exported, and the first file is a module). Thus the b/0 in the body of "a1 :- b." refers to the code in the first file.
The b/0 in the second file is exported. The b/0 in the clause "a2 :- b/0." refers to the definition in the second file.
The third file is also a module which uses a1/0 and a2/0. It also uses b/0. Which b/0 does it use? b/0 in the first file is not exported and so it cannot be the definition from file 1, whereas the definition of b/0 in the second file is visible (being exported) and so it is this definition used in the third file.
Notice that the predicate write/1 is not explicitly declared to be imported it is a globally known as a built-in predicate.
When the loader (the portion of the runtime system responsible for loading compiled code) detects such a predicate it will print out its Name/Arity and then abort:
Cannot fixup local symbol foo/3 ABORT: Missing local predicatesIn the case where the loaded file is a linked file the name of the missing predicate will be preceded by a number (which is the number, in link order, of the file which contains the offending predicate):
Cannot fixup local symbol 4foo/3 ABORT: Missing local predicatesIn this example, foo/3 was used in the 4th file linked into the application.
If a stand-alone application has not defined the predicate main/0, or the predicate main/0 fails, then an error occurs and you are returned to the operating system with the message:
ERROR: main/0 did not succeed.
Copyright ©1987-2000 Amzi! inc. All Rights Reserved.