Skip to main content
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

import { evaluate } from "@lionlang/core/evaluation/evaluate";

export const evaluate = (expression: LionExpressionType): EvaluateResult

Parameters

expression
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.

Return value

EvaluateResult
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.

Dispatch logic

evaluate uses effect/Match to select a handler based on the expression shape:
ConditionHandler
Matches LionArrayExpressionSchemaevaluateArray
Matches LionRecordExpressionSchemaevaluateRecord
Matches JsonPrimitiveSchemaevaluatePrimitive
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.
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.

Example

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