import type { Expression } from "../types.js"; import type { BaseNode } from "./base.js"; import type { ArrayPattern, ObjectPattern } from "./pattern.js"; /** A list comprehension, `[expr for x in xs if cond]`, or its concurrent * form `fork [expr for x in xs if cond]` (spec: * docs/superpowers/specs/2026-07-18-list-comprehensions-design.md). * * The binder fields mirror ForLoop deliberately: `itemVar` may be a name * or a destructuring pattern, and `indexVar` is the optional second * binder, meaning the index for arrays and the value for objects. * Reusing that shape means the comprehension inherits the loop's * semantics rather than inventing its own. * * Lifecycle: the parser and agencyGenerator (for `agency fmt`) see this * node; comprehensionDesugar rewrites it into map/filter/fork calls * inside parseAgency's `lower` block, so the checker, the builder, and * the runtime never see it. */ export type Comprehension = BaseNode & { type: "comprehension"; expression: Expression; itemVar: string | ObjectPattern | ArrayPattern; indexVar?: string; iterable: Expression; condition?: Expression; /** Which call the comprehension desugars to: "seq" lowers to `map`, * the other two lower to the call of the same name. */ mode: "seq" | "fork" | "race"; /** True for the `forkShared`/`raceShared` prefixes. Non-optional so * the invariant "seq is never shared" is carried by the prefix table * (SEQ_PREFIX below) rather than by a comment. Lowers to a * `shared: true` named argument on the desugared call, which * processForkCall already understands. */ shared: boolean; }; /** Comprehension concurrency prefixes: keyword -> node fields. The * parser matches these keywords; the formatter prints them back via * comprehensionPrefixString, a reverse lookup over this SAME table. * Adding a prefix is one row here plus one str(...) in the parser's * or(...) (longest keyword first). Neither word is reserved - they are * only special immediately before a comprehension bracket. */ export declare const COMPREHENSION_PREFIXES: Record; /** The no-prefix (sequential) fields. A table row, not a special case in * the parser: seq carries shared: false because this says so. */ export declare const SEQ_PREFIX: { mode: "seq"; shared: boolean; }; /** fields -> keyword, for the formatter. Reverse lookup over * COMPREHENSION_PREFIXES so a prefix that parses always prints back as * itself. Throws on an unprintable combination rather than emitting * source text that would not re-parse. */ export declare function comprehensionPrefixString(node: Pick): string;