4.3.5 Term and Goal Expansion

During loading of source code, all terms being read in are subject to term expansion. Grammar rules is a special, built-in case of this mechanism. By defining the hook predicates user:term_expansion/6 and goal_expansion/5, you can specify any desired transformation to be done as clauses are loaded.

Term expansions are added by defining clauses for the following hook predicate. Such clauses should follow the pattern:

     :- multifile user:term_expansion/6.
     user:term_expansion(Term1, Layout1, Ids, Term2, Layout2, [token|Ids]) :- ...
             nonmember(token, Ids),
             token_expansion(Term1, Layout1, Term2, Layout2), !.

where token_expansion/4 should be a predicate defining how to transform a given Term1 into Term2. The hook is called for every Term1 read, including at end of file, represented as the term end_of_file. If it succeeds, Term2 is used for further processing; otherwise, the default grammar rule expansion is attempted. It is often useful to let a term expand to a list of directives and clauses, which will then be processed sequentially.

A key idea here is Ids, which is used to look up what expansions have already been applied. The argument is supposed to be a list of tokens, each token uniquely identifying an expansion. The tokens are arbitrary atoms, and are simply added to the input list, before expansions recursively are applied. This token list is used to avoid cyclic expansions.

The other arguments are for supporting source-linked debugging; see the reference page for details.

Goal expansions are added by defining the hook predicate:

     M:goal_expansion(Goal1, Layout1, Module, Goal2, Layout2) :- ...

which should define how to transform a given Goal1 into Goal2. Expansions are per module and should be defined in the module M in which Goal1 is locally defined. It is called for every goal occurring in a clause being loaded, asserted, or meta-called. If it succeeds, Goal2 is used for further processing, and may be arbitrarily complex.

The other arguments are for supporting source-linked debugging and passing the source module; see the reference page for details.

To invoke term expansion from a program, use:

     ?- expand_term(Term1, Term2).

which transforms Term1 into Term2 using the built-in (for grammar rules) as well as user-defined term expansion rules.

Send feedback on this subject.