Macro — Elixir v1.18.3 (original) (raw)

Functions for manipulating AST and implementing macros.

Macros are compile-time constructs that receive Elixir's AST as input and return Elixir's AST as output.

Many of the functions in this module exist precisely to work with Elixir AST, to traverse, query, and transform it.

Let's see a simple example that shows the difference between functions and macros:

defmodule Example do
  defmacro macro_inspect(value) do
    IO.inspect(value)
    value
  end

  def fun_inspect(value) do
    IO.inspect(value)
    value
  end
end

Now let's give it a try:

import Example

macro_inspect(1)
#=> 1
#=> 1

fun_inspect(1)
#=> 1
#=> 1

So far they behave the same, as we are passing an integer as argument. But let's see what happens when we pass an expression:

macro_inspect(1 + 2)
#=> {:+, [line: 3], [1, 2]}
#=> 3

fun_inspect(1 + 2)
#=> 3
#=> 3

The macro receives the representation of the code given as argument, while a function receives the result of the code given as argument. A macro must return a superset of the code representation. Seeinput/0 and output/0 for more information.

To learn more about Elixir's AST and how to build them programmatically, see quote/2.

Evaluating code

The functions in this module do not evaluate code. In fact, evaluating code from macros is often an anti-pattern. For code evaluation, see the Code module.

Summary

Types

A captured remote function in the format of &Mod.fun/arity

A keyword list of AST metadata.

Abstract Syntax Tree (AST)

Functions

Converts the given string to CamelCase format.

Classifies an atom based on its possible AST placement.

Applies a mod, function, and args at compile-time in caller.

Decomposes a local or remote call into its remote part (when provided), function name and argument list.

Recursively escapes a value so it can be inserted into a syntax tree.

Receives an AST node and expands it until it can no longer be expanded.

Expands all literals in ast with the given env.

Expands all literals in ast with the given acc and fun.

Receives an AST node and expands it once.

Generates AST nodes for a given number of required argument variables using Macro.var/2.

Generates AST nodes for a given number of required argument variables using Macro.unique_var/2.

Inspects atom according to different source formats.

Returns true if the given name and arity is an operator.

Returns the path to the node in ast for which fun returns a truthy value.

Pipes expr into the call_args at the given position.

This function behaves like prewalk/2, but performs a depth-first, post-order traversal of quoted expressions.

This functions behaves like prewalk/3, but performs a depth-first, post-order traversal of quoted expressions using an accumulator.

Returns an enumerable that traverses the ast in depth-first, post-order traversal.

Performs a depth-first, pre-order traversal of quoted expressions.

Performs a depth-first, pre-order traversal of quoted expressions using an accumulator.

Returns an enumerable that traverses the ast in depth-first, pre-order traversal.

Returns true if the given quoted expression represents a quoted literal.

Returns true if the given name and arity is a special form.

struct!(module, env) deprecated

Extracts the struct information (equivalent to callingmodule.__info__(:struct)).

Converts the given expression AST to a string.

to_string(tree, fun) deprecated

Converts the given expression AST to a string.

Performs a depth-first traversal of quoted expressions using an accumulator.

Converts the given argument to a string with the underscore-slash format.

Unescapes characters in a string.

Unescapes characters in a string according to the given mapping.

Generates an AST node representing a unique variable given by the atoms var and context.

Breaks a pipeline expression into a list.

Applies the given function to the node metadata if it contains one.

Validates the given expressions are valid quoted expressions.

Generates an AST node representing the variable given by the atoms var and context.

Types

@type captured_remote_function() :: fun()

A captured remote function in the format of &Mod.fun/arity

The inputs of a macro

A keyword list of AST metadata.

The metadata in Elixir AST is a keyword list of values. Any key can be used and different parts of the compiler may use different keys. For example, the AST received by a macro will always include the :line annotation, while the AST emitted by quote/2 will only have the :line annotation if the :line option is provided.

The following metadata keys are public:

