[erlang-questions] How to get syntax tree out of abstract forms?

Justin Calleja <>
Thu Feb 7 14:55:12 CET 2013


Hi,

Let's say I have this module:

-module(hello).
-export([send_hello/1, receive_hello/0]).

send_hello(To) ->
 To ! {hello, self()}.

receive_hello() ->
 receive
  {hello, From} ->
   {ok, From};
  Msg ->
   {unknown_msg, Msg}
 end.

which  gives the following abstract forms (lets bind to Forms for ease of
reference):

[{attribute,1,file,{"../src/eaop_explore/hello.erl",1}},
 {attribute,1,module,hello},
 {attribute,2,export,[{send_hello,1},{receive_hello,0}]},
 {function,4,send_hello,1,
     [{clause,4,
          [{var,4,'To'}],
          [],
          [{op,5,'!',
               {var,5,'To'},
               {tuple,5,[{atom,5,hello},{call,5,{atom,5,self},[]}]}}]}]},
 {function,7,receive_hello,0,
     [{clause,7,[],[],
          [{'receive',8,
               [{clause,9,
                    [{tuple,9,[{atom,9,hello},{var,9,'From'}]}],
                    [],
                    [{tuple,10,[{atom,10,ok},{var,10,'From'}]}]},
                {clause,11,
                    [{var,11,'Msg'}],
                    [],

[{tuple,12,[{atom,12,unknown_msg},{var,12,'Msg'}]}]}]}]}]},
 {eof,13}]

I would like to use the postorder/2 function in the comments of erl_syntax:

postorder(F, Tree) ->
        F(case erl_syntax:subtrees(Tree) of
            [] -> Tree;
            List -> erl_syntax:update_tree(Tree,
                                [[postorder(F, Subtree)
                                  || Subtree <- Group]
                                 || Group <- List])
          end).

to traverse a syntax tree and do some kind of manipulation.

The problems is that, although the documentation (or how I understood the
doc anyway) claims that abstract forms are a subset of syntax trees, I
cannot do the following:

postorder(getAtomFun(), Forms)

where:

getAtomFun() ->
    fun(Node) ->
        case erl_syntax:type(Node) of
            atom ->
                case erl_syntax:atom_name(Node) of
                    "module" -> Node;
                    "export" -> Node;
                    _ -> erl_syntax:atom("a_" ++ erl_syntax:atom_name(Node))
                end;
            _ ->
                Node
        end
    end.

However, if Forms is constructed manually using the erl_syntax module, I
can do that. e.g. taking a small part of Forms and constructing using
erl_syntax (namely, only the module and export attributes), I can do the
following:

get_tree() ->
    erl_syntax:form_list([
        erl_syntax:attribute(erl_syntax:atom(module),
[erl_syntax:atom(hello)]),
        erl_syntax:attribute(erl_syntax:atom(export), [
            erl_syntax:list([
                erl_syntax:arity_qualifier(erl_syntax:atom(send_hello),
erl_syntax:integer(1)),
                erl_syntax:arity_qualifier(erl_syntax:atom(receive_hello),
erl_syntax:integer(0))
            ])
        ])
    ]).


20> postorder(getAtomFun(), get_tree())
...
21> erl_syntax:revert_forms(v(20)).
[{attribute,0,module,a_hello},
 {attribute,0,export,[{a_send_hello,1},{a_receive_hello,0}]}]


The problem is that I can't seem to be able to do such an operation unless
I can somehow get the forms into syntax trees.

Is there a function I'm missing in erl_syntax which transforms from forms
to syntax trees? (revert_forms/1 exists to do the transformation in the
other way).

Regards,
Justin
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://erlang.org/pipermail/erlang-questions/attachments/20130207/0fdb2a69/attachment.html>


More information about the erlang-questions mailing list