BeamFile is mainly a wrapper around the Erlang module :beam_lib
.
BeamFile provides different views to the data in a BEAM file: BeamFile.elixir_code/2
, BeamFile.erl_code/1
, BeamFile.abstract_code/1
and BeamFile.byte_code/1
. The reconstructed Elixir code is not the original code. In this code all macros and reference are resolved.
Example:
defmodule Say do
def hello(name \\ "World"), do: name |> format() |> puts()
def format(name), do: "Hello, #{name}!"
defdelegate puts(item), to: IO
end
iex> {:ok, code} = BeamFile.elixir_code(Say)
iex> IO.puts(code)
defmodule Elixir.Say do
def hello(name) do
puts(format(name))
end
def hello do
hello("World")
end
def format(name) do
<<"Hello, ", String.Chars.to_string(name)::binary(), "!">>
end
def puts(item) do
IO.puts(item)
end
end
:ok
iex> {:ok, code} = BeamFile.erl_code(Say)
iex> IO.puts(code)
file("test/fixtures/default.ex", 7).
-module('Elixir.Say').
-compile([no_auto_import]).
-export(['__info__'/1,
format/1,
hello/0,
hello/1,
puts/1]).
-spec '__info__'(attributes |
compile |
functions |
macros |
md5 |
exports_md5 |
module |
deprecated) -> any().
'__info__'(module) -> 'Elixir.Say';
'__info__'(functions) ->
[{format, 1}, {hello, 0}, {hello, 1}, {puts, 1}];
'__info__'(macros) -> [];
'__info__'(exports_md5) -> <<"VÑ>Qlf`zâ\202--*ÐP®">>;
'__info__'(Key = attributes) ->
erlang:get_module_info('Elixir.Say', Key);
'__info__'(Key = compile) ->
erlang:get_module_info('Elixir.Say', Key);
'__info__'(Key = md5) ->
erlang:get_module_info('Elixir.Say', Key);
'__info__'(deprecated) -> [].
format(_name@1) ->
<<"Hello, ",
case _name@1 of
_@1 when erlang:is_binary(_@1) -> _@1;
_@1 -> 'Elixir.String.Chars':to_string(_@1)
end/binary,
"!">>.
hello() -> hello(<<"World">>).
hello(_name@1) -> puts(format(_name@1)).
puts(_item@1) -> 'Elixir.IO':puts(_item@1).
:ok
iex> {:ok, code} = BeamFile.byte_code(Say)
iex> IO.inspect(code)
{:beam_file, Say,
[
{:__info__, 1, 2},
{:format, 1, 9},
{:hello, 0, 13},
{:hello, 1, 15},
{:module_info, 0, 19},
{:module_info, 1, 21},
{:puts, 1, 17}
], [vsn: [328337295702536866380643469106329237584]],
[
version: '7.6.7',
options: [:dialyzer, :no_spawn_compiler_process, :from_core,
:no_core_prepare, :no_auto_import],
source: '.../say.ex'
],
[
{:function, :__info__, 1, 2,
[
{:label, 1},
{:line, 0},
{:func_info, {:atom, Say}, {:atom, :__info__}, 1},
{:label, 2},
{:select_val, {:x, 0}, {:f, 1},
{:list,
[
atom: :attributes,
f: 7,
atom: :compile,
f: 7,
atom: :deprecated,
f: 6,
atom: :exports_md5,
f: 5,
atom: :functions,
f: 4,
atom: :macros,
f: 6,
atom: :md5,
f: 7,
atom: :module,
f: 3
]}},
{:label, 3},
{:move, {:atom, Say}, {:x, 0}},
:return,
{:label, 4},
{:move, {:literal, [format: 1, hello: 0, hello: 1, puts: 1]}, {:x, 0}},
:return,
{:label, 5},
{:move,
{:literal,
<<86, 209, 62, 81, 108, 102, 96, 122, 226, 130, 45, 45, 42, 208, 80,
174>>}, {:x, 0}},
:return,
{:label, 6},
{:move, nil, {:x, 0}},
:return,
{:label, 7},
{:move, {:x, 0}, {:x, 1}},
{:move, {:atom, Say}, {:x, 0}},
{:line, 0},
{:call_ext_only, 2, {:extfunc, :erlang, :get_module_info, 2}}
]},
{:function, :format, 1, 9,
[
{:line, 1},
{:label, 8},
{:func_info, {:atom, Say}, {:atom, :format}, 1},
{:label, 9},
{:allocate, 1, 1},
{:move, {:x, 0}, {:y, 0}},
{:test, :is_binary, {:f, 10}, [x: 0]},
{:move, {:y, 0}, {:x, 0}},
{:jump, {:f, 11}},
{:label, 10},
{:init, {:y, 0}},
{:line, 1},
{:call_ext, 1, {:extfunc, String.Chars, :to_string, 1}},
{:label, 11},
{:line, 1},
{:gc_bif, :byte_size, {:f, 0}, 1, [x: 0], {:x, 1}},
{:bs_add, {:f, 0}, [{:x, 1}, {:integer, 8}, 1], {:x, 1}},
{:line, 1},
{:bs_init2, {:f, 0}, {:x, 1}, 0, 2, {:field_flags, 0}, {:x, 1}},
{:bs_put_string, 7, {:string, 'Hello, '}},
{:bs_put_binary, {:f, 0}, {:atom, :all}, 8, {:field_flags, 0}, {:x, 0}},
{:bs_put_string, 1, {:string, '!'}},
{:move, {:x, 1}, {:x, 0}},
{:deallocate, 1},
:return
]},
{:function, :hello, 0, 13,
[
{:line, 2},
{:label, 12},
{:func_info, {:atom, Say}, {:atom, :hello}, 0},
{:label, 13},
{:move, {:literal, "World"}, {:x, 0}},
{:call_only, 1, {Say, :hello, 1}}
]},
{:function, :hello, 1, 15,
[
{:line, 2},
{:label, 14},
{:func_info, {:atom, Say}, {:atom, :hello}, 1},
{:label, 15},
{:allocate, 0, 1},
{:line, 2},
{:call, 1, {Say, :format, 1}},
{:call_last, 1, {Say, :puts, 1}, 0}
]},
{:function, :puts, 1, 17,
[
{:line, 3},
{:label, 16},
{:func_info, {:atom, Say}, {:atom, :puts}, 1},
{:label, 17},
{:line, 3},
{:call_ext_only, 1, {:extfunc, IO, :puts, 1}}
]},
{:function, :module_info, 0, 19,
[
{:line, 0},
{:label, 18},
{:func_info, {:atom, Say}, {:atom, :module_info}, 0},
{:label, 19},
{:move, {:atom, Say}, {:x, 0}},
{:line, 0},
{:call_ext_only, 1, {:extfunc, :erlang, :get_module_info, 1}}
]},
{:function, :module_info, 1, 21,
[
{:line, 0},
{:label, 20},
{:func_info, {:atom, Say}, {:atom, :module_info}, 1},
{:label, 21},
{:move, {:x, 0}, {:x, 1}},
{:move, {:atom, Say}, {:x, 0}},
{:line, 0},
{:call_ext_only, 2, {:extfunc, :erlang, :get_module_info, 2}}
]}
]}