/** Slice 4 layer 2 — stdlib preamble for Result / Option compact form. * * Spec: docs/language/result-option-spec.md. * * When a kern module references the reserved type names `Result` or * `Option` in any type-annotation position, the generated TS module needs * the corresponding type alias in scope. This module provides: * * 1. `detectKernStdlibUsage(root)` — walks the IR and flags whether each * reserved name appears in any string prop value (typeAnnotation, params, * generics, etc.). Skips the synthesised type alias itself if already * present at the root, so a re-emission stays idempotent. * * 2. `kernStdlibPreamble(usage)` — returns the TS preamble lines to prepend * to the generated module. Empty when no usage detected. * * Scope: TS-family targets only in this slice. The lib transpiler in * packages/cli/src/shared.ts is the first integrator; web / native / * nextjs / express / mcp / terminal pick this up in follow-up commits with * the same call pattern. * * NOT in scope here: * - Helper functions (`ok`, `err`, `some`, `none`, `map`, …) — usage * detection inside handler bodies is name-collision risky and is its * own design (deferred to a follow-up slice). * - Python / Vue codegen — Python's `generateType` does not yet handle * generic type aliases, so injecting `Result` would regress. * The explicit `union name=X kind=result …` form already works on * every target. */ import type { IRNode } from '../types.js'; export interface KernStdlibUsage { /** Module references `Result<…>` somewhere in a type annotation. */ result: boolean; /** Module references `Option<…>` somewhere in a type annotation. */ option: boolean; /** Module uses `KernUnwrapError` — auto-emitted by the slice 7 `!` * rewriter when a user wrote `expr!`. Optional for back-compat with * callers who only construct the result/option flags. */ unwrap?: boolean; /** DECIMAL Slice 2 (Finding 1) — a `lang="kern"` handler body in this module * constructs/operates on a Decimal via the KERN_STDLIB.Decimal surface * (`Decimal.of`/`Decimal.add`/…). The TS leg lowers those to `decimal.js` * (`new Decimal(...)` / `.plus()` / …) — an EXTERNAL npm package, NOT a global * — so the generated TS file needs the `import Decimal from 'decimal.js'` line * PLUS the one-time `Decimal.set({...})` canonical-context preamble at file * top-level. This flag drives that injection in {@link kernStdlibPreamble}. * Optional for back-compat with callers that only build the result/option * flags. */ decimal?: boolean; /** D1b — the EMITTED output of this module contains a `__kern_loose_eq(` call (the * emitter lowers a NATIVE-body loose `==`/`!=` through that helper, so `1 == "1"` * is FALSE — KERN loose `==` adds ONLY the null/undefined crossing on top of strict, * no JS coercion), so its one-time top-level definition must be injected. UNLIKE the * other flags this is NOT set by the IR-walk `detectKernStdlibUsage`: it is set by * each injection site from the emitted code via {@link emittedCodeUsesLooseEq}, so * detection equals emission exactly (an IR text-scan diverged for `==` inside `${…}` * interpolations and structured-IR differential fixtures → missing def → runtime * ReferenceError). Optional for back-compat with callers that only build the * result/option flags. */ looseEq?: boolean; } /** D1b — `__kern_loose_eq` is detected from the EMITTED OUTPUT, not an IR text-scan. * The token below appears in generated TS exactly when the emitter lowered a loose * `==`/`!=` (it gates the call on `ctx.coerceJsValues`), so scanning the emitted code * is EXACT — detection equals emission by construction. An earlier IR-walk approach * diverged from emission (a `==` inside a `${…}` template interpolation, or a * structured-IR differential fixture, lowered to `__kern_loose_eq(...)` while a * string-prop token-scan missed it → missing def → runtime ReferenceError). See * {@link emittedCodeUsesLooseEq}; the per-target injection sites set `usage.looseEq` * from it (`packages/cli/src/shared.ts`, the differential TS leg, the conformance * harness). The only residual false-positive — a user STRING literal containing the * literal text `__kern_loose_eq(` — is harmless (one unused helper def) and the * `__kern_`-reserved prefix makes it astronomically unlikely. */ export declare function emittedCodeUsesLooseEq(code: string): boolean; export declare function detectKernStdlibUsage(root: IRNode): KernStdlibUsage; /** D1b — type-FREE rendering of the loose-equality helper for plain-JS execution * contexts that cannot run TypeScript (the differential TS leg's `vm` sandbox). The * production preamble keeps the typed {@link KERN_LOOSE_EQ_HELPER}; both share the * same `KERN_LOOSE_EQ_BODY`, so there is no drift. */ export declare const KERN_LOOSE_EQ_HELPER_JS: string; export declare function kernStdlibPreamble(usage: KernStdlibUsage): string[]; /** Slice 4 follow-up — inject the preamble INSIDE a Vue/Nuxt SFC's first * `` block instead of before the SFC. The plain * `injectKernStdlibPreamble` would prepend `type Result<…>` text ahead of * the SFC, breaking the file's parse. * * Only matches a TS-language script block. JavaScript script blocks * (`lang="js"` or no `lang`) are left alone — the preamble emits TS * syntax (generics, type aliases) which JS can't host. * * When no matching script tag exists (template-only SFC, JS-only SFC), * the preamble is dropped entirely — silently injecting it elsewhere * would corrupt the file. The handler bodies in such SFCs cannot use * `Result<…>` / `Option<…>` types anyway, so the dropped preamble is * not load-bearing. */ export declare function injectKernStdlibPreambleIntoSFC(code: string, preamble: string[]): string; export declare function injectKernStdlibPreamble(code: string, preamble: string[]): string;