Inject an abstract form when '$form' is seen

'$form' works much like '$var', only that it makes it possible to
inject ready-made abstract forms into the generated
functions/expressions.  The following call:

  gen(Name, F) ->
     codegen:gen_function(Name, fun(X) -> X =:= {'$form',F} end).

generates the following if called like this: gen(is_foo, {atom,0,foo})

  is_foo(X) ->
     X =:= foo.
This commit is contained in:
Klas Johansson 2010-10-26 21:23:11 +02:00
parent c0bfe0849b
commit 1ec65427e4
7 changed files with 66 additions and 6 deletions

View File

@ -46,4 +46,4 @@ For example, the line
`parse_transform(Forms, Options) -> any()`
_Generated by EDoc, Oct 23 2010, 21:00:45._
_Generated by EDoc, Oct 26 2010, 21:17:38._

View File

@ -125,4 +125,4 @@ Whenever record definitions need to be exported from a module,
`parse_transform(Forms, Options) -> any()`
_Generated by EDoc, Oct 23 2010, 21:00:45._
_Generated by EDoc, Oct 26 2010, 21:17:38._

View File

@ -273,4 +273,4 @@ Note that the Erlang forms are a subset of the Syntax Tools
Makes one pass
_Generated by EDoc, Oct 23 2010, 21:00:44._
_Generated by EDoc, Oct 26 2010, 21:17:38._

View File

@ -122,4 +122,31 @@ It is possible to do some limited expansion (importing a value
lists:member(17, L).
</pre>
_Generated by EDoc, Oct 23 2010, 21:00:44._
##Form substitution##
It is possible to inject abstract forms, using the construct
`{'$form', F}`, where `F` is bound to a parsed form in
the scope of the call to `gen_function/2`.
Example:
<pre>
gen(Name, F) ->
codegen:gen_function(Name, fun(X) -> X =:= {'$form',F} end).
</pre>
After transformation, calling `gen(is_foo, {atom,0,foo})` will yield the
abstract form corresponding to:
<pre>
is_foo(X) ->
X =:= foo.
</pre>
_Generated by EDoc, Oct 26 2010, 21:17:38._

View File

@ -83,4 +83,4 @@ a file could be pretty-printed using the following command:
Pretty-prints the erlang source code corresponding to Forms into Out
_Generated by EDoc, Oct 23 2010, 21:00:44._
_Generated by EDoc, Oct 26 2010, 21:17:38._

View File

@ -2,7 +2,7 @@
-compile({parse_transform, parse_trans_codegen}).
-export([f/1, g/2, h/0, i/0, gen/2, fs/0]).
-export([f/1, g/2, h/0, i/0, j/2, gen/2, fs/0]).
f(Name) ->
@ -39,6 +39,12 @@ i() ->
end
end).
j(Name, Form) ->
codegen:gen_function(
Name,
fun(L) ->
member({'$form',Form}, L)
end).
gen(Name, X) ->
codegen:gen_function(Name, fun(L) -> lists:member({'$var',X}, L) end).

View File

@ -95,6 +95,25 @@
%% contains_17(L) ->
%% lists:member(17, L).
%% </pre>
%%
%% <h2>Form substitution</h2>
%%
%% It is possible to inject abstract forms, using the construct
%% <code>{'$form', F}</code>, where `F' is bound to a parsed form in
%% the scope of the call to `gen_function/2'.
%%
%% Example:
%% <pre>
%% gen(Name, F) ->
%% codegen:gen_function(Name, fun(X) -> X =:= {'$form',F} end).
%% </pre>
%%
%% After transformation, calling `gen(is_foo, {atom,0,foo})' will yield the
%% abstract form corresponding to:
%% <pre>
%% is_foo(X) ->
%% X =:= foo.
%% </pre>
%% @end
%%
parse_transform(Forms, Options) ->
@ -184,6 +203,14 @@ substitute({tuple,L0,[{atom,_,tuple},
{call, L0, {remote,L0,{atom,L0,erl_parse},
{atom,L0,abstract}},
[{var, L0, V}, {integer, L0, L}]};
substitute({tuple,L0,[{atom,_,tuple},
{integer,_,_},
{cons,_,
{tuple,_,[{atom,_,atom},{integer,_,_},{atom,_,'$form'}]},
{cons,_,
{tuple,_,[{atom,_,var},{integer,_,_},{atom,_,F}]},
{nil,_}}}]}) ->
{var, L0, F};
substitute([]) ->
[];
substitute([H|T]) ->