import type { VariableType } from "../types.js"; export type ScopeType = VariableType; export declare class Scope { readonly key: string; readonly parent?: Scope; /** * True for throwaway child() scopes (synthesizer callback params, legacy * branch narrowing). Detached scopes are never flow-reachable — no flow * `start` node may be built over one (asserted in buildFlowGraphs) — so * their local writes do not bump the generation counter. This is the perf * carve-out that keeps lambda synthesis in checkScopes from flushing the * typeAt memo on every call. */ readonly detached: boolean; private readonly vars; private readonly consts; private readonly isFunctionBoundary; /** * Tree-wide mutation counter, stored on the ROOT scope only. typeAt * (flow.ts) compares it against its memo generation and discards stale * entries automatically — the mechanism that replaced the manual * "discard the memo if scope contents change" contract. */ private generation; constructor(key: string, parent?: Scope, isFunctionBoundary?: boolean, detached?: boolean); private root; /** * The tree-wide mutation count. O(parent-chain depth) in general (narrowing * child chains can nest arbitrarily); the hot path (typeAt) reads through * the flow env scope, which is the parent-less top-level scope — O(1). */ currentGeneration(): number; private bumpGeneration; /** * Declare a binding. Writes to the nearest function scope (function-scoped * semantics). Block-level Scope instances delegate upward. */ declare(name: string, type: ScopeType, isConst?: boolean): void; /** * Declare a binding *only* in this scope, without delegating to the * enclosing function scope. Use this for genuinely block-scoped * bindings whose lifetime ends with the enclosing block (e.g. callback * parameters introduced when synthesizing the body of a `xs.map(\(x) -> * …)` lambda — `x` must not leak to the surrounding function). * * Behaves like `declare` for one-shot use: `lookup` will find it via * the normal parent walk, and dropping the scope drops the binding. */ declareLocal(name: string, type: ScopeType): void; lookup(name: string): ScopeType | undefined; /** * Like `lookup`, but stops at the enclosing function boundary instead of * walking into outer (module-level) scopes. Used to decide whether a * `let`/`const` statement redeclares an existing local or shadows an * outer binding with a fresh one. */ lookupInFunction(name: string): ScopeType | undefined; isConst(name: string): boolean; /** Names declared directly in THIS scope (not parents). Used by the * finalize flow rule to widen every local to `T | null` inside a * finalize body — any statement might not have run when it executes. */ declaredNames(): string[]; has(name: string): boolean; child(key?: string): Scope; private functionScope; }