Источник Macro.Env
Структура, хранящая информацию об окружении во время компиляции.
Текущее окружение можно получить в любой момент как __ENV__/0. Внутри макросов, окружение вызывающего макрос можно получить как __CALLER__/0.
Большинство функций в этом модуле предназначены для инструментов низкого уровня, которым необходимо взаимодействовать с компилятором Elixir, таких как серверы языка и встроенные языки. Для обычного использования в коде Elixir и макросах необходимо использовать модуль Macro вместо этого. В частности, избегайте непосредственного изменения структуры Macro.Env и предпочитайте использовать высокоуровневые конструкции, такие как import, aliases, и т. д., для построения собственного окружения. Например, для построения пользовательского окружения можно определить функцию, такую как:
def make_custom_env do import SomeModule, only: [some_function: 2], warn: false alias A.B.C, warn: false __ENV__ end
Поля структуры
Структура Macro.Env содержит следующие поля:
-
context- контекст окружения; он может бытьnil(по умолчанию),:guard(внутри условия) или:match(внутри совпадения) -
context_modules- список модулей, определённых в текущем контексте -
file- текущее абсолютное имя файла в виде бинарного значения -
function- кортеж как{atom, integer}, где первый элемент - имя функции, а второй - её арность; возвращаетnilесли не находится внутри функции -
line- текущая строка в виде целого числа -
module- текущее имя модуля
Следующие поля предназначены для механизма макрорасширения Elixir и не должны использоваться напрямую:
aliasesfunctionsmacro_aliasesmacroslexical_trackerrequirestracersversioned_vars
Резюме
Типы
Функции
- define_alias(env, meta, module, opts \\ [])
Определяет заданный
asкак псевдоним дляmoduleв окружении.- define_import(env, meta, module, opts \\ [])
Определяет заданный
moduleкак импорт в окружении.- define_require(env, meta, module, opts \\ [])
Определяет заданный
moduleкак require в окружении.- expand_alias(env, meta, list, opts \\ [])
Расширяет псевдоним, заданный сегментами псевдонима.
- expand_import(env, meta, name, arity, opts \\ [])
Расширяет импорт, заданный
nameиarity.- expand_require(env, meta, module, name, arity, opts \\ [])
Расширяет require, заданный
module,name, иarity.- has_var?(env, var)
Проверяет, принадлежит ли переменная окружению.
- in_guard?(env)
Возвращает значение true, если окружение компиляции находится внутри условия.
- in_match?(env)
Возвращает значение true, если окружение компиляции находится внутри блока совпадения.
- location(env)
Возвращает список ключевых слов, содержащий информацию о файле и строке в качестве ключей.
- lookup_alias_as(env, atom)
Возвращает имена любых псевдонимов для данного модуля или атома.
- lookup_import(env, name_arity)
Возвращает модули, из которых был импортирован данный
{name, arity}.- prepend_tracer(env, tracer)
Добавляет отслеживатель в начало списка отслеживателей в окружении.
- prune_compile_info(env)
Удаляет информацию о компиляции из окружения.
- required?(env, module)
Возвращает
trueесли указанный модуль был загружен.- stacktrace(env)
Возвращает стек вызовов окружения.
- to_guard(env)
Возвращает окружение в контексте условия.
- to_match(env)
Возвращает окружение в контексте совпадения.
- vars(env)
Возвращает список переменных в текущем окружении.
Типы
context()Источник
@type context() :: :match | :guard | nil
context_modules()Источник
@type context_modules() :: [module()]
file()Источник
@type file() :: binary()
line()Источник
@type line() :: non_neg_integer()
name_arity()Источник
@type name_arity() :: {atom(), arity()} t()Источник
@type t() :: %Macro.Env{
aliases: aliases(),
context: context(),
context_modules: context_modules(),
file: file(),
function: name_arity() | nil,
functions: functions(),
lexical_tracker: lexical_tracker(),
line: line(),
macro_aliases: macro_aliases(),
macros: macros(),
module: module(),
requires: requires(),
tracers: tracers(),
versioned_vars: versioned_vars()
} variable()Источник
@type variable() :: {atom(), atom() | term()} Функции
define_alias(env, meta, module, opts \\ [])Source
@spec define_alias(t(), Macro.metadata(), module(), keyword()) ::
{:ok, t()} | {:error, String.t()} Определяет заданный as как псевдоним для module в среде.
Используется инструментами, которые нуждаются в имитации компилятора Elixir. Будет выброшено соответствующее событие отслеживания компилятора :alias.
Дополнительные параметры
Принимает те же параметры, что и Kernel.SpecialForm.alias/2, плюс:
-
:trace- при установке вfalse, отключает отслеживание компиляции и отслеживание лексических единиц. Этот параметр должен использоваться только серверами языков программирования и другими инструментами, которым необходимо инспектировать код без влияния на его компиляцию. Отключение отслеживания внутри макросов или обычного расширения кода крайне не рекомендуется, так как это блокирует компилятор от точного отслеживания зависимостей.
Примеры
iex> env = __ENV__
iex> Macro.Env.expand_alias(env, [], [:Baz])
:error
iex> {:ok, env} = Macro.Env.define_alias(env, [line: 10], Foo.Bar, as: Baz)
iex> Macro.Env.expand_alias(env, [], [:Baz])
{:alias, Foo.Bar}
iex> Macro.Env.expand_alias(env, [], [:Baz, :Bat])
{:alias, Foo.Bar.Bat}
Если параметр :as не задан, псевдоним будет выведен из модуля:
iex> env = __ENV__
iex> {:ok, env} = Macro.Env.define_alias(env, [line: 10], Foo.Bar)
iex> Macro.Env.expand_alias(env, [], [:Bar])
{:alias, Foo.Bar}
Если это невозможно определить, возвращается ошибка:
iex> Macro.Env.define_alias(__ENV__, [line: 10], :an_atom)
{:error,
"alias cannot be inferred automatically for module: :an_atom, " <>
"please use the :as option. Implicit aliasing is only supported with Elixir modules"} define_import(env, meta, module, opts \\ [])Source
@spec define_import(t(), Macro.metadata(), module(), keyword()) ::
{:ok, t()} | {:error, String.t()} Определяет заданный module как импортированный в среде.
Предполагает, что module доступен. Используется инструментами, которые нуждаются в имитации компилятора Elixir. Будет выброшено соответствующее событие отслеживания компилятора :import.
Дополнительные параметры
Принимает те же параметры, что и Kernel.SpecialForm.import/2, плюс:
:emit_warnings- генерировать предупреждения, найденные при определении импортов:trace- при установке вfalse, отключает отслеживание компиляции и отслеживание лексических единиц. Этот параметр должен использоваться только серверами языков программирования и другими инструментами, которым необходимо инспектировать код без влияния на его компиляцию. Отключение отслеживания внутри макросов или обычного расширения кода крайне не рекомендуется, так как это блокирует компилятор от точного отслеживания зависимостей:info_callback- функция, используемая вместоModule.__info__/1. Функция будет вызвана с аргументом:functionsили:macros. Она должна возвращать список пар ключ-значение{function, arity}. В случае ошибки используется метаданные модуля, основанные наmodule_info/1.
Примеры
iex> env = __ENV__
iex> Macro.Env.lookup_import(env, {:flatten, 1})
[]
iex> {:ok, env} = Macro.Env.define_import(env, [line: 10], List)
iex> Macro.Env.lookup_import(env, {:flatten, 1})
[{:function, List}]
Принимает те же параметры, что и Kernel.SpecialForm.import/2:
iex> env = __ENV__
iex> Macro.Env.lookup_import(env, {:is_odd, 1})
[]
iex> {:ok, env} = Macro.Env.define_import(env, [line: 10], Integer, only: :macros)
iex> Macro.Env.lookup_import(env, {:is_odd, 1})
[{:macro, Integer}]
Переопределение обратного вызова info
iex> env = __ENV__
iex> Macro.Env.lookup_import(env, {:flatten, 1})
[]
iex> {:ok, env} = Macro.Env.define_import(env, [line: 10], SomeModule, [info_callback: fn :functions -> [{:flatten, 1}]; :macros -> [{:some, 2}]; end])
iex> Macro.Env.lookup_import(env, {:flatten, 1})
[{:function, SomeModule}]
iex> Macro.Env.lookup_import(env, {:some, 2})
[{:macro, SomeModule}] define_require(env, meta, module, opts \\ [])Source
Определяет заданный module как требуемый в среде.
Не проверяет и не утверждает, что модуль доступен. Используется инструментами, которые нуждаются в имитации компилятора Elixir. Будет выброшено соответствующее событие отслеживания компилятора :require.
Дополнительные параметры
Принимает те же параметры, что и Kernel.SpecialForm.require/2, плюс:
-
:trace- при установке вfalse, отключает отслеживание компиляции и отслеживание лексических единиц. Этот параметр должен использоваться только серверами языков программирования и другими инструментами, которым необходимо инспектировать код без влияния на его компиляцию. Отключение отслеживания внутри макросов или обычного расширения кода крайне не рекомендуется, так как это блокирует компилятор от точного отслеживания зависимостей
Примеры
iex> env = __ENV__
iex> Macro.Env.required?(env, Integer)
false
iex> {:ok, env} = Macro.Env.define_require(env, [line: 10], Integer)
iex> Macro.Env.required?(env, Integer)
true
Если задан параметр :as, будет также определен псевдоним:
iex> env = __ENV__
iex> {:ok, env} = Macro.Env.define_require(env, [line: 10], Foo.Bar, as: Baz)
iex> Macro.Env.expand_alias(env, [], [:Baz])
{:alias, Foo.Bar} expand_alias(env, meta, list, opts \\ [])Source
@spec expand_alias(t(), keyword(), [atom()], keyword()) :: {:alias, atom()} | :error Расширяет псевдоним, заданный сегментами псевдонима.
Возвращает {:alias, alias} если сегменты — список атомов и псевдоним был найден. В противном случае возвращает :error.
Это расширение может генерировать событие отслеживания :alias_expansion, но не :alias_reference.
Параметры
-
:trace- при установке вfalse, отключает отслеживание компиляции и отслеживание лексических единиц. Этот параметр должен использоваться только серверами языков программирования и другими инструментами, которым необходимо инспектировать код без влияния на его компиляцию. Отключение отслеживания внутри макросов или обычного расширения кода крайне не рекомендуется, так как это блокирует компилятор от точного отслеживания зависимостей
Примеры
iex> alias List, as: MyList
iex> Macro.Env.expand_alias(__ENV__, [], [:MyList])
{:alias, List}
iex> Macro.Env.expand_alias(__ENV__, [], [:MyList, :Nested])
{:alias, List.Nested}
Если псевдонима нет или псевдоним начинается с Elixir. (что отключает алиасинг), возвращается :error:
iex> alias List, as: MyList iex> Macro.Env.expand_alias(__ENV__, [], [:Elixir, MyList]) :error iex> Macro.Env.expand_alias(__ENV__, [], [:AnotherList]) :error
expand_import(env, meta, name, arity, opts \\ [])Source
@spec expand_import(t(), keyword(), atom(), arity(), keyword()) ::
{:macro, module(), (Macro.metadata(), args :: [Macro.t()] -> Macro.t())}
| {:function, module(), atom()}
| {:error, :not_found | {:conflict, module()} | {:ambiguous, [module()]}} Расширяет импорт, заданный name и arity.
Если импорт указывает на макрос, возвращает кортеж с модулем и функцией, расширяющей макрос. Функция ожидает, что метаданные будут прикреплены к расширению и аргументы макроса.
Если импорт указывает на функцию, возвращает кортеж с модулем и именем функции.
Если найден какой-либо импорт, будет выброшено соответствующее событие отслеживания компилятора.
В противном случае возвращает {:error, reason}.
Параметры
:allow_locals- при установке вfalse, не пытается захватить локальные макросы, определенные в текущем модуле вenv:check_deprecations- при установке вfalse, не проверяет устаревшие функции при расширении макросов:trace- при установке вfalse, отключает отслеживание компиляции и отслеживание лексических единиц. Этот параметр должен использоваться только серверами языков программирования и другими инструментами, которым необходимо инспектировать код без влияния на его компиляцию. Отключение отслеживания внутри макросов или обычного расширения кода крайне не рекомендуется, так как это блокирует компилятор от точного отслеживания зависимостей
expand_require(env, meta, module, name, arity, opts \\ [])Source
@spec expand_require(t(), keyword(), module(), atom(), arity(), keyword()) ::
{:macro, module(), (Macro.metadata(), args :: [Macro.t()] -> Macro.t())}
| :error Расширяет require, заданный module, name, и arity.
Если require указывает на макрос, и модуль был загружен, возвращает кортеж с модулем и функцией, расширяющей макрос. Функция ожидает, что метаданные будут прикреплены к расширению и аргументы макроса. Соответствующее событие отслеживания компилятора :remote_macro будет выброшено, если найден макрос (обратите внимание, что событие :remote_function не генерируется в случаях :error).
В противном случае возвращает :error.
Параметры
:check_deprecations- при установке вfalse, не проверяет устаревшие функции при расширении макросов:trace- при установке вfalse, отключает отслеживание компиляции и отслеживание лексических единиц. Этот параметр должен использоваться только серверами языков программирования и другими инструментами, которым необходимо инспектировать код без влияния на его компиляцию. Отключение отслеживания внутри макросов или обычного расширения кода крайне не рекомендуется, так как это блокирует компилятор от точного отслеживания зависимостей
has_var?(env, var)Source
@spec has_var?(t(), variable()) :: boolean()
Проверяет, принадлежит ли переменная среде.
Примеры
iex> x = 13
iex> x
13
iex> Macro.Env.has_var?(__ENV__, {:x, nil})
true
iex> Macro.Env.has_var?(__ENV__, {:unknown, nil})
false in_guard?(env)Source
@spec in_guard?(t()) :: boolean()
Возвращает значение, указывающее, находится ли среда компиляции в данный момент внутри условия.
in_match?(env)Source
@spec in_match?(t()) :: boolean()
Возвращает значение, указывающее, находится ли среда компиляции в данный момент внутри условия соответствия.
location(env)Source
@spec location(t()) :: keyword()
Возвращает список ключевых слов, содержащих информацию о файле и строке в качестве ключей.
lookup_alias_as(env, atom)Source
@spec lookup_alias_as(t(), atom()) :: [atom()]
Возвращает имена любых псевдонимов для данного модуля или атома.
Примеры
iex> alias Foo.Bar iex> Bar Foo.Bar iex> Macro.Env.lookup_alias_as(__ENV__, Foo.Bar) [Elixir.Bar] iex> alias Foo.Bar, as: Baz iex> Baz Foo.Bar iex> Macro.Env.lookup_alias_as(__ENV__, Foo.Bar) [Elixir.Bar, Elixir.Baz] iex> Macro.Env.lookup_alias_as(__ENV__, Unknown) []
lookup_import(env, name_arity)Source
@spec lookup_import(t(), name_arity()) :: [{:function | :macro, module()}] Возвращает модули, из которых был импортирован данный {name, arity}.
Возвращает список кортежей из двух элементов в форме {:function | :macro, module}. Элементы в списке расположены в произвольном порядке, и порядок не гарантируется.
Использовать только для интроспекции
Эта функция не генерирует события отслеживания компилятора, что может помешать компилятору правильно отслеживать зависимости. Используйте эту функцию для целей рефлексии, но не используйте её для расширения импортов в квалифицированные вызовы. Вместо этого используйте expand_import/5.
Примеры
iex> Macro.Env.lookup_import(__ENV__, {:duplicate, 2})
[]
iex> import Tuple, only: [duplicate: 2], warn: false
iex> Macro.Env.lookup_import(__ENV__, {:duplicate, 2})
[{:function, Tuple}]
iex> import List, only: [duplicate: 2], warn: false
iex> Macro.Env.lookup_import(__ENV__, {:duplicate, 2})
[{:function, List}, {:function, Tuple}]
iex> Macro.Env.lookup_import(__ENV__, {:def, 1})
[{:macro, Kernel}] prepend_tracer(env, tracer)Source
@spec prepend_tracer(t(), module()) :: t()
Добавляет отслеживатель в начало списка отслеживателей в среде.
Примеры
Macro.Env.prepend_tracer(__ENV__, MyCustomTracer)
prune_compile_info(env)Source
@spec prune_compile_info(t()) :: t()
Удаляет информацию о компиляции из среды.
Это происходит, когда среда захватывается во время компиляции, например, в теле модуля, а затем используется для оценки кода после определения модуля.
required?(env, module)Source
@spec required?(t(), module()) :: boolean()
Возвращает true, если данный модуль был загружен.
Примеры
iex> Macro.Env.required?(__ENV__, Integer) false iex> require Integer iex> Macro.Env.required?(__ENV__, Integer) true iex> Macro.Env.required?(__ENV__, Kernel) true
stacktrace(env)Source
@spec stacktrace(t()) :: list()
Возвращает стек вызовов среды.
to_guard(env)Source
@spec to_guard(t()) :: t()
Возвращает среду в контексте условия.
to_match(env)Source
@spec to_match(t()) :: t()
Возвращает среду в контексте сопоставления.
vars(env)Source
@spec vars(t()) :: [variable()]
Возвращает список переменных в текущей среде.
Каждая переменная идентифицируется кортежем из двух элементов: имя переменной в виде атома и её контекст, который может быть атомом или целым числом.
© 2012-2024 The Elixir Team
Licensed under the Apache License, Version 2.0.
https://hexdocs.pm/elixir/1.18.1/Macro.Env.html