/** Native KERN handler-body codegen — TypeScript target (slices 1–3). * * Walks the children of a handler with `lang=kern` and emits a TypeScript * body string. Recognized statements: * * - `let name=X value="EXPR"` — `const X = EXPR;` (slice 1) * - `clamp name=X value=V min=LO max=HI` — `const X = Math.max(LO, Math.min(HI, V));` * - `destructure source="EXPR"` — `const { X } = EXPR;` / `const [X] = EXPR;` * - `return value="EXPR"` / bare `return` — `return EXPR;` (slice 1) * - `if cond="EXPR"` / sibling `else` — `if (EXPR) { … } else { … }` (slice 2c) * - `while cond="EXPR"` — `while (EXPR) { … }` * - `for name=i from=0 to="List.length(xs)"` — numeric range loop * * Statement-level propagation `?` lowers to the same hoisted shape that * slice 7 established for raw-body propagation: * * const __k_t1 = await call(); * if (__k_t1.kind === 'err') return __k_t1; * const u = __k_t1.value; * * Slice 3 — symmetric `{ code, imports }` shape with the Python target so * body-emitter callers have a uniform signature regardless of language. * TS's KERN-stdlib lowerings don't currently demand any imports (`Math` is * global, `Set`/`Map` are global), so `imports` is typically empty. The * `BodyEmitOptions.symbolMap` parameter is currently unused on the TS * target — TS preserves the camelCase identifier shape end-to-end — but * is plumbed through for parity with the Python emitter (and for any * future TS-only renames such as reserved-word collision handling). * * Slice scope: * - Result-flavored propagation only (`'err'` discriminant). Option * propagation in native bodies is deferred to slice 8 (typecheck-driven). * - `if` requires `cond="EXPR"`. `else` is a sibling node (no condition). * `else if` chains: an `else` whose first child is an `if` (with optional * sibling inner `else`) is collapsed to `else if (...)` in the emitted * TS. Same shape works for hand-written nested KERN and for slice 5b's * `kern migrate native-handlers` output, which emits `else > if(…)` so * raw `else if` chains round-trip byte-equivalent through `--verify`. * * `gensymCounter` is local to each emit call — every handler gets its own * fresh `__k_t1`, `__k_t2`, … sequence (same convention as slice 7). * * Indentation: the recursive walk threads an `indent` string so nested * `if`/`else` branches indent correctly. The caller adds the leading indent * for the surrounding function body. */ import type { IRNode } from '../types.js'; /** Slice 3e — caller-provided options, parity with the Python body emitter. * `symbolMap` is currently unused on the TS target; reserved for future * use (e.g., reserved-word renames). * * `stateBindings` — names of surrounding-scope React `useState` bindings * (the screen's `state name=…` declarations). The body emitter treats * these as `cell`-kind bindings in an outer scope so that * `assign target=count value=...` inside a callback/memo/effect lowers to * the matching `setCount(...)` setter rather than emitting an illegal * reassignment of the `const` returned by `useState`. */ export interface BodyEmitOptions { symbolMap?: Record; stateBindings?: ReadonlyArray; /** * Opt-in trace-hook injection for the IR-semantics differential harness. * Not used by production codegen. When `eachIterNext` is true, the `each` * loop emits a `__kernTrace({op:'iter-next', binding, value})` call as the * first statement inside each loop iteration — after the target runtime has * accepted the next iteration value and KERN bindings have been * established, before the loop body's first child executes. * * `letAssign` is shared by the `let` (declaration) and `assign` * (reassignment) contracts — both emit a `__kernTrace({op:'assign', target, * value})` call after the binding is written, on identifier targets only. * * Scoped per-flag. Adding hooks for other nodes is an explicit spec * revision and a new flag. */ traceHooks?: { eachIterNext?: boolean; forIterNext?: boolean; letAssign?: boolean; }; } /** Slice 3e — public return shape, parity with the Python body emitter. * TS's KERN-stdlib lowerings don't currently demand any imports; the * `imports` set will typically be empty until a future slice introduces * TS-stdlib entries with `requires.ts` (e.g., a `node:crypto` import). */ export interface BodyEmitResult { code: string; imports: Set; } /** Emit the body of a native KERN handler as TypeScript source. Returns * the joined body text. Each top-level line is unindented; nested * branches indent by 2 spaces per level. * * Legacy slice 1/2 signature — returns just the code string. Callers * that also need the import set (slice 3b parity with Python) should * use `emitNativeKernBodyTSWithImports`. */ export declare function emitNativeKernBodyTS(handlerNode: IRNode, options?: BodyEmitOptions): string; /** Slice 3e — context-aware variant returning `{ code, imports }`. * TS's KERN-stdlib lowerings don't currently demand any imports; the * `imports` set will typically be empty until a future slice introduces * TS-stdlib entries with `requires.ts` (e.g., a `node:crypto` import). * Provided for symmetry with the Python target so generators that drive * both languages have a uniform call shape. */ export declare function emitNativeKernBodyTSWithImports(handlerNode: IRNode, options?: BodyEmitOptions): BodyEmitResult;