Поскольку метапрограммирование Elixir позволяет вам исследовать AST [...]
Это не совсем так.Что делает макрос, он буквально вставляет AST вместо вызова до того, как произойдет компиляция .В скомпилированном коде нет следов каких-либо макросов, все они пропали, их заменили на AST, которые они возвращали на этапе компиляции.
Это означает, что ваш макрос не работает так, как вы ожидаете.IO.inspect
выполняется на этапе компиляции .ЛУЧ не будет распечатывать ничего, равно как и __ENV__.line
или что-либо подобное.
OTOH, Kernel.SpecialForms.quote/2
имеет специально выделенную опцию location: :keep
для сохранения файла.и номер строки.Это не произойдет автоматически из коробки.
Кроме того, есть атрибут модуля @compile
, который можно вставить в модули, чтобы указать, какие функции должны быть встроены;в основном, inlining делает почти то же самое, что и вызов макроса.
Я не смог понять, к какой именно цели вы стремитесь, но предположение, что макрос мог бы волшебным образом помочь засечь точный номер строки, совершенно неверно..
Вот демонстрация всех возможностей получить строку из __ENV__
:
bat /tmp/foo.ex
───────┬───────────────────────────────────────────────────────────────────
│ File: /tmp/foo.ex
───────┼───────────────────────────────────────────────────────────────────
1 │ defmodule Foo do
2 │ @compile {:inline, print_block_inline: 2}
3 │
4 │ def print_block_inline(_msg, do: code_block), do: code_block
5 │ def print_block_normal(_msg, do: code_block), do: code_block
6 │ defmacro print_block_macro(_msg, do: code_block), do: code_block
7 │
8 │ def test do
9 │ print_block_normal "prints message" do
10 │ IO.puts("hello world!")
11 │ IO.inspect(__ENV__.line, label: "11")
12 │ end
13 │
14 │ print_block_inline "prints message" do
15 │ IO.puts("hello world!")
16 │ IO.inspect(__ENV__.line, label: "16")
17 │ end
18 │
19 │ print_block_macro "prints message" do
20 │ IO.puts("hello world!")
21 │ IO.inspect(__ENV__.line, label: "21")
22 │ end
23 │ end
24 │ end
25 │
26 │ Foo.test()
Все успешно напечатано.
elixir /tmp/foo.ex
hello world!
11: 11
hello world!
16: 16
hello world!
21: 21