# `Beaver.MLIR`

Core functionality for working with MLIR.

This module serves as the primary interface for MLIR operations and entities in Beaver. It provides:

- String conversion utilities for debugging and serialization
- Null checking for safe operation handling
- Context and location retrieval for MLIR entities

## Printing Operations

When converting operations to strings, you can specify the output format:
- `generic: true` - Uses MLIR's generic format
- `generic: false` - Uses MLIR's specialized format
- `bytecode: true` - Uses MLIR's bytecode format

The default format may vary between MLIR versions, so explicitly specify the format
when consistent output is required.

## Inspecting MLIR Entities
Beaver doesn't implement `Inspect` protocol for MLIR entities because the output might be too verbose and can crash the BEAM if invalid entities are passed. Use `Beaver.MLIR.to_string/2` to convert entities to inspect it.

## Null Safety

Many MLIR operations can return null values. Use `null?/1` to safely check entities
before performing operations that require non-null values.

## Name spaces to include different kinds of CAPI delegates
- `Beaver.MLIR.***`: APIs related to lifecycle, including creating and destroying MLIR entities.
- `Beaver.MLIR`: APIs like `Beaver.MLIR.dump!/1` or `Beaver.MLIR.null?/1`. These are standard features generally expected in any MLIR tools.

# `apply_error`

```elixir
@type apply_error() :: String.t()
```

# `apply_option`

```elixir
@type apply_option() ::
  {:debug, boolean()}
  | {:ctx, Beaver.Deferred.context_arg()}
  | Beaver.MLIR.Rewrite.config_option()
```

# `apply_opts`

```elixir
@type apply_opts() :: [apply_option()] | Beaver.MLIR.Rewrite.config_callback() | nil
```

# `apply_outcome`

```elixir
@type apply_outcome(t) :: {:ok, t} | {:error, apply_error()}
```

# `diagnostic`

```elixir
@type diagnostic() :: Beaver.MLIR.Rewrite.diagnostic()
```

# `diagnostics`

```elixir
@type diagnostics() :: Beaver.MLIR.Rewrite.diagnostics()
```

# `dump_opts`

```elixir
@type dump_opts() :: [{:generic, boolean()}]
```

# `null_safe_result`

```elixir
@type null_safe_result(t) :: t | {:error, String.t()}
```

# `nullable`

```elixir
@type nullable() ::
  Beaver.MLIR.Attribute.t()
  | Beaver.MLIR.Value.t()
  | Beaver.MLIR.Type.t()
  | Beaver.MLIR.Operation.t()
  | Beaver.MLIR.Module.t()
  | Beaver.MLIR.Block.t()
  | Beaver.MLIR.Dialect.t()
  | Beaver.MLIR.ExecutionEngine.t()
```

# `print_opts`

```elixir
@type print_opts() :: [
  generic: boolean(),
  bytecode: boolean(),
  bytecode_version: integer(),
  ctx: Beaver.Deferred.context_arg()
]
```

# `printable`

```elixir
@type printable() ::
  Beaver.MLIR.Attribute.t()
  | Beaver.MLIR.Value.t()
  | Beaver.MLIR.Type.t()
  | Beaver.MLIR.Operation.t()
  | Beaver.MLIR.AffineMap.t()
  | Beaver.MLIR.Location.t()
  | Beaver.MLIR.OpPassManager.t()
  | Beaver.MLIR.PassManager.t()
  | Beaver.MLIR.Module.t()
  | Beaver.MLIR.Identifier.t()
```

# `rewrite_pattern_input`

```elixir
@type rewrite_pattern_input() ::
  Beaver.MLIR.Rewrite.pattern_list()
  | Beaver.MLIR.FrozenRewritePatternSet.t()
  | Beaver.MLIR.RewritePatternSet.t()
```

# `verifiable`

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

# `verify_result`

```elixir
@type verify_result(t) :: {:ok, t} | :null | {:error, diagnostics()}
```

# `verify_summary`

```elixir
@type verify_summary() :: boolean()
```

# `apply!`

```elixir
@spec apply!(verifiable(), rewrite_pattern_input(), apply_opts()) :: verifiable()
```

Apply patterns on a container (region, operation, module).
It returns the container if it succeeds otherwise it raises.

# `apply_`

```elixir
@spec apply_(verifiable(), rewrite_pattern_input(), apply_opts()) ::
  apply_outcome(verifiable())
```

Apply patterns on a container (operation, module).
It is named `apply_` with a underscore to avoid name collision with `Kernel.apply/2`

# `context`

Get the MLIR context of an MLIR entity.

# `dump`

```elixir
@spec dump(printable(), dump_opts()) :: null_safe_result(:ok)
```

Dump MLIR element to stdio.

This will call the printer registered in C/C++. Note that the outputs wouldn't go through Erlang's IO system, so it's not possible to capture the output in Elixir. If you need to capture the output, use `to_string/1` instead.

# `dump!`

```elixir
@spec dump!(printable(), dump_opts()) :: printable()
```

Dump MLIR element to stdio and raise an error if it fails.

# `equal?`

Compare two MLIR entities.

# `location`

Get the MLIR location of an MLIR entity.

# `null?`

```elixir
@spec null?(nullable()) :: boolean()
```

Check if an MLIR entity is null.

To prevent crashing the BEAM, it is encouraged to use this function to check if an entity is null before calling functions that require a non-null entity.

# `to_string`

```elixir
@spec to_string(printable() | Beaver.Deferred.contextual(printable()), print_opts()) ::
  null_safe_result(String.t())
```

Print MLIR element or StringRef as Elixir binary string.

When printing an operation, it is recommended to use `generic: false` or `generic: true` to explicitly specify the format if your usage requires consistent output. If not specified, the default behavior is subject to change according to the MLIR version.

# `verify`

```elixir
@spec verify(verifiable()) :: verify_result(verifiable())
```

# `verify!`

```elixir
@spec verify!(verifiable()) :: verifiable()
```

# `verify?`

```elixir
@spec verify?(verifiable()) :: verify_summary()
```

