__ENV__

Bring Elixir-style __ENV__ macro into Erlang via parse transform.

Installation

Add macro_env to your rebar.config:

{deps, [
    {macro_env, "0.1.0"}
]}.

Usage

Apply the parse transform to your module:

-compile({parse_transform, '__ENV__'}).

Then use __ENV__ anywhere in your code:

io:format("~p~n", [__ENV__])

__ENV__ expands to a map matching the Elixir.Macro.Env struct with the following fields populated at compile time:

Field Value
__struct__'Elixir.Macro.Env'
file Absolute path to the source file (binary)
line Line number of the __ENV__ reference
module The current module atom
function{FunctionName, Arity} tuple
contextnil
functions List of {Module, [{Fun, Arity}]} from -import attributes
context_modules[CurrentModule]

Calling Elixir macros from Erlang

Elixir macros look like ordinary functions but are compile-time AST transformations. You cannot call them with a plain remote call like 'Elixir.Logger':info(<<"hello">>) — that will fail because Logger.info/1 is a macro, not a function.

With __ENV__ available you can invoke Elixir macros directly:

-compile({parse_transform, &#39;__ENV__&#39;}).

-define(APPLY_MACRO(Module, Macro, Args),
    &#39;Elixir.Code&#39;:eval_quoted(
        Module,
        list_to_atom(string:concat("MACRO-", atom_to_list(Macro))),
        [__ENV__ | Args]
    )
).

example() ->
    ?APPLY_MACRO(&#39;Elixir.Logger&#39;, info, [<<"hello from Erlang">>]).

Build

$ rebar3 compile

Test

$ rebar3 eunit

License

Apache 2.0 — see LICENSE.md.