Compilation 如何使用Elixir宏获取模块的完整生成代码

Compilation 如何使用Elixir宏获取模块的完整生成代码,compilation,metaprogramming,elixir,phoenix-framework,Compilation,Metaprogramming,Elixir,Phoenix Framework,下面是一个示例Phoenix应用程序的路由器模块。我想在宏注入函数后看到模块的完整代码 我尝试了类似于Macro.to\u string(Macro.expand(code.string\u to\u quoted!File.read!(“web/router.ex”),\uu ENV\uuuu)之类的方法,但它没有完全展开宏。如何递归地展开每个宏,即管道,插头,范围,管道和获取 谢谢 defmodule HelloPhoenix.Router do use HelloPhoenix.Web

下面是一个示例Phoenix应用程序的路由器模块。我想在宏注入函数后看到模块的完整代码

我尝试了类似于
Macro.to\u string(Macro.expand(code.string\u to\u quoted!File.read!(“web/router.ex”),\uu ENV\uuuu)之类的方法,但它没有完全展开宏。如何递归地展开每个宏,即
管道
插头
范围
管道
获取

谢谢

defmodule HelloPhoenix.Router do
  use HelloPhoenix.Web, :router

  pipeline :browser do
    plug :accepts, ["html"]
    plug :fetch_session
    plug :fetch_flash
    plug :protect_from_forgery
    plug :put_secure_browser_headers
  end

  pipeline :api do
    plug :accepts, ["json"]
  end

  scope "/", HelloPhoenix do
    pipe_through :browser # Use the default browser stack

    get "/", PageController, :index
  end

end

正如您正确观察到的,您需要递归地使用
Macro.expand/1
来真正扩展所有宏级别。有一个内置的工具可以实现这一点:
Macro.prewalk/2
。这应该让你开始:

ast
|> Macro.prewalk(&Macro.expand(&1, __ENV__))
|> Macro.to_string
|> IO.puts

这段代码将把beam文件反编译回erlang。我还没有在基于插件的模块上运行它,所以我不知道结果会有多糟糕,但这会给出任何模块的最终结果

原始来源和更多信息:


请注意,此方法采用[module].beam的文件路径。我还发现了一个名为Mex的包,它似乎也无法打印完整的代码。不过还是要谢谢你,我会再修改一下哦,看来检查模块不是那么简单,对不起。如果您想得到一个快速且不干净的解决方案,您可以尝试手动将检查代码注入模块本身,以便您的
\uuuu ENV\uuu
位于模块内。现在无法检查,但您可能在这方面取得了一些成功。很遗憾,我们没有长生不老药代码,但因为我可以比长生不老药更好地阅读erlang,所以对我来说没关系:)谢谢
  def disassemble(beam_file) do
    beam_file = String.to_char_list(beam_file)
    {:ok,
      {_, [{:abstract_code, {_, ac}}]}} = :beam_lib.chunks(beam_file,
                                                           [:abstract_code])
    :io.fwrite('~s~n', [:erl_prettypr.format(:erl_syntax.form_list(ac))])
  end