The following metadata keys are enabled by Code.string_to_quoted/2:

The following metadata keys are private:

Do not rely on them as they may change or be fully removed in future versions of the language. They are often used by quote/2 and the compiler to provide features like hygiene, better error messages, and so forth.

If you introduce custom keys into the AST metadata, please make sure to prefix them with the name of your library or application, so that they will not conflict with keys that could potentially be introduced by the compiler in the future.

The output of a macro

Abstract Syntax Tree (AST)

Functions

Converts the given string to CamelCase format.

This function was designed to camelize language identifiers/tokens, that's why it belongs to the Macro module. Do not use it as a general mechanism for camelizing strings as it does not support Unicode or characters that are not valid in Elixir identifiers.

Examples

iex> Macro.camelize("foo_bar")
"FooBar"

iex> Macro.camelize("foo/bar")
"Foo.Bar"

If uppercase characters are present, they are not modified in any way as a mechanism to preserve acronyms:

iex> Macro.camelize("API.V1")
"API.V1"
iex> Macro.camelize("API_SPEC")
"API_SPEC"

@spec classify_atom(atom()) :: :alias | :identifier | :quoted | :unquoted

Classifies an atom based on its possible AST placement.

It returns one of the following atoms:

Most operators are going to be :unquoted, such as :+, with some exceptions returning :quoted due to ambiguity, such as:"::". Use operator?/2 to check if a given atom is an operator.

Examples

iex> Macro.classify_atom(:foo)
:identifier
iex> Macro.classify_atom(Foo)
:alias
iex> Macro.classify_atom(:foo@bar)
:unquoted
iex> Macro.classify_atom(:+)
:unquoted
iex> Macro.classify_atom(:Foo)
:unquoted
iex> Macro.classify_atom(:"with spaces")
:quoted

Applies a mod, function, and args at compile-time in caller.

This is used when you want to programmatically invoke a macro at compile-time.

Default backend for Kernel.dbg/2.

This function provides a default backend for Kernel.dbg/2. See theKernel.dbg/2 documentation for more information.

This function:

You can call this function directly to build Kernel.dbg/2 backends that fall back to this function.

This function raises if the context of the given env is :match or :guard.

@spec decompose_call(t()) :: {atom(), [t()]} | {t(), atom(), [t()]} | :error

Decomposes a local or remote call into its remote part (when provided), function name and argument list.

Returns :error when an invalid call syntax is provided.

Examples

iex> Macro.decompose_call(quote(do: foo))
{:foo, []}

iex> Macro.decompose_call(quote(do: foo()))
{:foo, []}

iex> Macro.decompose_call(quote(do: foo(1, 2, 3)))
{:foo, [1, 2, 3]}

iex> Macro.decompose_call(quote(do: Elixir.M.foo(1, 2, 3)))
{{:__aliases__, [], [:Elixir, :M]}, :foo, [1, 2, 3]}

iex> Macro.decompose_call(quote(do: 42))
:error

iex> Macro.decompose_call(quote(do: {:foo, [], []}))
:error

Recursively escapes a value so it can be inserted into a syntax tree.

Examples

iex> Macro.escape(:foo)
:foo

iex> Macro.escape({:a, :b, :c})
{:{}, [], [:a, :b, :c]}

iex> Macro.escape({:unquote, [], [1]}, unquote: true)
1

Options

Comparison to quote/2

The escape/2 function is sometimes confused with quote/2, because the above examples behave the same with both. The key difference is best illustrated when the value to escape is stored in a variable.

iex> Macro.escape({:a, :b, :c})
{:{}, [], [:a, :b, :c]}
iex> quote do: {:a, :b, :c}
{:{}, [], [:a, :b, :c]}

iex> value = {:a, :b, :c}
iex> Macro.escape(value)
{:{}, [], [:a, :b, :c]}

iex> quote do: value
{:value, [], __MODULE__}

iex> value = {:a, :b, :c}
iex> quote do: unquote(value)
** (ArgumentError) tried to unquote invalid AST: {:a, :b, :c}
Did you forget to escape term using Macro.escape/1?

