# `Predicator.Errors`
[🔗](https://github.com/riddler/predicator-ex/blob/v9.4.1/lib/predicator/errors.ex#L1)

Common utilities for error formatting across all Predicator error modules.

This module provides shared functions for formatting error messages,
type names, and operation names consistently across all error types.

# `expected_type_name`

```elixir
@spec expected_type_name(atom()) :: String.t()
```

Formats an expected type name for error messages with proper articles.

## Examples

    iex> Predicator.Errors.expected_type_name(:integer)
    "an integer"

    iex> Predicator.Errors.expected_type_name(:boolean)
    "a boolean"

    iex> Predicator.Errors.expected_type_name(:custom_type)
    "a custom_type"

# `operation_display_name`

```elixir
@spec operation_display_name(atom()) :: String.t()
```

Formats an operation name for user-friendly error messages.

## Examples

    iex> Predicator.Errors.operation_display_name(:add)
    "Arithmetic add"

    iex> Predicator.Errors.operation_display_name(:logical_and)
    "Logical AND"

    iex> Predicator.Errors.operation_display_name(:unary_bang)
    "Logical NOT"

    iex> Predicator.Errors.operation_display_name(:pop_jump_if_falsy)
    "Condition"

# `put_position`

```elixir
@spec put_position(
  term(),
  Predicator.Types.position() | Predicator.Types.span() | nil
) :: term()
```

Attaches a source position or span to an error struct.

Given a `t:Predicator.Types.position/0`, sets `:position`. Given a
`t:Predicator.Types.span/0`, sets `:span` to the span and `:position` to its
start, so a caller reading only `:position` keeps getting a usable caret when
the program was compiled with spans.

Returns the error unchanged when the location is `nil` or when the value has no
`:position` field, so it is safe to call on any error value - including the
bare-string errors some evaluator paths return internally.

## Examples

    iex> error = Predicator.Errors.EvaluationError.new("boom", "boom")
    iex> Predicator.Errors.put_position(error, {1, 3}).position
    {1, 3}

    iex> error = Predicator.Errors.EvaluationError.new("boom", "boom")
    iex> decorated = Predicator.Errors.put_position(error, {{1, 1}, {1, 9}})
    iex> {decorated.position, decorated.span}
    {{1, 1}, {{1, 1}, {1, 9}}}

    iex> error = Predicator.Errors.ParseError.new("boom", 1, 1)
    iex> decorated = Predicator.Errors.put_position(error, {{1, 1}, {1, 6}})
    iex> {decorated.position, decorated.span}
    {{1, 1}, {{1, 1}, {1, 6}}}

    iex> error = Predicator.Errors.ParseError.new("boom", 1, 1)
    iex> decorated = Predicator.Errors.put_position(error, {1, 3})
    iex> {decorated.position, decorated.span}
    {{1, 3}, nil}

    iex> error = Predicator.Errors.EvaluationError.new("boom", "boom")
    iex> Predicator.Errors.put_position(error, nil).position
    nil

    iex> Predicator.Errors.put_position("boom", {1, 3})
    "boom"

# `type_name_with_value`

```elixir
@spec type_name_with_value(atom(), any()) :: String.t()
```

Formats a type name with its value for error messages.

## Examples

    iex> Predicator.Errors.type_name_with_value(:string, "hello")
    "\"hello\" (string)"

    iex> Predicator.Errors.type_name_with_value(:integer, 42)
    "42 (integer)"

    iex> Predicator.Errors.type_name_with_value(:undefined, :undefined)
    ":undefined (undefined)"

---

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