bonsai-js 1.0.0 → 1.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (60) hide show
  1. package/CHANGELOG.md +20 -0
  2. package/README.md +24 -4
  3. package/dist/artifact.d.mts +47 -0
  4. package/dist/artifact.mjs +139 -0
  5. package/dist/artifact.mjs.map +1 -0
  6. package/dist/builtins/index.d.mts +91 -0
  7. package/dist/builtins/index.mjs +93 -0
  8. package/dist/builtins/index.mjs.map +1 -0
  9. package/dist/check/bind.mjs +117 -0
  10. package/dist/check/bind.mjs.map +1 -0
  11. package/dist/check/checker.mjs +34 -120
  12. package/dist/check/checker.mjs.map +1 -1
  13. package/dist/compile/compiler.mjs +2 -3
  14. package/dist/compile/compiler.mjs.map +1 -1
  15. package/dist/declared.mjs +8 -1
  16. package/dist/declared.mjs.map +1 -1
  17. package/dist/digest.mjs +109 -0
  18. package/dist/digest.mjs.map +1 -0
  19. package/dist/environment.d.mts +14 -1
  20. package/dist/environment.mjs +65 -315
  21. package/dist/environment.mjs.map +1 -1
  22. package/dist/errors.d.mts +21 -2
  23. package/dist/errors.mjs +17 -1
  24. package/dist/errors.mjs.map +1 -1
  25. package/dist/features.mjs +3 -3
  26. package/dist/features.mjs.map +1 -1
  27. package/dist/functions/builtins.mjs +551 -474
  28. package/dist/functions/builtins.mjs.map +1 -1
  29. package/dist/functions/define.mjs +53 -11
  30. package/dist/functions/define.mjs.map +1 -1
  31. package/dist/functions/descriptions.mjs +110 -0
  32. package/dist/functions/descriptions.mjs.map +1 -0
  33. package/dist/index.d.mts +4 -3
  34. package/dist/index.mjs +3 -2
  35. package/dist/lite/index.d.mts +4 -3
  36. package/dist/lite/index.mjs +3 -2
  37. package/dist/lite/index.mjs.map +1 -1
  38. package/dist/load.mjs +307 -0
  39. package/dist/load.mjs.map +1 -0
  40. package/dist/program.mjs +321 -0
  41. package/dist/program.mjs.map +1 -0
  42. package/dist/query/index.mjs +1 -1
  43. package/dist/runtime/core.d.mts +18 -0
  44. package/dist/runtime/core.mjs +31 -0
  45. package/dist/runtime/core.mjs.map +1 -0
  46. package/dist/runtime/create.d.mts +61 -0
  47. package/dist/runtime/create.mjs +76 -0
  48. package/dist/runtime/create.mjs.map +1 -0
  49. package/dist/runtime/index.d.mts +24 -0
  50. package/dist/runtime/index.mjs +34 -0
  51. package/dist/runtime/index.mjs.map +1 -0
  52. package/dist/service/index.mjs +12 -8
  53. package/dist/service/index.mjs.map +1 -1
  54. package/dist/syntax/parser.mjs +1 -1
  55. package/dist/syntax/printer.mjs +1 -1
  56. package/dist/types.mjs +103 -23
  57. package/dist/types.mjs.map +1 -1
  58. package/dist/version.mjs +7 -0
  59. package/dist/version.mjs.map +1 -0
  60. package/package.json +26 -2
