Preprocessor

Pre-processing is an ephemeral activity that takes place at read time, and none of the controls are ever seen by Prolog. It's purpose is to tailor a program for a specific environment, facilitate code sharing, and to provide succinct denotations (and hiding) of more complex code. It is based on the syntax and semantics of the C preprocessor. Preprocessor expressions are written in C functional style, not Prolog relational style.

For example, consider this small program that has macros defined for tracing and rigorous error checking that are used during debug mode, but are disabled (set to the Prolog no-op true) when not debugging. It also illustrates use of the predefined macros for date, time and line numbers.

#define DEBUG

#ifdef DEBUG
#define TRACE(X) writeq(trace - X), nl
#define CHECK(X,MSG) ( X -> true; throw(check(MSG, __LINE__)) )
#else
#define TRACE(X) true
#define CHECK(X,MSG) true
#endif

main :-
   write('Build date': __DATE__), nl,
   write('Build time': __TIME__), nl,
   catch(go, ERR, error(ERR)).

error(check(MESSAGE, LINE)) :-
   write('Error':MESSAGE),
   tab(2), write('on line':LINE),
   nl.

go :-
   A = 2,
   TRACE(`calling square with A` = A),
   CHECK(integer(A), `argument to square not an integer`),
   square(A, AA),
   write(answer:AA), nl,
   B = hi,
   TRACE(`calling square with B` = B),
   CHECK(integer(B), `argument to square not an integer`),
   square(B, BB),
   write(answer:BB), nl.

square(A, AA) :-
   AA is A * A.  

Running this program yields ths result:

Build date: 4/15/2002
Build time:17:13:24
trace - `calling square with A` = 2
answer:4
trace - `calling square with B` = hi
Error:argument to square not an integer  on line:29

Expanded macro definitions are read by Prolog and must be valid Prolog syntax, so the use of extant C macros beyond simple values requires careful consideration.

Directives

A preprocessor control directive is denoted by '#' in column one:

#if, #ifdef, #ifndef, #else, #elif, #endif, 
#define, #undef, 
#error

Controls can be block commented out.

#define

This defines a global macro which will be stored by Prolog. There can only be one macro with a given name.

A macro is strictly text replacement, expanded at load time so the arguments are text, not values, and there is no other environment. A macro body should not contain text that denotes free Prolog variables, ie. variables that are not the names of it's own arguments or the names of other macros, unless it is defining a self-contained clause to be asserted.

It consists of two parts, the definiend (head) and the definition (body). The definiend has a name and parameters, all of which must conform to Prolog syntax for variables; but they are neither, they are just names. There is a limit of 15 parameters. Each argument takes up size+1 space and the total space available is only 64. This helps to ensure that a definiend does not need more than one line of text.

The rest of the line following the definiend is the definition, which shall be text, possibly containing references to parameter names. The definition is delimited by a line feed symbol, but may employ a backslash symbol to shield a linefeed from view. Then both the backslash symbol and the linefeed are elided. Thus, the definition is stored as a single line of text with no particular limit on size.

A macro reference is a token which is the name of a defined macro, followed by its arguments (if any). It is never seen by Prolog. When a macro reference is encountered at load time it is replaced by the macro definition, which itself is expanded by replacing parameter references by arguments, and the result is expected to be a fragment of syntactically acceptable Prolog.

There is no particular limit to the size of a macro argument but it must be balanced with respect to quotes and parentheses. There is no syntactic reason for the definition itself to be balanced, but an unbalanced macro would be highly context dependent.

Some macros are pre-defined because they are are 'dynamic'. Their semantics are not constant text but depend upon hidden code at expansion time.

The following macros are pre-defined:

Macro Definition
__DATE__ expansion date
__TIME__ expansion time
__LINE__ line number

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