Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
defmodule Mix.Tasks.PrintCode do
@shortdoc "Prints decompiled Erlang source for a module"
@moduledoc """
Pretty-prints the *Erlang-equivalent* source code of an *Elixir*
module. This is useful for understanding how particular Elixir
features (e.g. macros, protocols) operate under the covers.
*Erlang modules are not yet supported.*
## Usage
```shell
$ mix print_code [--ast] MODULE
```
## Options
* `--ast`: Inspects the Erlang abstract format instead of
pretty-printing as source.
"""
use Mix.Task
def run(argv) do
Mix.Task.run(:compile, argv)
{flags, [modname|_], _rest} = OptionParser.parse(argv, switches: [ast: :boolean])
mod = Module.safe_concat([modname])
{:module, ^mod} = Code.ensure_loaded(mod)
{^mod, beam, fname} = :code.get_object_code(mod)
{:ok, {^mod, [abstract_code: {:raw_abstract_v1, forms}]}} = :beam_lib.chunks(beam, [:abstract_code])
{header, source} = if flags[:ast] do
{"Abstract format from #{fname}:", inspect(forms, pretty: true)}
else
{"Erlang source from #{fname}:", forms |> :erl_syntax.form_list |> :erl_prettypr.format}
end
separator = String.duplicate("-", String.length(header))
Mix.shell.info(header)
Mix.shell.info(separator)
Mix.shell.info(source)
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.