[elixir! #0081] 编译后的 beam code 重建为 erlang 代码

elixir 或 erlang 或其它运行在 beam vm 上的语言,都会被编译成 .beam 文件。那么能否通过这些文件重建 erlang 代码呢?答案是可以的。

[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)))

【[elixir! #0081] 编译后的 beam code 重建为 erlang 代码】将上面的代码保存为 beam2erl.exs 文件。
然后我们随便找一个 elixir 文件, 比如:
defmodule Demo do defdelegate puts(str), to: IO end

将其编译,然后把对应的 beam 文件复制到 beam2erl.exs 的目录下,再执行:
$ elixir beam2erl.exs Elixir.Demo.beam

就能看到生成了一个 .erl 文件,内容是:
-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).

上面的一大串是模块中内置的函数,最后一行是我们代码的内容。
有了这个小脚本,学习和调整包含复杂的 elixir 宏的代码,就方便多了。

    推荐阅读