> ## Documentation Index
> Fetch the complete documentation index at: https://docs.lionlang.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# evaluate() — the core Lion dispatcher

> Low-level dispatcher that routes a decoded LionExpressionType to the correct handler. Requires LionEnvironmentService; prefer run() for most use cases.

`evaluate` is the central dispatch function inside the Lion evaluator. It receives an already-validated `LionExpressionType` and routes it to one of three sub-evaluators based on the expression's runtime shape. Most callers should use `run` instead — `evaluate` is useful when you are composing evaluation steps manually or writing a custom special form handler.

## Signature

```typescript theme={null}
import { evaluate } from "@lionlang/core/evaluation/evaluate";

export const evaluate = (expression: LionExpressionType): EvaluateResult
```

## Parameters

<ParamField path="expression" type="LionExpressionType" required>
  A value that has already been decoded against `LionExpressionSchema`. Passing
  a raw `unknown` value directly will cause a compile-time error — use `run`
  or `Schema.decodeUnknown(LionExpressionSchema)` first.
</ParamField>

## Return value

<ResponseField name="EvaluateResult" type="Effect.Effect<unknown, ParseError | ArgumentMismatchError | InvalidFunctionCallError, LionEnvironmentService>">
  An Effect that requires `LionEnvironmentService` in its context. Unlike the
  Effect returned by `run`, this Effect is **not** self-contained — it must be
  provided with an environment before it can be executed.
</ResponseField>

## Dispatch logic

`evaluate` uses `effect/Match` to select a handler based on the expression shape:

| Condition                            | Handler             |
| ------------------------------------ | ------------------- |
| Matches `LionArrayExpressionSchema`  | `evaluateArray`     |
| Matches `LionRecordExpressionSchema` | `evaluateRecord`    |
| Matches `JsonPrimitiveSchema`        | `evaluatePrimitive` |

The match is exhaustive — every valid `LionExpressionType` is covered by exactly one branch.

### `evaluatePrimitive`

Numbers, booleans, and `null` evaluate to themselves. Strings are looked up in `LionEnvironmentService`; if no binding exists the original string is returned unchanged.

### `evaluateRecord`

Each value in the record is evaluated independently via `evaluate`, and the results are collected with `Effect.all`. Keys are preserved as-is.

### `evaluateArray` dispatch order

Array expressions are matched in priority order:

1. **Empty array** — returned as-is via `Effect.succeed`.
2. **`eval`** — evaluates its argument, then evaluates the result.
3. **`quote`** — returns its argument without evaluating it.
4. **`begin`** — evaluates expressions in sequence, returning the last result.
5. **`define`** — evaluates a value and stores it in the global environment.
6. **`lambda`** — captures the current scope and returns a callable function value.
7. **`cond`** — evaluates predicate/result pairs and returns the first match.
8. **`match`** — pattern-matches a value against predicate/handler pairs.
9. **Function call** — evaluates the head expression and calls it as a function with the remaining elements as arguments.
10. **No match** — fails with `InvalidFunctionCallError`.

<Note>
  `evaluate` requires `LionEnvironmentService` to be present in the Effect
  context. If you are calling it directly, you must provide this service —
  either via `Effect.provideServiceEffect(LionEnvironmentService, makeEnvironment(env))`
  or by using `run`, which handles this automatically.
</Note>

## Example

```typescript theme={null}
import { Effect, pipe, Schema } from "effect";
import { evaluate } from "@lionlang/core/evaluation/evaluate";
import { makeEnvironment } from "@lionlang/core/evaluation/environment";
import { LionExpressionSchema } from "@lionlang/core/schemas/lion-expression";
import { LionEnvironmentService } from "@lionlang/core/services/evaluation";
import { stdlib } from "@lionlang/core/modules";

const expression = Schema.decodeUnknownSync(LionExpressionSchema)(
  ["number/add", 1, 2]
);

const result = await pipe(
  evaluate(expression),
  Effect.provideServiceEffect(LionEnvironmentService, makeEnvironment(stdlib)),
  Effect.runPromise
);
// => 3
```
