/** * Read-only type analysis over a parsed `Program`. Designed for editor * integrations (hover, type-ranked completion, signature help) that need to * answer "what is the type of this expression?" or "what is the type * environment at this cursor?" without re-running inference per query. * * The analysis runs once at construction time, walking the program in a * single pass and recording (a) a `Map` keyed by node * identity and (b) a list of nested scope regions with their type envs. * Subsequent `typeOf` / `envAt` / `typeAt` calls are O(1) and O(regions) * respectively — fast enough for keystroke-level use in Monaco. * * Known limit (carried over from `inferType` in `./semantic-types`): * comprehension binders and `fold` element binders are bound to * `unknown` in the inner env. Expressions inside the body that reference * the binder will therefore type as `unknown`; tightening this requires a * separate piece of upstream work on the inference engine. */ import type { Expression, Program } from './program'; import { TypeEnv, type Type } from './semantic-types'; export interface TypeAnalysis { /** Static type of an Expression node from this program. Returns * `unknown` for nodes that weren't part of the analysed program * (e.g. hand-built nodes the analyzer never visited). */ typeOf(node: Expression): Type; /** Static type environment at `offset`. Reflects the innermost scope: * top-level statements that precede the offset, plus binders from any * enclosing comprehension / fold whose body contains the offset. Binders * the inference engine doesn't track are bound to `unknown`. */ envAt(offset: number): TypeEnv; /** Static type at `offset` if the offset falls inside an Expression node * visited by the analyser; `undefined` otherwise (e.g. cursor in * whitespace, or inside a comment, or inside a node without `loc`). */ typeAt(offset: number): Type | undefined; } export declare function analyzeTypes(program: Program): TypeAnalysis;