Skip to main content
run is the primary entry point for executing Lion programs. It accepts any JSON-compatible value as the expression and a plain object as the evaluation environment, then takes care of schema decoding, evaluation dispatch, and Effect context provisioning so callers do not need to interact with the internals directly.

Signature

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

export const run = (
  expression: unknown,
  environment: Record<string, unknown>
) => Effect.Effect<unknown, ParseError | ArgumentMismatchError | InvalidFunctionCallError, never>

Parameters

expression
unknown
required
The Lion expression to evaluate. Accepts any JSON-compatible value — a JSON primitive (string, number, boolean, null), an array of Lion expressions, or a record with string keys and Lion expression values. The value is decoded against LionExpressionSchema before evaluation begins.
environment
Record<string, unknown>
required
Name bindings available during evaluation. Keys are identifier strings; values can be primitives, objects, or JavaScript functions. Pass the stdlib export from @lionlang/core/modules to make the standard library available, then spread in any additional host bindings.

Return value

Effect
Effect.Effect<unknown, ParseError | ArgumentMismatchError | InvalidFunctionCallError, never>
An Effect that, when run, yields the evaluated result or fails with one of three typed errors:

Pipeline

Internally, run composes three steps:
  1. Schema decodingSchema.decodeUnknown(LionExpressionSchema) validates and narrows expression to LionExpressionType.
  2. Evaluation — the decoded expression is passed to evaluate, which dispatches to the appropriate handler.
  3. Environment provisionLionEnvironmentService is provided via Effect.provideServiceEffect, wrapping environment in a mutable Ref-backed store so define can update bindings at runtime.

Example

import { Effect } from "effect";
import { run } from "@lionlang/core/evaluation/evaluate";
import { stdlib } from "@lionlang/core/modules";

// Simple arithmetic
const result = await Effect.runPromise(
  run(["number/add", 1, 2], stdlib)
);
// => 3

// Custom environment bindings
const env = {
  ...stdlib,
  price: 100,
  taxRate: 0.08,
};

const total = await Effect.runPromise(
  run(
    ["number/add", "price", ["number/multiply", "price", "taxRate"]],
    env
  )
);
// => 108
run provisions LionEnvironmentService internally, so the returned Effect has no remaining requirements (never). You can pass it directly to Effect.runPromise, Effect.runSync, or any other Effect runner without additional setup.