# `ExAST.Pattern`
[🔗](https://github.com/elixir-vibe/ex_ast/blob/v0.11.0/lib/ex_ast/pattern.ex#L1)

AST pattern matching with captures.

Patterns are valid Elixir syntax where:
- `name`, `expr` — capture the matched AST node
- `_` or `_name` — wildcard, matches anything, not captured
- `...` — matches zero or more nodes (args, list items, block statements)
- Structs and maps match partially (only specified keys must be present)
- Pipes are normalized (`data |> Enum.map(f)` matches `Enum.map(data, f)`)
- Multi-statement patterns match contiguous sequences in blocks

Repeated variable names require the same value at every position.

Patterns can be given as strings or as quoted expressions:

    Pattern.match(node, "IO.inspect(_)")
    Pattern.match(node, quote(do: IO.inspect(_)))

Use `...` for variable-arity matching:

    Pattern.match(node, "IO.inspect(...)")       # any arity
    Pattern.match(node, "foo(first, ...)")        # 1+ args, capture first
    Pattern.match(node, "def foo(_) do ... end")  # any body

# `captures`

```elixir
@type captures() :: %{required(atom()) =&gt; term()}
```

# `pattern`

```elixir
@type pattern() :: String.t() | Macro.t()
```

# `match`

```elixir
@spec match(Macro.t(), pattern()) :: {:ok, captures()} | :error
```

Matches an AST node against a pattern.

The pattern can be a string or a quoted expression.
Returns `{:ok, captures}` on match, `:error` otherwise.

Alias directives found in the surrounding AST can be expanded before matching,
so `alias AshPhoenix.Form` followed by `Form.for_update(...)` matches
`AshPhoenix.Form.for_update(...)`.

# `match`

```elixir
@spec match(Macro.t(), pattern(), %{optional(atom()) =&gt; [atom()]}) ::
  {:ok, captures()} | :error
```

# `match_ast`

```elixir
@spec match_ast(Macro.t(), Macro.t()) :: {:ok, captures()} | :error
```

Matches an AST node against an already-parsed pattern AST.

Equivalent to `match/2` with a quoted pattern, kept for
backward compatibility.

# `match_ast`

```elixir
@spec match_ast(Macro.t(), Macro.t(), %{optional(atom()) =&gt; [atom()]}) ::
  {:ok, captures()} | :error
```

# `match_sequences`

```elixir
@spec match_sequences([Macro.t()], [Macro.t()]) :: [{captures(), Range.t()}]
```

Finds all contiguous subsequences of `nodes` matching `pattern_asts`.

Returns a list of `{captures, start_index..end_index}` tuples.
Captures are accumulated across all matched nodes and must be consistent.

# `match_sequences`

```elixir
@spec match_sequences([Macro.t()], [Macro.t()], %{optional(atom()) =&gt; [atom()]}) :: [
  {captures(), Range.t()}
]
```

# `multi_node?`

```elixir
@spec multi_node?(pattern()) :: boolean()
```

Returns `true` if the pattern contains multiple statements
(separated by `;` or newlines), enabling sequential matching.

# `pattern_nodes`

```elixir
@spec pattern_nodes(pattern()) :: [Macro.t()]
```

Returns the individual pattern ASTs from a (possibly multi-node) pattern.

# `substitute`

```elixir
@spec substitute(Macro.t(), captures()) :: Macro.t()
```

Substitutes captured values into a replacement template AST.

Variables in the template that match capture names are replaced
with the captured AST nodes.

---

*Consult [api-reference.md](api-reference.md) for complete listing*
