Search code examples
erlangdialyzer

How do Erlang type specs get preprocessed


I am trying to extend the Erlang Mixer Library (https://github.com/opscode/mixer) to pass the "-spec()." lines for the functions that it is adding to a module. However I am unclear on how erlc places specs into the core erlang code.

I started with a really simple (test) module:

-module(mix1).
-export([square/1]).
-spec(square(number()) -> number()).
square(X) -> X * X.

And compiled it with "erlc +debug_info -S mix1.erl" and got this (module_info functions removed):

{module, mix1}.  %% version = 0

{exports, [{module_info,0},{module_info,1},{square,1}]}.

{attributes, []}.
{labels, 7}.
{function, square, 1, 2}.
  {label,1}.
    {line,[{location,"mix1.erl",7}]}.
    {func_info,{atom,mix1},{atom,square},1}.
  {label,2}.
    {line,[{location,"mix1.erl",8}]}.
    {gc_bif,'*',{f,0},1,[{x,0},{x,0}],{x,0}}.
    return.

I am trying to figure out how the "-spec()" are translated and I don't see them there, any ideas? What am I missing. The eventual goal here is to use this for a parse transform.


Solution

  • I believe your output is not exactly AST, but some normalized form of AST.

    {ok, Forms} = epp:parse_file("mix1.erl",[],[]).
    {ok,[{attribute,1,file,{"mix1.erl",1}},
         {attribute,1,module,mix1},
         {attribute,2,export,[{square,1}]},
         {attribute,3,spec,
                    {{square,1},
                     [{type,3,'fun',
                            [{type,3,product,[{type,3,number,[]}]},
                             {type,3,number,[]}]}]}},
         {function,4,square,1,
                   [{clause,4,
                            [{var,4,'X'}],
                            [],
                            [{op,4,'*',{var,4,'X'},{var,4,'X'}}]}]},
         {eof,6}]}