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