Erlang compile time macros
The Erlang enivironment is in need for a powerful macro system in order to meet the demand on code generation and simplify the process of writing generic code.
To achive this the following primitivs are introduced:
Backqouting:
`<expr>
The compiler will parse the expression and return the the abstract form of Expr. Example.
`1 => {integer,0,1}
An other example:
foo(X, Y) -> `(X + Y).
Returns
{op,L,'+',{var,L,'X'},{var,L,'Y'}}.
Where L is the linenumber used.
&<expe>
Partial eval operator. Reduce the expression by applying partial evaluation as much as possible without breaking the semantics of Erlang.
In a macro &X means replace X with the binding of X.
&`1 => {integer,1,1}
`(1+2) => {op,1,'+',{integer,1,1},{integer,1,2}}
&`(1+2) => 3
`&(1+2+X) => {op,1,'+',{integer,1,3},{var,1,'X'}}
Compile time functions
Macros are like functions and will evaluate as functions, the return value MUST however be a compilable form.
^plus(X,Y) ->
`(&X + &Y).
%% Expansion test
bar(A,B) ->
^plus(A+1, 2+B).
bar(A,B) ->
(A+1) + (2+B).
plus X={op,'+',{var,'A'},{integer,1}} Y={op,'+',{integer,2},{var,'B'}}
return the expression: {op,'+',{op,'+',{var,'A'},{integer,1}}, {op,'+',{integer,2},{var,'B'}}}
^bar(List) ->
`(&List).
^ite(Cond,Then,Else) ->
`case &Cond of
true -> &Then;
false -> &Else
end.
^may_cons(H, T) ->
`if &H == undefined -> &T;
true -> [&H|&T]
end.
Planned but not yet working:
^struct(X) ->
case X of
`if &H -> &B1 end -> {H,B1};
`case &Expr of &Cases end -> {Expr, Cases};
`(&A + &B) -> {A,B};
_ -> `false
end.
Function prototypes, using & to generate instantiated functions.
map(F, [H|T]) ->
[F(H) | map(F,T)];
map(_F, []) ->
[].
bar(X, List) ->
<map>(fun(Y) -> Y+X end, List)
1. uniq function
map_12345(F, [H|T]) ->
[F(H) | map_12345(F,T)];
map_12345(_F, []) ->
[].
2a. substitue literal arguments
map_12345(F, Y, [H|T]) ->
[(fun(Y)->Y+X end)(H) | map_12345(F,Y,T)];
map_12345(_F, _Y, []) ->
[].
2b. partial evaluate.
map_12345(F, Y, [H|T]) ->
[H+X | map_12345(F,Y,T)];
map_12345(_F, _Y, []) ->
[].
2c. remove substituted arguments
map_12345(Y, [H|T]) ->
[H+X | map_12345(Y,T)];
map_12345(_Y, []) ->
[].
Other example:
fold(F, A, [H|T]) ->
fold(F, F(H,A), T);
fold(_F, A, []) ->
A.
test(N,List) ->
%% <fold>(fun(X,A) -> A+N end, 1, List)
fold_123(N, 1, List).
fold_123(N, A, [_|T]) ->
fold_123(N, A+N, T);
fold_123(_N, A, []) ->
N.