[erlang-questions] Re: implementing annotation in erlang

Steve Vinoski vinoski@REDACTED
Thu Sep 10 06:17:31 CEST 2009


2009/9/9 paweł kamiński <kamiseq@REDACTED>

> hi,
> finally I went through parse_transform but constructing even simple format
> from scratch is a nightmare.
>

It's not all that bad once you get used to it.


> to prepare something like
> cmdCallbackList()->
> [{"cmdDevSetTime",setTime,1},{"cmdFpSetStatus",setStatus,2}].
>
> I need to build
> {function,19,cmdCallbackList,0,
>      [{clause,19,[],[],
>           [{cons,20,
>                {tuple,20,
>                    [{atom,20,"cmdDevSetTime"},
>                     {atom,20,setTime},
>                     {integer,20,1}]},
>                {cons,20,
>                    {tuple,20,
>                        [{atom,20,"cmdFpSetStatus"},
>                         {atom,20,setStatus},
>                         {integer,20,2}]},
>                    {nil,20}}}]}]}
>
> is there a way to construct code blocks in more elegant way, something like
> create_fun(LineNo, Name, Arity, Body, ..)-> would produce function block
> create_tuple(LineNo, Tuple)
> create_list(...)
> and so on
>

You can write a function like the one you're trying to create in straight
Erlang, making sure you compile it with debug_info, and then use
code:get_object_code(module_name) to get the beam code and then
use beam_lib:chunks(Beam,[abstract_code]) to get the equivalent Abstract
Format to give you a nice starting point for what you're trying to produce.
Another way to do it is to use erl_parse:abstract() -- you pass in the
Erlang data and it spits out the Abstract Format equivalent.

See also the erl_syntax module, including the revert() function that
converts any syntax trees you build with the erl_syntax functions into
Abstract Format. Passing normal Erlang data into erl_syntax:abstract() and
then passing that result to erl_syntax:revert() gives you Abstract Format,
for example, pretty much the equivalent of erl_parse:abstract().

and still Im thinking that extracting information from code in runtime is
> far more productive (elegant, sufficient, just simpler) then transforming
> code to something different. generally all I need is just to obtain
> information that this function is annoted with metadata and store that or
> make additional tasks. with parse transform I need to build and add new
> function to parsed module that other can call and get those information or
> create whole new file with well known name that other modules could refer
> to.
>

To extract something at runtime, you gotta get it into the beam code to
begin with. Seems to me that parse transforms are a great way to do just
that. With the Abstract Format, you get the "code is data, data is code"
equivalency that makes code augmentation easy, and with beam_lib you get the
ability to look through the compiled code, checking modules to see if they
export the functions you generated with the parse transform. Once you find
them, calling them to get the metadata you want is easy.

--steve


More information about the erlang-questions mailing list