@@ -1 +1 @@
1
- {"version":3,"file":"environment.mjs","names":[],"sources":["../src/environment.ts"],"sourcesContent":["import { analyze, type Analysis, type CheckEnv } from './check/checker.js'\nimport {\n compileProgram,\n type CompiledProgram,\n type CompileOptions as CompilerOptions,\n} from './compile/compiler.js'\nimport { escaping, isOwn, raised } from './runtime/attribution.js'\nimport {\n BonsaiCheckError,\n BonsaiError,\n BonsaiLimitError,\n BonsaiRuntimeError,\n locate,\n type Diagnostic,\n} from './errors.js'\nimport { BUILTINS, zoneParameter } from './functions/builtins.js'\nimport {\n assertHostSpec,\n assertType,\n conforms,\n describeMismatch,\n isRecord,\n overload,\n type FunctionDef,\n type Out,\n type ValidationBudget,\n} from './functions/define.js'\nimport type { PartialData, PartialOptions, PartialResult } from './partial.js'\nimport { isStackOverflow, tooDeep } from './runtime/overflow.js'\nimport { warmZone } from './runtime/time.js'\nimport {\n DEFAULT_RUNTIME_LIMITS,\n MAX_VALUE_DEPTH_LIMIT,\n State,\n type RuntimeLimits,\n} from './runtime/state.js'\nimport { recordDeclared } from './declared.js'\nimport { errorText, isMap } from './runtime/values.js'\nimport type { ExplanationJSON, Trace } from './runtime/trace.js'\nimport type { Node } from './syntax/ast.js'\nimport { isName } from './syntax/lexer.js'\nimport { DEFAULT_PARSE_LIMITS, MAX_DEPTH_LIMIT, parse, type ParseLimits } from './syntax/parser.js'\nimport {\n formatType,\n isNullable,\n type AnyType,\n type Infer,\n type InferVariables,\n type Type,\n} from './types.js'\n\n// === public option types ===\n\n/** Every field optional, and `undefined` accepted, even under `exactOptionalPropertyTypes`. */\ntype Optional<T> = { readonly [K in keyof T]?: T[K] | undefined }\n\nexport interface Limits extends Optional<ParseLimits>, Optional<RuntimeLimits> {\n /** Wall-clock budget per evaluation in milliseconds (0 = none; fractions allowed). Default 0. */\n readonly timeout?: number | undefined\n}\n\n/**\n * The part of an `AbortSignal` evaluation reads. A standard `AbortSignal`\n * satisfies it; declaring it structurally keeps the types free of DOM or Node\n * library requirements.\n */\nexport interface AbortSignalLike {\n readonly aborted: boolean\n readonly reason?: unknown\n addEventListener: (type: 'abort', listener: () => void, options?: { once?: boolean }) => void\n removeEventListener: (type: 'abort', listener: () => void) => void\n}\n\nexport interface EvaluateOptions {\n /** Wall-clock budget for this evaluation in milliseconds (0 = none; fractions allowed). */\n readonly timeout?: number | undefined\n /** Step budget for this evaluation (0 = none; overrides the environment limit). */\n readonly maxSteps?: number | undefined\n /** Cancels the evaluation. */\n readonly signal?: AbortSignalLike | undefined\n /** The time now() returns in this evaluation, instead of the environment's clock. */\n readonly now?: Date | undefined\n /**\n * Validates the context for this evaluation (true) or not (false), instead\n * of the environment's `validateContext`; for a context already validated upstream.\n */\n readonly validateContext?: boolean | undefined\n}\n\ntype InferParams<P extends readonly Type[]> = Extract<\n { -readonly [K in keyof P]: Infer<P[K]> },\n unknown[]\n>\n\n/** The arguments `run` receives: the declared parameters, then any rest arguments. */\ntype RunArgs<P extends readonly Type[], RT> = RT extends Type\n ? [...InferParams<P>, ...Infer<RT>[]]\n : InferParams<P>\n\n/** What `run` may return: a nullable result also accepts `undefined`, which reads as null. */\ntype RunResult<R extends Type> = null extends Infer<R> ? Infer<R> | undefined : Infer<R>\n\n/**\n * The standard `AbortSignal` when the consumer's types declare one (DOM or\n * Node), so it can be passed to `fetch`; otherwise {@link AbortSignalLike}.\n */\ntype HostAbortSignal = typeof globalThis extends { AbortSignal: { prototype: infer S } }\n ? S\n : AbortSignalLike\n\n/** What a host function declared with `call: true` receives before its arguments. */\nexport interface HostCall<Ctx = Readonly<Record<string, unknown>>> {\n /** The evaluation context, read-only. */\n readonly context: Readonly<Ctx>\n /**\n * Aborted when the evaluation times out or is cancelled while it waits on\n * this call, so an async function can stop its own work (pass it to `fetch`).\n */\n readonly signal: HostAbortSignal\n}\n\n/** A host function declaration. Create one with {@link fn}. */\nexport interface HostFunction {\n readonly params: readonly Type[]\n readonly returns: Type\n readonly required?: number | undefined\n readonly rest?: Type | undefined\n readonly async?: boolean | undefined\n /** Whether `run` receives a {@link HostCall} before its arguments. */\n readonly call?: boolean | undefined\n readonly description?: string | undefined\n /** Steps charged per call (default 32). */\n readonly cost?: number | undefined\n readonly run: (...args: never[]) => unknown\n}\n\n/** The declaration passed to {@link fn}, without `run`, `async`, and `call`. */\nexport interface FnSpec<\n P extends readonly Type[] = readonly Type[],\n R extends Type = Type,\n RT extends Type | undefined = Type | undefined,\n> {\n /** Parameter types, in order. */\n readonly params: P\n /** Declared result type; results are checked against its kind. */\n readonly returns: R\n /** Number of required leading parameters (default: all). Missing optional arguments arrive as null. */\n readonly required?: number | undefined\n /** Type of further variadic arguments. */\n readonly rest?: RT\n readonly description?: string | undefined\n /**\n * Steps charged per call (default 32), so one evaluation makes at most\n * maxSteps / cost calls. Lower it for cheap pure functions; raise it for\n * expensive ones.\n */\n readonly cost?: number | undefined\n}\n\n/**\n * Declares a host function.\n *\n * ```ts\n * fn({ params: [t.string()], returns: t.boolean(), run: (perm) => user.can(perm) })\n * fn({ params: [t.string()], returns: t.string(), async: true, run: async (id) => lookup(id) })\n * fn({ params: [t.string()], returns: t.number(), async: true, call: true,\n * run: async (call, id) => (await fetch(`/stock/${id}`, { signal: call.signal })).json() })\n * ```\n */\nexport function fn<\n const P extends readonly Type[],\n R extends Type,\n RT extends Type | undefined = undefined,\n>(\n spec: FnSpec<P, R, RT> &\n (\n | {\n readonly async?: false | undefined\n readonly call?: false | undefined\n readonly run: (...args: RunArgs<P, RT>) => RunResult<R>\n }\n | {\n readonly async: true\n readonly call?: false | undefined\n readonly run: (...args: RunArgs<P, RT>) => Promise<RunResult<R>>\n }\n | {\n readonly async?: false | undefined\n readonly call: true\n readonly run: (call: HostCall, ...args: RunArgs<P, RT>) => RunResult<R>\n }\n | {\n readonly async: true\n readonly call: true\n readonly run: (call: HostCall, ...args: RunArgs<P, RT>) => Promise<RunResult<R>>\n }\n ),\n): HostFunction {\n assertHostSpec(spec, 'fn()')\n return Object.freeze({ ...spec })\n}\n\n/**\n * Declares host functions that read a typed evaluation context: like `fn`\n * with `call: true`, with `call.context` typed as `Readonly<Ctx>`.\n *\n * ```ts\n * const contextFn = withContext<{ user: { id: string } }>()\n * const functions = { userId: contextFn({ params: [], returns: t.string(), run: (call) => call.context.user.id }) }\n * ```\n */\nexport function withContext<Ctx>() {\n return <const P extends readonly Type[], R extends Type, RT extends Type | undefined = undefined>(\n spec: FnSpec<P, R, RT> &\n (\n | {\n readonly async?: false | undefined\n /** Implied; may be written out when moving a function over from `fn`. */\n readonly call?: true | undefined\n readonly run: (call: HostCall<Ctx>, ...args: RunArgs<P, RT>) => RunResult<R>\n }\n | {\n readonly async: true\n readonly call?: true | undefined\n readonly run: (call: HostCall<Ctx>, ...args: RunArgs<P, RT>) => Promise<RunResult<R>>\n }\n ),\n ): HostFunction => {\n assertHostSpec(spec, 'withContext()')\n return Object.freeze({ ...spec, call: true })\n }\n}\n\n/**\n * A reusable bundle of host functions (and optionally variables). Declare one\n * with `satisfies Library` (not `: Library`) so its variables keep their types\n * and become part of the context type of every environment that uses it.\n */\nexport interface Library<\n V extends Readonly<Record<string, Type>> = Readonly<Record<string, Type>>,\n> {\n readonly name: string\n readonly functions?: Readonly<Record<string, HostFunction>> | undefined\n readonly variables?: V | undefined\n}\n\n/** No declared variables: the empty record, which adds nothing to a context type. */\n// oxlint-disable-next-line typescript/no-generated-empty-object-type -- intentionally empty\nexport type NoVariables = Record<never, never>\n\n/**\n * The variables one library declares. A library annotated `: Library` has the\n * wide default (any string key), which names no variable, so it adds nothing.\n */\ntype VariablesOf<Lib> = Lib extends { readonly variables?: infer V }\n ? string extends keyof NonNullable<V>\n ? NoVariables\n : NonNullable<V>\n : NoVariables\n\n/**\n * The variables a list of libraries declares, merged. Only a list whose\n * elements are known (written inline, or `as const`) contributes; a value\n * typed as `Library[]` adds nothing to the context type.\n */\ntype LibraryVariables<L> = L extends readonly [infer First, ...infer Rest]\n ? VariablesOf<First> & LibraryVariables<Rest>\n : NoVariables\n\n/**\n * Any further keys, as a context with `strict: false` may carry. Its values are\n * `any` because only that lets an interface or a class instance (which have no\n * index signature) still satisfy it; declared keys keep their own types.\n */\n// oxlint-disable-next-line typescript/no-explicit-any -- the only index signature interfaces and classes satisfy\ntype MoreKeys = Readonly<Record<string, any>>\n\n/**\n * The context type of an environment with variables `V` and libraries `L`.\n * With `strict: false` (`S`), undeclared variables are allowed, so the context\n * may carry keys beyond the declared ones.\n */\nexport type ContextFor<V, L, S = undefined> = [S] extends [false]\n ? ContextOf<V & LibraryVariables<L>> & MoreKeys\n : ContextOf<V & LibraryVariables<L>>\n\n/**\n * `Ctx` with the variables `New` declares replacing those of the same name,\n * as extend() replaces them at run time (\"later wins\"). Remapping keys (not\n * Omit) keeps an index signature and the other keys' types.\n */\ntype Override<Ctx, New> = [keyof New] extends [never]\n ? Ctx\n : { [K in keyof Ctx as K extends keyof New ? never : K]: Ctx[K] } & New\n\n/** The context type extend() produces: re-declared variables replaced, strict: false loosened. */\nexport type Extended<Ctx, V, L, S> = [S] extends [false]\n ? Override<Ctx, ContextOf<V & LibraryVariables<L>>> & MoreKeys\n : Override<Ctx, ContextOf<V & LibraryVariables<L>>>\n\nexport interface EnvironmentOptions<\n V extends Readonly<Record<string, Type>> = Readonly<Record<string, Type>>,\n L extends readonly Library[] = readonly Library[],\n> {\n /** Declared context variables and their types. */\n readonly variables?: V | undefined\n /**\n * Report unknown variables as errors. Default: true when `variables` is\n * declared (even as `{}`), false for an open environment.\n */\n readonly strict?: boolean | undefined\n /** Host functions by name. A host function replaces a built-in of the same name. */\n readonly functions?: Readonly<Record<string, HostFunction>> | undefined\n /** Libraries of host functions and variables; a name defined twice is an error. */\n readonly libraries?: L | undefined\n readonly limits?: Limits | undefined\n /**\n * Compiled programs kept for `evaluate(source)` and `evaluateSync(source)`. Default 256; 0\n * disables the cache. The cache also holds at most 256K characters of source in total, and\n * never a source longer than 16K characters.\n */\n readonly cacheSize?: number | undefined\n /** Source of now(). Default: the system clock. */\n readonly clock?: (() => Date) | undefined\n /**\n * Check the context against the declared variable types before every\n * evaluation (deep, proportional to the data) and fail with INVALID_CONTEXT\n * naming the first mismatching path. Default: false.\n */\n readonly validateContext?: boolean | undefined\n}\n\n/**\n * What check() found. Only `ok`, `type`, and `diagnostics` are data (and the\n * JSON form); `program`, `ast`, and `typeOf` are accessors computed on demand,\n * so spreading the result or `structuredClone` does not copy them.\n */\n// oxlint-disable-next-line typescript/no-explicit-any -- the same erased context as a bare Program\nexport type CheckResult<Ctx = any, R = unknown> = Checked<Program<Ctx, R>>\n\n/** What check() found, over the kind of program it compiles. */\ntype Checked<P> = (\n | {\n readonly ok: true\n readonly type: Type\n readonly diagnostics: readonly Diagnostic[]\n /**\n * The checked expression, compiled when first read: a program equal to\n * the one compile() returns, without parsing and checking again.\n */\n readonly program: P\n }\n | {\n readonly ok: false\n readonly type: Type | undefined\n readonly diagnostics: readonly Diagnostic[]\n }\n) & {\n /**\n * The checked syntax tree (implicit lambdas made explicit, as `program.ast`),\n * or undefined when the source did not parse.\n */\n readonly ast: Node | undefined\n /** The inferred type of a node of `ast`, or undefined for another tree's node. */\n readonly typeOf: (node: Node) => Type | undefined\n}\n\ntype Args<Ctx> =\n Record<string, never> extends Ctx\n ? [context?: Ctx, options?: EvaluateOptions]\n : [context: Ctx, options?: EvaluateOptions]\n\n/**\n * A checked, compiled expression. Immutable and safe to share. A bare\n * `Program` accepts any context, so a program typed for one context can be\n * stored as a `Program`.\n */\n// oxlint-disable-next-line typescript/no-explicit-any -- the erased context type every typed program is assignable to\nexport interface Program<Ctx = any, R = unknown> {\n readonly source: string\n /** The syntax tree after implicit lambdas are made explicit. */\n readonly ast: Node\n /** The statically inferred result type. */\n readonly type: Type\n /** Whether the expression calls an async host function (evaluateSync rejects it). */\n readonly async: boolean\n /** Non-fatal findings from the checker. */\n readonly warnings: readonly Diagnostic[]\n readonly references: {\n readonly variables: readonly string[]\n readonly functions: readonly string[]\n }\n evaluate: (...args: Args<Ctx>) => Promise<R>\n evaluateSync: (...args: Args<Ctx>) => R\n /**\n * Evaluates and records the value of every sub-expression, so you can show\n * why the result came out as it did. Never rejects for evaluation errors:\n * they are returned in the explanation. Slower than evaluate.\n */\n explain: (...args: ExplainArgs<Ctx>) => Promise<Explanation<R>>\n /** Like explain, synchronously; an expression that calls an async host function is an ASYNC_IN_SYNC error. */\n explainSync: (...args: ExplainArgs<Ctx>) => Explanation<R>\n /**\n * Evaluates what can be evaluated from partial data. Returns the value when\n * the known data decides it, or a simplified residual expression (source and\n * syntax tree) that needs only the unknown data. Evaluating the residual with\n * the full data gives the same result as evaluating this program.\n */\n partial: (known: PartialData<Ctx> & object, options?: PartialOptions) => PartialResult<Ctx, R>\n}\n\nexport interface ExplainOptions extends EvaluateOptions {\n /** How many lambda runs to record per call (the rest are counted). Default 20. */\n readonly maxIterations?: number | undefined\n /** Sub-expressions to record in total before stopping (the result stays exact). Default 10,000. */\n readonly maxTraceNodes?: number | undefined\n /**\n * Also evaluate the side of && and || that short-circuiting would skip, so\n * reasons() lists every failing condition rather than the first. Those\n * parts are marked `extra`; their evaluation errors are ignored and the\n * result is unchanged. They spend from the same step and time budget, so a\n * limit reached there (STEP_LIMIT, TIMEOUT, a size limit) fails the\n * explanation even when evaluation alone would stay inside it. Host\n * functions on those parts do run. Default false.\n */\n readonly exhaustive?: boolean | undefined\n}\n\ntype ExplainArgs<Ctx> =\n Record<string, never> extends Ctx\n ? [context?: Ctx, options?: ExplainOptions]\n : [context: Ctx, options?: ExplainOptions]\n\n/** The result of explain(): the outcome plus a trace of every sub-expression. */\nexport type Explanation<R = unknown> = (\n | { readonly ok: true; readonly value: R }\n | { readonly ok: false; readonly error: BonsaiError }\n) & {\n /** The root of the trace; its `value` is the result. Values are live references. */\n readonly trace: Trace\n /** True when maxTraceNodes stopped recording before evaluation finished. */\n readonly truncated: boolean\n /**\n * The conditions that decided the result, following &&, ||, and ! down to\n * the comparisons and values (or the error) behind it.\n */\n reasons: () => readonly Trace[]\n /** The trace as an indented, human-readable tree. */\n toString: () => string\n /**\n * A JSON-safe snapshot: values are bounded copies (cycles, bigints, dates,\n * and durations handled) and getters are never run. `JSON.stringify` uses it.\n */\n toJSON: () => ExplanationJSON\n}\n\nexport interface CompileOptions<E extends Type = Type> {\n /** The type the expression must produce; also types the program's result. */\n readonly expect?: E | undefined\n}\n\nexport interface FunctionInfo {\n readonly name: string\n readonly description: string\n readonly host: boolean\n readonly async: boolean\n /** Whether a host function receives a {@link HostCall} (declared `call: true`). */\n readonly call: boolean\n /** Steps charged per call, when the host function declares a `cost` (otherwise 32). */\n readonly cost?: number\n readonly signatures: readonly {\n readonly params: readonly Type[]\n readonly required: number\n readonly rest?: Type\n readonly returns: Type\n }[]\n}\n\n/** An environment. A bare `Environment` accepts any context, like a bare `Program`. */\n// oxlint-disable-next-line typescript/no-explicit-any -- the erased context type every typed environment is assignable to\nexport interface Environment<Ctx = any> {\n /** Declared variables, or undefined for an open environment. */\n readonly variables: Readonly<Record<string, Type>> | undefined\n readonly strict: boolean\n /** Parses without checking. */\n parse: (source: string) => Node\n /**\n * Parses and checks, reporting every finding instead of throwing. When `ok`,\n * `program` is the compiled expression, so an editor needs only this call.\n */\n check: <E extends Type = AnyType>(\n source: string,\n options?: CompileOptions<E>,\n ) => CheckResult<Ctx, Infer<E>>\n /**\n * Parses, checks, and compiles. Throws BonsaiSyntaxError / BonsaiCheckError /\n * BonsaiLimitError. Cached: the same source and expected type return the same program.\n */\n compile: <E extends Type = AnyType>(\n source: string,\n options?: CompileOptions<E>,\n ) => Program<Ctx, Infer<E>>\n /**\n * Compiles (cached) and partially evaluates; see Program.partial. Throws for\n * syntax, check, and limit errors, and a TypeError or RangeError for invalid options.\n * `R` is an unchecked type assertion, as for evaluate().\n */\n partial: <R = unknown>(\n source: string,\n known: PartialData<Ctx> & object,\n options?: PartialOptions,\n ) => PartialResult<Ctx, R>\n /**\n * Compiles (cached) and evaluates asynchronously. `R` is an unchecked type\n * assertion on the result, like a cast; for a checked result type, use\n * `compile(source, { expect })` and evaluate the program.\n */\n evaluate: <R = unknown>(source: string, ...args: Args<Ctx>) => Promise<R>\n /**\n * Compiles (cached) and evaluates synchronously. `R` is an unchecked type\n * assertion, as for evaluate().\n */\n evaluateSync: <R = unknown>(source: string, ...args: Args<Ctx>) => R\n /**\n * Compiles (cached) and explains; see Program.explain. Rejects for syntax and\n * check errors and parse limits, and with a TypeError or RangeError for invalid options.\n * `R` is an unchecked type assertion, as for evaluate().\n */\n explain: <R = unknown>(source: string, ...args: ExplainArgs<Ctx>) => Promise<Explanation<R>>\n /**\n * Compiles (cached) and explains synchronously. Throws for syntax and check\n * errors and parse limits, and a TypeError or RangeError for invalid options.\n * `R` is an unchecked type assertion, as for evaluate().\n */\n explainSync: <R = unknown>(source: string, ...args: ExplainArgs<Ctx>) => Explanation<R>\n /** Looks up a function (host or built-in). */\n describeFunction: (name: string) => FunctionInfo | undefined\n /** Every callable function, host functions first. */\n listFunctions: () => readonly FunctionInfo[]\n /**\n * A new environment with more variables, functions, or libraries. A\n * variable or function declared again replaces the earlier one.\n */\n extend: <\n const V2 extends Readonly<Record<string, Type>> = NoVariables,\n const L2 extends readonly Library[] = [],\n const S2 extends boolean | undefined = undefined,\n >(\n options: EnvironmentOptions<V2, L2> & { readonly strict?: S2 },\n ) => Environment<Extended<Ctx, V2, L2, S2>>\n}\n\n/**\n * A program from `bonsai-js/lite`: a {@link Program} without `explain`,\n * `explainSync`, and `partial`. Every Program is also a LiteProgram, so code\n * that only evaluates can accept either.\n */\n// oxlint-disable-next-line typescript/no-explicit-any -- the same erased context as a bare Program\nexport type LiteProgram<Ctx = any, R = unknown> = Omit<\n Program<Ctx, R>,\n 'explain' | 'explainSync' | 'partial'\n>\n\n/** What a `bonsai-js/lite` environment's check() found. */\n// oxlint-disable-next-line typescript/no-explicit-any -- the same erased context as a bare Program\nexport type LiteCheckResult<Ctx = any, R = unknown> = Checked<LiteProgram<Ctx, R>>\n\n/**\n * An environment from `bonsai-js/lite`: an {@link Environment} without\n * `explain`, `explainSync`, and `partial`, whose programs are LitePrograms.\n * Every Environment is also a LiteEnvironment.\n */\n// oxlint-disable-next-line typescript/no-explicit-any -- the same erased context as a bare Environment\nexport interface LiteEnvironment<Ctx = any> extends Omit<\n Environment<Ctx>,\n 'check' | 'compile' | 'extend' | 'explain' | 'explainSync' | 'partial'\n> {\n /** See Environment.check. */\n check: <E extends Type = AnyType>(\n source: string,\n options?: CompileOptions<E>,\n ) => LiteCheckResult<Ctx, Infer<E>>\n /** See Environment.compile. */\n compile: <E extends Type = AnyType>(\n source: string,\n options?: CompileOptions<E>,\n ) => LiteProgram<Ctx, Infer<E>>\n /** See Environment.extend. */\n extend: <\n const V2 extends Readonly<Record<string, Type>> = NoVariables,\n const L2 extends readonly Library[] = [],\n const S2 extends boolean | undefined = undefined,\n >(\n options: EnvironmentOptions<V2, L2> & { readonly strict?: S2 },\n ) => LiteEnvironment<Extended<Ctx, V2, L2, S2>>\n}\n\n/**\n * The context type of declared variables `V`. An open environment (no\n * variables) accepts any object, including values typed by an interface, and\n * so does a schema only known at run time (`Record<string, Type>`), whose\n * variables are not known statically.\n */\ntype ContextOf<V> = [keyof V] extends [never]\n ? object\n : string extends keyof V\n ? MoreKeys\n : InferVariables<V>\n\n// === implementation ===\n\n/** Internals shared with the language service (not public API). */\nexport interface EnvironmentInternals {\n readonly checkEnv: CheckEnv\n readonly parseLimits: ParseLimits\n}\n\nconst internals = new WeakMap<object, EnvironmentInternals>()\n\nexport function internalsOf(env: object): EnvironmentInternals {\n const found = internals.get(env)\n if (found === undefined) throw new TypeError('Not a Bonsai environment')\n return found\n}\n\n/** Compiled programs kept per environment unless `cacheSize` says otherwise. */\nconst DEFAULT_CACHE_SIZE = 256\n\n/** An environment's settings (not public API). */\nexport interface Settings {\n readonly variables: Readonly<Record<string, Type>> | undefined\n /** The explicit `strict` option, if one was given (here or in a base environment). */\n readonly strictOption: boolean | undefined\n readonly strict: boolean\n readonly host: ReadonlyMap<string, FunctionDef>\n readonly parseLimits: ParseLimits\n readonly runtimeLimits: RuntimeLimits\n readonly timeout: number\n readonly cacheSize: number\n readonly clock: () => Date\n readonly validateContext: boolean\n /** Explaining and partial evaluation, when the entry point provides them. */\n readonly features: Features | undefined\n}\n\n/**\n * What a program shares with the features that extend it (not public API):\n * its source, analysis, and settings, and how it prepares, checks, and settles\n * an evaluation.\n */\nexport interface ProgramCore<R> {\n readonly source: string\n readonly analysis: Analysis\n readonly expect: Type | undefined\n readonly settings: Settings\n readonly checkEnv: CheckEnv\n readonly compileOptions: CompilerOptions\n /** Set when the program is a partial-evaluation residual. */\n readonly residualOf: ResidualOf | undefined\n prepare: (\n state: State,\n ctx: Record<string, unknown>,\n limits: EvaluationLimits,\n locals: number,\n ) => void\n checked: (result: unknown, state: State) => void\n settle: (result: R) => R\n /** Compiles a residual of this program and returns how it runs. */\n residual: (\n analysis: Analysis,\n constants: ReadonlyMap<string, unknown>,\n residualOf: ResidualOf,\n ) => ResidualRunner\n}\n\n/** The program methods a feature set provides (not public API). */\nexport interface ProgramFeatures<Ctx, R> {\n explainSync: (\n context: unknown,\n options: ExplainOptions | undefined,\n promised?: boolean,\n ) => Explanation<R>\n explainAsync: (context: unknown, options: ExplainOptions | undefined) => Promise<Explanation<R>>\n partial: (program: object, known: object, options: unknown) => PartialResult<Ctx, R>\n}\n\n/**\n * Explaining and partial evaluation, supplied by the entry point (not public\n * API): kept out of this module so a bundle that only checks and evaluates\n * does not carry them.\n */\nexport interface Features {\n program: <Ctx, R>(core: ProgramCore<R>) => ProgramFeatures<Ctx, R>\n}\n\n/** What a residual keeps from its partial evaluation. */\nexport interface ResidualOf {\n /** Its printed source: the text of its explanations. */\n readonly source: string\n /** Whether `call: true` host functions read the context it is given. */\n readonly readsContext: boolean\n /** The variables known to partial(), which a context read whole must hold. */\n readonly knownRoots: readonly string[]\n /** The context paths it reads: all a context it does not read whole needs. */\n readonly dependsOn: readonly string[]\n /** Size and depth of the lists and maps partial() built into its bindings. */\n readonly shapes: WeakMap<object, number> | undefined\n}\n\n/** How a partial-evaluation residual runs and explains, with the caller's context. */\nexport interface ResidualRunner {\n /** Whether the residual calls an async host function. */\n async: boolean\n runSync: (ctx: unknown, options: unknown) => unknown\n runAsync: (ctx: unknown, options: unknown) => Promise<unknown>\n explainSync: (ctx: unknown, options: unknown) => Explanation\n explainAsync: (ctx: unknown, options: unknown) => Promise<Explanation>\n}\n\nfunction toDef(name: string, host: HostFunction): FunctionDef {\n // `has` and `try` read as syntax, so a function with either name could never be called.\n if (!isName(name) || name === 'has' || name === 'try') {\n throw new TypeError(`Invalid function name \"${name}\"`)\n }\n assertHostSpec(host, `Function \"${name}\"`)\n const run = host.run as (...args: unknown[]) => unknown\n const count = host.params.length\n host.params.forEach((param, index) => {\n if (index >= (host.required ?? count) && !isNullable(param)) {\n throw new TypeError(\n `Optional parameter ${index + 1} of \"${name}\" receives null when omitted; declare it as t.optional(...)`,\n )\n }\n })\n return Object.freeze({\n name,\n description: host.description ?? '',\n host: true,\n async: host.async === true,\n call: host.call === true,\n ...(host.cost === undefined ? {} : { cost: host.cost }),\n overloads: [\n overload(\n host.params,\n host.returns,\n (args) => {\n // Missing optional arguments arrive as null.\n const offset = host.call === true ? 1 : 0\n while (args.length < count + offset) args.push(null)\n return run(...args)\n },\n {\n required: host.required ?? count,\n ...(host.rest === undefined ? {} : { rest: host.rest }),\n },\n ),\n ],\n })\n}\n\nfunction mergeFunctions(\n base: ReadonlyMap<string, FunctionDef>,\n options: EnvironmentOptions,\n): Map<string, FunctionDef> {\n const out = new Map(base)\n const added = new Map<string, string>()\n const add = (name: string, def: HostFunction, origin: string): void => {\n const previous = added.get(name)\n if (previous !== undefined) {\n throw new TypeError(`Function \"${name}\" is defined by both ${previous} and ${origin}`)\n }\n added.set(name, origin)\n out.set(name, toDef(name, def))\n }\n for (const library of options.libraries ?? []) {\n for (const [name, def] of Object.entries(library.functions ?? {}))\n add(name, def, `library \"${library.name}\"`)\n }\n for (const [name, def] of Object.entries(options.functions ?? {}))\n add(name, def, 'the functions option')\n return out\n}\n\nfunction mergeVariables(\n base: Readonly<Record<string, Type>> | undefined,\n options: EnvironmentOptions,\n): Readonly<Record<string, Type>> | undefined {\n // Declaring `variables` (even as {}) makes the environment declared, and so strict by default.\n let out: Record<string, Type> | undefined =\n base === undefined && options.variables === undefined ? undefined : { ...base }\n const added = new Map<string, string>()\n const add = (name: string, type: Type, origin: string): void => {\n if (!isName(name)) {\n throw new TypeError(`Invalid variable name \"${name}\" (in ${origin})`)\n }\n const previous = added.get(name)\n if (previous !== undefined) {\n throw new TypeError(`Variable \"${name}\" is declared by both ${previous} and ${origin}`)\n }\n added.set(name, origin)\n assertType(type, `Variable \"${name}\"`)\n out ??= {}\n out[name] = type\n }\n for (const library of options.libraries ?? []) {\n for (const [k, v] of Object.entries(library.variables ?? {}))\n add(k, v, `library \"${library.name}\"`)\n }\n for (const [k, v] of Object.entries(options.variables ?? {})) add(k, v, 'the variables option')\n return out === undefined ? undefined : Object.freeze(out)\n}\n\n/** A number option: TypeError when it is not a number, RangeError when out of range. */\nfunction numberOption(name: string, value: unknown, fallback: number, minimum: number): number {\n if (value === undefined) return fallback\n if (typeof value !== 'number') throw new TypeError(`${name} must be a number`)\n if (!Number.isInteger(value) || value < minimum) {\n throw new RangeError(\n minimum === 0\n ? `${name} must be a non-negative integer (0 disables it)`\n : `${name} must be a positive integer`,\n )\n }\n return value\n}\n\n/**\n * A timeout in milliseconds: 0 turns it off; any other non-negative number,\n * fractions included, is a limit, so a budget computed down to its last\n * fraction of a millisecond stays a limit rather than becoming 0.\n */\nfunction timeoutOption(name: string, value: unknown, fallback: number): number {\n if (value === undefined) return fallback\n if (typeof value !== 'number') throw new TypeError(`${name} must be a number`)\n if (!Number.isFinite(value) || value < 0) {\n throw new RangeError(`${name} must be a non-negative number of milliseconds (0 disables it)`)\n }\n return value\n}\n\nconst OPTION_KEYS = new Set([\n 'variables',\n 'strict',\n 'functions',\n 'libraries',\n 'limits',\n 'cacheSize',\n 'clock',\n 'validateContext',\n])\nconst LIMIT_KEYS: ReadonlySet<string> = new Set([\n ...Object.keys(DEFAULT_PARSE_LIMITS),\n ...Object.keys(DEFAULT_RUNTIME_LIMITS),\n 'timeout',\n])\nconst LIBRARY_KEYS = new Set(['name', 'functions', 'variables'])\n\nfunction assertKeys(value: unknown, allowed: ReadonlySet<string>, what: string): void {\n if (!isRecord(value)) throw new TypeError(`${what} must be an object`)\n for (const key of Object.keys(value)) {\n if (!allowed.has(key)) {\n throw new TypeError(\n `Unknown ${what.toLowerCase()} key \"${key}\" (expected one of: ${[...allowed].join(', ')})`,\n )\n }\n }\n}\n\n/** Environment options come from configuration: mistakes there are programming errors. */\nfunction assertOptions(options: unknown): asserts options is EnvironmentOptions {\n assertKeys(options, OPTION_KEYS, 'Options')\n const o = options as Record<string, unknown>\n if (o.limits !== undefined) assertKeys(o.limits, LIMIT_KEYS, 'Limits')\n if (o.variables !== undefined && !isRecord(o.variables))\n throw new TypeError('variables must be an object of types')\n if (o.functions !== undefined && !isRecord(o.functions))\n throw new TypeError('functions must be an object of fn() declarations')\n if (o.libraries !== undefined) {\n if (!Array.isArray(o.libraries)) throw new TypeError('libraries must be an array')\n const names = new Set<string>()\n for (const library of o.libraries) {\n assertKeys(library, LIBRARY_KEYS, 'Library')\n const l = library as Record<string, unknown>\n if (typeof l.name !== 'string' || l.name === '') throw new TypeError('A library needs a name')\n if (names.has(l.name)) throw new TypeError(`Library \"${l.name}\" is listed twice`)\n names.add(l.name)\n if (l.functions !== undefined && !isRecord(l.functions))\n throw new TypeError(`functions of library \"${l.name}\" must be an object`)\n if (l.variables !== undefined && !isRecord(l.variables))\n throw new TypeError(`variables of library \"${l.name}\" must be an object`)\n }\n }\n for (const flag of ['strict', 'validateContext'] as const) {\n if (o[flag] !== undefined && typeof o[flag] !== 'boolean')\n throw new TypeError(`${flag} must be a boolean`)\n }\n if (o.clock !== undefined && typeof o.clock !== 'function')\n throw new TypeError('clock must be a function returning a Date')\n}\n\ntype Numbers = Readonly<Record<string, number>>\n\n/**\n * The limits in `defaults` (parse or runtime), overridden by `limits` over\n * `current`. 0 turns `maxSteps` off; every other limit must be at least 1.\n */\nfunction pickLimits(\n defaults: object,\n current: object,\n limits: Readonly<Record<string, unknown>>,\n): Numbers {\n const base = current as Numbers\n return Object.freeze(\n Object.fromEntries(\n Object.keys(defaults).map((name) => {\n const value = numberOption(\n `Limit \"${name}\"`,\n limits[name],\n base[name],\n name === 'maxSteps' ? 0 : 1,\n )\n const cap = DEPTH_CAPS[name]\n if (cap !== undefined && value > cap)\n throw new RangeError(`Limit \"${name}\" must be at most ${cap}`)\n return [name, value]\n }),\n ),\n )\n}\n\n/** Depth limits are capped: deeper nesting would run out of call stack. */\nconst DEPTH_CAPS: Readonly<Record<string, number>> = {\n maxDepth: MAX_DEPTH_LIMIT,\n maxValueDepth: MAX_VALUE_DEPTH_LIMIT,\n}\n\nfunction settingsFrom(base: Settings | undefined, options: unknown): Settings {\n assertOptions(options)\n const limits = (options.limits ?? {}) as Readonly<Record<string, unknown>>\n const variables = mergeVariables(base?.variables, options)\n const strictOption = options.strict ?? base?.strictOption\n return {\n variables,\n strictOption,\n strict: strictOption ?? variables !== undefined,\n host: mergeFunctions(base?.host ?? new Map(), options),\n parseLimits: pickLimits(\n DEFAULT_PARSE_LIMITS,\n base?.parseLimits ?? DEFAULT_PARSE_LIMITS,\n limits,\n ) as unknown as ParseLimits,\n runtimeLimits: pickLimits(\n DEFAULT_RUNTIME_LIMITS,\n base?.runtimeLimits ?? DEFAULT_RUNTIME_LIMITS,\n limits,\n ) as unknown as RuntimeLimits,\n timeout: timeoutOption('Limit \"timeout\"', limits.timeout, base?.timeout ?? 0),\n cacheSize: numberOption(\n 'cacheSize',\n options.cacheSize,\n base?.cacheSize ?? DEFAULT_CACHE_SIZE,\n 0,\n ),\n clock: options.clock === undefined ? (base?.clock ?? systemClock) : checkedClock(options.clock),\n validateContext: options.validateContext ?? base?.validateContext ?? false,\n features: base?.features,\n }\n}\n\n/**\n * Source characters the program cache holds in total, and the longest source it\n * keeps. A compiled program can retain a hundred times its source in memory, so\n * the cache is bounded by size as well as by count.\n */\nconst CACHE_CHARS = 262_144\nconst CACHE_MAX_SOURCE = 16_384\n\n/**\n * Approximately least recently used (\"second chance\"): a hit only marks its\n * entry, so the hot path is one lookup. When the cache is full, the oldest\n * entry is evicted, unless it was used since it last reached the front (or is\n * the entry being added), in which case it moves to the back unmarked.\n */\nclass ProgramCache<V> {\n private readonly map = new Map<string, { readonly value: V; used: boolean }>()\n private readonly size: number\n private chars = 0\n\n constructor(size: number) {\n this.size = size\n }\n\n get(key: string): V | undefined {\n const slot = this.map.get(key)\n if (slot === undefined) return undefined\n slot.used = true\n return slot.value\n }\n\n set(key: string, value: V): void {\n if (this.size === 0 || key.length > CACHE_MAX_SOURCE) return\n if (this.map.delete(key)) this.chars -= key.length\n this.map.set(key, { value, used: false })\n this.chars += key.length\n while (this.map.size > this.size || this.chars > CACHE_CHARS) {\n const [oldest, slot] = this.map.entries().next().value as [\n string,\n { readonly value: V; used: boolean },\n ]\n this.map.delete(oldest)\n if (slot.used || oldest === key) {\n slot.used = false\n this.map.set(oldest, slot)\n } else {\n this.chars -= oldest.length\n }\n }\n }\n}\n\nconst EMPTY_CONTEXT: Record<string, unknown> = Object.freeze({})\nconst NO_DIAGNOSTICS: readonly Diagnostic[] = Object.freeze([])\n\n/**\n * What check() found. `ok`, `type`, and `diagnostics` are the JSON form; the\n * tree is read on demand (a prototype getter), so an editor checking on every\n * keystroke pays only for what it uses.\n */\nclass CheckFailure {\n readonly ok: boolean = false\n readonly type: Type | undefined\n readonly diagnostics: readonly Diagnostic[]\n /** The inferred type of a node of `ast`, or undefined for another tree's node. */\n readonly typeOf: (node: Node) => Type | undefined\n readonly #analysis: Analysis | undefined\n\n constructor(type: Type | undefined, diagnostics: readonly Diagnostic[], analysis?: Analysis) {\n this.type = type\n this.diagnostics = diagnostics\n this.#analysis = analysis\n this.typeOf = (node) => {\n const found = analysis?.types.get(node)\n return found === undefined ? undefined : deepFreeze(found)\n }\n }\n\n get ast(): Node | undefined {\n return this.#analysis === undefined ? undefined : deepFreeze(this.#analysis.root)\n }\n}\n\n/** A check that passed: also the compiled program, made the first time it is read. */\nclass CheckSuccess extends CheckFailure {\n override readonly ok: boolean = true\n readonly #program: () => unknown\n\n constructor(\n type: Type,\n diagnostics: readonly Diagnostic[],\n analysis: Analysis,\n program: () => unknown,\n ) {\n super(type, diagnostics, analysis)\n this.#program = program\n }\n\n get program(): unknown {\n return this.#program()\n }\n}\n\nexport const EVALUATE_OPTION_KEYS = new Set([\n 'timeout',\n 'maxSteps',\n 'signal',\n 'now',\n 'validateContext',\n])\n\nexport interface EvaluationLimits {\n readonly maxSteps: number\n readonly timeout: number\n readonly signal: AbortSignal | undefined\n /** The time now() returns, when the caller fixed it. */\n readonly now: Date | undefined\n /** Whether to validate the context, when the caller overrides the environment. */\n readonly validateContext: boolean | undefined\n}\n\n/** Whether a value is a valid Date (an object that only inherits from Date.prototype is not). */\nexport function isValidDate(value: unknown): value is Date {\n try {\n return value instanceof Date && !Number.isNaN(Date.prototype.getTime.call(value))\n } catch {\n return false\n }\n}\n\n/** Whether a value has an AbortSignal's members; a signal whose getters throw does not. */\nfunction looksLikeSignal(signal: object): boolean {\n try {\n const s = signal as Record<string, unknown>\n return (\n typeof s.aborted === 'boolean' &&\n typeof s.addEventListener === 'function' &&\n typeof s.removeEventListener === 'function'\n )\n } catch {\n return false\n }\n}\n\n/** Validates per-evaluation options the way `limits` are validated; nothing fails open. */\nexport function evaluationLimits(options: unknown, settings: Settings): EvaluationLimits {\n if (options === undefined) {\n return {\n maxSteps: settings.runtimeLimits.maxSteps,\n timeout: settings.timeout,\n signal: undefined,\n now: undefined,\n validateContext: undefined,\n }\n }\n // Options are the caller's own object; one whose getters or Proxy traps throw\n // is invalid options (a TypeError), never an error from inside evaluation.\n let o: Record<string, unknown>\n try {\n assertKeys(options, EVALUATE_OPTION_KEYS, 'Evaluate option')\n const read = options as Record<string, unknown>\n o = {\n maxSteps: read.maxSteps,\n timeout: read.timeout,\n signal: read.signal,\n now: read.now,\n validateContext: read.validateContext,\n }\n } catch (error) {\n if (error instanceof TypeError || error instanceof RangeError) throw error\n throw new TypeError(`Evaluate options could not be read: ${errorText(error)}`, { cause: error })\n }\n const signal = o.signal\n if (\n signal !== undefined &&\n (typeof signal !== 'object' || signal === null || !looksLikeSignal(signal))\n ) {\n throw new TypeError('signal must be an AbortSignal')\n }\n if (o.now !== undefined && !isValidDate(o.now)) throw new TypeError('now must be a valid Date')\n if (o.validateContext !== undefined && typeof o.validateContext !== 'boolean')\n throw new TypeError('validateContext must be a boolean')\n return {\n maxSteps: numberOption('maxSteps', o.maxSteps, settings.runtimeLimits.maxSteps, 0),\n timeout: timeoutOption('timeout', o.timeout, settings.timeout),\n // A structurally checked AbortSignalLike; evaluation only reads the members checked above.\n signal: signal as AbortSignal | undefined,\n now: o.now,\n validateContext: o.validateContext,\n }\n}\n\n/** Freezes a syntax tree (or any tree of plain objects and arrays) in place, without recursion. */\nfunction deepFreeze<T>(root: T): T {\n // Visits frozen objects too: a frozen type can hold a type the checker built\n // unfrozen (and shares between analyses).\n const seen = new Set<object>()\n const pending: unknown[] = [root]\n while (pending.length > 0) {\n const value = pending.pop()\n if (typeof value !== 'object' || value === null || seen.has(value)) continue\n seen.add(value)\n Object.freeze(value)\n for (const child of Object.values(value)) pending.push(child)\n }\n return root\n}\n\ninterface ValidationLimits {\n readonly maxDepth: number\n readonly maxSteps: number\n readonly timeout: number\n}\n\nexport function validationBudget(source: string, limits: ValidationLimits): ValidationBudget {\n return {\n maxDepth: limits.maxDepth,\n remaining: limits.maxSteps > 0 ? limits.maxSteps : Number.POSITIVE_INFINITY,\n deadline: limits.timeout > 0 ? performance.now() + limits.timeout : 0,\n onExhausted: (reason) => {\n if (reason === 'depth') {\n throw raised(\n new BonsaiLimitError(\n 'VALUE_DEPTH_LIMIT',\n `Context nests deeper than ${limits.maxDepth}`,\n {\n source,\n },\n ),\n )\n }\n if (reason === 'time')\n throw raised(new BonsaiLimitError('TIMEOUT', 'Context validation timed out', { source }))\n throw raised(\n new BonsaiLimitError('STEP_LIMIT', 'Context validation exceeded the step limit', {\n source,\n }),\n )\n },\n }\n}\n\nexport function invalidContext(problem: string | undefined, source: string): void {\n if (problem !== undefined) {\n throw raised(\n new BonsaiRuntimeError('INVALID_CONTEXT', `Invalid context: ${problem}`, { source }),\n )\n }\n}\n\nfunction validateContext(\n ctx: Record<string, unknown>,\n variables: Readonly<Record<string, Type>>,\n source: string,\n limits: ValidationLimits,\n): void {\n const budget = validationBudget(source, limits)\n for (const [name, type] of Object.entries(variables)) {\n const value = Object.hasOwn(ctx, name) ? ctx[name] : undefined\n invalidContext(describeMismatch(value, type, name, budget), source)\n }\n}\n\n/**\n * Why the value read along `segments` (from index `at`) does not conform, or\n * undefined. Each step is judged by its own declared type: an absent or null\n * value is fine only where that type is nullable; a declared field is followed\n * (a missing required one fails); an undeclared key of an object (objects are\n * open) or an absent record entry ends the check; past a type that is not a\n * map, and at the end of the path, the value is checked whole, as a context is.\n * Fields the path does not name are not checked.\n */\nfunction describeAlong(\n value: unknown,\n type: Type,\n segments: readonly string[],\n at: number,\n path: string,\n budget: ValidationBudget,\n): string | undefined {\n if (at === segments.length) return describeMismatch(value, type, path, budget)\n if (--budget.remaining < 0) budget.onExhausted('steps')\n if (type.kind === 'union') {\n let first: string | undefined\n for (const member of type.types) {\n const problem = describeAlong(value, member, segments, at, path, budget)\n if (problem === undefined) return undefined\n first ??= problem\n }\n return first\n }\n const actual = value === undefined ? null : value\n if (type.kind !== 'map' || !isMap(actual)) return describeMismatch(value, type, path, budget)\n const key = segments[at]\n const field = Object.hasOwn(actual, key) ? actual[key] : undefined\n if (Object.hasOwn(type.fields, key))\n return describeAlong(field, type.fields[key], segments, at + 1, `${path}.${key}`, budget)\n if (type.rest === undefined || field === undefined) return undefined\n return describeAlong(field, type.rest, segments, at + 1, `${path}.${key}`, budget)\n}\n\n/**\n * Validates the values a residual reads: each path in `dependsOn`, step by\n * step against the types declared along it (see describeAlong), so a context\n * holding exactly those paths passes and invalid data on them fails as it\n * would for the program.\n */\nfunction validatePaths(\n ctx: Record<string, unknown>,\n variables: Readonly<Record<string, Type>>,\n paths: readonly string[],\n source: string,\n limits: ValidationLimits,\n): void {\n const budget = validationBudget(source, limits)\n for (const path of paths) {\n const segments = path.split('.')\n const name = segments[0]\n if (!Object.hasOwn(variables, name)) continue\n const value = Object.hasOwn(ctx, name) ? ctx[name] : undefined\n invalidContext(describeAlong(value, variables[name], segments, 1, name, budget), source)\n }\n}\n\n/**\n * Reading host data (a getter, a Proxy trap, a `then` hook) can throw. Such a\n * failure is a HOST_ERROR, never a raw JavaScript error. Only the errors this\n * evaluation raised pass through: any other Bonsai error (from another\n * evaluation, from parsing, checking, or translating, or built by the host)\n * that host data threw is the host data's failure too.\n */\nexport function hostDataFailure(error: unknown, source: string): BonsaiError {\n if (isOwn(error)) return error\n if (isStackOverflow(error)) return raised(tooDeep(source, error))\n return raised(\n new BonsaiRuntimeError('HOST_ERROR', `Reading host data failed: ${errorText(error)}`, {\n source,\n cause: error,\n }),\n )\n}\n\nconst systemClock = (): Date => new Date()\n\n/** A host clock whose results are checked: now() must be a valid timestamp. */\nfunction checkedClock(clock: () => Date): () => Date {\n return () => {\n let value: unknown\n try {\n value = clock()\n } catch (error) {\n throw raised(new BonsaiRuntimeError('HOST_ERROR', 'The clock failed', { cause: error }))\n }\n if (!(value instanceof Date) || Number.isNaN(Date.prototype.getTime.call(value))) {\n throw raised(\n new BonsaiRuntimeError(\n 'HOST_CONTRACT',\n 'The clock must return a valid Date (for example () => new Date())',\n ),\n )\n }\n return value\n }\n}\n\n/** The most zones one program warms when it is compiled. */\nconst WARMED_ZONES = 16\n\n/**\n * Loads the time zone data a program's calls need, so its first evaluation\n * does not pay for it inside its deadline. Only built-in functions that take a\n * zone count: a zone written as text is loaded itself, and any other zone\n * argument loads the data every zone shares. Each zone is warmed once, and at\n * most WARMED_ZONES of them, so a source full of zone names compiles quickly.\n */\nfunction warmZones(analysis: Analysis): void {\n const seen = new Set<string | undefined>()\n for (const [call, plan] of analysis.calls) {\n const index = zoneParameter(plan.def)\n const arg = index === undefined ? undefined : call.args[index]\n if (arg === undefined) continue\n const zone = arg.type === 'Literal' ? arg.value : undefined\n if ((zone !== undefined && typeof zone !== 'string') || seen.has(zone)) continue\n seen.add(zone)\n warmZone(zone)\n if (seen.size >= WARMED_ZONES) return\n }\n}\n\n/** Reads compile() and check() options: only `expect`, which must be a type built with t. */\nfunction compileExpect(options: unknown): Type | undefined {\n if (options === undefined) return undefined\n if (typeof options !== 'object' || options === null || Array.isArray(options))\n throw new TypeError('Compile options must be an object')\n let expect: unknown\n try {\n for (const key of Object.keys(options)) {\n if (key !== 'expect')\n throw new TypeError(`Unknown compile option key \"${key}\" (expected one of: expect)`)\n }\n expect = (options as { expect?: unknown }).expect\n } catch (error) {\n if (error instanceof TypeError) throw error\n throw new TypeError('Compile options could not be read', { cause: error })\n }\n if (expect !== undefined) assertType(expect, 'Compile option \"expect\"')\n return expect\n}\n\nexport function contextOf(value: unknown): Record<string, unknown> {\n if (value === undefined || value === null) return EMPTY_CONTEXT\n let map: boolean\n try {\n // A Proxy (even a revoked one) answers these through its traps.\n map = typeof value === 'object' && isMap(value)\n } catch (error) {\n throw new BonsaiRuntimeError('HOST_ERROR', 'Reading the evaluation context failed', {\n cause: error,\n })\n }\n // A caller's mistake, like invalid options, not an error in the expression's data.\n if (!map) throw new TypeError('The evaluation context must be a plain object or class instance')\n return value as Record<string, unknown>\n}\n\nfunction createEnvironment<Ctx>(settings: Settings): Environment<Ctx> {\n const checkEnv: CheckEnv = {\n variables: settings.variables,\n strict: settings.strict,\n lookup: (name) => settings.host.get(name) ?? BUILTINS.get(name),\n *functionNames() {\n yield* settings.host.keys()\n for (const name of BUILTINS.keys()) if (!settings.host.has(name)) yield name\n },\n }\n // Each entry records the source and expected type it was compiled for: a key\n // alone could collide (a comment may end a source with what looks like a type).\n const cache = new ProgramCache<{\n readonly program: Program<Ctx>\n readonly source: string\n readonly expect: string | undefined\n }>(settings.cacheSize)\n\n function parseSource(source: string): Node {\n if (typeof source !== 'string') throw new TypeError('An expression must be a string')\n return parse(source, settings.parseLimits)\n }\n\n function analyzeSource(source: string, expect: Type | undefined): Analysis {\n const root = parseSource(source)\n try {\n return analyze(root, checkEnv, { expected: expect })\n } catch (error) {\n // The checker has no source text; attach it so the error can show where.\n if (error instanceof BonsaiLimitError && error.source === undefined) {\n throw new BonsaiLimitError(error.code, error.message, {\n source,\n ...(error.span === undefined ? {} : { span: error.span }),\n limit: error.limit ?? null,\n })\n }\n throw error\n }\n }\n\n function makeProgram<R>(source: string, analysis: Analysis, expect?: Type): Program<Ctx, R>\n function makeProgram(\n source: string,\n analysis: Analysis,\n expect: Type | undefined,\n constants: ReadonlyMap<string, unknown>,\n residualOf: ResidualOf,\n ): ResidualRunner\n function makeProgram<R>(\n source: string,\n analysis: Analysis,\n expect?: Type,\n constants?: ReadonlyMap<string, unknown>,\n residualOf?: ResidualOf,\n ): Program<Ctx, R> | ResidualRunner {\n // Residuals are not warmed: partial() runs often, and a zone it writes into\n // the residual as text loads on first use (the shared data is already loaded).\n if (residualOf === undefined) warmZones(analysis)\n // When the checker cannot prove the result matches `expect` (part of it is\n // `any`, or an open object may hold an unlisted key), it is checked at run\n // time, so the declared result type holds.\n const guard = expect !== undefined && analysis.checkResult ? expect : undefined\n const checked = (result: unknown, state: State): void => {\n if (guard !== undefined && !conforms(result, guard, state)) {\n throw raised(\n new BonsaiRuntimeError(\n 'TYPE_ERROR',\n `The result does not match the expected type ${formatType(guard)}`,\n { source },\n ),\n )\n }\n }\n // The limits of an evaluation without options: built once, not per run.\n const defaultLimits = evaluationLimits(undefined, settings)\n const limitsOf = (options: EvaluateOptions | undefined): EvaluationLimits =>\n options === undefined ? defaultLimits : evaluationLimits(options, settings)\n let syncCode: CompiledProgram | undefined\n let asyncCode: CompiledProgram | undefined\n let pooled: State | undefined\n let pooledInUse = false\n\n const compileOptions = constants === undefined ? {} : { constants, shapes: residualOf?.shapes }\n const syncProgram = (): CompiledProgram =>\n (syncCode ??= compileProgram(analysis, 'sync', compileOptions))\n const asyncProgram = (): CompiledProgram =>\n (asyncCode ??= analysis.async\n ? compileProgram(analysis, 'async', compileOptions)\n : syncProgram())\n\n // Options and the context's shape are the caller's own mistakes (TypeError,\n // RangeError, INVALID_ARGUMENT), so they are checked before anything reads\n // host data and are never reported as host failures.\n function prepare(\n state: State,\n ctx: Record<string, unknown>,\n limits: EvaluationLimits,\n locals: number,\n ): void {\n state.reset(ctx, source, locals, limits.maxSteps, limits.timeout, limits.signal)\n if (limits.now !== undefined) state.nowValue = limits.now\n const residual = residualOf\n if (residual !== undefined && residual.readsContext) {\n // call: true functions read the whole context, which must then hold\n // the variables partial() knew, as the program's context would.\n const roots = residual.knownRoots\n state.charge(roots.length)\n // In a strict environment, a known key that is not a declared variable is\n // not part of any context the program accepts, so it is not required.\n const declared = settings.strict ? settings.variables : undefined\n // Decided from the property itself, never running a getter: an accessor is\n // present, and so is a data property unless it holds undefined.\n const missing = roots.find((name) => {\n if (declared !== undefined && !Object.hasOwn(declared, name)) return false\n const descriptor = Object.getOwnPropertyDescriptor(ctx, name)\n return (\n descriptor === undefined || ('value' in descriptor && descriptor.value === undefined)\n )\n })\n if (missing !== undefined) {\n throw raised(\n new BonsaiRuntimeError(\n 'INVALID_CONTEXT',\n `Invalid context: ${missing} is missing; this residual calls a call: true host function, so pass the full context, as for the program`,\n { source },\n ),\n )\n }\n }\n const validation =\n (limits.validateContext ?? settings.validateContext) ? settings.variables : undefined\n if (validation !== undefined) {\n const validationLimits = {\n maxDepth: settings.runtimeLimits.maxValueDepth,\n maxSteps: limits.maxSteps,\n timeout: limits.timeout,\n }\n if (residual === undefined || residual.readsContext)\n validateContext(ctx, validation, source, validationLimits)\n else validatePaths(ctx, validation, residual.dependsOn, source, validationLimits)\n }\n }\n\n function runSync(context: unknown, options: EvaluateOptions | undefined): R {\n if (analysis.async) {\n throw escaping(\n new BonsaiRuntimeError(\n 'ASYNC_IN_SYNC',\n 'This expression calls an async function; use evaluate() instead of evaluateSync()',\n { source },\n ),\n )\n }\n const code = syncProgram()\n const limits = limitsOf(options)\n const ctx = contextOf(context)\n let state: State\n const reuse = !pooledInUse\n if (reuse) {\n pooled ??= new State(settings.runtimeLimits, settings.clock)\n state = pooled\n pooledInUse = true\n } else {\n state = new State(settings.runtimeLimits, settings.clock)\n }\n try {\n prepare(state, ctx, limits, code.localCount)\n const result = code.run(state)\n checked(result, state)\n state.checkTime()\n return result as R\n } catch (error) {\n throw escaping(hostDataFailure(error, source))\n } finally {\n state.release()\n if (reuse) pooledInUse = false\n }\n }\n\n async function runAsync(context: unknown, options: EvaluateOptions | undefined): Promise<R> {\n if (!analysis.async) {\n const result = runSync(context, options)\n try {\n return settle(result)\n } catch (error) {\n throw escaping(hostDataFailure(error, source))\n }\n }\n const code = asyncProgram()\n const limits = limitsOf(options)\n const ctx = contextOf(context)\n const state = new State(settings.runtimeLimits, settings.clock)\n try {\n prepare(state, ctx, limits, code.localCount)\n const result = ((await code.run(state)) as Out).v\n checked(result, state)\n state.checkTime()\n return settle(result as R)\n } catch (error) {\n throw escaping(hostDataFailure(error, source))\n } finally {\n state.release()\n }\n }\n\n // Returning a thenable from an async function would call its `then`\n // (an ORM query object would execute), so it is an error instead.\n function settle(result: R): R {\n if (\n result !== null &&\n (typeof result === 'object' || typeof result === 'function') &&\n typeof (result as { then?: unknown }).then === 'function'\n ) {\n throw raised(\n new BonsaiRuntimeError(\n 'TYPE_ERROR',\n 'evaluate() cannot return a promise-like value; use evaluateSync()',\n { source },\n ),\n )\n }\n return result\n }\n\n const features = settings.features?.program<Ctx, R>({\n source,\n analysis,\n expect,\n settings,\n checkEnv,\n compileOptions,\n residualOf,\n prepare,\n checked,\n settle,\n residual: (residualAnalysis, residualConstants, residualFrom) =>\n makeProgram(source, residualAnalysis, expect, residualConstants, residualFrom),\n })\n\n if (residualOf !== undefined) {\n // Only partial() makes residuals, so the features that made this one are present.\n const made = features as ProgramFeatures<Ctx, R>\n // A residual is used only through its runner, so no Program is built for\n // it (freezing its type and references would be work on every partial());\n // its tree is the result's `ast`, and compiles lazily, so it is frozen.\n deepFreeze(analysis.root)\n const runner: ResidualRunner = {\n async: analysis.async,\n runSync: (ctx, options) => runSync(ctx, options as EvaluateOptions | undefined),\n runAsync: (ctx, options) => runAsync(ctx, options as EvaluateOptions | undefined),\n explainSync: (ctx, options) => made.explainSync(ctx, options as ExplainOptions | undefined),\n explainAsync: (ctx, options) =>\n made.explainAsync(ctx, options as ExplainOptions | undefined),\n }\n return runner\n }\n // Programs are shared: the tree compiles lazily, so it must not change afterwards.\n // A lite program is typed as a LiteProgram by its entry point.\n const program = Object.freeze({\n // Without features (bonsai-js/lite), a program has no explain or partial.\n ...(features === undefined\n ? {}\n : {\n explain: (...args: ExplainArgs<Ctx>) => features.explainAsync(args[0], args[1]),\n explainSync: (...args: ExplainArgs<Ctx>) => features.explainSync(args[0], args[1]),\n partial: (known: object, options?: PartialOptions) =>\n features.partial(program, known, options),\n }),\n source,\n ast: deepFreeze(analysis.root),\n type: deepFreeze(analysis.type),\n async: analysis.async,\n warnings: deepFreeze(\n locate(\n source,\n analysis.diagnostics.filter((d) => d.severity === 'warning'),\n ),\n ),\n references: deepFreeze(analysis.references),\n evaluate: (...args: Args<Ctx>) => runAsync(args[0], args[1]),\n evaluateSync: (...args: Args<Ctx>) => runSync(args[0], args[1]),\n })\n recordDeclared(program, settings.variables)\n return program as Program<Ctx, R>\n }\n\n function compile<R>(source: string, expect: Type | undefined): Program<Ctx, R> {\n const analysis = analyzeSource(source, expect)\n const errors = analysis.diagnostics.filter((d) => d.severity === 'error')\n if (errors.length > 0) throw new BonsaiCheckError(source, errors)\n return makeProgram<R>(source, analysis, expect)\n }\n\n /**\n * compile(), through the program cache: programs are immutable, so the same\n * source with an equal expected type (types are plain JSON data) shares one.\n */\n function cachedCompile<R>(source: string, expect: Type | undefined): Program<Ctx, R> {\n if (typeof source !== 'string') throw new TypeError('An expression must be a string')\n const expectKey = expect === undefined ? undefined : JSON.stringify(expect)\n const key = expectKey === undefined ? source : `${source}\\u0000${expectKey}`\n const entry = cache.get(key)\n if (entry !== undefined && entry.source === source && entry.expect === expectKey)\n return entry.program as Program<Ctx, R>\n const program = compile<R>(source, expect)\n cache.set(key, { program, source, expect: expectKey })\n return program\n }\n\n function cached(source: string): Program<Ctx> {\n return cachedCompile(source, undefined)\n }\n\n function info(def: FunctionDef): FunctionInfo {\n return {\n name: def.name,\n description: def.description,\n host: def.host === true,\n async: def.async === true,\n call: def.call === true,\n ...(def.cost === undefined ? {} : { cost: def.cost }),\n signatures: def.overloads.map((o) => ({\n params: o.params,\n required: o.required ?? o.params.length,\n returns: o.result,\n ...(o.rest === undefined ? {} : { rest: o.rest }),\n })),\n }\n }\n\n // A lite environment is typed as a LiteEnvironment by its entry point.\n const env = Object.freeze({\n variables: settings.variables,\n strict: settings.strict,\n parse: parseSource,\n check<E extends Type = AnyType>(\n source: string,\n options?: CompileOptions<E>,\n ): CheckResult<Ctx, Infer<E>> {\n const expect = compileExpect(options)\n let analysis: Analysis\n try {\n analysis = analyzeSource(source, expect)\n } catch (error) {\n if (!(error instanceof BonsaiError)) throw error\n const diagnostics = locate(source, [\n {\n code: error.code === 'SYNTAX' ? 'SYNTAX' : 'LIMIT',\n message: error.message,\n severity: 'error',\n start: error.span?.start ?? 0,\n end: error.span?.end ?? source.length,\n },\n ])\n return Object.freeze(new CheckFailure(undefined, diagnostics, undefined)) as CheckResult<\n Ctx,\n Infer<E>\n >\n }\n const diagnostics =\n analysis.diagnostics.length === 0 ? NO_DIAGNOSTICS : locate(source, analysis.diagnostics)\n const type = deepFreeze(analysis.type)\n if (analysis.diagnostics.some((d) => d.severity === 'error'))\n return Object.freeze(new CheckFailure(type, diagnostics, analysis)) as CheckResult<\n Ctx,\n Infer<E>\n >\n let program: Program<Ctx, Infer<E>> | undefined\n return Object.freeze(\n new CheckSuccess(\n type,\n diagnostics,\n analysis,\n () => (program ??= makeProgram<Infer<E>>(source, analysis, expect)),\n ),\n ) as CheckResult<Ctx, Infer<E>>\n },\n compile: <E extends Type = AnyType>(source: string, options?: CompileOptions<E>) =>\n cachedCompile<Infer<E>>(source, compileExpect(options)),\n // Without features (bonsai-js/lite), an environment has no partial or explain.\n ...(settings.features === undefined\n ? {}\n : {\n partial: <R>(\n source: string,\n known: PartialData<Ctx> & object,\n options?: PartialOptions,\n ) => cached(source).partial(known, options) as PartialResult<Ctx, R>,\n }),\n evaluate<R>(source: string, ...args: Args<Ctx>): Promise<R> {\n try {\n return cached(source).evaluate(...args) as Promise<R>\n } catch (error) {\n return Promise.reject(error instanceof Error ? error : new Error(String(error)))\n }\n },\n evaluateSync: <R>(source: string, ...args: Args<Ctx>) =>\n cached(source).evaluateSync(...args) as R,\n ...(settings.features === undefined\n ? {}\n : {\n explain<R>(source: string, ...args: ExplainArgs<Ctx>): Promise<Explanation<R>> {\n try {\n return cached(source).explain(...args) as Promise<Explanation<R>>\n } catch (error) {\n return Promise.reject(error instanceof Error ? error : new Error(String(error)))\n }\n },\n explainSync: <R>(source: string, ...args: ExplainArgs<Ctx>) =>\n cached(source).explainSync(...args) as Explanation<R>,\n }),\n describeFunction(name: string): FunctionInfo | undefined {\n const def = checkEnv.lookup(name)\n return def === undefined ? undefined : info(def)\n },\n listFunctions(): FunctionInfo[] {\n return [...checkEnv.functionNames()].map((name) => info(checkEnv.lookup(name) as FunctionDef))\n },\n extend<\n V2 extends Readonly<Record<string, Type>>,\n L2 extends readonly Library[],\n S2 extends boolean | undefined,\n >(options: EnvironmentOptions<V2, L2> & { readonly strict?: S2 }) {\n return createEnvironment<Extended<Ctx, V2, L2, S2>>(settingsFrom(settings, options))\n },\n })\n internals.set(env, { checkEnv, parseLimits: settings.parseLimits })\n return env as Environment<Ctx>\n}\n\n/**\n * An environment from `bonsai()` options, with the features its entry point\n * provides (not public API): `bonsai-js` passes explaining and partial\n * evaluation, `bonsai-js/lite` passes none.\n */\nexport function environmentWith<Ctx>(\n features: Features | undefined,\n options: unknown,\n): Environment<Ctx> {\n return createEnvironment<Ctx>({ ...settingsFrom(undefined, options), features })\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"environment.mjs","names":[],"sources":["../src/environment.ts"],"sourcesContent":["import { analyze, type Analysis, type CheckEnv } from './check/checker.js'\nimport type { CompileOptions as CompilerOptions } from './compile/compiler.js'\nimport { raised } from './runtime/attribution.js'\nimport {\n BonsaiCheckError,\n BonsaiError,\n BonsaiLimitError,\n BonsaiRuntimeError,\n locate,\n type Diagnostic,\n} from './errors.js'\nimport { BUILTINS } from './functions/builtins.js'\nimport { descriptionOf } from './functions/descriptions.js'\nimport {\n assertHostSpec,\n assertType,\n builtinsOption,\n isRecord,\n overload,\n type FunctionDef,\n} from './functions/define.js'\nimport type { PartialData, PartialOptions, PartialResult } from './partial.js'\nimport {\n DEFAULT_RUNTIME_LIMITS,\n MAX_VALUE_DEPTH_LIMIT,\n type State,\n type RuntimeLimits,\n} from './runtime/state.js'\nimport { recordCompiled, recordDeclared } from './declared.js'\nimport {\n assertKeys,\n numberOption,\n programRunner,\n timeoutOption,\n type EvaluationLimits,\n warmZones,\n} from './program.js'\nimport type { ExplanationJSON, Trace } from './runtime/trace.js'\nimport type { Node } from './syntax/ast.js'\nimport { isName } from './syntax/lexer.js'\nimport { DEFAULT_PARSE_LIMITS, MAX_DEPTH_LIMIT, parse, type ParseLimits } from './syntax/parser.js'\nimport {\n isExact,\n isNullable,\n typeData,\n type AnyType,\n type Infer,\n type InferVariables,\n type Type,\n} from './types.js'\n\n// === public option types ===\n\n/** Every field optional, and `undefined` accepted, even under `exactOptionalPropertyTypes`. */\ntype Optional<T> = { readonly [K in keyof T]?: T[K] | undefined }\n\nexport interface Limits extends Optional<ParseLimits>, Optional<RuntimeLimits> {\n /** Wall-clock budget per evaluation in milliseconds (0 = none; fractions allowed). Default 0. */\n readonly timeout?: number | undefined\n}\n\n/**\n * The part of an `AbortSignal` evaluation reads. A standard `AbortSignal`\n * satisfies it; declaring it structurally keeps the types free of DOM or Node\n * library requirements.\n */\nexport interface AbortSignalLike {\n readonly aborted: boolean\n readonly reason?: unknown\n addEventListener: (type: 'abort', listener: () => void, options?: { once?: boolean }) => void\n removeEventListener: (type: 'abort', listener: () => void) => void\n}\n\nexport interface EvaluateOptions {\n /** Wall-clock budget for this evaluation in milliseconds (0 = none; fractions allowed). */\n readonly timeout?: number | undefined\n /** Step budget for this evaluation (0 = none; overrides the environment limit). */\n readonly maxSteps?: number | undefined\n /** Cancels the evaluation. */\n readonly signal?: AbortSignalLike | undefined\n /** The time now() returns in this evaluation, instead of the environment's clock. */\n readonly now?: Date | undefined\n /**\n * Validates the context for this evaluation (true) or not (false), instead\n * of the environment's `validateContext`; for a context already validated upstream.\n */\n readonly validateContext?: boolean | undefined\n}\n\ntype InferParams<P extends readonly Type[]> = Extract<\n { -readonly [K in keyof P]: Infer<P[K]> },\n unknown[]\n>\n\n/** The arguments `run` receives: the declared parameters, then any rest arguments. */\ntype RunArgs<P extends readonly Type[], RT> = RT extends Type\n ? [...InferParams<P>, ...Infer<RT>[]]\n : InferParams<P>\n\n/** What `run` may return: a nullable result also accepts `undefined`, which reads as null. */\ntype RunResult<R extends Type> = null extends Infer<R> ? Infer<R> | undefined : Infer<R>\n\n/**\n * The standard `AbortSignal` when the consumer's types declare one (DOM or\n * Node), so it can be passed to `fetch`; otherwise {@link AbortSignalLike}.\n */\ntype HostAbortSignal = typeof globalThis extends { AbortSignal: { prototype: infer S } }\n ? S\n : AbortSignalLike\n\n/** What a host function declared with `call: true` receives before its arguments. */\nexport interface HostCall<Ctx = Readonly<Record<string, unknown>>> {\n /** The evaluation context, read-only. */\n readonly context: Readonly<Ctx>\n /**\n * Aborted when the evaluation times out or is cancelled while it waits on\n * this call, so an async function can stop its own work (pass it to `fetch`).\n */\n readonly signal: HostAbortSignal\n}\n\n/** A host function declaration. Create one with {@link fn}. */\nexport interface HostFunction {\n readonly params: readonly Type[]\n readonly returns: Type\n readonly required?: number | undefined\n readonly rest?: Type | undefined\n readonly async?: boolean | undefined\n /** Whether `run` receives a {@link HostCall} before its arguments. */\n readonly call?: boolean | undefined\n readonly description?: string | undefined\n /** Steps charged per call (default 32). */\n readonly cost?: number | undefined\n readonly run: (...args: never[]) => unknown\n}\n\n/** The declaration passed to {@link fn}, without `run`, `async`, and `call`. */\nexport interface FnSpec<\n P extends readonly Type[] = readonly Type[],\n R extends Type = Type,\n RT extends Type | undefined = Type | undefined,\n> {\n /** Parameter types, in order. */\n readonly params: P\n /** Declared result type; results are checked against its kind. */\n readonly returns: R\n /** Number of required leading parameters (default: all). Missing optional arguments arrive as null. */\n readonly required?: number | undefined\n /** Type of further variadic arguments. */\n readonly rest?: RT\n readonly description?: string | undefined\n /**\n * Steps charged per call (default 32), so one evaluation makes at most\n * maxSteps / cost calls. Lower it for cheap pure functions; raise it for\n * expensive ones.\n */\n readonly cost?: number | undefined\n}\n\n/**\n * Declares a host function.\n *\n * ```ts\n * fn({ params: [t.string()], returns: t.boolean(), run: (perm) => user.can(perm) })\n * fn({ params: [t.string()], returns: t.string(), async: true, run: async (id) => lookup(id) })\n * fn({ params: [t.string()], returns: t.number(), async: true, call: true,\n * run: async (call, id) => (await fetch(`/stock/${id}`, { signal: call.signal })).json() })\n * ```\n */\nexport function fn<\n const P extends readonly Type[],\n R extends Type,\n RT extends Type | undefined = undefined,\n>(\n spec: FnSpec<P, R, RT> &\n (\n | {\n readonly async?: false | undefined\n readonly call?: false | undefined\n readonly run: (...args: RunArgs<P, RT>) => RunResult<R>\n }\n | {\n readonly async: true\n readonly call?: false | undefined\n readonly run: (...args: RunArgs<P, RT>) => Promise<RunResult<R>>\n }\n | {\n readonly async?: false | undefined\n readonly call: true\n readonly run: (call: HostCall, ...args: RunArgs<P, RT>) => RunResult<R>\n }\n | {\n readonly async: true\n readonly call: true\n readonly run: (call: HostCall, ...args: RunArgs<P, RT>) => Promise<RunResult<R>>\n }\n ),\n): HostFunction {\n assertHostSpec(spec, 'fn()')\n return Object.freeze({ ...spec })\n}\n\n/**\n * Declares host functions that read a typed evaluation context: like `fn`\n * with `call: true`, with `call.context` typed as `Readonly<Ctx>`.\n *\n * ```ts\n * const contextFn = withContext<{ user: { id: string } }>()\n * const functions = { userId: contextFn({ params: [], returns: t.string(), run: (call) => call.context.user.id }) }\n * ```\n */\nexport function withContext<Ctx>() {\n return <const P extends readonly Type[], R extends Type, RT extends Type | undefined = undefined>(\n spec: FnSpec<P, R, RT> &\n (\n | {\n readonly async?: false | undefined\n /** Implied; may be written out when moving a function over from `fn`. */\n readonly call?: true | undefined\n readonly run: (call: HostCall<Ctx>, ...args: RunArgs<P, RT>) => RunResult<R>\n }\n | {\n readonly async: true\n readonly call?: true | undefined\n readonly run: (call: HostCall<Ctx>, ...args: RunArgs<P, RT>) => Promise<RunResult<R>>\n }\n ),\n ): HostFunction => {\n assertHostSpec(spec, 'withContext()')\n return Object.freeze({ ...spec, call: true })\n }\n}\n\n/**\n * A reusable bundle of host functions (and optionally variables). Declare one\n * with `satisfies Library` (not `: Library`) so its variables keep their types\n * and become part of the context type of every environment that uses it.\n */\nexport interface Library<\n V extends Readonly<Record<string, Type>> = Readonly<Record<string, Type>>,\n> {\n readonly name: string\n readonly functions?: Readonly<Record<string, HostFunction>> | undefined\n readonly variables?: V | undefined\n}\n\n/** No declared variables: the empty record, which adds nothing to a context type. */\n// oxlint-disable-next-line typescript/no-generated-empty-object-type -- intentionally empty\nexport type NoVariables = Record<never, never>\n\n/**\n * The variables one library declares. A library annotated `: Library` has the\n * wide default (any string key), which names no variable, so it adds nothing.\n */\ntype VariablesOf<Lib> = Lib extends { readonly variables?: infer V }\n ? string extends keyof NonNullable<V>\n ? NoVariables\n : NonNullable<V>\n : NoVariables\n\n/**\n * The variables a list of libraries declares, merged. Only a list whose\n * elements are known (written inline, or `as const`) contributes; a value\n * typed as `Library[]` adds nothing to the context type.\n */\ntype LibraryVariables<L> = L extends readonly [infer First, ...infer Rest]\n ? VariablesOf<First> & LibraryVariables<Rest>\n : NoVariables\n\n/**\n * Any further keys, as a context with `strict: false` may carry. Its values are\n * `any` because only that lets an interface or a class instance (which have no\n * index signature) still satisfy it; declared keys keep their own types.\n */\n// oxlint-disable-next-line typescript/no-explicit-any -- the only index signature interfaces and classes satisfy\ntype MoreKeys = Readonly<Record<string, any>>\n\n/**\n * The context type of an environment with variables `V` and libraries `L`.\n * With `strict: false` (`S`), undeclared variables are allowed, so the context\n * may carry keys beyond the declared ones.\n */\nexport type ContextFor<V, L, S = undefined> = [S] extends [false]\n ? ContextOf<V & LibraryVariables<L>> & MoreKeys\n : ContextOf<V & LibraryVariables<L>>\n\n/**\n * `Ctx` with the variables `New` declares replacing those of the same name,\n * as extend() replaces them at run time (\"later wins\"). Remapping keys (not\n * Omit) keeps an index signature and the other keys' types.\n */\ntype Override<Ctx, New> = [keyof New] extends [never]\n ? Ctx\n : { [K in keyof Ctx as K extends keyof New ? never : K]: Ctx[K] } & New\n\n/** The context type extend() produces: re-declared variables replaced, strict: false loosened. */\nexport type Extended<Ctx, V, L, S> = [S] extends [false]\n ? Override<Ctx, ContextOf<V & LibraryVariables<L>>> & MoreKeys\n : Override<Ctx, ContextOf<V & LibraryVariables<L>>>\n\nexport interface EnvironmentOptions<\n V extends Readonly<Record<string, Type>> = Readonly<Record<string, Type>>,\n L extends readonly Library[] = readonly Library[],\n> {\n /** Declared context variables and their types. */\n readonly variables?: V | undefined\n /**\n * Report unknown variables as errors. Default: true when `variables` is\n * declared (even as `{}`), false for an open environment.\n */\n readonly strict?: boolean | undefined\n /** Host functions by name. A host function replaces a built-in of the same name. */\n readonly functions?: Readonly<Record<string, HostFunction>> | undefined\n /** Libraries of host functions and variables; a name defined twice is an error. */\n readonly libraries?: L | undefined\n readonly limits?: Limits | undefined\n /**\n * Compiled programs kept for `evaluate(source)` and `evaluateSync(source)`. Default 256; 0\n * disables the cache. The cache also holds at most 256K characters of source in total, and\n * never a source longer than 16K characters.\n */\n readonly cacheSize?: number | undefined\n /** Source of now(). Default: the system clock. */\n readonly clock?: (() => Date) | undefined\n /**\n * Check the context against the declared variable types before every\n * evaluation (deep, proportional to the data) and fail with INVALID_CONTEXT\n * naming the first mismatching path. Default: false.\n */\n readonly validateContext?: boolean | undefined\n /**\n * The built-ins available, from bonsai-js/builtins. Default: all of them\n * (none in bonsai-js/runtime/core). Calling one left out is a CHECK error, so\n * an environment that checks rules for bonsai-js/runtime/core passes the same\n * list as the runtime. On extend(), these are added to the base's.\n */\n readonly builtins?: readonly Builtin[] | undefined\n}\n\ndeclare const builtinBrand: unique symbol\n\n/** A built-in function from bonsai-js/builtins, for the `builtins` option. */\nexport interface Builtin {\n readonly name: string\n readonly [builtinBrand]: true\n}\n\n/**\n * What check() found. Only `ok`, `type`, and `diagnostics` are data (and the\n * JSON form); `program`, `ast`, and `typeOf` are accessors computed on demand,\n * so spreading the result or `structuredClone` does not copy them.\n */\n// oxlint-disable-next-line typescript/no-explicit-any -- the same erased context as a bare Program\nexport type CheckResult<Ctx = any, R = unknown> = Checked<Program<Ctx, R>>\n\n/** What check() found, over the kind of program it compiles. */\ntype Checked<P> = (\n | {\n readonly ok: true\n readonly type: Type\n readonly diagnostics: readonly Diagnostic[]\n /**\n * The checked expression, compiled when first read: a program equal to\n * the one compile() returns, without parsing and checking again.\n */\n readonly program: P\n }\n | {\n readonly ok: false\n readonly type: Type | undefined\n readonly diagnostics: readonly Diagnostic[]\n }\n) & {\n /**\n * The checked syntax tree (implicit lambdas made explicit, as `program.ast`),\n * or undefined when the source did not parse.\n */\n readonly ast: Node | undefined\n /** The inferred type of a node of `ast`, or undefined for another tree's node. */\n readonly typeOf: (node: Node) => Type | undefined\n}\n\nexport type Args<Ctx> =\n Record<string, never> extends Ctx\n ? [context?: Ctx, options?: EvaluateOptions]\n : [context: Ctx, options?: EvaluateOptions]\n\n/**\n * A checked, compiled expression. Immutable and safe to share. A bare\n * `Program` accepts any context, so a program typed for one context can be\n * stored as a `Program`.\n */\n// oxlint-disable-next-line typescript/no-explicit-any -- the erased context type every typed program is assignable to\nexport interface Program<Ctx = any, R = unknown> {\n readonly source: string\n /** The syntax tree after implicit lambdas are made explicit. */\n readonly ast: Node\n /** The statically inferred result type. */\n readonly type: Type\n /** Whether the expression calls an async host function (evaluateSync rejects it). */\n readonly async: boolean\n /** Non-fatal findings from the checker. */\n readonly warnings: readonly Diagnostic[]\n readonly references: {\n readonly variables: readonly string[]\n readonly functions: readonly string[]\n }\n evaluate: (...args: Args<Ctx>) => Promise<R>\n evaluateSync: (...args: Args<Ctx>) => R\n /**\n * Evaluates and records the value of every sub-expression, so you can show\n * why the result came out as it did. Never rejects for evaluation errors:\n * they are returned in the explanation. Slower than evaluate.\n */\n explain: (...args: ExplainArgs<Ctx>) => Promise<Explanation<R>>\n /** Like explain, synchronously; an expression that calls an async host function is an ASYNC_IN_SYNC error. */\n explainSync: (...args: ExplainArgs<Ctx>) => Explanation<R>\n /**\n * Evaluates what can be evaluated from partial data. Returns the value when\n * the known data decides it, or a simplified residual expression (source and\n * syntax tree) that needs only the unknown data. Evaluating the residual with\n * the full data gives the same result as evaluating this program.\n */\n partial: (known: PartialData<Ctx> & object, options?: PartialOptions) => PartialResult<Ctx, R>\n}\n\nexport interface ExplainOptions extends EvaluateOptions {\n /** How many lambda runs to record per call (the rest are counted). Default 20. */\n readonly maxIterations?: number | undefined\n /** Sub-expressions to record in total before stopping (the result stays exact). Default 10,000. */\n readonly maxTraceNodes?: number | undefined\n /**\n * Also evaluate the side of && and || that short-circuiting would skip, so\n * reasons() lists every failing condition rather than the first. Those\n * parts are marked `extra`; their evaluation errors are ignored and the\n * result is unchanged. They spend from the same step and time budget, so a\n * limit reached there (STEP_LIMIT, TIMEOUT, a size limit) fails the\n * explanation even when evaluation alone would stay inside it. Host\n * functions on those parts do run. Default false.\n */\n readonly exhaustive?: boolean | undefined\n}\n\ntype ExplainArgs<Ctx> =\n Record<string, never> extends Ctx\n ? [context?: Ctx, options?: ExplainOptions]\n : [context: Ctx, options?: ExplainOptions]\n\n/** The result of explain(): the outcome plus a trace of every sub-expression. */\nexport type Explanation<R = unknown> = (\n | { readonly ok: true; readonly value: R }\n | { readonly ok: false; readonly error: BonsaiError }\n) & {\n /** The root of the trace; its `value` is the result. Values are live references. */\n readonly trace: Trace\n /** True when maxTraceNodes stopped recording before evaluation finished. */\n readonly truncated: boolean\n /**\n * The conditions that decided the result, following &&, ||, and ! down to\n * the comparisons and values (or the error) behind it.\n */\n reasons: () => readonly Trace[]\n /** The trace as an indented, human-readable tree. */\n toString: () => string\n /**\n * A JSON-safe snapshot: values are bounded copies (cycles, bigints, dates,\n * and durations handled) and getters are never run. `JSON.stringify` uses it.\n */\n toJSON: () => ExplanationJSON\n}\n\nexport interface CompileOptions<E extends Type = Type> {\n /** The type the expression must produce; also types the program's result. */\n readonly expect?: E | undefined\n}\n\nexport interface FunctionInfo {\n readonly name: string\n readonly description: string\n readonly host: boolean\n readonly async: boolean\n /** Whether a host function receives a {@link HostCall} (declared `call: true`). */\n readonly call: boolean\n /** Steps charged per call, when the host function declares a `cost` (otherwise 32). */\n readonly cost?: number\n readonly signatures: readonly {\n readonly params: readonly Type[]\n readonly required: number\n readonly rest?: Type\n readonly returns: Type\n }[]\n}\n\n/** An environment. A bare `Environment` accepts any context, like a bare `Program`. */\n// oxlint-disable-next-line typescript/no-explicit-any -- the erased context type every typed environment is assignable to\nexport interface Environment<Ctx = any> {\n /** Declared variables, or undefined for an open environment. */\n readonly variables: Readonly<Record<string, Type>> | undefined\n readonly strict: boolean\n /** Parses without checking. */\n parse: (source: string) => Node\n /**\n * Parses and checks, reporting every finding instead of throwing. When `ok`,\n * `program` is the compiled expression, so an editor needs only this call.\n */\n check: <E extends Type = AnyType>(\n source: string,\n options?: CompileOptions<E>,\n ) => CheckResult<Ctx, Infer<E>>\n /**\n * Parses, checks, and compiles. Throws BonsaiSyntaxError / BonsaiCheckError /\n * BonsaiLimitError. Cached: the same source and expected type return the same program.\n */\n compile: <E extends Type = AnyType>(\n source: string,\n options?: CompileOptions<E>,\n ) => Program<Ctx, Infer<E>>\n /**\n * Compiles (cached) and partially evaluates; see Program.partial. Throws for\n * syntax, check, and limit errors, and a TypeError or RangeError for invalid options.\n * `R` is an unchecked type assertion, as for evaluate().\n */\n partial: <R = unknown>(\n source: string,\n known: PartialData<Ctx> & object,\n options?: PartialOptions,\n ) => PartialResult<Ctx, R>\n /**\n * Compiles (cached) and evaluates asynchronously. `R` is an unchecked type\n * assertion on the result, like a cast; for a checked result type, use\n * `compile(source, { expect })` and evaluate the program.\n */\n evaluate: <R = unknown>(source: string, ...args: Args<Ctx>) => Promise<R>\n /**\n * Compiles (cached) and evaluates synchronously. `R` is an unchecked type\n * assertion, as for evaluate().\n */\n evaluateSync: <R = unknown>(source: string, ...args: Args<Ctx>) => R\n /**\n * Compiles (cached) and explains; see Program.explain. Rejects for syntax and\n * check errors and parse limits, and with a TypeError or RangeError for invalid options.\n * `R` is an unchecked type assertion, as for evaluate().\n */\n explain: <R = unknown>(source: string, ...args: ExplainArgs<Ctx>) => Promise<Explanation<R>>\n /**\n * Compiles (cached) and explains synchronously. Throws for syntax and check\n * errors and parse limits, and a TypeError or RangeError for invalid options.\n * `R` is an unchecked type assertion, as for evaluate().\n */\n explainSync: <R = unknown>(source: string, ...args: ExplainArgs<Ctx>) => Explanation<R>\n /** Looks up a function (host or built-in). */\n describeFunction: (name: string) => FunctionInfo | undefined\n /** Every callable function, host functions first. */\n listFunctions: () => readonly FunctionInfo[]\n /**\n * A new environment with more variables, functions, or libraries. A\n * variable or function declared again replaces the earlier one.\n */\n extend: <\n const V2 extends Readonly<Record<string, Type>> = NoVariables,\n const L2 extends readonly Library[] = [],\n const S2 extends boolean | undefined = undefined,\n >(\n options: EnvironmentOptions<V2, L2> & { readonly strict?: S2 },\n ) => Environment<Extended<Ctx, V2, L2, S2>>\n}\n\n/**\n * A program from `bonsai-js/lite`: a {@link Program} without `explain`,\n * `explainSync`, and `partial`. Every Program is also a LiteProgram, so code\n * that only evaluates can accept either.\n */\n// oxlint-disable-next-line typescript/no-explicit-any -- the same erased context as a bare Program\nexport type LiteProgram<Ctx = any, R = unknown> = Omit<\n Program<Ctx, R>,\n 'explain' | 'explainSync' | 'partial'\n>\n\n/** What a `bonsai-js/lite` environment's check() found. */\n// oxlint-disable-next-line typescript/no-explicit-any -- the same erased context as a bare Program\nexport type LiteCheckResult<Ctx = any, R = unknown> = Checked<LiteProgram<Ctx, R>>\n\n/**\n * An environment from `bonsai-js/lite`: an {@link Environment} without\n * `explain`, `explainSync`, and `partial`, whose programs are LitePrograms.\n * Every Environment is also a LiteEnvironment.\n */\n// oxlint-disable-next-line typescript/no-explicit-any -- the same erased context as a bare Environment\nexport interface LiteEnvironment<Ctx = any> extends Omit<\n Environment<Ctx>,\n 'check' | 'compile' | 'extend' | 'explain' | 'explainSync' | 'partial'\n> {\n /** See Environment.check. */\n check: <E extends Type = AnyType>(\n source: string,\n options?: CompileOptions<E>,\n ) => LiteCheckResult<Ctx, Infer<E>>\n /** See Environment.compile. */\n compile: <E extends Type = AnyType>(\n source: string,\n options?: CompileOptions<E>,\n ) => LiteProgram<Ctx, Infer<E>>\n /** See Environment.extend. */\n extend: <\n const V2 extends Readonly<Record<string, Type>> = NoVariables,\n const L2 extends readonly Library[] = [],\n const S2 extends boolean | undefined = undefined,\n >(\n options: EnvironmentOptions<V2, L2> & { readonly strict?: S2 },\n ) => LiteEnvironment<Extended<Ctx, V2, L2, S2>>\n}\n\n/**\n * The context type of declared variables `V`. An open environment (no\n * variables) accepts any object, including values typed by an interface, and\n * so does a schema only known at run time (`Record<string, Type>`), whose\n * variables are not known statically.\n */\ntype ContextOf<V> = [keyof V] extends [never]\n ? object\n : string extends keyof V\n ? MoreKeys\n : InferVariables<V>\n\n// === implementation ===\n\n/** Internals shared with the language service (not public API). */\nexport interface EnvironmentInternals {\n readonly checkEnv: CheckEnv\n readonly parseLimits: ParseLimits\n}\n\nconst internals = new WeakMap<object, EnvironmentInternals>()\n\nexport function internalsOf(env: object): EnvironmentInternals {\n const found = internals.get(env)\n if (found === undefined) throw new TypeError('Not a Bonsai environment')\n return found\n}\n\n/** Compiled programs kept per environment unless `cacheSize` says otherwise. */\nconst DEFAULT_CACHE_SIZE = 256\n\n/** An environment's settings (not public API). */\nexport interface Settings {\n readonly variables: Readonly<Record<string, Type>> | undefined\n /** The explicit `strict` option, if one was given (here or in a base environment). */\n readonly strictOption: boolean | undefined\n readonly strict: boolean\n readonly host: ReadonlyMap<string, FunctionDef>\n /** The built-ins available (host functions of the same name replace them). */\n readonly builtins: ReadonlyMap<string, FunctionDef>\n readonly parseLimits: ParseLimits\n readonly runtimeLimits: RuntimeLimits\n readonly timeout: number\n readonly cacheSize: number\n readonly clock: () => Date\n readonly validateContext: boolean\n /** Explaining and partial evaluation, when the entry point provides them. */\n readonly features: Features | undefined\n}\n\n/**\n * What a program shares with the features that extend it (not public API):\n * its source, analysis, and settings, and how it prepares, checks, and settles\n * an evaluation.\n */\nexport interface ProgramCore<R> {\n readonly source: string\n readonly analysis: Analysis\n readonly expect: Type | undefined\n readonly settings: Settings\n readonly checkEnv: CheckEnv\n readonly compileOptions: CompilerOptions\n /** Set when the program is a partial-evaluation residual. */\n readonly residualOf: ResidualOf | undefined\n prepare: (\n state: State,\n ctx: Record<string, unknown>,\n limits: EvaluationLimits,\n locals: number,\n ) => void\n checked: (result: unknown, state: State) => void\n settle: (result: R) => R\n /** Compiles a residual of this program and returns how it runs. */\n residual: (\n analysis: Analysis,\n constants: ReadonlyMap<string, unknown>,\n residualOf: ResidualOf,\n ) => ResidualRunner\n}\n\n/** The program methods a feature set provides (not public API). */\nexport interface ProgramFeatures<Ctx, R> {\n explainSync: (\n context: unknown,\n options: ExplainOptions | undefined,\n promised?: boolean,\n ) => Explanation<R>\n explainAsync: (context: unknown, options: ExplainOptions | undefined) => Promise<Explanation<R>>\n partial: (program: object, known: object, options: unknown) => PartialResult<Ctx, R>\n}\n\n/**\n * Explaining and partial evaluation, supplied by the entry point (not public\n * API): kept out of this module so a bundle that only checks and evaluates\n * does not carry them.\n */\nexport interface Features {\n program: <Ctx, R>(core: ProgramCore<R>) => ProgramFeatures<Ctx, R>\n}\n\n/** What a residual keeps from its partial evaluation. */\nexport interface ResidualOf {\n /** Its printed source: the text of its explanations. */\n readonly source: string\n /** Whether `call: true` host functions read the context it is given. */\n readonly readsContext: boolean\n /** The variables known to partial(), which a context read whole must hold. */\n readonly knownRoots: readonly string[]\n /** The context paths it reads: all a context it does not read whole needs. */\n readonly dependsOn: readonly string[]\n /** Size and depth of the lists and maps partial() built into its bindings. */\n readonly shapes: WeakMap<object, number> | undefined\n}\n\n/** How a partial-evaluation residual runs and explains, with the caller's context. */\nexport interface ResidualRunner {\n /** Whether the residual calls an async host function. */\n async: boolean\n runSync: (ctx: unknown, options: unknown) => unknown\n runAsync: (ctx: unknown, options: unknown) => Promise<unknown>\n explainSync: (ctx: unknown, options: unknown) => Explanation\n explainAsync: (ctx: unknown, options: unknown) => Promise<Explanation>\n}\n\nfunction toDef(name: string, host: HostFunction): FunctionDef {\n // `has` and `try` read as syntax, so a function with either name could never be called.\n if (!isName(name) || name === 'has' || name === 'try') {\n throw new TypeError(`Invalid function name \"${name}\"`)\n }\n assertHostSpec(host, `Function \"${name}\"`)\n const run = host.run as (...args: unknown[]) => unknown\n const count = host.params.length\n host.params.forEach((param, index) => {\n if (index >= (host.required ?? count) && !isNullable(param)) {\n throw new TypeError(\n `Optional parameter ${index + 1} of \"${name}\" receives null when omitted; declare it as t.optional(...)`,\n )\n }\n })\n return Object.freeze({\n name,\n description: host.description ?? '',\n host: true,\n async: host.async === true,\n call: host.call === true,\n ...(host.cost === undefined ? {} : { cost: host.cost }),\n overloads: [\n overload(\n host.params,\n host.returns,\n (args) => {\n // Missing optional arguments arrive as null.\n const offset = host.call === true ? 1 : 0\n while (args.length < count + offset) args.push(null)\n return run(...args)\n },\n {\n required: host.required ?? count,\n ...(host.rest === undefined ? {} : { rest: host.rest }),\n },\n ),\n ],\n })\n}\n\nfunction mergeFunctions(\n base: ReadonlyMap<string, FunctionDef>,\n options: EnvironmentOptions,\n): Map<string, FunctionDef> {\n const out = new Map(base)\n const added = new Map<string, string>()\n const add = (name: string, def: HostFunction, origin: string): void => {\n const previous = added.get(name)\n if (previous !== undefined) {\n throw new TypeError(`Function \"${name}\" is defined by both ${previous} and ${origin}`)\n }\n added.set(name, origin)\n out.set(name, toDef(name, def))\n }\n for (const library of options.libraries ?? []) {\n for (const [name, def] of Object.entries(library.functions ?? {}))\n add(name, def, `library \"${library.name}\"`)\n }\n for (const [name, def] of Object.entries(options.functions ?? {}))\n add(name, def, 'the functions option')\n return out\n}\n\nfunction mergeVariables(\n base: Readonly<Record<string, Type>> | undefined,\n options: EnvironmentOptions,\n): Readonly<Record<string, Type>> | undefined {\n // Declaring `variables` (even as {}) makes the environment declared, and so strict by default.\n let out: Record<string, Type> | undefined =\n base === undefined && options.variables === undefined ? undefined : { ...base }\n const added = new Map<string, string>()\n const add = (name: string, type: Type, origin: string): void => {\n if (!isName(name)) {\n throw new TypeError(`Invalid variable name \"${name}\" (in ${origin})`)\n }\n const previous = added.get(name)\n if (previous !== undefined) {\n throw new TypeError(`Variable \"${name}\" is declared by both ${previous} and ${origin}`)\n }\n added.set(name, origin)\n assertType(type, `Variable \"${name}\"`)\n out ??= {}\n out[name] = type\n }\n for (const library of options.libraries ?? []) {\n for (const [k, v] of Object.entries(library.variables ?? {}))\n add(k, v, `library \"${library.name}\"`)\n }\n for (const [k, v] of Object.entries(options.variables ?? {})) add(k, v, 'the variables option')\n return out === undefined ? undefined : Object.freeze(out)\n}\n\nconst OPTION_KEYS = new Set([\n 'variables',\n 'strict',\n 'functions',\n 'libraries',\n 'limits',\n 'cacheSize',\n 'clock',\n 'validateContext',\n 'builtins',\n])\nconst LIMIT_KEYS: ReadonlySet<string> = new Set([\n ...Object.keys(DEFAULT_PARSE_LIMITS),\n ...Object.keys(DEFAULT_RUNTIME_LIMITS),\n 'timeout',\n])\nconst LIBRARY_KEYS = new Set(['name', 'functions', 'variables'])\n\n/** Environment options come from configuration: mistakes there are programming errors. */\nfunction assertOptions(options: unknown): asserts options is EnvironmentOptions {\n assertKeys(options, OPTION_KEYS, 'Options')\n const o = options as Record<string, unknown>\n if (o.limits !== undefined) assertKeys(o.limits, LIMIT_KEYS, 'Limits')\n if (o.variables !== undefined && !isRecord(o.variables))\n throw new TypeError('variables must be an object of types')\n if (o.functions !== undefined && !isRecord(o.functions))\n throw new TypeError('functions must be an object of fn() declarations')\n if (o.libraries !== undefined) {\n if (!Array.isArray(o.libraries)) throw new TypeError('libraries must be an array')\n const names = new Set<string>()\n for (const library of o.libraries) {\n assertKeys(library, LIBRARY_KEYS, 'Library')\n const l = library as Record<string, unknown>\n if (typeof l.name !== 'string' || l.name === '') throw new TypeError('A library needs a name')\n if (names.has(l.name)) throw new TypeError(`Library \"${l.name}\" is listed twice`)\n names.add(l.name)\n if (l.functions !== undefined && !isRecord(l.functions))\n throw new TypeError(`functions of library \"${l.name}\" must be an object`)\n if (l.variables !== undefined && !isRecord(l.variables))\n throw new TypeError(`variables of library \"${l.name}\" must be an object`)\n }\n }\n for (const flag of ['strict', 'validateContext'] as const) {\n if (o[flag] !== undefined && typeof o[flag] !== 'boolean')\n throw new TypeError(`${flag} must be a boolean`)\n }\n if (o.clock !== undefined && typeof o.clock !== 'function')\n throw new TypeError('clock must be a function returning a Date')\n}\n\ntype Numbers = Readonly<Record<string, number>>\n\n/**\n * The limits in `defaults` (parse or runtime), overridden by `limits` over\n * `current`. 0 turns `maxSteps` off; every other limit must be at least 1.\n */\nfunction pickLimits(\n defaults: object,\n current: object,\n limits: Readonly<Record<string, unknown>>,\n): Numbers {\n const base = current as Numbers\n return Object.freeze(\n Object.fromEntries(\n Object.keys(defaults).map((name) => {\n const value = numberOption(\n `Limit \"${name}\"`,\n limits[name],\n base[name],\n name === 'maxSteps' ? 0 : 1,\n )\n const cap = DEPTH_CAPS[name]\n if (cap !== undefined && value > cap)\n throw new RangeError(`Limit \"${name}\" must be at most ${cap}`)\n return [name, value]\n }),\n ),\n )\n}\n\n/** Depth limits are capped: deeper nesting would run out of call stack. */\nconst DEPTH_CAPS: Readonly<Record<string, number>> = {\n maxDepth: MAX_DEPTH_LIMIT,\n maxValueDepth: MAX_VALUE_DEPTH_LIMIT,\n}\n\n/**\n * Settings from options, over a base (extend) or, for a new environment or\n * runtime, over the entry point's built-ins.\n */\nexport function settingsFrom(\n base: Settings | undefined,\n options: unknown,\n builtins: ReadonlyMap<string, FunctionDef> = new Map(),\n): Settings {\n assertOptions(options)\n const limits = (options.limits ?? {}) as Readonly<Record<string, unknown>>\n const variables = mergeVariables(base?.variables, options)\n const strictOption = options.strict ?? base?.strictOption\n return {\n variables,\n strictOption,\n strict: strictOption ?? variables !== undefined,\n host: mergeFunctions(base?.host ?? new Map(), options),\n builtins: builtinsOption(\n options.builtins,\n base?.builtins ?? (options.builtins === undefined ? builtins : new Map()),\n ),\n parseLimits: pickLimits(\n DEFAULT_PARSE_LIMITS,\n base?.parseLimits ?? DEFAULT_PARSE_LIMITS,\n limits,\n ) as unknown as ParseLimits,\n runtimeLimits: pickLimits(\n DEFAULT_RUNTIME_LIMITS,\n base?.runtimeLimits ?? DEFAULT_RUNTIME_LIMITS,\n limits,\n ) as unknown as RuntimeLimits,\n timeout: timeoutOption('Limit \"timeout\"', limits.timeout, base?.timeout ?? 0),\n cacheSize: numberOption(\n 'cacheSize',\n options.cacheSize,\n base?.cacheSize ?? DEFAULT_CACHE_SIZE,\n 0,\n ),\n clock: options.clock === undefined ? (base?.clock ?? systemClock) : checkedClock(options.clock),\n validateContext: options.validateContext ?? base?.validateContext ?? false,\n features: base?.features,\n }\n}\n\n/**\n * Source characters the program cache holds in total, and the longest source it\n * keeps. A compiled program can retain a hundred times its source in memory, so\n * the cache is bounded by size as well as by count.\n */\nconst CACHE_CHARS = 262_144\nconst CACHE_MAX_SOURCE = 16_384\n\n/**\n * Approximately least recently used (\"second chance\"): a hit only marks its\n * entry, so the hot path is one lookup. When the cache is full, the oldest\n * entry is evicted, unless it was used since it last reached the front (or is\n * the entry being added), in which case it moves to the back unmarked.\n */\nexport class ProgramCache<V> {\n private readonly map = new Map<string, { readonly value: V; used: boolean }>()\n private readonly size: number\n private chars = 0\n\n constructor(size: number) {\n this.size = size\n }\n\n get(key: string): V | undefined {\n const slot = this.map.get(key)\n if (slot === undefined) return undefined\n slot.used = true\n return slot.value\n }\n\n set(key: string, value: V): void {\n if (this.size === 0 || key.length > CACHE_MAX_SOURCE) return\n if (this.map.delete(key)) this.chars -= key.length\n this.map.set(key, { value, used: false })\n this.chars += key.length\n while (this.map.size > this.size || this.chars > CACHE_CHARS) {\n const [oldest, slot] = this.map.entries().next().value as [\n string,\n { readonly value: V; used: boolean },\n ]\n this.map.delete(oldest)\n if (slot.used || oldest === key) {\n slot.used = false\n this.map.set(oldest, slot)\n } else {\n this.chars -= oldest.length\n }\n }\n }\n}\n\nconst NO_DIAGNOSTICS: readonly Diagnostic[] = Object.freeze([])\n\n/**\n * What check() found. `ok`, `type`, and `diagnostics` are the JSON form; the\n * tree is read on demand (a prototype getter), so an editor checking on every\n * keystroke pays only for what it uses.\n */\nclass CheckFailure {\n readonly ok: boolean = false\n readonly type: Type | undefined\n readonly diagnostics: readonly Diagnostic[]\n /** The inferred type of a node of `ast`, or undefined for another tree's node. */\n readonly typeOf: (node: Node) => Type | undefined\n readonly #analysis: Analysis | undefined\n\n constructor(type: Type | undefined, diagnostics: readonly Diagnostic[], analysis?: Analysis) {\n this.type = type\n this.diagnostics = diagnostics\n this.#analysis = analysis\n this.typeOf = (node) => {\n const found = analysis?.types.get(node)\n return found === undefined ? undefined : deepFreeze(found)\n }\n }\n\n get ast(): Node | undefined {\n return this.#analysis === undefined ? undefined : deepFreeze(this.#analysis.root)\n }\n}\n\n/** A check that passed: also the compiled program, made the first time it is read. */\nclass CheckSuccess extends CheckFailure {\n override readonly ok: boolean = true\n readonly #program: () => unknown\n\n constructor(\n type: Type,\n diagnostics: readonly Diagnostic[],\n analysis: Analysis,\n program: () => unknown,\n ) {\n super(type, diagnostics, analysis)\n this.#program = program\n }\n\n get program(): unknown {\n return this.#program()\n }\n}\n\n/** Freezes a syntax tree (or any tree of plain objects and arrays) in place, without recursion. */\nfunction deepFreeze<T>(root: T): T {\n // Visits frozen objects too: a frozen type can hold a type the checker built\n // unfrozen (and shares between analyses).\n const seen = new Set<object>()\n const pending: unknown[] = [root]\n while (pending.length > 0) {\n const value = pending.pop()\n if (typeof value !== 'object' || value === null || seen.has(value)) continue\n seen.add(value)\n Object.freeze(value)\n for (const child of Object.values(value)) pending.push(child)\n }\n return root\n}\n\nconst systemClock = (): Date => new Date()\n\n/** A host clock whose results are checked: now() must be a valid timestamp. */\nfunction checkedClock(clock: () => Date): () => Date {\n return () => {\n let value: unknown\n try {\n value = clock()\n } catch (error) {\n throw raised(new BonsaiRuntimeError('HOST_ERROR', 'The clock failed', { cause: error }))\n }\n if (!(value instanceof Date) || Number.isNaN(Date.prototype.getTime.call(value))) {\n throw raised(\n new BonsaiRuntimeError(\n 'HOST_CONTRACT',\n 'The clock must return a valid Date (for example () => new Date())',\n ),\n )\n }\n return value\n }\n}\n\n/** Whether a type has an exact map type anywhere in it. */\nfunction holdsExact(type: Type): boolean {\n const stack: Type[] = [type]\n const seen = new Set<Type>()\n while (stack.length > 0) {\n const next = stack.pop() as Type\n if (seen.has(next)) continue\n seen.add(next)\n if (isExact(next)) return true\n if (next.kind === 'list') stack.push(next.element)\n else if (next.kind === 'union') stack.push(...next.types)\n else if (next.kind === 'map') {\n stack.push(...Object.values(next.fields))\n if (next.rest !== undefined) stack.push(next.rest)\n }\n }\n return false\n}\n\n/** Reads compile(), check(), and the runtime's load() options: only `expect`, which must be a type built with t. Returns a frozen copy of it. */\nexport function expectOption(options: unknown, what: 'Compile' | 'Load'): Type | undefined {\n if (options === undefined) return undefined\n if (typeof options !== 'object' || options === null || Array.isArray(options))\n throw new TypeError(`${what} options must be an object`)\n let expect: unknown\n try {\n for (const key of Object.keys(options)) {\n if (key !== 'expect')\n throw new TypeError(\n `Unknown ${what.toLowerCase()} option key \"${key}\" (expected one of: expect)`,\n )\n }\n expect = (options as { expect?: unknown }).expect\n } catch (error) {\n if (error instanceof TypeError) throw error\n throw new TypeError(`${what} options could not be read`, { cause: error })\n }\n if (expect === undefined) return undefined\n // Checked, copied, and the copy checked: the program and its cache key use\n // one private copy, so no getter, toJSON, or later change can split them.\n assertType(expect, `${what} option \"expect\"`)\n const own = typeData(expect)\n if (own !== expect) assertType(own, `${what} option \"expect\"`)\n return own\n}\n\nfunction createEnvironment<Ctx>(settings: Settings): Environment<Ctx> {\n const checkEnv: CheckEnv = {\n variables: settings.variables,\n strict: settings.strict,\n lookup: (name) => settings.host.get(name) ?? settings.builtins.get(name),\n *functionNames() {\n yield* settings.host.keys()\n for (const name of settings.builtins.keys()) if (!settings.host.has(name)) yield name\n },\n }\n // Each entry records the source and expected type it was compiled for: a key\n // alone could collide (a comment may end a source with what looks like a type).\n const cache = new ProgramCache<{\n readonly program: Program<Ctx>\n readonly source: string\n readonly expect: string | undefined\n }>(settings.cacheSize)\n\n function parseSource(source: string): Node {\n if (typeof source !== 'string') throw new TypeError('An expression must be a string')\n return parse(source, settings.parseLimits)\n }\n\n function analyzeSource(source: string, expect: Type | undefined): Analysis {\n const root = parseSource(source)\n try {\n return analyze(root, checkEnv, { expected: expect })\n } catch (error) {\n // The checker has no source text; attach it so the error can show where.\n if (error instanceof BonsaiLimitError && error.source === undefined) {\n throw new BonsaiLimitError(error.code, error.message, {\n source,\n ...(error.span === undefined ? {} : { span: error.span }),\n limit: error.limit ?? null,\n })\n }\n throw error\n }\n }\n\n function makeProgram<R>(source: string, analysis: Analysis, expect?: Type): Program<Ctx, R>\n function makeProgram(\n source: string,\n analysis: Analysis,\n expect: Type | undefined,\n constants: ReadonlyMap<string, unknown>,\n residualOf: ResidualOf,\n ): ResidualRunner\n function makeProgram<R>(\n source: string,\n analysis: Analysis,\n expect?: Type,\n constants?: ReadonlyMap<string, unknown>,\n residualOf?: ResidualOf,\n ): Program<Ctx, R> | ResidualRunner {\n // Residuals are not warmed: partial() runs often, and a zone it writes into\n // the residual as text loads on first use (the shared data is already loaded).\n if (residualOf === undefined) warmZones(analysis)\n // When the checker cannot prove the result matches `expect` (part of it is\n // `any`, or an open object may hold an unlisted key), it is checked at run\n // time, so the declared result type holds.\n const guard = expect !== undefined && analysis.checkResult ? expect : undefined\n const { prepare, checked, settle, runSync, runAsync, compileOptions } = programRunner<R>({\n source,\n analysis,\n guard,\n settings,\n constants,\n residualOf,\n })\n\n const features = settings.features?.program<Ctx, R>({\n source,\n analysis,\n expect,\n settings,\n checkEnv,\n compileOptions,\n residualOf,\n prepare,\n checked,\n settle,\n residual: (residualAnalysis, residualConstants, residualFrom) =>\n makeProgram(source, residualAnalysis, expect, residualConstants, residualFrom),\n })\n\n if (residualOf !== undefined) {\n // Only partial() makes residuals, so the features that made this one are present.\n const made = features as ProgramFeatures<Ctx, R>\n // A residual is used only through its runner, so no Program is built for\n // it (freezing its type and references would be work on every partial());\n // its tree is the result's `ast`, and compiles lazily, so it is frozen.\n deepFreeze(analysis.root)\n const runner: ResidualRunner = {\n async: analysis.async,\n runSync: (ctx, options) => runSync(ctx, options as EvaluateOptions | undefined),\n runAsync: (ctx, options) => runAsync(ctx, options as EvaluateOptions | undefined),\n explainSync: (ctx, options) => made.explainSync(ctx, options as ExplainOptions | undefined),\n explainAsync: (ctx, options) =>\n made.explainAsync(ctx, options as ExplainOptions | undefined),\n }\n return runner\n }\n // Programs are shared: the tree compiles lazily, so it must not change afterwards.\n // A lite program is typed as a LiteProgram by its entry point.\n const program = Object.freeze({\n // Without features (bonsai-js/lite), a program has no explain or partial.\n ...(features === undefined\n ? {}\n : {\n explain: (...args: ExplainArgs<Ctx>) => features.explainAsync(args[0], args[1]),\n explainSync: (...args: ExplainArgs<Ctx>) => features.explainSync(args[0], args[1]),\n partial: (known: object, options?: PartialOptions) =>\n features.partial(program, known, options),\n }),\n source,\n ast: deepFreeze(analysis.root),\n type: deepFreeze(analysis.type),\n async: analysis.async,\n warnings: deepFreeze(\n locate(\n source,\n analysis.diagnostics.filter((d) => d.severity === 'warning'),\n ),\n ),\n references: deepFreeze(analysis.references),\n evaluate: (...args: Args<Ctx>) => runAsync(args[0], args[1]),\n evaluateSync: (...args: Args<Ctx>) => runSync(args[0], args[1]),\n })\n recordDeclared(program, settings.variables)\n recordCompiled(program, {\n source,\n analysis,\n expect,\n lookup: checkEnv.lookup,\n variables: settings.variables,\n })\n return program as Program<Ctx, R>\n }\n\n function compile<R>(source: string, expect: Type | undefined): Program<Ctx, R> {\n const analysis = analyzeSource(source, expect)\n const errors = analysis.diagnostics.filter((d) => d.severity === 'error')\n if (errors.length > 0) throw new BonsaiCheckError(source, errors)\n return makeProgram<R>(source, analysis, expect)\n }\n\n /**\n * compile(), through the program cache: programs are immutable, so the same\n * source with an equal expected type shares one. `expect` is expectOption's\n * plain copy, so its JSON is the type the program is checked against.\n */\n function cachedCompile<R>(source: string, expect: Type | undefined): Program<Ctx, R> {\n if (typeof source !== 'string') throw new TypeError('An expression must be a string')\n // An exact map type (a checked program's inferred type passed back as\n // `expect`) checks differently from a declared one with the same JSON.\n if (expect !== undefined && holdsExact(expect)) return compile<R>(source, expect)\n const expectKey = expect === undefined ? undefined : JSON.stringify(expect)\n const key = expectKey === undefined ? source : `${source}\\u0000${expectKey}`\n const entry = cache.get(key)\n if (entry !== undefined && entry.source === source && entry.expect === expectKey)\n return entry.program as Program<Ctx, R>\n const program = compile<R>(source, expect)\n cache.set(key, { program, source, expect: expectKey })\n return program\n }\n\n function cached(source: string): Program<Ctx> {\n return cachedCompile(source, undefined)\n }\n\n function info(def: FunctionDef): FunctionInfo {\n return {\n name: def.name,\n description: descriptionOf(def),\n host: def.host === true,\n async: def.async === true,\n call: def.call === true,\n ...(def.cost === undefined ? {} : { cost: def.cost }),\n signatures: def.overloads.map((o) => ({\n params: o.params,\n required: o.required ?? o.params.length,\n returns: o.result,\n ...(o.rest === undefined ? {} : { rest: o.rest }),\n })),\n }\n }\n\n // A lite environment is typed as a LiteEnvironment by its entry point.\n const env = Object.freeze({\n variables: settings.variables,\n strict: settings.strict,\n parse: parseSource,\n check<E extends Type = AnyType>(\n source: string,\n options?: CompileOptions<E>,\n ): CheckResult<Ctx, Infer<E>> {\n const expect = expectOption(options, 'Compile')\n let analysis: Analysis\n try {\n analysis = analyzeSource(source, expect)\n } catch (error) {\n if (!(error instanceof BonsaiError)) throw error\n const diagnostics = locate(source, [\n {\n code: error.code === 'SYNTAX' ? 'SYNTAX' : 'LIMIT',\n message: error.message,\n severity: 'error',\n start: error.span?.start ?? 0,\n end: error.span?.end ?? source.length,\n },\n ])\n return Object.freeze(new CheckFailure(undefined, diagnostics, undefined)) as CheckResult<\n Ctx,\n Infer<E>\n >\n }\n const diagnostics =\n analysis.diagnostics.length === 0 ? NO_DIAGNOSTICS : locate(source, analysis.diagnostics)\n const type = deepFreeze(analysis.type)\n if (analysis.diagnostics.some((d) => d.severity === 'error'))\n return Object.freeze(new CheckFailure(type, diagnostics, analysis)) as CheckResult<\n Ctx,\n Infer<E>\n >\n let program: Program<Ctx, Infer<E>> | undefined\n return Object.freeze(\n new CheckSuccess(\n type,\n diagnostics,\n analysis,\n () => (program ??= makeProgram<Infer<E>>(source, analysis, expect)),\n ),\n ) as CheckResult<Ctx, Infer<E>>\n },\n compile: <E extends Type = AnyType>(source: string, options?: CompileOptions<E>) =>\n cachedCompile<Infer<E>>(source, expectOption(options, 'Compile')),\n // Without features (bonsai-js/lite), an environment has no partial or explain.\n ...(settings.features === undefined\n ? {}\n : {\n partial: <R>(\n source: string,\n known: PartialData<Ctx> & object,\n options?: PartialOptions,\n ) => cached(source).partial(known, options) as PartialResult<Ctx, R>,\n }),\n evaluate<R>(source: string, ...args: Args<Ctx>): Promise<R> {\n try {\n return cached(source).evaluate(...args) as Promise<R>\n } catch (error) {\n return Promise.reject(error instanceof Error ? error : new Error(String(error)))\n }\n },\n evaluateSync: <R>(source: string, ...args: Args<Ctx>) =>\n cached(source).evaluateSync(...args) as R,\n ...(settings.features === undefined\n ? {}\n : {\n explain<R>(source: string, ...args: ExplainArgs<Ctx>): Promise<Explanation<R>> {\n try {\n return cached(source).explain(...args) as Promise<Explanation<R>>\n } catch (error) {\n return Promise.reject(error instanceof Error ? error : new Error(String(error)))\n }\n },\n explainSync: <R>(source: string, ...args: ExplainArgs<Ctx>) =>\n cached(source).explainSync(...args) as Explanation<R>,\n }),\n describeFunction(name: string): FunctionInfo | undefined {\n const def = checkEnv.lookup(name)\n return def === undefined ? undefined : info(def)\n },\n listFunctions(): FunctionInfo[] {\n return [...checkEnv.functionNames()].map((name) => info(checkEnv.lookup(name) as FunctionDef))\n },\n extend<\n V2 extends Readonly<Record<string, Type>>,\n L2 extends readonly Library[],\n S2 extends boolean | undefined,\n >(options: EnvironmentOptions<V2, L2> & { readonly strict?: S2 }) {\n return createEnvironment<Extended<Ctx, V2, L2, S2>>(settingsFrom(settings, options))\n },\n })\n internals.set(env, { checkEnv, parseLimits: settings.parseLimits })\n return env as Environment<Ctx>\n}\n\n/**\n * An environment from `bonsai()` options, with the features its entry point\n * provides (not public API): `bonsai-js` passes explaining and partial\n * evaluation, `bonsai-js/lite` passes none.\n */\nexport function environmentWith<Ctx>(\n features: Features | undefined,\n options: unknown,\n): Environment<Ctx> {\n return createEnvironment<Ctx>({ ...settingsFrom(undefined, options, BUILTINS), features })\n}\n"],"mappings":"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"}
package/dist/errors.d.mts CHANGED
@@ -1,6 +1,6 @@
1
1
  //#region src/errors.d.ts
2
2
  /** Stable machine-readable error codes. Adding a code is a minor change; renaming one is major. */
3
- export type ErrorCode = 'SYNTAX' | 'CHECK' | 'SOURCE_TOO_LONG' | 'TOO_DEEP' | 'TOO_MANY_NODES' | 'TOO_COMPLEX' | 'STEP_LIMIT' | 'STRING_LIMIT' | 'PATTERN_LIMIT' | 'LIST_LIMIT' | 'VALUE_DEPTH_LIMIT' | 'TIMEOUT' | 'ABORTED' | 'TYPE_ERROR' | 'NO_OVERLOAD' | 'NULL_RECEIVER' | 'DIVISION_BY_ZERO' | 'NON_FINITE' | 'BLOCKED_PROPERTY' | 'INVALID_ARGUMENT' | 'ASYNC_IN_SYNC' | 'HOST_ERROR' | 'HOST_CONTRACT' | 'INVALID_CONTEXT' | 'UNTRANSLATABLE';
3
+ export type ErrorCode = 'SYNTAX' | 'CHECK' | 'SOURCE_TOO_LONG' | 'TOO_DEEP' | 'TOO_MANY_NODES' | 'TOO_COMPLEX' | 'STEP_LIMIT' | 'STRING_LIMIT' | 'PATTERN_LIMIT' | 'LIST_LIMIT' | 'VALUE_DEPTH_LIMIT' | 'TIMEOUT' | 'ABORTED' | 'TYPE_ERROR' | 'NO_OVERLOAD' | 'NULL_RECEIVER' | 'DIVISION_BY_ZERO' | 'NON_FINITE' | 'BLOCKED_PROPERTY' | 'INVALID_ARGUMENT' | 'ASYNC_IN_SYNC' | 'HOST_ERROR' | 'HOST_CONTRACT' | 'INVALID_CONTEXT' | 'UNTRANSLATABLE' | 'ARTIFACT';
4
4
  export interface Span {
5
5
  readonly start: number;
6
6
  readonly end: number;
@@ -24,6 +24,8 @@ export interface BonsaiErrorJSON {
24
24
  readonly limit?: LimitName;
25
25
  /** For a check error: every finding, without the `formatted` code frame. */
26
26
  readonly diagnostics?: readonly DiagnosticJSON[];
27
+ /** For an artifact error: why the artifact could not be loaded. */
28
+ readonly reason?: ArtifactProblem;
27
29
  }
28
30
  /** Options for constructing a {@link BonsaiError}. */
29
31
  export interface ErrorInit {
@@ -35,7 +37,7 @@ export interface ErrorInit {
35
37
  * The `name` of every Bonsai error class. Each class sets its name as a
36
38
  * literal, so a minified bundle keeps it.
37
39
  */
38
- export type BonsaiErrorName = 'BonsaiError' | 'BonsaiSyntaxError' | 'BonsaiLimitError' | 'BonsaiRuntimeError' | 'BonsaiCheckError' | 'BonsaiTranslationError';
40
+ export type BonsaiErrorName = 'BonsaiError' | 'BonsaiSyntaxError' | 'BonsaiLimitError' | 'BonsaiRuntimeError' | 'BonsaiCheckError' | 'BonsaiTranslationError' | 'BonsaiArtifactError';
39
41
  /** Base class of every error Bonsai throws. */
40
42
  export declare class BonsaiError extends Error {
41
43
  name: BonsaiErrorName;
@@ -137,6 +139,23 @@ export declare class BonsaiTranslationError extends BonsaiError {
137
139
  /** @internal */
138
140
  constructor(message: string, source: string, span?: Span, cause?: unknown);
139
141
  }
142
+ /**
143
+ * Why `bonsai-js/runtime` refused an artifact. `digest`: it was made for other
144
+ * definitions (a fresh artifact from the producer may load). `version`,
145
+ * `syntax`, `function`, `limit`: this runtime cannot run what the producer
146
+ * made, so only a newer runtime or a full compile of the source can.
147
+ * `variable`: it reads a variable this strict runtime does not declare. `shape`,
148
+ * `binding`, `plan`, `expect`: the artifact is malformed or does not match the
149
+ * expected type the host passed.
150
+ */
151
+ export type ArtifactProblem = 'version' | 'shape' | 'limit' | 'syntax' | 'binding' | 'function' | 'variable' | 'digest' | 'plan' | 'expect';
152
+ /** An artifact could not be loaded by `bonsai-js/runtime`; `reason` says why. */
153
+ export declare class BonsaiArtifactError extends BonsaiError {
154
+ readonly reason: ArtifactProblem;
155
+ /** @internal */
156
+ constructor(reason: ArtifactProblem, message: string, init?: ErrorInit);
157
+ toJSON(): BonsaiErrorJSON;
158
+ }
140
159
  /**
141
160
  * Whether `value` is a Bonsai error, including one thrown by another copy of
142
161
  * the package (where `instanceof` fails).
package/dist/errors.mjs CHANGED
@@ -227,6 +227,22 @@ var BonsaiTranslationError = class extends BonsaiError {
227
227
  this.name = "BonsaiTranslationError";
228
228
  }
229
229
  };
230
+ /** An artifact could not be loaded by `bonsai-js/runtime`; `reason` says why. */
231
+ var BonsaiArtifactError = class extends BonsaiError {
232
+ reason;
233
+ /** @internal */
234
+ constructor(reason, message, init = {}) {
235
+ super("ARTIFACT", message, init);
236
+ this.name = "BonsaiArtifactError";
237
+ this.reason = reason;
238
+ }
239
+ toJSON() {
240
+ return {
241
+ ...super.toJSON(),
242
+ reason: this.reason
243
+ };
244
+ }
245
+ };
230
246
  /**
231
247
  * Whether `value` is a Bonsai error, including one thrown by another copy of
232
248
  * the package (where `instanceof` fails).
@@ -240,6 +256,6 @@ function isBonsaiError(value) {
240
256
  }
241
257
  }
242
258
  //#endregion
243
- export { BonsaiCheckError, BonsaiError, BonsaiLimitError, BonsaiRuntimeError, BonsaiSyntaxError, BonsaiTranslationError, isBonsaiError, locate };
259
+ export { BonsaiArtifactError, BonsaiCheckError, BonsaiError, BonsaiLimitError, BonsaiRuntimeError, BonsaiSyntaxError, BonsaiTranslationError, isBonsaiError, locate };
244
260
 
245
261
  //# sourceMappingURL=errors.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"errors.mjs","names":[],"sources":["../src/errors.ts"],"sourcesContent":["/** Stable machine-readable error codes. Adding a code is a minor change; renaming one is major. */\nexport type ErrorCode =\n // syntax\n | 'SYNTAX'\n // static checking (the individual diagnostics carry their own codes)\n | 'CHECK'\n // resource limits\n | 'SOURCE_TOO_LONG'\n | 'TOO_DEEP'\n | 'TOO_MANY_NODES'\n | 'TOO_COMPLEX'\n | 'STEP_LIMIT'\n | 'STRING_LIMIT'\n | 'PATTERN_LIMIT'\n | 'LIST_LIMIT'\n | 'VALUE_DEPTH_LIMIT'\n | 'TIMEOUT'\n | 'ABORTED'\n // evaluation\n | 'TYPE_ERROR'\n | 'NO_OVERLOAD'\n | 'NULL_RECEIVER'\n | 'DIVISION_BY_ZERO'\n | 'NON_FINITE'\n | 'BLOCKED_PROPERTY'\n | 'INVALID_ARGUMENT'\n | 'ASYNC_IN_SYNC'\n | 'HOST_ERROR'\n | 'HOST_CONTRACT'\n | 'INVALID_CONTEXT'\n // query translation\n | 'UNTRANSLATABLE'\n\nexport interface Span {\n readonly start: number\n readonly end: number\n}\n\nconst LINE_FEED = 10\n\n/** 1-based line and column of an offset in `source`. */\nfunction positionOf(source: string, offset: number): { line: number; column: number } {\n let line = 1\n let lineStart = 0\n const end = Math.min(Math.max(offset, 0), source.length)\n for (let i = 0; i < end; i++) {\n if (source.charCodeAt(i) === LINE_FEED) {\n line++\n lineStart = i + 1\n }\n }\n return { line, column: end - lineStart + 1 }\n}\n\n/** The widest excerpt of a line a code frame shows. */\nconst FRAME_WIDTH = 120\n/** Columns shown before the span when a long line is cut on the left. */\nconst FRAME_LEAD = 40\n\n/**\n * A source excerpt with a caret line under `span`, e.g. for terminal output.\n * A long line is cut to a window around the span (marked `...`), so a frame\n * costs the same however long the source is.\n */\nfunction codeFrame(\n source: string,\n span: Span,\n { line, column }: { line: number; column: number },\n): string {\n const start = Math.min(Math.max(span.start, 0), source.length)\n const lineStart = start - (column - 1)\n let from = start - lineStart > FRAME_WIDTH - FRAME_LEAD ? start - FRAME_LEAD : lineStart\n // Never start or end the window between the halves of a surrogate pair.\n if (from > lineStart && LOW_SURROGATE.test(source[from] ?? '')) from++\n const window = source.slice(from, from + FRAME_WIDTH + 1)\n const newline = window.indexOf('\\n')\n let to = from + (newline === -1 ? Math.min(window.length, FRAME_WIDTH) : newline)\n const cutRight = newline === -1 && window.length > FRAME_WIDTH ? '...' : ''\n if (cutRight !== '' && LOW_SURROGATE.test(source[to] ?? '')) to--\n // A CRLF line ends at its \\n; the \\r before it is not shown.\n if (newline !== -1 && to > from && source[to - 1] === '\\r') to--\n const cutLeft = from > lineStart ? '...' : ''\n const text = `${cutLeft}${source.slice(from, to)}${cutRight}`\n // The caret lines up by characters, not UTF-16 units, and a tab stays a tab.\n const lead = source.slice(from, Math.min(start, to)).replace(/[^\\t]/gu, ' ')\n const width = Math.max(1, Array.from(source.slice(start, Math.min(span.end, to))).length)\n const gutter = String(line)\n return `${gutter} | ${text}\\n${' '.repeat(gutter.length)} | ${' '.repeat(cutLeft.length)}${lead}${'^'.repeat(width)}`\n}\n\n/** One UTF-16 unit that is the second half of a surrogate pair (with u, only a lone one matches). */\nconst LOW_SURROGATE = /^[\\uDC00-\\uDFFF]$/u\n\n/**\n * The JSON form of a {@link BonsaiError} (`JSON.stringify(error)`), the same\n * wherever an error is serialized: thrown, in an explanation, or in a partial\n * result. The source text and the `cause` are left out; keep the source with\n * the error if you store it.\n */\nexport interface BonsaiErrorJSON {\n readonly name: BonsaiErrorName\n readonly code: ErrorCode\n readonly message: string\n readonly span?: Span\n readonly position?: { readonly line: number; readonly column: number }\n /** For a limit error: the option that bounds it, when there is one. */\n readonly limit?: LimitName\n /** For a check error: every finding, without the `formatted` code frame. */\n readonly diagnostics?: readonly DiagnosticJSON[]\n}\n\n/**\n * Marks Bonsai errors across copies of the package (two installed versions,\n * or a bundle beside node_modules), so isBonsaiError recognizes them all.\n */\nconst BRAND = Symbol.for('bonsai-js.error')\n\n/** Options for constructing a {@link BonsaiError}. */\nexport interface ErrorInit {\n readonly source?: string | undefined\n readonly span?: Span | undefined\n readonly cause?: unknown\n}\n\n/**\n * The `name` of every Bonsai error class. Each class sets its name as a\n * literal, so a minified bundle keeps it.\n */\nexport type BonsaiErrorName =\n | 'BonsaiError'\n | 'BonsaiSyntaxError'\n | 'BonsaiLimitError'\n | 'BonsaiRuntimeError'\n | 'BonsaiCheckError'\n | 'BonsaiTranslationError'\n\n/** Base class of every error Bonsai throws. */\nexport class BonsaiError extends Error {\n declare name: BonsaiErrorName\n readonly code: ErrorCode\n readonly source: string | undefined\n readonly span: Span | undefined\n\n /** @internal Bonsai errors are thrown by the library; constructing them is not public API. */\n constructor(code: ErrorCode, message: string, init: ErrorInit = {}) {\n super(message, init.cause === undefined ? undefined : { cause: init.cause })\n this.name = 'BonsaiError'\n this.code = code\n this.source = init.source\n this.span = init.span\n Object.defineProperty(this, BRAND, { value: true })\n }\n\n /** 1-based position of the error, when it is tied to a source span. */\n get position(): { line: number; column: number } | undefined {\n if (this.source === undefined || this.span === undefined) return undefined\n return positionOf(this.source, this.span.start)\n }\n\n /** The message followed by a code frame, when a span is known. */\n get formatted(): string {\n if (this.source === undefined || this.span === undefined) return this.message\n return `${this.message}\\n${codeFrame(this.source, this.span, positionOf(this.source, this.span.start))}`\n }\n\n /** The stable JSON form; see {@link BonsaiErrorJSON}. */\n toJSON(): BonsaiErrorJSON {\n const position = this.position\n return {\n name: this.name,\n code: this.code,\n message: this.message,\n ...(this.span === undefined ? {} : { span: { start: this.span.start, end: this.span.end } }),\n ...(position === undefined ? {} : { position }),\n }\n }\n}\n\n/** The expression text is not valid Bonsai syntax. */\nexport class BonsaiSyntaxError extends BonsaiError {\n /** @internal */\n constructor(message: string, init: ErrorInit = {}) {\n super('SYNTAX', message, init)\n this.name = 'BonsaiSyntaxError'\n }\n}\n\n/**\n * The option that bounds a limit error: a key of `limits` (or the\n * per-evaluation `timeout`), or `signal` for a cancellation.\n */\nexport type LimitName =\n | 'maxSourceLength'\n | 'maxDepth'\n | 'maxNodes'\n | 'maxSteps'\n | 'maxStringLength'\n | 'maxListLength'\n | 'maxValueDepth'\n | 'maxPatternLength'\n | 'timeout'\n | 'signal'\n\nconst LIMIT_OF: Partial<Record<ErrorCode, LimitName>> = {\n SOURCE_TOO_LONG: 'maxSourceLength',\n TOO_DEEP: 'maxDepth',\n TOO_MANY_NODES: 'maxNodes',\n STEP_LIMIT: 'maxSteps',\n STRING_LIMIT: 'maxStringLength',\n LIST_LIMIT: 'maxListLength',\n VALUE_DEPTH_LIMIT: 'maxValueDepth',\n PATTERN_LIMIT: 'maxPatternLength',\n TIMEOUT: 'timeout',\n ABORTED: 'signal',\n}\n\n/** A resource limit, timeout, or cancellation stopped parsing or evaluation. */\nexport class BonsaiLimitError extends BonsaiError {\n /**\n * The option that bounds this limit, so a caller can tell which to raise:\n * undefined for a fixed internal bound (TOO_COMPLEX, template nesting).\n */\n readonly limit: LimitName | undefined\n\n /** @internal */\n constructor(\n code: ErrorCode,\n message: string,\n init: ErrorInit & { readonly limit?: LimitName | null } = {},\n ) {\n super(code, message, init)\n this.name = 'BonsaiLimitError'\n // `null` marks a bound that is not configurable even though the code usually is.\n this.limit = init.limit === null ? undefined : (init.limit ?? LIMIT_OF[code])\n }\n\n override toJSON(): BonsaiErrorJSON {\n return this.limit === undefined ? super.toJSON() : { ...super.toJSON(), limit: this.limit }\n }\n}\n\n/** Evaluation failed: a type mismatch, invalid argument, or host failure. */\nexport class BonsaiRuntimeError extends BonsaiError {\n /** @internal */\n constructor(code: ErrorCode, message: string, init: ErrorInit = {}) {\n super(code, message, init)\n this.name = 'BonsaiRuntimeError'\n }\n}\n\n/** One static-checking finding. */\nexport interface Diagnostic {\n readonly code: DiagnosticCode\n readonly message: string\n readonly severity: 'error' | 'warning'\n /** UTF-16 offset where the finding starts (the same as `span.start`). */\n readonly start: number\n /** UTF-16 offset where the finding ends (the same as `span.end`). */\n readonly end: number\n /** The offsets as a span, as on a {@link BonsaiError}. */\n readonly span: Span\n /** 1-based line and column of `start`, as on a {@link BonsaiError}. */\n readonly position: { readonly line: number; readonly column: number }\n /**\n * The message followed by a code frame, as on a {@link BonsaiError}. An\n * accessor computed when read: not part of the JSON form, and not copied by\n * spreading the diagnostic.\n */\n readonly formatted: string\n /**\n * For an unknown variable, property, or function: the declared name the\n * checker suggests instead (the \"did you mean\" in the message).\n */\n readonly suggestion?: string\n}\n\n/** A {@link Diagnostic} as JSON: every field except the `formatted` accessor. */\nexport type DiagnosticJSON = Omit<Diagnostic, 'formatted'>\n\n/** A finding as the checker records it, before it is tied to a source. */\nexport interface Finding {\n readonly code: DiagnosticCode\n readonly message: string\n readonly severity: 'error' | 'warning'\n readonly start: number\n readonly end: number\n readonly suggestion?: string\n}\n\nclass SourceDiagnostic implements Diagnostic {\n readonly code: DiagnosticCode\n readonly message: string\n readonly severity: 'error' | 'warning'\n readonly start: number\n readonly end: number\n readonly span: Span\n readonly position: { readonly line: number; readonly column: number }\n declare readonly suggestion?: string\n readonly #source: string\n\n constructor(source: string, finding: Finding, position: { line: number; column: number }) {\n this.code = finding.code\n this.message = finding.message\n this.severity = finding.severity\n this.start = finding.start\n this.end = finding.end\n this.span = { start: finding.start, end: finding.end }\n this.position = position\n if (finding.suggestion !== undefined) {\n Object.defineProperty(this, 'suggestion', { value: finding.suggestion, enumerable: true })\n }\n this.#source = source\n }\n\n get formatted(): string {\n return `${this.message}\\n${codeFrame(this.#source, this.span, this.position)}`\n }\n}\n\n/**\n * Ties findings to their source: spans, 1-based positions (one pass over the\n * source, however many findings), and a code frame computed when read.\n */\nexport function locate(source: string, findings: readonly Finding[]): readonly Diagnostic[] {\n const lineStarts = [0]\n for (let i = source.indexOf('\\n'); i !== -1; i = source.indexOf('\\n', i + 1)) {\n lineStarts.push(i + 1)\n }\n const located = findings.map((finding) => {\n const offset = Math.min(Math.max(finding.start, 0), source.length)\n // The last line starting at or before the offset.\n let low = 0\n let high = lineStarts.length - 1\n while (low < high) {\n const middle = (low + high + 1) >> 1\n if (lineStarts[middle] <= offset) low = middle\n else high = middle - 1\n }\n return Object.freeze(\n new SourceDiagnostic(source, finding, {\n line: low + 1,\n column: offset - lineStarts[low] + 1,\n }),\n )\n })\n return Object.freeze(located)\n}\n\nexport type DiagnosticCode =\n // warnings\n | 'ALWAYS_FALSE'\n | 'ALWAYS_TRUE'\n | 'NEVER_NULL'\n | 'MAYBE_NULL'\n | 'UNSAFE_INTEGER'\n // errors\n | 'SYNTAX'\n | 'LIMIT'\n | 'UNKNOWN_VARIABLE'\n | 'UNKNOWN_PROPERTY'\n | 'UNKNOWN_FUNCTION'\n | 'NO_OVERLOAD'\n | 'TYPE_ERROR'\n | 'NULLABLE_RECEIVER'\n | 'INVALID_LAMBDA'\n | 'BLOCKED_PROPERTY'\n | 'EXPECTED_TYPE'\n | 'INVALID_ARGUMENT'\n\n/** Static checking rejected the expression; `diagnostics` lists every finding. */\nexport class BonsaiCheckError extends BonsaiError {\n readonly diagnostics: readonly Diagnostic[]\n\n /** @internal */\n constructor(source: string, diagnostics: readonly Diagnostic[] | readonly Finding[]) {\n const first = diagnostics[0]\n const more = diagnostics.length > 1 ? ` (and ${diagnostics.length - 1} more)` : ''\n super('CHECK', `${first?.message ?? 'Check failed'}${more}`, {\n source,\n span: first === undefined ? undefined : { start: first.start, end: first.end },\n })\n this.name = 'BonsaiCheckError'\n this.diagnostics = locate(source, diagnostics)\n }\n\n override toJSON(): BonsaiErrorJSON {\n return { ...super.toJSON(), diagnostics: this.diagnostics }\n }\n}\n\n/**\n * A filter (or part of it) has no exact equivalent in the target database:\n * thrown by `toSQL` and `toMongo` from `bonsai-js/query`.\n */\nexport class BonsaiTranslationError extends BonsaiError {\n /** @internal */\n constructor(message: string, source: string, span?: Span, cause?: unknown) {\n super('UNTRANSLATABLE', message, { source, span, cause })\n this.name = 'BonsaiTranslationError'\n }\n}\n\n/**\n * Whether `value` is a Bonsai error, including one thrown by another copy of\n * the package (where `instanceof` fails).\n */\nexport function isBonsaiError(value: unknown): value is BonsaiError {\n // The brand alone, not instanceof, so importing only this function does not\n // bundle the error classes and their code-frame formatting.\n if (typeof value !== 'object' || value === null) return false\n try {\n return (value as Record<symbol, unknown>)[BRAND] === true\n } catch {\n // A hostile Proxy is not a Bonsai error.\n return false\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"errors.mjs","names":[],"sources":["../src/errors.ts"],"sourcesContent":["/** Stable machine-readable error codes. Adding a code is a minor change; renaming one is major. */\nexport type ErrorCode =\n // syntax\n | 'SYNTAX'\n // static checking (the individual diagnostics carry their own codes)\n | 'CHECK'\n // resource limits\n | 'SOURCE_TOO_LONG'\n | 'TOO_DEEP'\n | 'TOO_MANY_NODES'\n | 'TOO_COMPLEX'\n | 'STEP_LIMIT'\n | 'STRING_LIMIT'\n | 'PATTERN_LIMIT'\n | 'LIST_LIMIT'\n | 'VALUE_DEPTH_LIMIT'\n | 'TIMEOUT'\n | 'ABORTED'\n // evaluation\n | 'TYPE_ERROR'\n | 'NO_OVERLOAD'\n | 'NULL_RECEIVER'\n | 'DIVISION_BY_ZERO'\n | 'NON_FINITE'\n | 'BLOCKED_PROPERTY'\n | 'INVALID_ARGUMENT'\n | 'ASYNC_IN_SYNC'\n | 'HOST_ERROR'\n | 'HOST_CONTRACT'\n | 'INVALID_CONTEXT'\n // query translation\n | 'UNTRANSLATABLE'\n // loading an artifact into bonsai-js/runtime\n | 'ARTIFACT'\n\nexport interface Span {\n readonly start: number\n readonly end: number\n}\n\nconst LINE_FEED = 10\n\n/** 1-based line and column of an offset in `source`. */\nfunction positionOf(source: string, offset: number): { line: number; column: number } {\n let line = 1\n let lineStart = 0\n const end = Math.min(Math.max(offset, 0), source.length)\n for (let i = 0; i < end; i++) {\n if (source.charCodeAt(i) === LINE_FEED) {\n line++\n lineStart = i + 1\n }\n }\n return { line, column: end - lineStart + 1 }\n}\n\n/** The widest excerpt of a line a code frame shows. */\nconst FRAME_WIDTH = 120\n/** Columns shown before the span when a long line is cut on the left. */\nconst FRAME_LEAD = 40\n\n/**\n * A source excerpt with a caret line under `span`, e.g. for terminal output.\n * A long line is cut to a window around the span (marked `...`), so a frame\n * costs the same however long the source is.\n */\nfunction codeFrame(\n source: string,\n span: Span,\n { line, column }: { line: number; column: number },\n): string {\n const start = Math.min(Math.max(span.start, 0), source.length)\n const lineStart = start - (column - 1)\n let from = start - lineStart > FRAME_WIDTH - FRAME_LEAD ? start - FRAME_LEAD : lineStart\n // Never start or end the window between the halves of a surrogate pair.\n if (from > lineStart && LOW_SURROGATE.test(source[from] ?? '')) from++\n const window = source.slice(from, from + FRAME_WIDTH + 1)\n const newline = window.indexOf('\\n')\n let to = from + (newline === -1 ? Math.min(window.length, FRAME_WIDTH) : newline)\n const cutRight = newline === -1 && window.length > FRAME_WIDTH ? '...' : ''\n if (cutRight !== '' && LOW_SURROGATE.test(source[to] ?? '')) to--\n // A CRLF line ends at its \\n; the \\r before it is not shown.\n if (newline !== -1 && to > from && source[to - 1] === '\\r') to--\n const cutLeft = from > lineStart ? '...' : ''\n const text = `${cutLeft}${source.slice(from, to)}${cutRight}`\n // The caret lines up by characters, not UTF-16 units, and a tab stays a tab.\n const lead = source.slice(from, Math.min(start, to)).replace(/[^\\t]/gu, ' ')\n const width = Math.max(1, Array.from(source.slice(start, Math.min(span.end, to))).length)\n const gutter = String(line)\n return `${gutter} | ${text}\\n${' '.repeat(gutter.length)} | ${' '.repeat(cutLeft.length)}${lead}${'^'.repeat(width)}`\n}\n\n/** One UTF-16 unit that is the second half of a surrogate pair (with u, only a lone one matches). */\nconst LOW_SURROGATE = /^[\\uDC00-\\uDFFF]$/u\n\n/**\n * The JSON form of a {@link BonsaiError} (`JSON.stringify(error)`), the same\n * wherever an error is serialized: thrown, in an explanation, or in a partial\n * result. The source text and the `cause` are left out; keep the source with\n * the error if you store it.\n */\nexport interface BonsaiErrorJSON {\n readonly name: BonsaiErrorName\n readonly code: ErrorCode\n readonly message: string\n readonly span?: Span\n readonly position?: { readonly line: number; readonly column: number }\n /** For a limit error: the option that bounds it, when there is one. */\n readonly limit?: LimitName\n /** For a check error: every finding, without the `formatted` code frame. */\n readonly diagnostics?: readonly DiagnosticJSON[]\n /** For an artifact error: why the artifact could not be loaded. */\n readonly reason?: ArtifactProblem\n}\n\n/**\n * Marks Bonsai errors across copies of the package (two installed versions,\n * or a bundle beside node_modules), so isBonsaiError recognizes them all.\n */\nconst BRAND = Symbol.for('bonsai-js.error')\n\n/** Options for constructing a {@link BonsaiError}. */\nexport interface ErrorInit {\n readonly source?: string | undefined\n readonly span?: Span | undefined\n readonly cause?: unknown\n}\n\n/**\n * The `name` of every Bonsai error class. Each class sets its name as a\n * literal, so a minified bundle keeps it.\n */\nexport type BonsaiErrorName =\n | 'BonsaiError'\n | 'BonsaiSyntaxError'\n | 'BonsaiLimitError'\n | 'BonsaiRuntimeError'\n | 'BonsaiCheckError'\n | 'BonsaiTranslationError'\n | 'BonsaiArtifactError'\n\n/** Base class of every error Bonsai throws. */\nexport class BonsaiError extends Error {\n declare name: BonsaiErrorName\n readonly code: ErrorCode\n readonly source: string | undefined\n readonly span: Span | undefined\n\n /** @internal Bonsai errors are thrown by the library; constructing them is not public API. */\n constructor(code: ErrorCode, message: string, init: ErrorInit = {}) {\n super(message, init.cause === undefined ? undefined : { cause: init.cause })\n this.name = 'BonsaiError'\n this.code = code\n this.source = init.source\n this.span = init.span\n Object.defineProperty(this, BRAND, { value: true })\n }\n\n /** 1-based position of the error, when it is tied to a source span. */\n get position(): { line: number; column: number } | undefined {\n if (this.source === undefined || this.span === undefined) return undefined\n return positionOf(this.source, this.span.start)\n }\n\n /** The message followed by a code frame, when a span is known. */\n get formatted(): string {\n if (this.source === undefined || this.span === undefined) return this.message\n return `${this.message}\\n${codeFrame(this.source, this.span, positionOf(this.source, this.span.start))}`\n }\n\n /** The stable JSON form; see {@link BonsaiErrorJSON}. */\n toJSON(): BonsaiErrorJSON {\n const position = this.position\n return {\n name: this.name,\n code: this.code,\n message: this.message,\n ...(this.span === undefined ? {} : { span: { start: this.span.start, end: this.span.end } }),\n ...(position === undefined ? {} : { position }),\n }\n }\n}\n\n/** The expression text is not valid Bonsai syntax. */\nexport class BonsaiSyntaxError extends BonsaiError {\n /** @internal */\n constructor(message: string, init: ErrorInit = {}) {\n super('SYNTAX', message, init)\n this.name = 'BonsaiSyntaxError'\n }\n}\n\n/**\n * The option that bounds a limit error: a key of `limits` (or the\n * per-evaluation `timeout`), or `signal` for a cancellation.\n */\nexport type LimitName =\n | 'maxSourceLength'\n | 'maxDepth'\n | 'maxNodes'\n | 'maxSteps'\n | 'maxStringLength'\n | 'maxListLength'\n | 'maxValueDepth'\n | 'maxPatternLength'\n | 'timeout'\n | 'signal'\n\nconst LIMIT_OF: Partial<Record<ErrorCode, LimitName>> = {\n SOURCE_TOO_LONG: 'maxSourceLength',\n TOO_DEEP: 'maxDepth',\n TOO_MANY_NODES: 'maxNodes',\n STEP_LIMIT: 'maxSteps',\n STRING_LIMIT: 'maxStringLength',\n LIST_LIMIT: 'maxListLength',\n VALUE_DEPTH_LIMIT: 'maxValueDepth',\n PATTERN_LIMIT: 'maxPatternLength',\n TIMEOUT: 'timeout',\n ABORTED: 'signal',\n}\n\n/** A resource limit, timeout, or cancellation stopped parsing or evaluation. */\nexport class BonsaiLimitError extends BonsaiError {\n /**\n * The option that bounds this limit, so a caller can tell which to raise:\n * undefined for a fixed internal bound (TOO_COMPLEX, template nesting).\n */\n readonly limit: LimitName | undefined\n\n /** @internal */\n constructor(\n code: ErrorCode,\n message: string,\n init: ErrorInit & { readonly limit?: LimitName | null } = {},\n ) {\n super(code, message, init)\n this.name = 'BonsaiLimitError'\n // `null` marks a bound that is not configurable even though the code usually is.\n this.limit = init.limit === null ? undefined : (init.limit ?? LIMIT_OF[code])\n }\n\n override toJSON(): BonsaiErrorJSON {\n return this.limit === undefined ? super.toJSON() : { ...super.toJSON(), limit: this.limit }\n }\n}\n\n/** Evaluation failed: a type mismatch, invalid argument, or host failure. */\nexport class BonsaiRuntimeError extends BonsaiError {\n /** @internal */\n constructor(code: ErrorCode, message: string, init: ErrorInit = {}) {\n super(code, message, init)\n this.name = 'BonsaiRuntimeError'\n }\n}\n\n/** One static-checking finding. */\nexport interface Diagnostic {\n readonly code: DiagnosticCode\n readonly message: string\n readonly severity: 'error' | 'warning'\n /** UTF-16 offset where the finding starts (the same as `span.start`). */\n readonly start: number\n /** UTF-16 offset where the finding ends (the same as `span.end`). */\n readonly end: number\n /** The offsets as a span, as on a {@link BonsaiError}. */\n readonly span: Span\n /** 1-based line and column of `start`, as on a {@link BonsaiError}. */\n readonly position: { readonly line: number; readonly column: number }\n /**\n * The message followed by a code frame, as on a {@link BonsaiError}. An\n * accessor computed when read: not part of the JSON form, and not copied by\n * spreading the diagnostic.\n */\n readonly formatted: string\n /**\n * For an unknown variable, property, or function: the declared name the\n * checker suggests instead (the \"did you mean\" in the message).\n */\n readonly suggestion?: string\n}\n\n/** A {@link Diagnostic} as JSON: every field except the `formatted` accessor. */\nexport type DiagnosticJSON = Omit<Diagnostic, 'formatted'>\n\n/** A finding as the checker records it, before it is tied to a source. */\nexport interface Finding {\n readonly code: DiagnosticCode\n readonly message: string\n readonly severity: 'error' | 'warning'\n readonly start: number\n readonly end: number\n readonly suggestion?: string\n}\n\nclass SourceDiagnostic implements Diagnostic {\n readonly code: DiagnosticCode\n readonly message: string\n readonly severity: 'error' | 'warning'\n readonly start: number\n readonly end: number\n readonly span: Span\n readonly position: { readonly line: number; readonly column: number }\n declare readonly suggestion?: string\n readonly #source: string\n\n constructor(source: string, finding: Finding, position: { line: number; column: number }) {\n this.code = finding.code\n this.message = finding.message\n this.severity = finding.severity\n this.start = finding.start\n this.end = finding.end\n this.span = { start: finding.start, end: finding.end }\n this.position = position\n if (finding.suggestion !== undefined) {\n Object.defineProperty(this, 'suggestion', { value: finding.suggestion, enumerable: true })\n }\n this.#source = source\n }\n\n get formatted(): string {\n return `${this.message}\\n${codeFrame(this.#source, this.span, this.position)}`\n }\n}\n\n/**\n * Ties findings to their source: spans, 1-based positions (one pass over the\n * source, however many findings), and a code frame computed when read.\n */\nexport function locate(source: string, findings: readonly Finding[]): readonly Diagnostic[] {\n const lineStarts = [0]\n for (let i = source.indexOf('\\n'); i !== -1; i = source.indexOf('\\n', i + 1)) {\n lineStarts.push(i + 1)\n }\n const located = findings.map((finding) => {\n const offset = Math.min(Math.max(finding.start, 0), source.length)\n // The last line starting at or before the offset.\n let low = 0\n let high = lineStarts.length - 1\n while (low < high) {\n const middle = (low + high + 1) >> 1\n if (lineStarts[middle] <= offset) low = middle\n else high = middle - 1\n }\n return Object.freeze(\n new SourceDiagnostic(source, finding, {\n line: low + 1,\n column: offset - lineStarts[low] + 1,\n }),\n )\n })\n return Object.freeze(located)\n}\n\nexport type DiagnosticCode =\n // warnings\n | 'ALWAYS_FALSE'\n | 'ALWAYS_TRUE'\n | 'NEVER_NULL'\n | 'MAYBE_NULL'\n | 'UNSAFE_INTEGER'\n // errors\n | 'SYNTAX'\n | 'LIMIT'\n | 'UNKNOWN_VARIABLE'\n | 'UNKNOWN_PROPERTY'\n | 'UNKNOWN_FUNCTION'\n | 'NO_OVERLOAD'\n | 'TYPE_ERROR'\n | 'NULLABLE_RECEIVER'\n | 'INVALID_LAMBDA'\n | 'BLOCKED_PROPERTY'\n | 'EXPECTED_TYPE'\n | 'INVALID_ARGUMENT'\n\n/** Static checking rejected the expression; `diagnostics` lists every finding. */\nexport class BonsaiCheckError extends BonsaiError {\n readonly diagnostics: readonly Diagnostic[]\n\n /** @internal */\n constructor(source: string, diagnostics: readonly Diagnostic[] | readonly Finding[]) {\n const first = diagnostics[0]\n const more = diagnostics.length > 1 ? ` (and ${diagnostics.length - 1} more)` : ''\n super('CHECK', `${first?.message ?? 'Check failed'}${more}`, {\n source,\n span: first === undefined ? undefined : { start: first.start, end: first.end },\n })\n this.name = 'BonsaiCheckError'\n this.diagnostics = locate(source, diagnostics)\n }\n\n override toJSON(): BonsaiErrorJSON {\n return { ...super.toJSON(), diagnostics: this.diagnostics }\n }\n}\n\n/**\n * A filter (or part of it) has no exact equivalent in the target database:\n * thrown by `toSQL` and `toMongo` from `bonsai-js/query`.\n */\nexport class BonsaiTranslationError extends BonsaiError {\n /** @internal */\n constructor(message: string, source: string, span?: Span, cause?: unknown) {\n super('UNTRANSLATABLE', message, { source, span, cause })\n this.name = 'BonsaiTranslationError'\n }\n}\n\n/**\n * Why `bonsai-js/runtime` refused an artifact. `digest`: it was made for other\n * definitions (a fresh artifact from the producer may load). `version`,\n * `syntax`, `function`, `limit`: this runtime cannot run what the producer\n * made, so only a newer runtime or a full compile of the source can.\n * `variable`: it reads a variable this strict runtime does not declare. `shape`,\n * `binding`, `plan`, `expect`: the artifact is malformed or does not match the\n * expected type the host passed.\n */\nexport type ArtifactProblem =\n | 'version'\n | 'shape'\n | 'limit'\n | 'syntax'\n | 'binding'\n | 'function'\n | 'variable'\n | 'digest'\n | 'plan'\n | 'expect'\n\n/** An artifact could not be loaded by `bonsai-js/runtime`; `reason` says why. */\nexport class BonsaiArtifactError extends BonsaiError {\n readonly reason: ArtifactProblem\n\n /** @internal */\n constructor(reason: ArtifactProblem, message: string, init: ErrorInit = {}) {\n super('ARTIFACT', message, init)\n this.name = 'BonsaiArtifactError'\n this.reason = reason\n }\n\n override toJSON(): BonsaiErrorJSON {\n return { ...super.toJSON(), reason: this.reason }\n }\n}\n\n/**\n * Whether `value` is a Bonsai error, including one thrown by another copy of\n * the package (where `instanceof` fails).\n */\nexport function isBonsaiError(value: unknown): value is BonsaiError {\n // The brand alone, not instanceof, so importing only this function does not\n // bundle the error classes and their code-frame formatting.\n if (typeof value !== 'object' || value === null) return false\n try {\n return (value as Record<symbol, unknown>)[BRAND] === true\n } catch {\n // A hostile Proxy is not a Bonsai error.\n return false\n }\n}\n"],"mappings":"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"}
package/dist/features.mjs CHANGED
@@ -2,13 +2,13 @@ import { BonsaiRuntimeError } from "./errors.mjs";
2
2
  import { BLOCKED_NAMES, isName } from "./syntax/lexer.mjs";
3
3
  import { isMap, keyListCost } from "./runtime/values.mjs";
4
4
  import { describeMismatch } from "./functions/define.mjs";
5
- import { isStackOverflow, tooDeep } from "./runtime/overflow.mjs";
6
5
  import { forEachChild } from "./syntax/ast.mjs";
6
+ import { isStackOverflow, tooDeep } from "./runtime/overflow.mjs";
7
7
  import { analyze } from "./check/checker.mjs";
8
8
  import { escaping, isOwn, raised } from "./runtime/attribution.mjs";
9
- import { compileProgram } from "./compile/compiler.mjs";
10
9
  import { State } from "./runtime/state.mjs";
11
- import { EVALUATE_OPTION_KEYS, contextOf, evaluationLimits, hostDataFailure, invalidContext, isValidDate, validationBudget } from "./environment.mjs";
10
+ import { compileProgram } from "./compile/compiler.mjs";
11
+ import { EVALUATE_OPTION_KEYS, contextOf, evaluationLimits, hostDataFailure, invalidContext, isValidDate, validationBudget } from "./program.mjs";
12
12
  import { DEFAULT_MAX_TRACE_NODES, SNAPSHOT_ENTRIES, Tracer, freezeAll, reasonsOf, renderTrace, snapshot, snapshotTrace } from "./runtime/trace.mjs";
13
13
  import { forTranslation, partiallyEvaluate, residualTexts } from "./partial.mjs";
14
14
  //#region src/features.ts