term.
Any atoms with names consisting of a dollar sign followed
by an integer are considered variables, e.g., $1, $2, $57. Two
’variables’ with the same number are considered to be equal and
for match-all either a singleton variable is used or the atom ’ ’.
Look in Figure 7 for an example.
Examples of the how the functions would look given the decla-
ration in Figure 5 are found in Figure 10 to Figure 13. The func-
tions have slightly more readable names, as has the name of the
look-ahead. The real names are much less esthetically pleasing to
avoid accidental name clashes.
The generated selection functions always have an extra priority
level, that is because it should act like a proper behaviour. The
messages on the form {system, _, _} are system messages
generated from the sys module. They are used, e.g., to suspend
process when a code upgrade is performed. The exit messages from
the parent must be observed to fulfil the shutdown protocol that is
followed by all behaviours.
In total the parse transform/2 function with auxiliary func-
tions makes circa 250 lines of code.
-selection([[{Type.1.1, Pattern.1.1},
{Type.1.2, Pattern.1.2},
...
{Type.1.n1, Pattern.1.n1}],
...
[{Type.m.1, Patter.m.1},
...
{Type.m.nm, Patter.m.nm}]]).
Figure 5. General form of declaration.
4.2 Invoking the Parse Transform
In all this we have failed to mention how we invoke the parse
transform. This was initially achieved by a compiler directive in
the callback module:
-compile({parse_transform, gen_select_server}).
This instructs the compiler to include the parse transform/2
function amongst those applied to the module.
This however means, that not only do we have the behaviour
declaration to say what behaviour were writing a callback module
for, and all that generates are checks that the right call functions
are exported, but we also have to have a separate declaration of the
parse transform.
The natural thing, would be for the behaviour declaration to
suffice. If the behaviour defines a parse transform this will be run
at compile time.
The make this work we have make some small changes to
the compiler. The compiler will if there is a behaviour compiler
attribute check the behaviour info/1 if a parse transform exists.
If one exists, that is included among the parse transforms run.
In the behaviour implementation all that has to be added is the
clause:
behaviour_info(parse_transform) -> true;
The changes made to the compiler are detailed in the Erlang
Extension Proposal included in Appendix A.