# `Beaver.MLIR.Conversion.Plan`

An inspectable, declarative, scoped composition layer for MLIR dialect conversion.

A conversion plan records target legality rules, type conversions, materializations,
and rewrite patterns into a reusable data structure. When executed via `run/2`
or `run!/2`, the plan materializes fresh conversion targets, type converters,
and pattern sets in declaration order for the target `MLIR.Context`.

## Callbacks and Metadata

Callbacks registered with plan builders accept optional `:version` metadata.
`declaration/1` returns a deterministic map of plan configuration and step
metadata with function bodies and runtime state omitted. Unversioned callbacks
are marked as `:unversioned`. This metadata is only reproducible across runs
when callback versions are explicitly provided.

## Ownership & Scoping

Plans do not hold native handles; they can be safely reused across multiple
MLIR contexts. During `run/2`, temporary native resources (`MLIR.ConversionTarget`,
`MLIR.TypeConverter`, `MLIR.RewritePatternSet`) are created and cleaned up.
In case of errors or caller termination, resources are cleaned up deterministically:
pattern destruction occurs before type converter destruction, which occurs before
conversion target destruction.

# `mode`

```elixir
@type mode() :: :full | :partial
```

# `option`

```elixir
@type option() ::
  {:mode, mode()}
  | {:timeout, non_neg_integer() | nil}
  | {:folding_mode, :never | :before_patterns | :after_patterns | nil}
  | {:build_materializations, boolean() | nil}
```

# `t`

```elixir
@type t() :: %Beaver.MLIR.Conversion.Plan{
  build_materializations: boolean() | nil,
  entries: [term()],
  folding_mode: :never | :before_patterns | :after_patterns | nil,
  mode: mode(),
  timeout: non_neg_integer() | nil
}
```

# `add_1_to_n_conversion`

```elixir
@spec add_1_to_n_conversion(
  t(),
  (Beaver.MLIR.Type.t() -&gt; Beaver.MLIR.TypeConverter.one_to_n_result()),
  keyword()
) :: t()
```

# `add_1_to_n_target_materialization`

```elixir
@spec add_1_to_n_target_materialization(t(), function(), keyword()) :: t()
```

# `add_conversion`

```elixir
@spec add_conversion(
  t(),
  (Beaver.MLIR.Type.t() -&gt; Beaver.MLIR.TypeConverter.conversion_result()),
  keyword()
) :: t()
```

# `add_conversion_pattern`

```elixir
@spec add_conversion_pattern(
  t(),
  String.Chars.t(),
  Beaver.MLIR.ConversionPattern.callback(),
  keyword()
) :: t()
```

# `add_dynamically_legal_dialect`

```elixir
@spec add_dynamically_legal_dialect(
  t(),
  String.Chars.t(),
  Beaver.MLIR.ConversionTarget.legality_callback(),
  keyword()
) :: t()
```

# `add_dynamically_legal_op`

```elixir
@spec add_dynamically_legal_op(
  t(),
  String.Chars.t(),
  Beaver.MLIR.ConversionTarget.legality_callback(),
  keyword()
) :: t()
```

# `add_illegal_dialect`

```elixir
@spec add_illegal_dialect(t(), String.Chars.t()) :: t()
```

# `add_illegal_op`

```elixir
@spec add_illegal_op(t(), String.Chars.t()) :: t()
```

# `add_legal_dialect`

```elixir
@spec add_legal_dialect(t(), String.Chars.t()) :: t()
```

# `add_legal_op`

```elixir
@spec add_legal_op(t(), String.Chars.t()) :: t()
```

# `add_pattern`

```elixir
@spec add_pattern(t(), Beaver.Pattern.Native.Descriptor.t(), keyword()) :: t()
```

# `add_source_materialization`

```elixir
@spec add_source_materialization(t(), function(), keyword()) :: t()
```

# `add_target_materialization`

```elixir
@spec add_target_materialization(t(), function(), keyword()) :: t()
```

# `declaration`

```elixir
@spec declaration(t()) :: map()
```

Returns deterministic metadata for the given plan.

Function bodies and runtime state are omitted. Callback entries include their
`:version` if explicitly provided, or `:unversioned` if omitted.

> Note: Declaration metadata is only deterministic and reproducible across processes
> or runs when all callback versions are explicitly specified.

# `mark_recursively_legal`

```elixir
@spec mark_recursively_legal(
  t(),
  String.Chars.t(),
  Beaver.MLIR.ConversionTarget.legality_callback() | nil | keyword(),
  keyword()
) :: t()
```

# `mark_unknown_dynamically_legal`

```elixir
@spec mark_unknown_dynamically_legal(
  t(),
  Beaver.MLIR.ConversionTarget.legality_callback(),
  keyword()
) :: t()
```

# `new`

```elixir
@spec new(keyword()) :: t()
```

Creates a new conversion plan.

Options:
  * `:mode` - `:full` (default) or `:partial`.
  * `:timeout` - Timeout in milliseconds for conversion and callbacks (default `30_000`).
  * `:folding_mode` - `:never`, `:before_patterns`, `:after_patterns`, or `nil`.
  * `:build_materializations` - boolean or `nil`.

# `run`

```elixir
@spec run(t(), Beaver.MLIR.Conversion.conversion_ir()) ::
  Beaver.MLIR.Conversion.result()
```

Executes the conversion plan on the given IR (`MLIR.Module` or `MLIR.Operation`).

Fresh `MLIR.ConversionTarget`, `MLIR.TypeConverter`, and `MLIR.RewritePatternSet`
instances are created for the duration of the conversion and cleaned up afterwards.
Returns `MLIR.Conversion.result()`.

# `run!`

```elixir
@spec run!(t(), Beaver.MLIR.Conversion.conversion_ir()) ::
  Beaver.MLIR.Conversion.conversion_ir()
```

Executes the conversion plan on the given IR, returning the converted IR or raising `MLIR.Conversion.Error`.

