README.md

# `__ENV__`

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

## Installation

Add `macro_env` to your `rebar.config`:

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

## Usage

Apply the parse transform to your module:

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

Then use `__ENV__` anywhere in your code:

```erlang
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                 |
| `context`          | `nil`                                         |
| `functions`        | List of `{Module, [{Fun, Arity}]}` from `-import` attributes |
| `aliases`          | `[]`                                          |
| `lexical_tracker`  | `nil`                                         |
| `macro_aliases`    | `[]`                                          |
| `versioned_vars`   | `#{}`                                         |
| `tracers`          | `[]`                                          |
| `requires`         | `[]`                                          |
| `macros`           | `[]`                                          |
| `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:

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

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

example() ->
    ?APPLY_MACRO('Elixir.Logger', info, [<<"hello from Erlang">>]).
```

## Build

```
$ rebar3 compile
```

## Test

```
$ rebar3 eunit
```

## License

Apache 2.0 — see [LICENSE.md](LICENSE.md).