[erlang-questions] Function Reference to Code Tree
Ulf Wiger
ulf@REDACTED
Wed Jan 23 12:07:13 CET 2013
For deeper excavation, you might get something out of meditating over ct_expand.erl:
https://github.com/uwiger/parse_trans/blob/master/src/ct_expand.erl
Its uses are exemplified in
https://github.com/uwiger/parse_trans/blob/master/examples/ct_expand_test.erl
What it does is expand expresssions at compile-time, and if those expressions make use of e.g. function calls defined in the same module (i.e. not yet compiled), it finds the abstract code for those functions and evaluates it.
If one wanted to pull a self-contained abstract-code definition of a fun, this sort of thing, combined perhaps with inlining, might come in handy.
(That is, if the extracted abstract code contains a call to a non-exported function, it will be incomplete when pulled out of its context).
BR,
Ulf W
On 23 Jan 2013, at 11:35, Tyron Zerafa wrote:
> Fantastic, this is exactly what I had in mind :) I will surely give it a try (and some thought about the effect of free vars)
> Thanks
>
>
> On Wed, Jan 23, 2013 at 11:07 AM, Ulf Wiger <ulf@REDACTED> wrote:
>
> On 22 Jan 2013, at 20:11, Tyron Zerafa wrote:
>
>> Erlang:fun_info(F) is returning the function body because it is constructed in the shell which essentially passes the entire code tree to the erl_eval module for execution. If you call this for a function constructed in a module, you won't get this tree.
>>
>> I need something along these lines that work for functions constructed in modules rather than the shell.
>
> Mind you, this is just example code - not intended for mission-critical use.
>
> http://erlang.org/pipermail/erlang-questions/2007-December/031992.html
>
> I updated the program a little bit, since the internal naming of funs seems to have changed:
>
>
> -module(extract).
>
> -export([f/1]).
>
>
> f(F) ->
> {module, Mod} = erlang:fun_info(F, module),
> {name, Name} = erlang:fun_info(F, name),
> {ok, Abst} = get_abstract_code(Mod),
> extract_fun(Name, Abst).
>
> get_abstract_code(Module) ->
> {module,_} = code:ensure_loaded(Module),
> Beam = code:which(Module),
> case beam_lib:chunks(Beam, [abstract_code]) of
> {ok,{_,[{abstract_code,{_,AC}}]}} ->
> {ok, AC};
> Other ->
> Other
> end.
>
> extract_fun(Name, AC) ->
> {F,Arity,Rel} = split_name(Name),
> Clauses = [Cs || {function,_,F1,Arity1,Cs} <- AC,
> F1 == F, Arity1 == Arity],
> Funs = pick_funs(lists:concat(Clauses)),
> lists:nth(Rel, Funs).
>
> split_name(Name) ->
> [Fs, As, _, Rs] = string:tokens(atom_to_list(Name),"/-"),
> {list_to_atom(Fs), list_to_integer(As), list_to_integer(Rs)+1}.
>
> pick_funs(L) ->
> Flatten = fun({'fun',_,_} = Fun) -> [Fun];
> (T) when is_tuple(T) -> tuple_to_list(T);
> (_) -> []
> end,
> L1 = [X || X <- lists:flatten(lists:map(Flatten, L)),
> is_tuple(X)],
> case [F || F <- L1,
> element(1, F) =/= 'fun'] of
> [] -> L1;
> [_|_] ->
> pick_funs(L1)
> end.
>
>
> Example:
>
> -module(m1).
>
> -export([f/2]).
>
> f(N, X) ->
> if N==1; N==2 ->
> element(N, {fun() ->
> X + 1
> end,
> fun() ->
> X - 1
> end});
> N == 3 ->
> fun(Y) ->
> X + Y
> end
> end.
>
> Eshell V5.9.2 (abort with ^G)
> 1> [m1:f(N,17) || N <- [1,2,3]].
> [#Fun<m1.0.1800644>,#Fun<m1.1.1800644>,#Fun<m1.2.1800644>]
> 2> [extract:f(m1:f(N,17)) || N <- [1,2,3]].
> [{'fun',7,
> {clauses,[{clause,7,[],[],
> [{op,8,'+',{var,8,'X'},{integer,8,1}}]}]}},
> {'fun',10,
> {clauses,[{clause,10,[],[],
> [{op,11,'-',{var,11,'X'},{integer,11,1}}]}]}},
> {'fun',14,
> {clauses,[{clause,14,
> [{var,14,'Y'}],
> [],
> [{op,15,'+',{var,15,'X'},{var,15,'Y'}}]}]}}]
>
>
> The module m1 needs to be compiled with debug_info, of course.
>
> BR,
> Ulf W
>
> Ulf Wiger, Co-founder & Developer Advocate, Feuerlabs Inc.
> http://feuerlabs.com
>
>
>
>
>
>
> --
> Best Regards,
> Tyron Zerafa
Ulf Wiger, Co-founder & Developer Advocate, Feuerlabs Inc.
http://feuerlabs.com
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://erlang.org/pipermail/erlang-questions/attachments/20130123/ca92faf5/attachment.htm>
More information about the erlang-questions
mailing list