Elixir to Erlang Transformation

I want to see what happens when the elixir turns into beam files. Is there a way to print in the console or in a file, how is it translated? I want to know what this module looks like in erlang.

I was wondering if there is an elixir debugging mode that will output any of the above.

In particular, I have this example:

defmodule Test do def t1(a), do: a def t1(a, b \\ 2), do: a + b end 

In the above code, a warning occurs that cannot be explained, given what I did. Basically I want to understand a little more what is happening.

+5
source share
2 answers

First you need to compile the Elixir module into a .beam file:

 $ cat test.ex defmodule Test do def t1(a), do: a def t1(a, b \\ 2), do: a + b end $ elixirc test.ex warning: this clause cannot match because a previous clause at line 2 always matches test.ex:3 

This will lead to the creation of Elixir.Test.beam . You can then decompile this .beam to an Erlang source using the following escript (I copied this from some answer here on Stackoverflow a while ago. Unfortunately, I cannot find the exact source, but this code is in many answers here, including this one .) :

 $ cat decompile.erl #!/usr/bin/env escript main([BeamFile]) -> {ok,{_,[{abstract_code,{_,AC}}]}} = beam_lib:chunks(BeamFile,[abstract_code]), io:fwrite("~s~n", [erl_prettypr:format(erl_syntax:form_list(AC))]). 

Then run it:

 $ escript decompile.erl Elixir.Test.beam -compile(no_auto_import). -file("test.ex", 1). -module('Elixir.Test'). -export(['__info__'/1, t1/1, t1/2]). -spec '__info__'(attributes | compile | exports | functions | macros | md5 | module | native_addresses) -> atom() | [{atom(), any()} | {atom(), byte(), integer()}]. '__info__'(functions) -> [{t1, 1}, {t1, 2}]; '__info__'(macros) -> []; '__info__'(info) -> erlang:get_module_info('Elixir.Test', info). t1( a@1 ) -> a@1 ; t1( x0@1 ) -> t1( x0@1 , 2). t1( a@1 , b@1 ) -> a@1 + b@1. 
+8
source

This should probably be more of a comment on @Dogberts answer above, but I would post it as a separate answer for formatting.

No need to create .ex files and call the compiler on them to create bundles:

 {:module, _, bytecode, _} = defmodule Elixir.Test do def t1(a), do: a def t1(a, b \\ 2), do: a + b end # File.write!("Elixir.Test.beam", bytecode) 

Now you can have a ray file written (we saved it in the bytecode variable).

NB: beam_lib:chunks/2 works if and only the beam contains unencrypted debugging information (elixir beams are executed by default).

In addition, you do not need to write decompiled erlang code, you can simply transfer the binary directly to Elixir :

 :beam_lib.chunks(bytecode, [:abstract_code]) 

To extract the code itself:

 {:ok,{_,[abstract_code: {_, code}]}} = bytecode |> :beam_lib.chunks([:abstract_code]) 

code now contains code, it should be enough to learn it, but you can still use erlang assemblies:

 code |> :erl_syntax.form_list 

or

 code |> :erl_syntax.form_list |> :erl_prettypr.format 

The latter will provide you with a binary charlist containing erlang code, just like in @Dogberts answer. Use IO.puts for output.

+4
source

Source: https://habr.com/ru/post/1260189/