elixir or erlang or other languages running on beam vm will be compiled into .beam files. So is it possible to rebuild erlang code from these files? The answer is yes.

 [file] = System.argv()
beam = File.read!(file)

{:ok, {_, [{:abstract_code, {_, ac}}]}} = :beam_lib.chunks(beam, [:abstract_code])

out = file <> ".erl"
File.touch!(out)

File.write!(out, :erl_prettypr.format(:erl_syntax.form_list(ac)))

Save the above code as beam2erl.exs file.

Then we randomly find an elixir file, for example:

 defmodule Demo do
  defdelegate puts(str), to: IO
end

Compile it, then copy the corresponding beam file to the beam2erl.exs directory, and then execute:

 $ elixir beam2erl.exs Elixir.Demo.beam

You can see that a .erl file has been generated, the content is:

 -file("lib/demo.ex", 1).

-module('Elixir.Demo').

-compile([no_auto_import]).

-export(['__info__'/1, puts/1]).

-spec '__info__'(attributes |
                 compile |
                 functions |
                 macros |
                 md5 |
                 exports_md5 |
                 module |
                 deprecated) -> any().

'__info__'(module) -> 'Elixir.Demo';
'__info__'(functions) -> [{puts, 1}];
'__info__'(macros) -> [];
'__info__'(exports_md5) ->
    <<"\n\025Y�a#�x�\201W��a#�">>;
'__info__'(Key = attributes) ->
    erlang:get_module_info('Elixir.Demo', Key);
'__info__'(Key = compile) ->
    erlang:get_module_info('Elixir.Demo', Key);
'__info__'(Key = md5) ->
    erlang:get_module_info('Elixir.Demo', Key);
'__info__'(deprecated) -> [].

puts(_str@1) -> 'Elixir.IO':puts(_str@1).

The long list above is the functions built into the module, and the last line is the content of our code.

With this little script, it's much easier to learn and tweak code that contains complex elixir macros.

can be organized into a function

 defmodule M do
  defmacro ast_to_erl(ast) do
    [{_, beam}] = Code.compile_quoted(ast)
    {:ok, {_, [{:abstract_code, {_, ac}}]}} = :beam_lib.chunks(beam, [:abstract_code])
    :erl_prettypr.format(:erl_syntax.form_list(ac), encoding: :utf8)
    |> IO.puts()
  end
end

Ljzn
399 声望102 粉丝

网络安全;函数式编程;数字货币;人工智能


引用和评论

0 条评论