# `Beaver.Walker`

Provides traversal capabilities for MLIR structures.

This module implements traversal functionality for MLIR structures including:
- `operations/1`
- `results/1`
- `successors/1`
- `attributes/1`
- `regions/1`

It implements both the `Enumerable` protocol and the `Access` behavior to provide
a familiar interface for working with MLIR structures.

### Depth-first, pre-order and post-order walking
Allows traversing MLIR structures in depth-first order, visiting each node and its
children before moving to siblings. Supports both pre-order (visit node before children) and post-order (visit children
before node).

### Mutation Support
Walker callbacks should only traverse and inspect IR. Use
`Beaver.MLIR.PatternRewriter` inside rewrite patterns, or collect matches and
mutate them afterward with `Beaver.MLIR.IRRewriter`. Keeping traversal and
mutation separate prevents callbacks from retaining invalidated operations.

### Access Syntax
- Access behavior to provide convenient attribute access:
```elixir
op[:attr_name]
op["attr_name"]
```
- convenient access to get operands, results, regions
```
operands(op)[0]
```

# `container`

```elixir
@type container() ::
  operation()
  | Beaver.MLIR.Region.t()
  | Beaver.MLIR.Block.t()
  | Beaver.MLIR.NamedAttribute.t()
```

# `element`

```elixir
@type element() ::
  operation()
  | Beaver.MLIR.Region.t()
  | Beaver.MLIR.Block.t()
  | Beaver.MLIR.Value.t()
  | Beaver.MLIR.NamedAttribute.t()
```

# `element_module`

```elixir
@type element_module() ::
  Beaver.MLIR.Operation
  | Beaver.MLIR.Region
  | Beaver.MLIR.Block
  | Beaver.MLIR.Value
  | Beaver.MLIR.Attribute
```

# `mlir`

```elixir
@type mlir() :: container() | element()
```

# `operation`

```elixir
@type operation() :: Beaver.MLIR.Module.t() | Beaver.MLIR.Operation.t()
```

# `t`

```elixir
@type t() :: %Beaver.Walker{
  container: container(),
  element_module: element_module(),
  get_element: (container(), integer() -&gt; element()) | nil,
  get_first: (container() -&gt; element()) | nil,
  get_next: (element() -&gt; element()) | nil,
  get_num: (container() -&gt; Beaver.Native.I64.t() | integer()) | nil,
  get_parent: (element() -&gt; container()) | nil,
  is_null: (element() -&gt; Beaver.Native.Bool.t() | bool()) | nil,
  num: non_neg_integer() | nil,
  parent_equal: (element(), element() -&gt; Beaver.Native.Bool.t() | bool()) | nil,
  this: element() | non_neg_integer() | nil
}
```

# `arguments`

```elixir
@spec arguments(Beaver.MLIR.Block.t()) :: Enumerable.t()
```

Returns an enumerable of the arguments of an `Block.t()`

# `attributes`

```elixir
@spec attributes(operation()) :: Enumerable.t()
```

Returns an enumerable of the attributes of an `operation()`.

# `blocks`

```elixir
@spec blocks(Beaver.MLIR.Region.t()) :: Enumerable.t()
```

Returns an enumerable of the blocks of an `Region.t()`

# `operands`

```elixir
@spec operands(operation()) :: Enumerable.t()
```

Returns an enumerable of the operands of an `operation()`.

# `operations`

```elixir
@spec operations(Beaver.MLIR.Block.t()) :: Enumerable.t()
```

Returns an enumerable of the operations of an `Block.t()`

# `postwalk`

```elixir
@spec postwalk(mlir(), (mlir() -&gt; mlir())) :: mlir()
```

Performs a depth-first, post-order traversal of a MLIR structure.

# `postwalk`

```elixir
@spec postwalk(mlir(), any(), (mlir(), any() -&gt; {mlir(), any()})) :: {mlir(), any()}
```

Performs a depth-first, post-order traversal of a MLIR structure using an accumulator.

# `prewalk`

```elixir
@spec prewalk(mlir(), (mlir() -&gt; mlir())) :: mlir()
```

Performs a depth-first, pre-order traversal of a MLIR structure.

# `prewalk`

```elixir
@spec prewalk(mlir(), any(), (mlir(), any() -&gt; {mlir(), any()})) :: {mlir(), any()}
```

Performs a depth-first, pre-order traversal of a MLIR structure using an accumulator.

# `regions`

```elixir
@spec regions(operation()) :: Enumerable.t()
```

Returns an enumerable of the regions of an `operation()`.

# `results`

```elixir
@spec results(operation()) :: Enumerable.t()
```

Returns an enumerable of the results of an `operation()`.

# `successors`

```elixir
@spec successors(operation()) :: Enumerable.t()
```

Returns an enumerable of the successor blocks of an `operation()`.

# `traverse`

```elixir
@spec traverse(mlir(), any(), (mlir(), any() -&gt; {mlir(), any()}), (mlir(), any() -&gt;
                                                               {mlir(), any()})) ::
  {mlir(), any()}
```

Traverse a container in MLIR; it can be an operation, region, or block.
You might expect this function works like `Macro.traverse/4`.
### More on manipulating the IR
Keep mutation outside the active traversal. Use a pattern defined by
`Beaver.Pattern.defpat/2`, an Elixir `Beaver.MLIR.RewritePattern`, or first
collect the operations to change and then use `Beaver.MLIR.IRRewriter`.
### Some tips
- If your matching is very complicated, using `with/1` in Elixir should cover it.
- Use `defpat` if you want MLIR's greedy pattern application based on benefits instead of implementing something alike yourself.
- You can run traversals in a MLIR pass by calling them in `run/1` so that it joins the general MLIR pass manager's orchestration and will be run in parallel when possible.

# `uses`

```elixir
@spec uses(Beaver.MLIR.Value.t()) :: Enumerable.t()
```

Returns an enumerable of the uses of an `Value.t()`