escape/2 is used to escape values (either directly passed or variable bound), while quote/2 produces syntax trees for expressions.

Receives an AST node and expands it until it can no longer be expanded.

Note this function does not traverse the AST, only the root node is expanded.

This function uses expand_once/2 under the hood. Check it out for more information and examples.

Expands all literals in ast with the given env.

This function is mostly used to remove compile-time dependencies from AST nodes. In such cases, the given environment is usually manipulated to represent a function:

Macro.expand_literals(ast, %{env | function: {:my_code, 1}})

At the moment, the only expandable literal nodes in an AST are aliases, so this function only expands aliases (and it does so anywhere in a literal).

However, be careful when removing compile-time dependencies between modules. If you remove them but you still invoke the module at compile-time, Elixir will be unable to properly recompile modules when they change.

@spec expand_literals(t(), acc, (t(), acc -> {t(), acc})) :: t() when acc: term()

Expands all literals in ast with the given acc and fun.

fun will be invoked with an expandable AST node and acc and must return a new node with acc. This is a general version ofexpand_literals/2 which supports a custom expansion function. Please check expand_literals/2 for use cases and pitfalls.

Receives an AST node and expands it once.

The following contents are expanded:

If the expression cannot be expanded, it returns the expression itself. This function does not traverse the AST, only the root node is expanded. The expansion happens as if it was expanded by the Elixir compiler and therefore compilation tracers will be invoked and deprecation warnings will be emitted during the expansion.

expand_once/2 performs the expansion just once. Check expand/2to perform expansion until the node can no longer be expanded.

Examples

In the example below, we have a macro that generates a module with a function named name_length that returns the length of the module name. The value of this function will be calculated at compilation time and not at runtime.

Consider the implementation below:

defmacro defmodule_with_length(name, do: block) do
  length = length(Atom.to_charlist(name))

  quote do
    defmodule unquote(name) do
      def name_length, do: unquote(length)
      unquote(block)
    end
  end
end

When invoked like this:

defmodule_with_length My.Module do
  def other_function, do: ...
end

The compilation will fail because My.Module when quoted is not an atom, but a syntax tree as follows:

{:__aliases__, [], [:My, :Module]}

That said, we need to expand the aliases node above to an atom, so we can retrieve its length. Expanding the node is not straightforward because we also need to expand the caller aliases. For example:

alias MyHelpers, as: My

defmodule_with_length My.Module do
  def other_function, do: ...
end

The final module name will be MyHelpers.Module and notMy.Module. With Macro.expand/2, such aliases are taken into consideration. Local and remote macros are also expanded. We could rewrite our macro above to use this function as:

defmacro defmodule_with_length(name, do: block) do
  expanded = Macro.expand(name, __CALLER__)
  length = length(Atom.to_charlist(expanded))

  quote do
    defmodule unquote(name) do
      def name_length, do: unquote(length)
      unquote(block)
    end
  end
end

@spec generate_arguments(0, context :: atom()) :: []

@spec generate_arguments(pos_integer(), context) :: [{atom(), [], context}, ...] when context: atom()

Generates AST nodes for a given number of required argument variables using Macro.var/2.

Note the arguments are not unique. If you later on want to access the same variables, you can invoke this function with the same inputs. Use generate_unique_arguments/2 to generate unique arguments that can't be overridden.

Examples

iex> Macro.generate_arguments(2, __MODULE__)
[{:arg1, [], __MODULE__}, {:arg2, [], __MODULE__}]

@spec generate_unique_arguments(0, context :: atom()) :: []

@spec generate_unique_arguments(pos_integer(), context) :: [ {atom(), [{:counter, integer()}], context}, ... ] when context: atom()

Generates AST nodes for a given number of required argument variables using Macro.unique_var/2.

Examples

