Elixir进入Erlang转型

ipi*_*nak 5 elixir

我想看看当elixir被转换成束文件时会发生什么.有没有办法在控制台或文件中打印如何翻译?我想知道这个模块在erlang中会是什么样子.

我在想是否有elixir的调试模式,它将输出上述任何一个.

更具体地说,我有这个例子:

defmodule Test do
    def t1(a), do: a
    def t1(a, b \\ 2), do: a + b
end
Run Code Online (Sandbox Code Playgroud)

上面的代码提出了一个警告,考虑到我所做的事情,这是不可或缺的.基本上我想了解更多正在发生的事情.

Dog*_*ert 9

首先,您需要将Elixir模块编译为.beam文件:

$ 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
Run Code Online (Sandbox Code Playgroud)

这将产生Elixir.Test.beam.然后,您可以使用以下escript将此.beam反编译为Erlang源代码(我之前在Stackoverflow上的一些答案中复制了这个.不幸的是我似乎无法找到确切的源代码,但此代码在此处有许多答案,包括此一个.):

$ 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))]).
Run Code Online (Sandbox Code Playgroud)

然后运行它:

$ 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.
Run Code Online (Sandbox Code Playgroud)


Ale*_*kin 5

这可能更像是对@Dogbert 以上答案的评论,但为了格式化,我会将其作为单独的答案发布。

不需要创建.ex文件并在它们上调用编译器来生成梁:

{: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)
Run Code Online (Sandbox Code Playgroud)

现在您可能已经编写了一个 Beam 文件(bytecode顺便说一下,我们将它存储在变量中。)

注意: beam_lib:chunks/2当且仅当光束包含未加密的调试信息时才有效(默认情况下,灵药光束会这样做。)

此外,您不需要编写反编译的 erlang 代码,您可以直接在那里传递一个二进制文件Elixir

:beam_lib.chunks(bytecode, [:abstract_code])
Run Code Online (Sandbox Code Playgroud)

提取代码本身:

{:ok,{_,[abstract_code: {_, code}]}} = 
   bytecode |> :beam_lib.chunks([:abstract_code])
Run Code Online (Sandbox Code Playgroud)

现在code包含代码,检查它应该足够了,但是您仍然可以自由使用 erlang 内置插件:

code |> :erl_syntax.form_list
Run Code Online (Sandbox Code Playgroud)

或者:

code |> :erl_syntax.form_list |> :erl_prettypr.format
Run Code Online (Sandbox Code Playgroud)

后者将为您提供二进制字符列表,其中包含 erlang 代码,与@Dogbert 的回答完全相同。使用IO.puts以进行输出。