1 2 3# Module parse_trans_codegen # 4* [Description](#description) 5* [Function Index](#index) 6* [Function Details](#functions) 7 8Parse transform for code generation pseduo functions. 9 10__Authors:__ : Ulf Wiger ([`ulf@wiger.net`](mailto:ulf@wiger.net)). 11 12<a name="description"></a> 13 14## Description ## 15 16... 17 18<a name="index"></a> 19 20## Function Index ## 21 22 23<table width="100%" border="1" cellspacing="0" cellpadding="2" summary="function index"><tr><td valign="top"><a href="#format_error-1">format_error/1</a></td><td></td></tr><tr><td valign="top"><a href="#parse_transform-2">parse_transform/2</a></td><td> 24Searches for calls to pseudo functions in the module <code>codegen</code>, 25and converts the corresponding erlang code to a data structure 26representing the abstract form of that code.</td></tr></table> 27 28 29<a name="functions"></a> 30 31## Function Details ## 32 33<a name="format_error-1"></a> 34 35### format_error/1 ### 36 37`format_error(E) -> any()` 38 39<a name="parse_transform-2"></a> 40 41### parse_transform/2 ### 42 43<pre><code> 44parse_transform(Forms, Options) -> NewForms 45</code></pre> 46<br /> 47 48Searches for calls to pseudo functions in the module `codegen`, 49and converts the corresponding erlang code to a data structure 50representing the abstract form of that code. 51 52The purpose of these functions is to let the programmer write 53the actual code that is to be generated, rather than manually 54writing abstract forms, which is more error prone and cannot be 55checked by the compiler until the generated module is compiled. 56 57Supported functions: 58 59 60## gen_function/2 ## 61 62Usage: `codegen:gen_function(Name, Fun)` 63 64Substitutes the abstract code for a function with name `Name` 65and the same behaviour as `Fun`. 66 67`Fun` can either be a anonymous `fun`, which is then converted to 68a named function, or it can be an `implicit fun`, e.g. 69`fun is_member/2`. In the latter case, the referenced function is fetched 70and converted to an abstract form representation. It is also renamed 71so that the generated function has the name `Name`. 72 73Another alternative is to wrap a fun inside a list comprehension, e.g. 74 75``` 76 77 f(Name, L) -> 78 codegen:gen_function( 79 Name, 80 [ fun({'$var',X}) -> 81 {'$var', Y} 82 end || {X, Y} <- L ]). 83``` 84 85 86Calling the above with `f(foo, [{1,a},{2,b},{3,c}])` will result in 87generated code corresponding to: 88 89``` 90 91 foo(1) -> a; 92 foo(2) -> b; 93 foo(3) -> c. 94``` 95 96 97## gen_functions/1 ## 98 99Takes a list of `{Name, Fun}` tuples and produces a list of abstract 100data objects, just as if one had written 101`[codegen:gen_function(N1,F1),codegen:gen_function(N2,F2),...]`. 102 103 104## exprs/1 ## 105 106Usage: `codegen:exprs(Fun)` 107 108`Fun` is either an anonymous function, or an implicit fun with only one 109function clause. This "function" takes the body of the fun and produces 110a data type representing the abstract form of the list of expressions in 111the body. The arguments of the function clause are ignored, but can be 112used to ensure that all necessary variables are known to the compiler. 113 114 115## gen_module/3 ## 116 117Generates abstract forms for a complete module definition. 118 119Usage: `codegen:gen_module(ModuleName, Exports, Functions)` 120 121`ModuleName` is either an atom or a `{'$var', V}` reference. 122 123`Exports` is a list of `{Function, Arity}` tuples. 124 125`Functions` is a list of `{Name, Fun}` tuples analogous to that for 126`gen_functions/1`. 127 128 129## Variable substitution ## 130 131It is possible to do some limited expansion (importing a value 132bound at compile-time), using the construct `{'$var', V}`, where 133`V` is a bound variable in the scope of the call to `gen_function/2`. 134 135Example: 136 137``` 138 139 gen(Name, X) -> 140 codegen:gen_function(Name, fun(L) -> lists:member({'$var',X}, L) end). 141``` 142 143After transformation, calling `gen(contains_17, 17)` will yield the 144abstract form corresponding to: 145 146``` 147 148 contains_17(L) -> 149 lists:member(17, L). 150``` 151 152 153## Form substitution ## 154 155It is possible to inject abstract forms, using the construct 156`{'$form', F}`, where `F` is bound to a parsed form in 157the scope of the call to `gen_function/2`. 158 159Example: 160 161``` 162 163 gen(Name, F) -> 164 codegen:gen_function(Name, fun(X) -> X =:= {'$form',F} end). 165``` 166 167After transformation, calling `gen(is_foo, {atom,0,foo})` will yield the 168abstract form corresponding to: 169 170``` 171 172 is_foo(X) -> 173 X =:= foo. 174``` 175 176