/** * IR runtime semantics — executable contracts (the spec) for each IR node type. * * Source of truth for cross-target parity. Each contract module exports a * [[NodeContract]] describing preconditions, observable effects, completion, * forbidden rewrites, and machine-readable fixtures. The [[harness]] consumes * these directly. Docs (under `docs/ir-semantics/`, gitignored) are generated * from JSDoc on contracts and fixture descriptions — never hand-edited. * * Phase 1 started with `each`; later contracts add body-statement control * flow such as `if` / sibling `else`. */ import type { IRNode } from '../../types.js'; import type { CompletionRecord, Trace } from './trace.js'; /** * The execution environment a contract evaluator sees. Deliberately minimal — * additions require a contract revision because they widen observable state. * * - `bindings`: name → value lookup. Mutating this is an [[TraceEvent]] of * kind `assign`, not a silent change. * - `stdout` / `stderr`: write-only stream sinks. Implementations append to * a trace event list; readers never see them as strings. * - `seed`: RNG seed for fixtures that exercise randomness. Frozen per run. * - `now`: frozen clock value in ms. Same value for the duration of one * contract evaluation so async timing never leaks into traces. */ export interface SemanticEnv { bindings: Map; seed: number; now: number; } /** * Build a fresh environment with deterministic defaults. * * **Always clones `overrides.bindings` and their JSON-shaped values** — * passing the same fixture env to multiple legs (or multiple runs of the same * fixture) must not allow mutation in one to bleed into another. Callers that * want shared bindings must opt in by writing through a shared reference * explicitly. */ export declare function makeEnv(overrides?: Partial): SemanticEnv; /** * A fixture is a self-contained semantic test vector. The [[harness]] feeds * `ir` to the reference runner, the TS emitter, and the Python emitter, then * compares all three traces against `expected`. * * `description` is consumed by the doc generator AND surfaces in failure * messages — write it as a sentence-cased declarative statement. */ export interface NodeFixture { description: string; ir: IRNode; /** Optional initial bindings layered onto the default environment. */ env?: Partial; expected: Trace; } /** * The contract for one IR node type. Every field is intentional — adding or * removing one is a spec revision and requires touching all current contracts. */ export interface NodeContract { /** The `type:` discriminator value this contract governs (e.g. `'each'`). */ readonly nodeType: string; /** Whether this IR shape is well-formed. Returns false → schema violation. */ preconditions: (ir: TNode, env: SemanticEnv) => boolean; /** Compute the observable trace produced by executing `ir` in `env`. */ effects: (ir: TNode, env: SemanticEnv) => Trace; /** Compute the completion record. Usually `effects(...).completion`. */ completion: (ir: TNode, env: SemanticEnv) => CompletionRecord; /** * Emitter rewrites the spec explicitly forbids — e.g. `'hoist iteration * binding'`. Listed for human review; the harness does not enforce them * mechanically (yet). */ forbiddenRewrites: readonly string[]; fixtures: readonly NodeFixture[]; } /** * Registry of all node contracts. * Adding an entry here is the canonical way to register a new node spec — * the harness, doc generator, and CI gate all read from this map. */ export declare const CONTRACT_REGISTRY: Map; /** Register a contract. Idempotent: re-registering with the same nodeType throws. */ export declare function registerContract(contract: NodeContract): void; export { type ContractDoc, type FixtureSample, type RegistryDoc, serializeJson, serializeMarkdown, snapshotRegistry, } from './doc-generator.js'; export { type DifferentialResult, runAllContracts, runDifferential, type Verdict } from './harness.js'; export { ReferenceRunnerError, referenceRun, referenceRunSequence } from './reference-runner.js'; export { registerAllContracts } from './register-all.js'; export type { CanonicalError, CompletionKind, CompletionRecord, Trace, TraceEvent, } from './trace.js'; export { completionsEqual, deepEqual, emptyTrace, eventsEqual, tracesEqual } from './trace.js';