nia*_*hoo 7 compilation metaprogramming elixir phoenix-framework
以下是Phoenix应用程序示例的路由器模块.我想在宏注入函数后看到模块的完整代码.
我尝试了类似的东西,Macro.to_string (Macro.expand (Code.string_to_quoted! File.read!("web/router.ex")), __ENV__)但它没有完全扩展宏.我怎么能递归扩展每个宏,即pipeline,plug,scope,pipe_through和get.
谢谢
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
Run Code Online (Sandbox Code Playgroud)
正如您已经正确观察到的那样,您需要Macro.expand/1递归地使用以真正扩展所有宏级别.有一个内置的设施来实现这一目标:Macro.prewalk/2.这应该让你开始:
ast
|> Macro.prewalk(&Macro.expand(&1, __ENV__))
|> Macro.to_string
|> IO.puts
Run Code Online (Sandbox Code Playgroud)
这段代码会将一个beam文件反编译回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
Run Code Online (Sandbox Code Playgroud)
原始来源和更多信息:http : //erlang.org/doc/man/beam_lib.html
注意这个方法取的是[module].beam的文件路径