/**
* Evaluate `if`-attribute expressions against the sequence registry.
*
* Supports the operators listed in docs/vision/03-dsl.md:
* comparison: == != < > <= >=
* logical: && || !
* arithmetic: + - * /
*
* Identifiers resolve to the current-iteration value of the named
* sequence (string) or to the special `_count` (1-based iteration
* number). Numeric literals and quoted string literals are supported.
* Unquoted bare identifiers that happen to look like plain English
* words (e.g. `Male`, `Female`) also work and compare equal to the
* string of the same name — this mirrors the prototype's "if gender ==
* Male" style where "Male" is just a word, not a quoted string.
*
* Implementation: `jsep` handles parsing; evaluation is a small
* recursive walk over the AST. Expression compilation is cached per
* source string since the same `if` attribute is evaluated per
* iteration of the main loop.
*/
import './operators.js';
import type { SequenceRegistry } from '../sequence/types.js';
/**
* Evaluate `expr` against the given registry at `iteration` (0-based).
* Returns a boolean. Coercion to truthy/falsy uses `toBoolean` (below),
* which differs from raw JS `Boolean(...)` in one place: the literal
* string `"false"` is treated as falsy. This makes the built-in
* `_first` / `_last` / boolean-looking user values interoperate with
* `if` expressions intuitively:
*
* `...` — truthy only on the last row
* `,` — truthy on every row except last
* `${{_last}}` — interpolates as "true" / "false"
*/
export declare function evaluateIf(expr: string, registry: SequenceRegistry, iteration: number): boolean;
/**
* How a name in an expression is given a value.
*
* `undefined` means "no such name here" — the evaluator then falls back to
* treating the identifier as a bare word, which is what makes `if="x == Male"`
* read the way it does.
*
* The indirection exists because `filter=` on a `` evaluates
* the same expression language against TWO scopes at once: a candidate member's
* fields and the current row's columns. Rather than inventing a second
* evaluator that would drift from this one, the caller decides what a name
* means and the operators, the precedence and the truthiness stay shared.
*/
export type ExprScope = (name: string) => string | undefined;
/**
* The value of a column on the PREVIOUS row, for `prev()`.
*
* Separate from `ExprScope` rather than folded into it, because the two answer
* different questions about the same name and an expression asks both: `RR`
* means this row, `prev(RR, …)` means the one before. Absent — which is every
* caller but a sequential run — `prev()` is refused rather than quietly
* answering with the current row.
*/
export type PrevScope = (name: string) => string | undefined;
/** Evaluate `expr` with names resolved by `scope`, as a boolean. */
export declare function evaluateInScope(expr: string, scope: ExprScope): boolean;
/**
* Evaluate `expr` with names resolved by `scope`, and hand back the VALUE.
*
* The same walk `evaluateInScope` runs — this one simply does not throw the
* answer away. Everything the expression language already decided stays
* decided: a whole number arrives as a `bigint` and is still exact past 2⁵³,
* anything inexact arrives as a `number`, and a name that is no column arrives
* as its own text.
*
* `` is the only caller today. It exists as a separate
* entry point rather than a flag on the boolean one so that neither reading
* can quietly acquire the other's coercion.
*/
export declare function evaluateValueInScope(expr: string, scope: ExprScope, prev?: PrevScope): unknown;
/**
* The names this evaluator can actually call. Exported so a test can pin that
* it matches EXPR_FUNCTIONS in the validator: a name that validates and does
* not evaluate is worse than one that does neither, because `check` calls the
* config good and the run falls over.
*/
export declare const IMPLEMENTED_FUNCTION_NAMES: readonly string[];
//# sourceMappingURL=evaluate.d.ts.map