The following declarations and built-ins control macro expansion:
trans_function(OldTerm, NewTerm [, Module]) :- ... .At transformation time, the system will call TransPred in the module where macro/3 was invoked. The term to transform is passed as the first argument, the second is a free variable which the transformation predicate should bind to the transformed term, and the optional third argument is the module where the term is read or written.
Options is a list which may be empty (in this case the macro defaults to a local read term macro) or contain specifications from the following categories:
Here is an example of a conditional read macro:
[eclipse 1]: [user]. trans_a(a(X,Y), b(Y)) :- % transform a/2 into b/1, number(X), % but only under these X > 0. % conditions :- local macro(a/2, trans_a/2, []). user compiled traceable 204 bytes in 0.00 seconds yes. [eclipse 2]: read(X). a(1, hello). X = b(hello) % transformed yes. [eclipse 3]: read(X). a(-1, bye). X = a(-1, bye) % not transformed yes.If the transformation function fails, the term is not transformed. Thus, a(1, zzz) is transformed into b(zzz) but a(-1, zzz) is not transformed. The arguments are transformed bottom-up. It is possible to protect the subterms of a transformed term by specifying the flag protect_arg.
A term can be protected against transformation by quoting it with the ``protecting functor'' (by default it is no_macro_expansion/1):
[eclipse 4]: read(X). a(1, no_macro_expansion(a(1, zzz))). X = b(a(1, zzz)).Note that the protecting functor is itself defined as a macro:
trprotect(no_macro_expansion(X), X). :- export macro(no_macro_expansion/1, trprotect/2, [protect_arg]).
A local macro is only visible in the module where it has been defined. When it is defined as exported, then it is copied to all other modules that contain a use_module/1 or import/1 for this module. The transformation function should also be exported in this case. There are a few global macros predefined by the system, e.g. for -->/2 (grammar rules, see below) or with/2 and of/2 (structure syntax, see section 5.1). These predefined macros can be hidden by local macro definitions.
The global flag macro_expansion can be used to disable macro expansion globally, e.g. for debugging purposes. Use set_flag(macro_expansion, off) to do so.
The next example shows the use of a type macro. Suppose we want to represent integers as s/1 terms:
[eclipse 1]: [user]. tr_int(0, 0). tr_int(N, s(S)) :- N > 0, N1 is N-1, tr_int(N1, S). :- local macro(type(integer), tr_int/2, []). yes. [eclipse 2]: read(X). 3. X = s(s(s(0))) yes.When we want to convert the s/1 terms back to normal integers so that they are printed in the familiar form, we can use a write macro. Note that we first erase the read macro for integers, otherwise we would get unexpected effects since all integers occurring in the definition of tr_s/2 would turn into s/1 structures:
[eclipse 3]: erase_macro(type(integer)). yes. [eclipse 4]: [user]. tr_s(0, 0). tr_s(s(S), N) :- tr_s(S, N1), N is N1+1. :- local macro(s/1, tr_s/2, [write]). yes. [eclipse 2]: write(s(s(s(0)))). 3 yes.