4.3.1 Conditional compilation and program transformation
AllApplicationManualNameSummaryHelp

  • Documentation
    • Reference manual
      • Built-in Predicates
        • Loading Prolog source files
          • Conditional compilation and program transformation
            • term_expansion/2
            • expand_term/2
            • goal_expansion/2
            • expand_goal/2
            • compile_aux_clauses/1
            • dcg_translate_rule/2
            • var_property/2
            • Program transformation with source layout info
            • Conditional compilation
    • Packages
Availability:built-in
Sourceterm_expansion(+Term1, -Term2)
Dynamic and multifile predicate, normally not defined. When defined by the user all terms read during consulting are given to this predicate. If the predicate succeeds Prolog will assert Term2 in the database rather than the read term (Term1). Term2 may be a term of the form ?- Goal. or :- Goal. Goal is then treated as a directive. If Term2 is a list, all terms of the list are stored in the database or called (for directives). If Term2 is of the form below, the system will assert Clause and record the indicated source location with it:
’$source_location'(<File>, <Line>):<Clause>

When compiling a module (see chapter 6 and the directive module/2), expand_term/2 will first try term_expansion/2 in the module being compiled to allow for term expansion rules that are local to a module. If there is no local definition, or the local definition fails to translate the term, expand_term/2 will try term_expansion/2 in module user. For compatibility with SICStus and Quintus Prolog, this feature should not be used. See also expand_term/2, goal_expansion/2 and expand_goal/2.

It is possible to act on the beginning and end of a file by expanding the terms begin_of_file and end_of_file. The latter is supported by most Prolog systems that support term expansion as read_term/3 returns end_of_file on reaching the end of the input. Expanding begin_of_file may be used to initialise the compilation, for example base on the file name extension. It was added in SWI-Prolog 8.1.1.

The current macro-expansion mechanism originates from Prolog systems in the 1980s and 1990s. It has several flaws, (1) the hooks act globally (except for definitions in a module), (2) it is hard to deal with interactions between transformations, (3) macros can not be reused between modules using the normal module export/import protocol and (4) it is hard to make source code aware tools such as the graphical debugger act properly in the context of macro expansion. Several Prolog implementations have tried to implement better expansion mechanisms. None of these solve all problems and all are largely incompatible with our current macro expansion. Future versions may provide a new mechanism to solve these issues.

Controlled interaction is provided between macro expansion defined in a module and the user and system modules. Here, SWI-Prolog uses a pipeline where the result of local module expansion is the input for the expansion in user, which is the input for the expansion in system. See also section 6.10.

Scoping, i.e., make a rule defined in a module only active if this module is imported into the module being compiled, can be emulated by defining the macro globally in the user module and using prolog_load_context/2 and some logic to verify the macro expansion should apply. If (goal) expansion effectively defined inlining it is good practice to also define the predicate and have the macro expansion check that the predicate is in scope. Here is an example.

:- module(m1, [double/2]).

double(X, D) :- D is X*2.

user:goal_expansion(double(X,D), D is X*2) :-
    prolog_load_context(module, M),
    predicate_property(M:double(_,_), imported_from(m1)).

For term expansion that is not related to a specific predicate we can define a sentinel predicate rather than using the goal predicate and check it is imported into the current module to verify that the module that defines the expansion is imported into the current compilation context.