iex> [var1, var2] = Macro.generate_unique_arguments(2, __MODULE__)
iex> {:arg1, [counter: c1], __MODULE__} = var1
iex> {:arg2, [counter: c2], __MODULE__} = var2
iex> is_integer(c1) and is_integer(c2)
true

Inspects atom according to different source formats.

The atom can be inspected according to the three different formats it appears in the AST: as a literal (:literal), as a key (:key), or as the function name of a remote call (:remote_call).

Options

Examples

As a literal

Literals include regular atoms, quoted atoms, operators, aliases, and the special nil, true, and false atoms.

iex> Macro.inspect_atom(:literal, nil)
"nil"
iex> Macro.inspect_atom(:literal, :foo)
":foo"
iex> Macro.inspect_atom(:literal, :<>)
":<>"
iex> Macro.inspect_atom(:literal, :Foo)
":Foo"
iex> Macro.inspect_atom(:literal, Foo.Bar)
"Foo.Bar"
iex> Macro.inspect_atom(:literal, :"with spaces")
":\"with spaces\""

As a key

Inspect an atom as a key of a keyword list or a map.

iex> Macro.inspect_atom(:key, :foo)
"foo:"
iex> Macro.inspect_atom(:key, :<>)
"<>:"
iex> Macro.inspect_atom(:key, :Foo)
"Foo:"
iex> Macro.inspect_atom(:key, :"with spaces")
"\"with spaces\":"

As a remote call

Inspect an atom the function name of a remote call.

iex> Macro.inspect_atom(:remote_call, :foo)
"foo"
iex> Macro.inspect_atom(:remote_call, :<>)
"<>"
iex> Macro.inspect_atom(:remote_call, :Foo)
"\"Foo\""
iex> Macro.inspect_atom(:remote_call, :"with spaces")
"\"with spaces\""

Returns true if the given name and arity is an operator.

Examples

