Below is the router module for a sample Phoenix application. I would like to see the full code of the module after macros inject functions.
I tried things like Macro.to_string (Macro.expand (Code.string_to_quoted! File.read!("web/router.ex")), __ENV__)
but it doesn't fully expand the macros. How could I recursively expand every macro, i.e. pipeline
, plug
, scope
, pipe_through
and get
.
Thanks
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
This bit of code will decompile a beam file back to erlang. I haven't run it against a plug-based module, so I don't know how nasty the result will be, but this gives you the final result for any module.
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
original source, and more info: http://erlang.org/doc/man/beam_lib.html
Note that this method takes the file path of [module].beam
As you have correctly observed, you need to use Macro.expand/1
recursively to truly expand all macro levels. There is a built-in facility to achieve this: Macro.prewalk/2
. This should get you started:
ast
|> Macro.prewalk(&Macro.expand(&1, __ENV__))
|> Macro.to_string
|> IO.puts
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With