Исходный код 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как требуемый в окружении.- 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)
Возвращает значение, указывающее, находится ли среда компиляции в данный момент внутри условия.
- in_match?(env)
Возвращает значение, указывающее, находится ли среда компиляции в данный момент внутри соответствия.
- 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.17.2/Macro.Env.html