Compiler

The Amzi! Prolog compiler transforms Prolog source code files (.pro) into object code files (.plm). Source files must be plain text with no embedded control characters other than the newline.

The Compiler (and Linker) are automatically invoked in the IDE when you select Project | Rebuild Project or Project | Rebuild All. It is also invoked when you run or debug a compiled Prolog Projec.t

Advantages

Amzi! Prolog offers a compiler which optimizes a great deal of the searching procedure used on dynamic (or interpreted) predicates. General pattern matches are replaced by specific test-and-branch sequences of code, and procedure calls are flattened with the result that compiled programs run in much less space than their interpreted counterparts, and groups of clauses are cross-indexed to provide rapid table look up.

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.

Disadvantages

When code is compiled the code loses some features which may be important in some applications: Both of these restrictions can be ameliorated by selective intermixing of compiled and interpreted code in the same application.

Requirements

The compiler assumes that all clauses for a given predicate are contiguous and located in the same file. If they are not, then the source code containing the clauses must include the 'multifile' directive for all predicates that are defined in multiple files, and/or the 'discontiguous' directive for predicates whose clauses are not contiguous. (This is so the compiler can optimize the code for the various clauses.)

The compiler does not, by default (no discontiguous or multifile specified), accomodate split definitions of predicates. It compiles the separated clusters of continguous clauses as separate chunks of compiled code, each with the same name. So when you try to load the compiled program, when the loader reaches the second definition of a predicate you will get an error message indicating you have attempted to redefine a compiled predicate.

Directives

Interpreted code is simply loaded as dynamic clauses into the logicbase as it is 'consult'ed. The compiler, however, processes the code before compiling and may require you to specify certain directives on how you want it to proceed. The directives are summarized here and explained in greater detail in the Directives section:

There are also directives for defining a collection of predicates with a public interface called a module--see Modules for details.

Running from the IDE

Normally the compiler is invoked when you build a project by either choosing Project | Build Project or Project | Rebuild Project. Build will compile and link only the modified files in the project, whereas Rebuild compiles and links all the files.

Any compilation problems will be added to the Tasks View.

When you click on an error in the Tasks View the editor will position the cursor in the source file where the error was found.

Running from the Command-Line

There are two ways of supplying the names of files to be compiled to the compiler: The command-line can take three arguments. To use compile in prompting mode, do not specify any arguments. For example: or

Messages

When the compiler begins compiling, it indicates which clause of which predicate is being compiled by using a display of the form: 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.

Errors

Other than syntax errors, the most common cause of errors will be caused by trying to compile clauses or predicates which are too complex. In these cases you will likely receive a fatal error of the form "XXX stack full" where XXX is heap or control or local or trail. The easiest way around this trouble is to use 32-bit mode to compile the program, and set your stack sizes large enough in the .cfg file.

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.

Complex Clauses

The complexity of a clause is determined approximately by the number of variables in the clause. If this number gets too large then the compiler may fill a stack and cause a fatal error. To correct this it may be necessary to take a clause and split it into a number of smaller clauses.

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.,

To resolve this problem, cast the clause in the following form: 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.

Complex Predicates

Complex predicates generally occur because there are too many clauses in a given predicate. The precise number depends on the relative complexity of the individual clauses. The Amzi! Prolog Compiler can compile predicates with many hundreds of clauses, so in practice we do not expect this to be much of a problem.

Where it is a problem try dividing predicates into two or more predicates, e.g.,

can be replaced with a slight performance penalty by:

Main Predicate

The Prolog system treats the predicate main/0 in a special way. When Prolog initializes it looks to see if there is a definition for the predicate main/0. If there is a definition, then main/0 is proved instead of entering the listener (see the section on alis). Thus for an application to "load and run" it should contain a definition:

Then when the application loads it will immediately try to prove the user-written predicate run_user_program.

Copyright ©1987-2011 Amzi! inc. All Rights Reserved. Amzi! is a registered trademark and Logic Server is a trademark of Amzi! inc.