Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to read/decode temporary function names of list comprehension in Erlang when debugging

When debugging a module (e.g. foo) with list comprehensions temporary function names e.g.

foo:'-loop/4-lc$^2/1-3-'

can be found in trace output or error messages. If many list comprehensions are in a module its often hard to find out which one is running.

How can the function name be interpreted?

What are the meaning of the call parameters of these functions?

What is the meaning of the return value?

like image 670
Peer Stritzinger Avatar asked May 16 '11 15:05

Peer Stritzinger


1 Answers

The fields can be described as follows:

foo:'-loop/4-lc$^2/1-3-'
^     ^    ^ ^   ^ ^ ^
1     2    3 4   5 6 7
  1. Module name
  2. The enclosing function
  3. Arity of the enclosing function
  4. The type of fun (lc = list generator in a list comprehension, blc = binary generator in a list comprehension, lbc = list generator in a binary comprehension, fun = fun)
  5. Index of function within defining function (0 based)
  6. Arity of the generated function
  7. Index of lambda lifted function within defining function

Open questions: what is the meaning of the parameters and return values of these functions?

Just stumbled on this answer by Robert Virding to the same question on the erlang-questions Mailinglist.


The code which creates these names is spread among many modules: sys_pre_expand for funs; v3_core for functions created for comprehensions; and v3_kernel which adds more when lambda lifting the functions. The goal of all this is to create "unique" function names which also give some indication of why the functions were created and why.

In sys_pre_expand.erl there is code fore creating function names for funs:

%% new_fun_name(State) -> {FunName,State}.

new_fun_name(#expand{func=F,arity=A,fcount=I}=St) ->
    Name = "-" ++ atom_to_list(F) ++ "/" ++ integer_to_list(A)
        ++ "-fun-" ++ integer_to_list(I) ++ "-",
    {list_to_atom(Name),St#expand{fcount=I+1}}.

These names are passed on and expanded in a later pass (v3_kernel).

From the compilers v3_core.erl:

%% new_fun_name(Type, State) -> {FunName,State}.

new_fun_name(Type, #core{fcount=C}=St) ->
    {list_to_atom(Type ++ "$^" ++ integer_to_list(C)),St#core{fcount=C+1}}.

So this accounts for the "lc$^2" (parts 4 and 5) in the example. When looking at the places where it is used the possible values for part 4 can be deduced: lc, blc and lbc.

In v3_kernel.erl is the next phase when these functions are lambda lifted:

%% new_fun_name(Type, State) -> {FunName,State}.

new_fun_name(Type, #kern{func={F,Arity},fcount=C}=St) ->
    Name = "-" ++ atom_to_list(F) ++ "/" ++ integer_to_list(Arity) ++
    "-" ++ Type ++ "-" ++ integer_to_list(C) ++ "-",
    {list_to_atom(Name),St#kern{fcount=C+1}}.

This accounts for -loop/4- (parts 2 and 3) and -3- (part 7). Part 6 is added in the call to this new_fun_name/2.


(This post is a community wiki, please add the other entries if you know what they mean)

like image 183
9 revs, 4 users 43% Avatar answered Nov 15 '22 07:11

9 revs, 4 users 43%