iex> Macro.operator?(:not_an_operator, 3)
false
iex> Macro.operator?(:.., 0)
true
iex> Macro.operator?(:+, 1)
true
iex> Macro.operator?(:++, 2)
true
iex> Macro.operator?(:..//, 3)
true

Returns the path to the node in ast for which fun returns a truthy value.

The path is a list, starting with the node in which fun returns a truthy value, followed by all of its parents.

Returns nil if fun returns only falsy values.

Computing the path can be an efficient operation when you want to find a particular node in the AST within its context and then assert something about it.

Examples

iex> Macro.path(quote(do: [1, 2, 3]), & &1 == 3)
[3, [1, 2, 3]]

iex> Macro.path(quote(do: [1, 2]), & &1 == 5)
nil

iex> Macro.path(quote(do: Foo.bar(3)), & &1 == 3)
[3, quote(do: Foo.bar(3))]

iex> Macro.path(quote(do: %{foo: [bar: :baz]}), & &1 == :baz)
[
  :baz,
  {:bar, :baz},
  [bar: :baz],
  {:foo, [bar: :baz]},
  {:%{}, [], [foo: [bar: :baz]]}
]

Pipes expr into the call_args at the given position.

This function can be used to implement |> like functionality. For example,|> itself is implemented as:

defmacro left |> right do
  Macro.pipe(left, right, 0)
end

expr is the AST of an expression. call_args must be the AST of a call, otherwise this function will raise an error. As an example, consider the pipe operator |>/2, which uses this function to build pipelines.

Even if the expression is piped into the AST, it doesn't necessarily mean that the AST is valid. For example, you could pipe an argument to div/2, effectively turning it into a call to div/3, which is a function that doesn't exist by default. The code will raise unless a div/3 function is locally defined.

@spec postwalk(t(), (t() -> t())) :: t()

This function behaves like prewalk/2, but performs a depth-first, post-order traversal of quoted expressions.

@spec postwalk(t(), any(), (t(), any() -> {t(), any()})) :: {t(), any()}

This functions behaves like prewalk/3, but performs a depth-first, post-order traversal of quoted expressions using an accumulator.

Returns an enumerable that traverses the ast in depth-first, post-order traversal.

Examples

iex> ast = quote do: foo(1, "abc")
iex> Enum.map(Macro.postwalker(ast), & &1)
[1, "abc", {:foo, [], [1, "abc"]}]

@spec prewalk(t(), (t() -> t())) :: t()

Performs a depth-first, pre-order traversal of quoted expressions.

Returns a new AST where each node is the result of invoking fun on each corresponding node of ast.

Examples

iex> ast = quote do: 5 + 3 * 7
iex> {:+, _, [5, {:*, _, [3, 7]}]} = ast
iex> new_ast = Macro.prewalk(ast, fn
...>   {:+, meta, children} -> {:*, meta, children}
...>   {:*, meta, children} -> {:+, meta, children}
...>   other -> other
...> end)
iex> {:*, _, [5, {:+, _, [3, 7]}]} = new_ast
iex> Code.eval_quoted(ast)
{26, []}
iex> Code.eval_quoted(new_ast)
{50, []}

@spec prewalk(t(), any(), (t(), any() -> {t(), any()})) :: {t(), any()}

Performs a depth-first, pre-order traversal of quoted expressions using an accumulator.

Returns a tuple where the first element is a new AST where each node is the result of invoking fun on each corresponding node and the second one is the final accumulator.

Examples

iex> ast = quote do: 5 + 3 * 7
iex> {:+, _, [5, {:*, _, [3, 7]}]} = ast
iex> {new_ast, acc} = Macro.prewalk(ast, [], fn
...>   {:+, meta, children}, acc -> {{:*, meta, children}, [:+ | acc]}
...>   {:*, meta, children}, acc -> {{:+, meta, children}, [:* | acc]}
...>   other, acc -> {other, acc}
...> end)
iex> {{:*, _, [5, {:+, _, [3, 7]}]}, [:*, :+]} = {new_ast, acc}
iex> Code.eval_quoted(ast)
{26, []}
iex> Code.eval_quoted(new_ast)
{50, []}

Returns an enumerable that traverses the ast in depth-first, pre-order traversal.

Examples

iex> ast = quote do: foo(1, "abc")
iex> Enum.map(Macro.prewalker(ast), & &1)
[{:foo, [], [1, "abc"]}, 1, "abc"]

@spec quoted_literal?(t()) :: boolean()

Returns true if the given quoted expression represents a quoted literal.

Atoms and numbers are always literals. Binaries, lists, tuples, maps, and structs are only literals if all of their terms are also literals.

Examples

iex> Macro.quoted_literal?(quote(do: "foo"))
true
iex> Macro.quoted_literal?(quote(do: {"foo", 1}))
true
iex> Macro.quoted_literal?(quote(do: {"foo", 1, :baz}))
true
iex> Macro.quoted_literal?(quote(do: %{foo: "bar"}))
true
iex> Macro.quoted_literal?(quote(do: %URI{path: "/"}))
true
iex> Macro.quoted_literal?(quote(do: URI.parse("/")))
false
iex> Macro.quoted_literal?(quote(do: {foo, var}))
false

Returns true if the given name and arity is a special form.

This function is deprecated. Use Macro.struct_info!/2 instead.

Extracts the struct information (equivalent to callingmodule.__info__(:struct)).

This is useful when a struct needs to be expanded at compilation time and the struct being expanded may or may not have been compiled. This function is also capable of expanding structs defined under the module being compiled. Calling this function also adds an export dependency on the given struct.

It will raise ArgumentError if the struct is not available.

Converts the given expression AST to a string.

This is a convenience function for converting AST into a string, which discards all formatting of the original code and wraps newlines around 98 characters. SeeCode.quoted_to_algebra/2 as a lower level function with more control around formatting.

If the AST contains invalid nodes, this function will attempt to inspect them, to aid debugging, although the elements won't be formatted accordingly.

Examples

iex> Macro.to_string(quote(do: foo.bar(1, 2, 3)))
"foo.bar(1, 2, 3)"

This function is deprecated. Use Macro.to_string/1 instead.

Converts the given expression AST to a string.

The given fun is called for every node in the AST with two arguments: the AST of the node being printed and the string representation of that same node. The return value of this function is used as the final string representation for that AST node.

This function discards all formatting of the original code.

Examples

Macro.to_string(quote(do: 1 + 2), fn
  1, _string -> "one"
  2, _string -> "two"
  _ast, string -> string
end)
#=> "one + two"

@spec traverse(t(), any(), (t(), any() -> {t(), any()}), (t(), any() -> {t(), any()})) :: {t(), any()}

Performs a depth-first traversal of quoted expressions using an accumulator.

Returns a tuple where the first element is a new AST and the second one is the final accumulator. The new AST is the result of invoking pre on each node of ast during the pre-order phase and post during the post-order phase.

Examples

iex> ast = quote do: 5 + 3 * 7
iex> {:+, _, [5, {:*, _, [3, 7]}]} = ast
iex> {new_ast, acc} =
...>  Macro.traverse(
...>    ast,
...>    [],
...>    fn
...>      {:+, meta, children}, acc -> {{:-, meta, children}, [:- | acc]}
...>      {:*, meta, children}, acc -> {{:/, meta, children}, [:/ | acc]}
...>      other, acc -> {other, acc}
...>    end,
...>    fn
...>      {:-, meta, children}, acc -> {{:min, meta, children}, [:min | acc]}
...>      {:/, meta, children}, acc -> {{:max, meta, children}, [:max | acc]}
...>      other, acc -> {other, acc}
...>    end
...>  )
iex> {:min, _, [5, {:max, _, [3, 7]}]} = new_ast
iex> [:min, :max, :/, :-] = acc
iex> Code.eval_quoted(new_ast)
{5, []}

Converts the given argument to a string with the underscore-slash format.

The argument must either be an atom, representing an Elixir module, or a string representing a module without the Elixir. prefix.

This function was designed to format language identifiers/tokens with the underscore-slash format, that's why it belongs to the Macro module. Do not use it as a general mechanism for underscoring strings as it does not support Unicode or characters that are not valid in Elixir identifiers.

Examples

iex> Macro.underscore("FooBar")
"foo_bar"

iex> Macro.underscore("Foo.Bar")
"foo/bar"

iex> Macro.underscore(Foo.Bar)
"foo/bar"

In general, underscore can be thought of as the reverse ofcamelize, however, in some cases formatting may be lost:

iex> Macro.underscore("SAPExample")
"sap_example"

iex> Macro.camelize("sap_example")
"SapExample"

iex> Macro.camelize("hello_10")
"Hello10"

iex> Macro.camelize("foo/bar")
"Foo.Bar"

Unescapes characters in a string.

This is the unescaping behaviour used by default in Elixir single- and double-quoted strings. Check unescape_string/2for information on how to customize the escaping map.

In this setup, Elixir will escape the following: \0, \a, \b,\d, \e, \f, \n, \r, \s, \t and \v. Bytes can be given as hexadecimals via \xNN and Unicode code points as\uNNNN escapes.

This function is commonly used on sigil implementations (like ~r, ~s and others), which receive a raw, unescaped string, and it can be used anywhere that needs to mimic how Elixir parses strings.

Examples

iex> Macro.unescape_string("example\\n")
"example\n"

In the example above, we pass a string with \n escaped and return a version with it unescaped.

Unescapes characters in a string according to the given mapping.

Check unescape_string/1 if you want to use the same mapping as Elixir single- and double-quoted strings.

Mapping function

The mapping function receives an integer representing the code point of the character it wants to unescape. There are also the special atoms:newline, :unicode, and :hex, which control newline, unicode, and escaping respectively.

Here is the default mapping function implemented by Elixir:

def unescape_map(:newline), do: true
def unescape_map(:unicode), do: true
def unescape_map(:hex), do: true
def unescape_map(?0), do: ?0
def unescape_map(?a), do: ?\a
def unescape_map(?b), do: ?\b
def unescape_map(?d), do: ?\d
def unescape_map(?e), do: ?\e
def unescape_map(?f), do: ?\f
def unescape_map(?n), do: ?\n
def unescape_map(?r), do: ?\r
def unescape_map(?s), do: ?\s
def unescape_map(?t), do: ?\t
def unescape_map(?v), do: ?\v
def unescape_map(e), do: e

If the unescape_map/1 function returns false, the char is not escaped and the backslash is kept in the string.

Examples

Using the unescape_map/1 function defined above is easy:

Macro.unescape_string("example\\n", &unescape_map(&1))

@spec unique_var(var, context) :: {var, [{:counter, integer()}], context} when var: atom(), context: atom()

Generates an AST node representing a unique variable given by the atoms var and context.

Calling this function with the same arguments will generate another variable, with its own unique counter. See var/2 for an alternative.

Examples

iex> {:foo, [counter: c], __MODULE__} = Macro.unique_var(:foo, __MODULE__)
iex> is_integer(c)
true

@spec unpipe(t()) :: [t()]

Breaks a pipeline expression into a list.

The AST for a pipeline (a sequence of applications of |>/2) is similar to the AST of a sequence of binary operators or function applications: the top-level expression is the right-most :|> (which is the last one to be executed), and its left-hand and right-hand sides are its arguments:

quote do: 100 |> div(5) |> div(2)
#=> {:|>, _, [arg1, arg2]}

In the example above, the |>/2 pipe is the right-most pipe; arg1 is the AST for 100 |> div(5), and arg2 is the AST for div(2).

It's often useful to have the AST for such a pipeline as a list of function applications. This function does exactly that:

Macro.unpipe(quote do: 100 |> div(5) |> div(2))
#=> [{100, 0}, {{:div, [], [5]}, 0}, {{:div, [], [2]}, 0}]

We get a list that follows the pipeline directly: first the 100, then thediv(5) (more precisely, its AST), then div(2). The 0 as the second element of the tuples is the position of the previous element in the pipeline inside the current function application: {{:div, [], [5]}, 0} means that the previous element (100) will be inserted as the 0th (first) argument to thediv/2 function, so that the AST for that function will become {:div, [], [100, 5]} (div(100, 5)).

Applies the given function to the node metadata if it contains one.

This is often useful when used with Macro.prewalk/2 to remove information like lines and hygienic counters from the expression for either storage or comparison.

iex> quoted = quote line: 10, do: sample()
{:sample, [line: 10], []}
iex> Macro.update_meta(quoted, &Keyword.delete(&1, :line))
{:sample, [], []}

@spec validate(term()) :: :ok | {:error, term()}

Validates the given expressions are valid quoted expressions.

Check the type Macro.t/0 for a complete specification of a valid quoted expression.

It returns :ok if the expression is valid. Otherwise it returns a tuple in the form of {:error, remainder} where remainder is the invalid part of the quoted expression.

Examples

iex> Macro.validate({:two_element, :tuple})
:ok
iex> Macro.validate({:three, :element, :tuple})
{:error, {:three, :element, :tuple}}

iex> Macro.validate([1, 2, 3])
:ok
iex> Macro.validate([1, 2, 3, {4}])
{:error, {4}}

@spec var(var, context) :: {var, [], context} when var: atom(), context: atom()

Generates an AST node representing the variable given by the atoms var and context.

Note this variable is not unique. If you later on want to access this same variable, you can invoke var/2again with the same arguments. Use unique_var/2 to generate a unique variable that can't be overridden.

Examples

In order to build a variable, a context is expected. Most of the times, in order to preserve hygiene, the context must be __MODULE__/0:

iex> Macro.var(:foo, __MODULE__)
{:foo, [], __MODULE__}

However, if there is a need to access the user variable, nil can be given:

iex> Macro.var(:foo, nil)
{:foo, [], nil}