Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to get the full generated code of a module using Elixir macros

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
like image 848
lud Avatar asked Mar 15 '16 16:03

lud


2 Answers

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

like image 123
Chris Meyer Avatar answered Oct 24 '22 06:10

Chris Meyer


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
like image 42
Patrick Oscity Avatar answered Oct 24 '22 05:10

Patrick Oscity