/** * 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