# `Expression.Callbacks`

Use this module to implement one's own callbacks.
The standard callbacks available are implemented in `Expression.Callbacks.Standard`.

## Using `defexpr`

`defexpr` auto-evaluates arguments from their AST form before the body executes:

```elixir
defmodule MyCallbacks do
  use Expression.Callbacks

  defexpr dice_roll() do
    Enum.random(1..6)
  end

  defexpr greet(name), ctx do
    prefix = ctx.private[:prefix] || "Hello"
    "#{prefix}, #{name}!"
  end
end
```

## Using plain `def`

Traditional `def` callbacks still work — `defexpr` is optional sugar.
With plain `def`, you must manually call `eval!` on each argument:

```elixir
defmodule MyCallbacks do
  use Expression.Callbacks

  def dice_roll(_ctx) do
    Enum.random(1..6)
  end
end
```

## Options

  * `stdlib: false` — don't fall back to `Expression.Callbacks.Standard`
  * `also: [ModuleA, ModuleB]` — compose multiple callback modules;
    dispatch checks each in order before falling back to Standard

# `atom_function_name`

Convert a string function name into an atom meant to handle
that function

Reserved words such as `and`, `if`, and `or` are automatically suffixed
with an `_` underscore.

# `defexpr`
*macro* 

# `defexpr`
*macro* 

Macro for defining expression callback functions with automatic
argument evaluation.

## Without context (pure functions)

    defexpr upper(text) do
      String.upcase(to_string(text))
    end

Generates a standard callback where `text` is automatically
evaluated from its AST form before the body executes.

## With context access

    defexpr generate_ott(data), ctx do
      with %{number: number} <- ctx.private, ...
    end

The second argument names the context variable, giving access to
`ctx.vars`, `ctx.private`, and the full `Expression.Context` struct
(or plain map for legacy callers).

## Variadic functions

    @variadic true
    defexpr switch(args), ctx do
      # args is a list of all pre-evaluated arguments
    end

## Reserved words

Expression function names that are Elixir reserved words (`and`, `if`,
`or`, `not`) are automatically suffixed with `_` in the generated
function name.

# `handle`

```elixir
@spec handle(
  module :: module(),
  function_name :: binary(),
  arguments :: [any()],
  context :: map()
) ::
  {:ok, any()} | {:error, :not_implemented}
```

Handle a function call while evaluating the AST.

Handlers in this module are either:

1. The function name as is
2. The function name with an underscore suffix if the function name is a reserved word
3. The function name suffixed with `_vargs` if the takes a variable set of arguments

# `implements`

---

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