@scriptc/compiler 0.0.0 → 0.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (206) hide show
  1. package/LICENSE +202 -0
  2. package/ambient/package.json +3 -0
  3. package/ambient/scriptc-node-fallback.d.ts +3001 -0
  4. package/ambient/scriptc-overrides.d.ts +95 -0
  5. package/ambient/scriptc.d.ts +74 -0
  6. package/dist/backend/cc.d.ts +169 -0
  7. package/dist/backend/cc.js +897 -0
  8. package/dist/backend/cc.js.map +1 -0
  9. package/dist/backend/emission/emit-async.d.ts +145 -0
  10. package/dist/backend/emission/emit-async.js +996 -0
  11. package/dist/backend/emission/emit-async.js.map +1 -0
  12. package/dist/backend/emission/emit-exprs.d.ts +3 -0
  13. package/dist/backend/emission/emit-exprs.js +5949 -0
  14. package/dist/backend/emission/emit-exprs.js.map +1 -0
  15. package/dist/backend/emission/emit-island.d.ts +45 -0
  16. package/dist/backend/emission/emit-island.js +271 -0
  17. package/dist/backend/emission/emit-island.js.map +1 -0
  18. package/dist/backend/emission/emit-shapes.d.ts +142 -0
  19. package/dist/backend/emission/emit-shapes.js +575 -0
  20. package/dist/backend/emission/emit-shapes.js.map +1 -0
  21. package/dist/backend/emission/emit-stmts.d.ts +78 -0
  22. package/dist/backend/emission/emit-stmts.js +960 -0
  23. package/dist/backend/emission/emit-stmts.js.map +1 -0
  24. package/dist/backend/emission/emit-types.d.ts +65 -0
  25. package/dist/backend/emission/emit-types.js +652 -0
  26. package/dist/backend/emission/emit-types.js.map +1 -0
  27. package/dist/backend/emission/emit-walkers.d.ts +154 -0
  28. package/dist/backend/emission/emit-walkers.js +1587 -0
  29. package/dist/backend/emission/emit-walkers.js.map +1 -0
  30. package/dist/backend/emission/emitter.d.ts +452 -0
  31. package/dist/backend/emission/emitter.js +1249 -0
  32. package/dist/backend/emission/emitter.js.map +1 -0
  33. package/dist/backend/emission/may-throw.d.ts +15 -0
  34. package/dist/backend/emission/may-throw.js +250 -0
  35. package/dist/backend/emission/may-throw.js.map +1 -0
  36. package/dist/backend/llvm/blocks.d.ts +21 -0
  37. package/dist/backend/llvm/blocks.js +68 -0
  38. package/dist/backend/llvm/blocks.js.map +1 -0
  39. package/dist/backend/llvm/classes.d.ts +84 -0
  40. package/dist/backend/llvm/classes.js +438 -0
  41. package/dist/backend/llvm/classes.js.map +1 -0
  42. package/dist/backend/llvm/dyn.d.ts +123 -0
  43. package/dist/backend/llvm/dyn.js +2624 -0
  44. package/dist/backend/llvm/dyn.js.map +1 -0
  45. package/dist/backend/llvm/emitter.d.ts +3 -0
  46. package/dist/backend/llvm/emitter.js +10102 -0
  47. package/dist/backend/llvm/emitter.js.map +1 -0
  48. package/dist/backend/llvm/shapes.d.ts +78 -0
  49. package/dist/backend/llvm/shapes.js +754 -0
  50. package/dist/backend/llvm/shapes.js.map +1 -0
  51. package/dist/backend/llvm/unsupported.d.ts +6 -0
  52. package/dist/backend/llvm/unsupported.js +12 -0
  53. package/dist/backend/llvm/unsupported.js.map +1 -0
  54. package/dist/backend/llvm/walkers.d.ts +58 -0
  55. package/dist/backend/llvm/walkers.js +793 -0
  56. package/dist/backend/llvm/walkers.js.map +1 -0
  57. package/dist/backend/mangle.d.ts +124 -0
  58. package/dist/backend/mangle.js +232 -0
  59. package/dist/backend/mangle.js.map +1 -0
  60. package/dist/coverage/report.d.ts +65 -0
  61. package/dist/coverage/report.js +238 -0
  62. package/dist/coverage/report.js.map +1 -0
  63. package/dist/diagnostics/diagnostic.d.ts +140 -0
  64. package/dist/diagnostics/diagnostic.js +458 -0
  65. package/dist/diagnostics/diagnostic.js.map +1 -0
  66. package/dist/diagnostics/render.d.ts +11 -0
  67. package/dist/diagnostics/render.js +58 -0
  68. package/dist/diagnostics/render.js.map +1 -0
  69. package/dist/frontend/cjs-lexer.d.ts +20 -0
  70. package/dist/frontend/cjs-lexer.js +813 -0
  71. package/dist/frontend/cjs-lexer.js.map +1 -0
  72. package/dist/frontend/lowering/http2-constants.d.ts +1 -0
  73. package/dist/frontend/lowering/http2-constants.js +251 -0
  74. package/dist/frontend/lowering/http2-constants.js.map +1 -0
  75. package/dist/frontend/lowering/lib-boundary.d.ts +6 -0
  76. package/dist/frontend/lowering/lib-boundary.js +143 -0
  77. package/dist/frontend/lowering/lib-boundary.js.map +1 -0
  78. package/dist/frontend/lowering/lower-assert.d.ts +18 -0
  79. package/dist/frontend/lowering/lower-assert.js +1269 -0
  80. package/dist/frontend/lowering/lower-assert.js.map +1 -0
  81. package/dist/frontend/lowering/lower-builtins.d.ts +511 -0
  82. package/dist/frontend/lowering/lower-builtins.js +5249 -0
  83. package/dist/frontend/lowering/lower-builtins.js.map +1 -0
  84. package/dist/frontend/lowering/lower-calls.d.ts +581 -0
  85. package/dist/frontend/lowering/lower-calls.js +6286 -0
  86. package/dist/frontend/lowering/lower-calls.js.map +1 -0
  87. package/dist/frontend/lowering/lower-classes.d.ts +727 -0
  88. package/dist/frontend/lowering/lower-classes.js +4701 -0
  89. package/dist/frontend/lowering/lower-classes.js.map +1 -0
  90. package/dist/frontend/lowering/lower-comptime.d.ts +53 -0
  91. package/dist/frontend/lowering/lower-comptime.js +244 -0
  92. package/dist/frontend/lowering/lower-comptime.js.map +1 -0
  93. package/dist/frontend/lowering/lower-containers.d.ts +486 -0
  94. package/dist/frontend/lowering/lower-containers.js +6345 -0
  95. package/dist/frontend/lowering/lower-containers.js.map +1 -0
  96. package/dist/frontend/lowering/lower-dgram.d.ts +20 -0
  97. package/dist/frontend/lowering/lower-dgram.js +319 -0
  98. package/dist/frontend/lowering/lower-dgram.js.map +1 -0
  99. package/dist/frontend/lowering/lower-emitter.d.ts +10 -0
  100. package/dist/frontend/lowering/lower-emitter.js +688 -0
  101. package/dist/frontend/lowering/lower-emitter.js.map +1 -0
  102. package/dist/frontend/lowering/lower-enums.d.ts +22 -0
  103. package/dist/frontend/lowering/lower-enums.js +235 -0
  104. package/dist/frontend/lowering/lower-enums.js.map +1 -0
  105. package/dist/frontend/lowering/lower-expando.d.ts +35 -0
  106. package/dist/frontend/lowering/lower-expando.js +276 -0
  107. package/dist/frontend/lowering/lower-expando.js.map +1 -0
  108. package/dist/frontend/lowering/lower-exprs.d.ts +524 -0
  109. package/dist/frontend/lowering/lower-exprs.js +8111 -0
  110. package/dist/frontend/lowering/lower-exprs.js.map +1 -0
  111. package/dist/frontend/lowering/lower-generators.d.ts +50 -0
  112. package/dist/frontend/lowering/lower-generators.js +421 -0
  113. package/dist/frontend/lowering/lower-generators.js.map +1 -0
  114. package/dist/frontend/lowering/lower-inspect.d.ts +20 -0
  115. package/dist/frontend/lowering/lower-inspect.js +1074 -0
  116. package/dist/frontend/lowering/lower-inspect.js.map +1 -0
  117. package/dist/frontend/lowering/lower-island.d.ts +108 -0
  118. package/dist/frontend/lowering/lower-island.js +650 -0
  119. package/dist/frontend/lowering/lower-island.js.map +1 -0
  120. package/dist/frontend/lowering/lower-mixins.d.ts +96 -0
  121. package/dist/frontend/lowering/lower-mixins.js +534 -0
  122. package/dist/frontend/lowering/lower-mixins.js.map +1 -0
  123. package/dist/frontend/lowering/lower-modules.d.ts +135 -0
  124. package/dist/frontend/lowering/lower-modules.js +1613 -0
  125. package/dist/frontend/lowering/lower-modules.js.map +1 -0
  126. package/dist/frontend/lowering/lower-namespaces.d.ts +168 -0
  127. package/dist/frontend/lowering/lower-namespaces.js +706 -0
  128. package/dist/frontend/lowering/lower-namespaces.js.map +1 -0
  129. package/dist/frontend/lowering/lower-server.d.ts +90 -0
  130. package/dist/frontend/lowering/lower-server.js +3471 -0
  131. package/dist/frontend/lowering/lower-server.js.map +1 -0
  132. package/dist/frontend/lowering/lower-stmts.d.ts +361 -0
  133. package/dist/frontend/lowering/lower-stmts.js +5341 -0
  134. package/dist/frontend/lowering/lower-stmts.js.map +1 -0
  135. package/dist/frontend/lowering/lower-stream.d.ts +88 -0
  136. package/dist/frontend/lowering/lower-stream.js +1533 -0
  137. package/dist/frontend/lowering/lower-stream.js.map +1 -0
  138. package/dist/frontend/lowering/lower-test.d.ts +27 -0
  139. package/dist/frontend/lowering/lower-test.js +353 -0
  140. package/dist/frontend/lowering/lower-test.js.map +1 -0
  141. package/dist/frontend/lowering/lowerer.d.ts +1748 -0
  142. package/dist/frontend/lowering/lowerer.js +6257 -0
  143. package/dist/frontend/lowering/lowerer.js.map +1 -0
  144. package/dist/frontend/lowering/surfaces.d.ts +272 -0
  145. package/dist/frontend/lowering/surfaces.js +1096 -0
  146. package/dist/frontend/lowering/surfaces.js.map +1 -0
  147. package/dist/frontend/npm-static.d.ts +55 -0
  148. package/dist/frontend/npm-static.js +300 -0
  149. package/dist/frontend/npm-static.js.map +1 -0
  150. package/dist/frontend/npm.d.ts +330 -0
  151. package/dist/frontend/npm.js +1259 -0
  152. package/dist/frontend/npm.js.map +1 -0
  153. package/dist/frontend/program.d.ts +186 -0
  154. package/dist/frontend/program.js +2255 -0
  155. package/dist/frontend/program.js.map +1 -0
  156. package/dist/frontend/provenance-registry.d.ts +48 -0
  157. package/dist/frontend/provenance-registry.js +87 -0
  158. package/dist/frontend/provenance-registry.js.map +1 -0
  159. package/dist/frontend/provenance.d.ts +6 -0
  160. package/dist/frontend/provenance.js +459 -0
  161. package/dist/frontend/provenance.js.map +1 -0
  162. package/dist/frontend/resolve.d.ts +56 -0
  163. package/dist/frontend/resolve.js +682 -0
  164. package/dist/frontend/resolve.js.map +1 -0
  165. package/dist/frontend/shared.d.ts +67 -0
  166. package/dist/frontend/shared.js +241 -0
  167. package/dist/frontend/shared.js.map +1 -0
  168. package/dist/frontend/ts7/adapter.d.ts +7 -0
  169. package/dist/frontend/ts7/adapter.js +54 -0
  170. package/dist/frontend/ts7/adapter.js.map +1 -0
  171. package/dist/frontend/ts7/ast.d.ts +50 -0
  172. package/dist/frontend/ts7/ast.js +211 -0
  173. package/dist/frontend/ts7/ast.js.map +1 -0
  174. package/dist/frontend/ts7/census-check.d.ts +1 -0
  175. package/dist/frontend/ts7/census-check.js +12 -0
  176. package/dist/frontend/ts7/census-check.js.map +1 -0
  177. package/dist/frontend/ts7/checker.d.ts +140 -0
  178. package/dist/frontend/ts7/checker.js +544 -0
  179. package/dist/frontend/ts7/checker.js.map +1 -0
  180. package/dist/frontend/ts7/enums.d.ts +18 -0
  181. package/dist/frontend/ts7/enums.js +43 -0
  182. package/dist/frontend/ts7/enums.js.map +1 -0
  183. package/dist/frontend/ts7/program.d.ts +99 -0
  184. package/dist/frontend/ts7/program.js +278 -0
  185. package/dist/frontend/ts7/program.js.map +1 -0
  186. package/dist/frontend/ts7/world-check.d.ts +3 -0
  187. package/dist/frontend/ts7/world-check.js +34 -0
  188. package/dist/frontend/ts7/world-check.js.map +1 -0
  189. package/dist/frontend/types.d.ts +205 -0
  190. package/dist/frontend/types.js +2485 -0
  191. package/dist/frontend/types.js.map +1 -0
  192. package/dist/index.d.ts +85 -0
  193. package/dist/index.js +429 -0
  194. package/dist/index.js.map +1 -0
  195. package/dist/ir/nodes.d.ts +4334 -0
  196. package/dist/ir/nodes.js +1906 -0
  197. package/dist/ir/nodes.js.map +1 -0
  198. package/dist/ir/serialize.d.ts +4 -0
  199. package/dist/ir/serialize.js +34 -0
  200. package/dist/ir/serialize.js.map +1 -0
  201. package/dist/ir/validate.d.ts +36 -0
  202. package/dist/ir/validate.js +4885 -0
  203. package/dist/ir/validate.js.map +1 -0
  204. package/package.json +30 -6
  205. package/README.md +0 -3
  206. package/index.js +0 -2
@@ -0,0 +1,1748 @@
1
+ import * as ts from "../ts7/adapter.js";
2
+ import type { ScrDiagnostic } from "../../diagnostics/diagnostic.js";
3
+ import { UNSUPPORTED } from "../../diagnostics/diagnostic.js";
4
+ import type { IrClassDef, IrExpr, IrFunction, IrGlobal, IrLocal, IrModule, IrParam, IrRecordShape, IrStmt, IrType, IrUnionDef, SrcLoc } from "../../ir/nodes.js";
5
+ import { type DynamicImportResolution, type NpmBuiltinUse, type NpmLazyTrap } from "../npm.js";
6
+ import { type StartupCrash } from "../program.js";
7
+ import { ShapeRegistry, type TypeMapperCtx, UnionRegistry } from "../types.js";
8
+ import { CompoundOp, IslandFnEntry, BuiltinModuleFn } from "./surfaces.js";
9
+ import { FileParts } from "./lower-modules.js";
10
+ import { ClassInfo, ClassIteratorInfo, GenericClassInfo, findStaticOn } from "./lower-classes.js";
11
+ import { MixinFnShape } from "./lower-mixins.js";
12
+ import { ParamShape, FnSig, GenericFnInfo, GenericInstance } from "./lower-calls.js";
13
+ import { FieldTarget } from "./lower-exprs.js";
14
+ import type { ExpandoMember } from "./lower-expando.js";
15
+ /** Entry function name. '%' cannot appear in a TS identifier, so a user
16
+ * function can never collide with it (mangling is injective per prefix). */
17
+ export declare const ENTRY_NAME = "%main";
18
+ /** One step of the copy-reshape width relation (widthLiftPlan): how a
19
+ * source-typed value enters a destination slot. Pure data — the plan half;
20
+ * applyWidthLift is the build half. */
21
+ export type WidthLift = {
22
+ how: "copy";
23
+ } | {
24
+ how: "wrap";
25
+ tag: number;
26
+ } | {
27
+ how: "retag";
28
+ } | {
29
+ how: "liftWrap";
30
+ tag: number;
31
+ arm: IrType;
32
+ } | {
33
+ how: "width";
34
+ } | {
35
+ how: "arr";
36
+ } | {
37
+ how: "objWidth";
38
+ } | {
39
+ how: "clsWidth";
40
+ };
41
+ export declare class PoisonError extends Error {
42
+ }
43
+ /** Own-property lookup for the surface tables. They are plain object
44
+ * literals, so a bare `table[name]` would also find Object.prototype
45
+ * members ("toLocaleString", "constructor", "valueOf") — genuine member
46
+ * NAMES user code can spell now that the real lib declares them; treating
47
+ * an inherited function as a table entry would mis-lower or ICE. */
48
+ export declare function own<T>(table: Record<string, T | undefined>, key: string): T | undefined;
49
+ /** Sentinel binding key for `this` (which has no ts.Symbol): a stable
50
+ * object identity used in the same scope/capture maps as real symbols, so
51
+ * arrows capturing `this` ride the ordinary capture machinery. */
52
+ export declare const THIS_BINDING: ts.Symbol;
53
+ /** Per-function lowering context. A stack of these models nested functions:
54
+ * identifier resolution walks outward, and a hit in an enclosing context
55
+ * turns into a capture (boxing the binding at its origin and threading it
56
+ * through every function in between). */
57
+ export interface FnCtx {
58
+ locals: IrLocal[];
59
+ scopes: Map<ts.Symbol, IrLocal>[];
60
+ localCounters: Map<string, number>;
61
+ /** Lifted functions only: capture entries (also present in `locals`,
62
+ * boxed), in closure caps[] order. undefined ⇔ plain declared function. */
63
+ captures: IrParam[] | null;
64
+ /** Parent-function localIds feeding each capture, parallel to captures. */
65
+ captureSources: string[];
66
+ captureBySymbol: Map<ts.Symbol, IrLocal>;
67
+ /** Named function expressions/declarations: the function's own name
68
+ * symbol. Self-references become `selfRef` (NOT a capture — a box holding
69
+ * its own closure would be an RC cycle and leak). */
70
+ selfSymbol: ts.Symbol | null;
71
+ selfType: IrType | null;
72
+ /** Await is legal here (async function body). */
73
+ isAsync?: boolean;
74
+ /** Yield is legal here (generator function body): the yield/next value
75
+ * channels the yield lowering types itself against. */
76
+ generator?: {
77
+ yieldT: IrType;
78
+ nextT: IrType;
79
+ } | null;
80
+ /** VARIADIC `arguments` form (rest-marked func type with no declared
81
+ * rest param): the synthetic trailing DOM-array param `arguments`
82
+ * reads resolve to. */
83
+ argumentsLocal?: IrLocal | null;
84
+ /** Declared return type — lets `return` detect record-shape mismatches
85
+ * (SC2002) before the validator would ICE on them. */
86
+ returnType: IrType;
87
+ /** Implicit-any instance RETURN INFERENCE (resolveInferredReturn):
88
+ * present ⇔ `return` statements lower their values BARE (no coercion)
89
+ * and record themselves here; the post-pass unifies the types and wraps
90
+ * each return onto the settled one. `returnType` holds the DYN pin. */
91
+ inferReturn?: {
92
+ entries: {
93
+ stmt: IrStmt;
94
+ node: ts.Expression | null;
95
+ }[];
96
+ } | null;
97
+ /** Enclosing control constructs, innermost last: loops/switches/labeled
98
+ * blocks (jump targets — `labels` carries their JS label names so labeled
99
+ * break/continue resolve), try-with-finally regions ("tryFinally" — a
100
+ * try/catch body guarded by a finally: `return` crosses them now via the
101
+ * backend's pending-return path; break/continue still reject), and
102
+ * finally BLOCKS themselves ("finallyBlock" — jumps out stay rejected: a
103
+ * return there would REPLACE a pending completion, a model the emitter
104
+ * doesn't implement; see rejectJumpCrossingFinally). Per function: a
105
+ * nested function's jumps never bind to enclosing constructs. */
106
+ ctl: {
107
+ kind: "loop" | "switch" | "block" | "tryFinally" | "finallyBlock";
108
+ labels?: string[];
109
+ }[];
110
+ }
111
+ export declare function newFnCtx(lifted: boolean, selfSymbol: ts.Symbol | null, selfType: IrType | null, returnType: IrType): FnCtx;
112
+ export interface LowerStats {
113
+ /** Statements the lowerer attempted (nested statements count individually;
114
+ * statements inside a poisoned construct were never reached and don't). */
115
+ statementsTotal: number;
116
+ statementsFailed: number;
117
+ /** Statements that LOWERED but contain island constructs (jsOp/jsExit —
118
+ * package calls, island-backed lib members): they compile, but their
119
+ * work runs in the embedded engine. Only a --dynamic analysis produces
120
+ * these; coverage renders them as "compile dynamically". */
121
+ statementsIsland: number;
122
+ /** Functions whose signature couldn't be analyzed (bodies not counted). */
123
+ functionsSkipped: number;
124
+ }
125
+ /** IrStmt discriminants — the island walk below must not descend into
126
+ * NESTED statements (each is counted individually by its own lowerStmts
127
+ * visit; descending would attribute a nested island statement to every
128
+ * enclosing construct too). The top-level statement object itself is
129
+ * always visited. */
130
+ export declare const IR_STMT_KINDS: Set<string>;
131
+ /** True when a lowered statement's OWN expressions contain island
132
+ * constructs — a generic JSON walk (like moduleUsesRegex): `kind`
133
+ * discriminants live only on IR objects, so user string values can never
134
+ * false-positive. Nested statements are skipped (counted separately). */
135
+ /** Every identifier a binding name binds: the identifier itself, or all
136
+ * identifiers of a (possibly nested) destructuring pattern in source
137
+ * order. */
138
+ export declare function boundIdentifiersOf(name: ts.BindingName): ts.Identifier[];
139
+ export declare function stmtUsesIsland(stmts: IrStmt | IrStmt[]): boolean;
140
+ export interface LowerResult {
141
+ /** Present iff diagnostics is empty. */
142
+ module: IrModule | null;
143
+ diagnostics: ScrDiagnostic[];
144
+ /** JS statements whose compile fences DEFERRED to runtime (runtimeFence
145
+ * statements in the module) — off the build, on the coverage report. */
146
+ runtimeFences: ScrDiagnostic[];
147
+ stats: LowerStats;
148
+ /** --provenance-sources only: per-file statement attribution (the
149
+ * coverage report aggregates it per provenance package). */
150
+ statsByFile?: Map<string, {
151
+ total: number;
152
+ failed: number;
153
+ island: number;
154
+ }>;
155
+ /** --provenance-sources only: diagnostics of elided pure-annotated dead
156
+ * consts in fetched source modules — off the build, on the report. */
157
+ provenanceElided?: ScrDiagnostic[];
158
+ /** Coverage only (LowerOptions.coverage): the unreached remainder,
159
+ * lowered in a throwaway pass — blockers in it can never fail a build. */
160
+ unreached?: {
161
+ diagnostics: ScrDiagnostic[];
162
+ stats: LowerStats;
163
+ };
164
+ /** --dynamic only: every Node builtin the embedded npm graph imports,
165
+ * shimmed or not — the coverage report's island honesty. */
166
+ npmBuiltins?: NpmBuiltinUse[];
167
+ /** --dynamic only: unresolvable specifiers reached ONLY by require()/
168
+ * import() edges — the build embeds Node's call-time error as a runtime
169
+ * trap; the coverage report lists them beside the builtins. */
170
+ npmLazyTraps?: NpmLazyTrap[];
171
+ }
172
+ export interface LowerOptions {
173
+ /** --dynamic: the island engine is linked, so island constructs
174
+ * (__island_eval) may lower. Off by default — without it they produce a
175
+ * requires-dynamic diagnostic instead. */
176
+ dynamic?: boolean;
177
+ /** Coverage: additionally lower the unreached remainder (bodies nothing
178
+ * on the entry path reaches) in a throwaway pass and report its
179
+ * diagnostics and stats under `unreached` — the whole-program analysis
180
+ * builds deliberately gave up. */
181
+ coverage?: boolean;
182
+ /** The platform the build TARGETS ("win32" under a windows cross triple,
183
+ * the host platform otherwise — see buildTargetPlatform in index.ts).
184
+ * The whole program compiles for one platform, so the platform-keyed
185
+ * surfaces are compile-time constants: on win32 the bare path module
186
+ * binds path.win32 (Node on Windows IS path.win32) and path.sep /
187
+ * path.delimiter / os.EOL lower as the win32 literals; path.posix and
188
+ * path.win32 keep answering THEIR platform everywhere, like Node's. */
189
+ targetPlatform?: string;
190
+ /** Node's startup refusal (LoadResult.startupCrash — preflight's
191
+ * resolution walk and CJS named-import link check): the program
192
+ * compiles to that startup crash. */
193
+ startupCrash?: StartupCrash | null;
194
+ }
195
+ /** The Lowerer's pass configuration (see lowerToIr). */
196
+ export interface LowererMode {
197
+ /** Names of bodies the discovery pass reached; null lowers everything. */
198
+ reachable?: ReadonlySet<string> | null;
199
+ /** Coverage remainder: lower ONLY bodies outside `reachable`, skip the
200
+ * always-reachable init bodies and module building, and report deferred
201
+ * collection diagnostics nothing flushed. */
202
+ remainder?: boolean;
203
+ /** Symbols whose deferred diagnostics the emit pass already flushed —
204
+ * the remainder must not report them a second time. */
205
+ alreadyFlushed?: ReadonlySet<ts.Symbol>;
206
+ /** The build's target platform (LowerOptions.targetPlatform — lowerToIr
207
+ * passes it to every pass). Defaults to the host. */
208
+ targetPlatform?: string;
209
+ /** Node's startup refusal (preflight's resolution walk / CJS named-
210
+ * import link check): %main opens with exactly this throw, before any
211
+ * module init — Node refuses the whole graph before anything evaluates,
212
+ * so nothing runs. */
213
+ startupCrash?: StartupCrash | null;
214
+ }
215
+ /** Build lowering runs in two passes over the same ts.Program:
216
+ *
217
+ * 1. DISCOVERY — a worklist computes the set of reachable bodies. Seeds are
218
+ * the per-file init bodies (module top-level statements always run, in
219
+ * import order); lowering a body yields IR whose call/closure/new/
220
+ * virtualCall nodes are the edges that enqueue further bodies. The
221
+ * pass's IR, diagnostics, and stats are discarded — it exists only to
222
+ * answer "which bodies does the entry reach?".
223
+ * 2. EMIT — a fresh Lowerer lowers in the HISTORICAL order (per file:
224
+ * function declarations, then class members; then file inits, %main,
225
+ * generic instances, lifted lambdas), skipping bodies the discovery
226
+ * pass did not mark. Keeping the emit order (and lambda/instance
227
+ * numbering) identical to the pre-reachability compiler means a fully
228
+ * reachable program emits byte-identical C.
229
+ *
230
+ * `coverage: true` adds a third pass — the REMAINDER — that lowers only
231
+ * the bodies discovery did NOT mark (plus deferred collection diagnostics
232
+ * nothing flushed), reported separately: whole-program analysis without
233
+ * letting unreached code fail builds. */
234
+ export declare function lowerToIr(program: ts.Program, entry: ts.SourceFile, moduleOrder: ts.SourceFile[], options?: LowerOptions): LowerResult;
235
+ /** The island-handle type a `import(...)` initializer gives a binding
236
+ * whose DECLARED type has no static mapping (`Promise<typeof
237
+ * import("./m")>` — module-namespace types don't map): the direct form
238
+ * holds the static promise-of-handle, the awaited form holds the handle
239
+ * itself. Null for every other initializer shape. */
240
+ export declare function importCallHandleType(expr: ts.Expression | undefined): IrType | null;
241
+ /** True when `expr` is a call that resolved to an overload SIGNATURE of a
242
+ * source-implemented function whose implementation returns an island value
243
+ * (`any` under --dynamic): tsc never checks overload return types against
244
+ * the body — only the implementation signature is checked — so the
245
+ * overload's return is an unverifiable claim about an island value. The
246
+ * binding stores the HANDLE instead of trap-extracting the claimed type
247
+ * (reconcileOverloadReturn keeps the call jsval by the same rule), and
248
+ * uses dispatch to engine ops — exactly the value Node's binding holds.
249
+ * Ambient (.d.ts) declarations never reach this: they have no compiled
250
+ * implementation, so their calls lower through the island/builtin paths
251
+ * whose validated exits keep the checker-trust trap. */
252
+ export declare function uncheckedOverloadHandleCall(L: Lowerer, expr: ts.Expression | undefined): boolean;
253
+ /** The JavaScript declaration fallback for unmappable binding types (see
254
+ * irTypeOf): `any` and every other inference residue is the checked-
255
+ * dynamic 'unknown' kind, and array types keep their array-ness with the
256
+ * fallback applied to the ELEMENT (any[]/never[] evolving arrays become
257
+ * unknown[], so length/push/index still lower). Null for TypeScript
258
+ * files and for void (no value exists to represent). */
259
+ /** A JS-file type carrying `never[]` (or a never element) ANYWHERE in its
260
+ * array/tuple/union structure: tsc's inference residue for evolving and
261
+ * information-free shapes — the bare `const gb = []` (never[]), the mixed
262
+ * command tuple `['pwd', []]` ((string | never[])[]). never's f64
263
+ * representation (mapType's uninhabited stance, sound for genuinely dead
264
+ * TS reads) must not capture these VALUES — a later dyn push would
265
+ * dynCheck strings into a number array, a union arm would re-tag as
266
+ * number[] and fence. Callers treat a tainted type as unmappable so the
267
+ * checked-dynamic fallbacks apply, the pre-never-mapping behavior. Bare
268
+ * `never` at the ROOT stays out (`for (const v of [])`'s loop var — the
269
+ * dead read the f64 mapping is FOR). */
270
+ export declare function neverTaintedJsType(L: Lowerer, node: ts.Node, t: ts.Type): boolean;
271
+ /** The DOM undefined value — what an uninitialized checked-dynamic
272
+ * binding holds (JS: declared bindings read `undefined` before any
273
+ * assignment). A NULL dyn slot is a trap, never a value, so every dyn
274
+ * binding that is READABLE before its first assignment must start here:
275
+ * `let x;` declarations, hoisted `var`s (function and module scope,
276
+ * forward captures included), and the implicit-return completion
277
+ * (lower-calls' own copy of this pattern predates the helper). */
278
+ export declare function dynUndefinedExpr(loc: SrcLoc): IrExpr;
279
+ /** The checked-dynamic declaration fallback for unmappable binding types
280
+ * (see irTypeOf), two gates over one story:
281
+ *
282
+ * JAVASCRIPT files: `any` and every other inference residue is the
283
+ * checked-dynamic 'unknown' kind, and array types keep their array-ness
284
+ * with the fallback applied to the ELEMENT (any[]/never[] evolving arrays
285
+ * become unknown[], so length/push/index still lower).
286
+ *
287
+ * TYPESCRIPT files: genuine checker-`any` residue ONLY — a bare `any`
288
+ * binding (`flags & Any`), or a single-call-signature function type whose
289
+ * only unmappable pieces are `any` (`(value: any) => value is string` —
290
+ * the arrow the binding holds lowers those params to dyn, so the binding
291
+ * keeps its func-ness with the same per-piece fallback). The honest
292
+ * static subset of `any` is a binding whose VALUES are DOM-representable:
293
+ * the binding is 'unknown' storage with the boundary conversions
294
+ * coerceToExpected already applies (dynFrom into the slot, validated
295
+ * dynCheck out) and per-site SC2011 fences for the operations the DOM
296
+ * cannot carry JS-exactly (the island still lifts those). Every OTHER
297
+ * unmappable TS type keeps its own diagnostic — annotations exist there,
298
+ * and the fence names the real blocker. `--dynamic` builds never reach
299
+ * this fallback for `any` (mapType answers jsval first).
300
+ *
301
+ * Null for void (no value exists to represent). */
302
+ export declare function dynFallbackType(L: Lowerer, node: ts.Node, t: ts.Type): IrType | null;
303
+ /** The best-effort JS `Function.prototype.name` of an expression flowing
304
+ * into a dyn slot (the boxed function kind's inspect/error name):
305
+ * identifier and property reads answer the referenced NAME (a
306
+ * REFERENCE-SITE approximation of JS's creation-site naming — an aliased
307
+ * binding reports the alias; SEMANTICS.md), named function expressions
308
+ * their own name, anonymous function/arrow expressions their
309
+ * NamedEvaluation home (a variable initializer or property assignment).
310
+ * Null when nothing names the value (the box stays anonymous). */
311
+ export declare function jsFuncNameOf(node: ts.Node): string | null;
312
+ export declare class Lowerer {
313
+ readonly program: ts.Program;
314
+ readonly entry: ts.SourceFile;
315
+ readonly moduleOrder: ts.SourceFile[];
316
+ readonly dynamic: boolean;
317
+ readonly checker: ts.TypeChecker;
318
+ readonly diags: ScrDiagnostic[];
319
+ readonly fnSigsBySymbol: Map<ts.Symbol, FnSig>;
320
+ readonly genericFnsBySymbol: Map<ts.Symbol, GenericFnInfo>;
321
+ /** Object-literal GENERIC methods (`{ m<T>(x: T) {...} }`), interned by
322
+ * their function-like node — instances ride the same monomorphization
323
+ * queue (objLitGenericFnInfoOf). */
324
+ readonly objLitGenericFns: Map<ts.Node, GenericFnInfo>;
325
+ /** Generic arrow/function-expression INITIALIZERS of never-reassigned
326
+ * bindings (`const f = <T>(x: T) => x`), interned by the function-like
327
+ * node — registered in genericFnsBySymbol under the binding's symbol
328
+ * (and a named function expression's own inner name), so calls and
329
+ * pinned values resolve through genericFnOf exactly like top-level
330
+ * generic function declarations (bindingGenericFnInfoOf). */
331
+ readonly bindingGenericFns: Map<ts.Node, GenericFnInfo>;
332
+ /** Per-symbol result of the never-reassigned file scan
333
+ * (bindingNeverReassigned — object-literal generic-method receivers). */
334
+ readonly neverReassignedCache: Map<ts.Symbol, boolean>;
335
+ /** IMPLICIT-ANY function-value bindings (npm-static JS — `const knownBy
336
+ * = (cmd) => ...`), by their VariableDeclaration: the registered info,
337
+ * or null for probed non-qualifiers (implicitLocalFnNodeOf). */
338
+ readonly implicitLocalFns: Map<ts.Node, GenericFnInfo | null>;
339
+ /** Monomorphization worklist: instances queued by call sites, drained in
340
+ * run() (processing an instance body can queue more). */
341
+ readonly instantiationQueue: {
342
+ info: GenericFnInfo;
343
+ inst: GenericInstance;
344
+ }[];
345
+ /** Non-null while an instance body lowers: type-parameter symbol →
346
+ * concrete IR type, consulted inside mapType's recursion. */
347
+ typeParamBindings: Map<ts.Symbol, IrType> | null;
348
+ /** Non-null while an IMPLICIT-ANY instance body lowers (npm-static JS —
349
+ * lower-calls' implicit-monomorphization section): bound param symbol →
350
+ * the call site's checker type, consulted by typeOf for identifier
351
+ * references the checker still types `any`. The implicit twin of
352
+ * typeParamBindings — the checker has no `T` to substitute, so the
353
+ * binding rides the node-type accessor instead of mapType. */
354
+ implicitParamTypes: Map<ts.Symbol, ts.Type> | null;
355
+ /** IMPLICIT-ANY instances lowered EAGERLY at first demand (their return
356
+ * types are inferred from the body — the call site needs them settled),
357
+ * collected here for run()'s function list (the liftedFns discipline). */
358
+ readonly implicitFns: IrFunction[];
359
+ /** ALIASED-TYPEOF narrowing (npm-static JS — ms's `var type = typeof
360
+ * val; if (type === 'string') ...`): while a branch such a test proves
361
+ * lowers, the tested operand's symbol maps to the proven ARM's checker
362
+ * type here, and typeOf answers it — the checker only narrows const
363
+ * aliases, so this carries the var/let form the checker cannot.
364
+ * Scoped strictly by narrowingAliases (lowerIf / lowerCondition). */
365
+ readonly aliasNarrowTypes: Map<ts.Symbol, ts.Type>;
366
+ /** Runs `fn` with the given aliased-typeof narrows applied (and restored
367
+ * after) — the branch-scoping primitive. */
368
+ narrowingAliases<T>(narrows: readonly {
369
+ sym: ts.Symbol;
370
+ tsArm: ts.Type;
371
+ }[], fn: () => T): T;
372
+ /** Non-null while an instance body lowers: appended to every diagnostic
373
+ * so a body error names WHICH instantiation triggered it. */
374
+ instantiationContext: string | null;
375
+ /** True while re-lowering a base function's 2nd+ instance: the same source
376
+ * statements were already counted for the first instance. */
377
+ suppressStats: boolean;
378
+ /** Synthetic array-HOF loop functions (map/filter/forEach desugar),
379
+ * interned per method + element/callback-result type: key → fn name. */
380
+ readonly arrHofHelpers: Map<string, string>;
381
+ /** Width-coercion helpers (%rec.width.N / %arr.width.N), interned per
382
+ * (from, to) shape pair — see widthCoerce. */
383
+ readonly widthHelpers: Map<string, string>;
384
+ /** (fromShape, toShape) pairs whose width plan is being computed — the
385
+ * cycle guard for RECURSIVE shapes (a self-referential record narrowing
386
+ * into a self-referential subset). Re-entering an in-progress pair
387
+ * answers "assume coercible" (the greatest fixed point: every OTHER
388
+ * constraint of the cycle is still checked by the outer call, and the
389
+ * built helper terminates because recordWidthHelper interns its name
390
+ * before building the body, so the recursive reference resolves to the
391
+ * helper itself). */
392
+ private readonly widthPlanning;
393
+ /** Interned node:assert helpers (deep-equality comparisons keyed by
394
+ * typeKey, throws wrappers keyed by callback type + expected class) —
395
+ * the widthHelpers pattern with its own namespace. */
396
+ readonly assertHelpers: Map<string, string>;
397
+ /** util.inspect's per-type traversal helpers (%util.insp.N), interned
398
+ * by typeKey — the assertHelpers pattern with its own namespace. */
399
+ readonly inspectHelpers: Map<string, string>;
400
+ /** Union re-tag helpers (%union.retag.N), interned per (from, to)
401
+ * unionId pair — see unionRetagHelper. */
402
+ readonly retagHelpers: Map<string, string>;
403
+ /** Symbols bound by `const x = promisify(execFile)` — the one lowered
404
+ * util.promisify shape. Declarations register here and emit nothing;
405
+ * calls through the binding lower (lowerExecFileAsyncCall) and value
406
+ * uses fence. */
407
+ readonly promisifiedExecFile: Set<ts.Symbol>;
408
+ /** Symbols bound by `const process = globalThis.process` (and the other
409
+ * stdlib-global snapshot spellings): pure alias plumbing — receiver
410
+ * checks resolve through this map (stdlibGlobalNameOf), declarations
411
+ * emit nothing. */
412
+ readonly stdlibGlobalAliases: Map<ts.Symbol, string>;
413
+ /** CJS export-table ACCESSORS (`module.exports = { get path() {...} }`),
414
+ * lifted lazily as module-level functions and interned per accessor
415
+ * declaration: member reads call the getter (lower-exprs). */
416
+ readonly cjsAccessorFns: Map<ts.Node, {
417
+ fnName: string;
418
+ type: IrType & {
419
+ kind: "func";
420
+ };
421
+ }>;
422
+ readonly narrowHelpers: Map<string, string>;
423
+ /** Interned `%iter.drain.<n>` helpers (classIteratorDrainCall): one per
424
+ * receiver class — the eager drain of a class iterable's protocol into
425
+ * a fresh element array, behind array/call spreads. */
426
+ readonly iterDrainHelpers: Map<string, string>;
427
+ /** Island-lift builder helpers (%jsin.rec.N / %jsin.arr.N /
428
+ * %jsin.elems.N), interned per source type — see jsvalLiftExpr. */
429
+ readonly jsinHelpers: Map<string, string>;
430
+ /** Synthetic Map.forEach loop functions, interned per key/value type +
431
+ * callback arity: key → fn name (see lowerMapForEachCall). */
432
+ readonly mapHofHelpers: Map<string, string>;
433
+ /** Synthetic Set.forEach loop functions, interned per element type +
434
+ * callback arity/return — Map's pattern. */
435
+ readonly setHofHelpers: Map<string, string>;
436
+ /** Synthetic URLSearchParams.forEach loop functions, interned per
437
+ * callback arity/return — Map's pattern over the sp index walk. */
438
+ readonly spHofHelpers: Map<string, string>;
439
+ /** Optional-chain lowering state. While a chain body lowers, the guarded
440
+ * receiver NODE reads as a chainRecv (typed by the narrowed arm) instead
441
+ * of re-lowering, its checker type reads non-nullish (typeOf), and the
442
+ * node carrying the ?. token is marked handled so the receiver-typed
443
+ * lowerings stop declining it (chainBlocked). */
444
+ readonly chainRecvByNode: Map<ts.Node, IrExpr>;
445
+ readonly chainNarrowedType: Map<ts.Node, ts.Type>;
446
+ readonly chainHandled: Set<ts.Node>;
447
+ /** for-of-over-matchAll bindings whose `.index` reads the companion-index
448
+ * array: binding SYMBOL → the hidden number[] of match start indices plus
449
+ * the hidden cursor holding THIS iteration's position (registered while
450
+ * the loop body lowers; the property path serves `m.index` as
451
+ * idxs[cur] — computed only at an actual read, so a drain row is never
452
+ * touched for bodies that ignore it). */
453
+ readonly matchAllIndexBindings: Map<ts.Symbol, {
454
+ idxsLocalId: string;
455
+ curLocalId: string;
456
+ }>;
457
+ /** STORED matchAll drains: `const rows = s.matchAll(re)` lowers through
458
+ * matchAllInto with a hidden companion index array, registered here so a
459
+ * later `for (const m of rows)` in the SAME function serves `m.index`
460
+ * (the ctx guard keeps hidden locals out of closures — a cross-function
461
+ * walk falls back to the plain array walk and the fence). */
462
+ readonly matchAllDrainIndexes: Map<ts.Symbol, {
463
+ idxsLocalId: string;
464
+ ctx: FnCtx;
465
+ }>;
466
+ chainCounter: number;
467
+ /** Keyed by program-wide qualified class name (what IR object types carry). */
468
+ readonly classes: Map<string, ClassInfo>;
469
+ readonly classBySymbol: Map<ts.Symbol, ClassInfo>;
470
+ /** The class whose members are lowering — `super` binds lexically to it
471
+ * (arrows inside methods lower within this window, so they see it too). */
472
+ currentClass: ClassInfo | null;
473
+ readonly globalsBySymbol: Map<ts.Symbol, IrGlobal>;
474
+ /** Expando function members (`foo.bar = 12` on a module-level function
475
+ * or callable const): per function symbol, each written member's module
476
+ * global — string keys for spelled/folded names, ts.Symbols for
477
+ * unique-symbol keys (lower-expando.ts). */
478
+ readonly expandoMembers: Map<ts.Symbol, Map<string | ts.Symbol, ExpandoMember>>;
479
+ /** CJS export globals ALSO key by their declaration NODE: the checker
480
+ * hands importers a distinct (late-bound) symbol for `module.exports`
481
+ * property exports — different object, same declaration — so globalOf
482
+ * falls back through the shared node (collectGlobals registers both). */
483
+ readonly globalsByDeclNode: Map<ts.Node, IrGlobal>;
484
+ readonly globalsList: IrGlobal[];
485
+ /** npm-import init statements (--dynamic), keyed by file AND import
486
+ * declaration: the island.import assignments/side-effect loads for that
487
+ * statement. lowerFileInit splices them into the importing file's %init
488
+ * header at the statement's position — Node evaluates each imported
489
+ * module (island packages included) where the import appears, so an
490
+ * `import "polyfill"` before an `import "./app.js"` runs the package
491
+ * top-level BEFORE app's init, not after. */
492
+ readonly npmInitActions: Map<ts.SourceFile, Map<ts.StatementBase, IrStmt[]>>;
493
+ /** Per-file %init PRELUDE statements for JSON imports: bakeable DATA
494
+ * assignments with no observable evaluation order of their own —
495
+ * prepended by lowerFileInit so the bindings are live before any
496
+ * top-level statement runs. */
497
+ readonly jsonInitActions: Map<ts.SourceFile, IrStmt[]>;
498
+ /** The embedded npm runtime graph (collectNpmImports), attached to the
499
+ * emitted module. Null without npm imports or without --dynamic. */
500
+ npmEmbedded: IrModule["embedded"] | null;
501
+ npmBuiltins: NpmBuiltinUse[] | null;
502
+ npmLazyTraps: NpmLazyTrap[] | null;
503
+ /** Dynamic `import("literal")` resolutions, keyed
504
+ * `fileName\u0000specifier` (collectDynamicImports fills it during npm
505
+ * collection; lowerDynamicImportCall reads it per site). */
506
+ readonly dynImports: Map<string, DynamicImportResolution>;
507
+ /** Module → the name of its synthesized namespace-BUILDER function
508
+ * (lowerOwnModuleImport): every `import()` of the same program module
509
+ * shares one builder. */
510
+ readonly dynNsBuilders: Map<ts.SourceFile, string>;
511
+ /** Parameters forced to the island-handle type (jsval) regardless of
512
+ * their checker type: then-handler params whose settled value is an
513
+ * engine handle (a dynamic import's namespace object) — paramShape's
514
+ * early-out. */
515
+ readonly jsvalParamOverrides: Set<ts.ParameterDeclaration>;
516
+ /** File → qualifier prefix: "" for the entry, "%mI." otherwise. */
517
+ readonly fileTag: Map<ts.SourceFile, string>;
518
+ /** Namespace ModuleBlocks this program lowers, filled by splitFiles:
519
+ * "flattened" — an instantiated namespace whose body joined the file's
520
+ * parts (members resolve statically); "typeOnly" — a skipped
521
+ * non-instantiated one (its only value members are import= aliases,
522
+ * still resolved statically). Ambient blocks never register — their
523
+ * members keep the ReferenceError/fence paths (lower-namespaces.ts). */
524
+ readonly nsBlocks: Map<ts.Node, "typeOnly" | "flattened">;
525
+ /** File → its %init function name, filled by prepareModuleInits before
526
+ * any body lowers: import headers and inline require statements call
527
+ * dependency inits by these names. */
528
+ readonly initNameOf: Map<ts.SourceFile, string>;
529
+ /** File → the id of its run-once guard global (a bool module global,
530
+ * false at program start). Every non-entry module gets one: its %init
531
+ * may be called from several importers/requirers, and the guard is what
532
+ * makes each call after the first a Node-style cache hit. The entry has
533
+ * none — %main calls it exactly once (a dependency edge back to the
534
+ * entry would be a fenced cycle). */
535
+ readonly moduleGuardOf: Map<ts.SourceFile, string>;
536
+ /** Record-shape interner: canonical (name-sorted) field list → shapeId.
537
+ * Threaded into every mapType call; its `shapes` array becomes
538
+ * IrModule.records. */
539
+ readonly shapes: ShapeRegistry;
540
+ /** Union interner: canonical (typeKey-sorted) arm list → unionId.
541
+ * Threaded into every mapType call; its `unions` array becomes
542
+ * IrModule.unions. An arm's index in the canonical list is its runtime
543
+ * tag. */
544
+ readonly unions: UnionRegistry;
545
+ readonly ambient: string;
546
+ readonly overridesAmbient: string;
547
+ readonly fallbackAmbient: string;
548
+ /** The one mapType context: registries + hooks, assembled in the
549
+ * constructor (typeParamResolver reads the CURRENT instantiation bindings
550
+ * through `this`, so the same ctx serves generic bodies too). */
551
+ readonly typeCtx: TypeMapperCtx;
552
+ readonly stats: LowerStats;
553
+ /** Discovery-pass edge sink (null in the emit pass): every resolution of
554
+ * a reference to a lowerable body reports its name here — recorded even
555
+ * when the enclosing statement later poisons. */
556
+ onEdge: ((name: string) => void) | null;
557
+ fnStack: FnCtx[];
558
+ readonly liftedFns: IrFunction[];
559
+ lambdaCounter: number;
560
+ /** Statement lists currently mid-lowering, innermost last: the forward-
561
+ * capture machinery (predeclareForwardCapture) needs to know which later
562
+ * statements of an OPEN list a symbol's declaration sits in, which scope
563
+ * frame list-level declarations register into, and where to insert the
564
+ * scope-entry TDZ varDecl (before the statement being lowered). */
565
+ readonly activeStmtLists: {
566
+ stmts: readonly ts.Statement[];
567
+ index: number;
568
+ ctx: FnCtx;
569
+ frame: Map<ts.Symbol, IrLocal>;
570
+ out: IrStmt[];
571
+ }[];
572
+ /** Forward-captured consts pre-declared as TDZ boxes, keyed by symbol:
573
+ * lowerVarDecl consumes the entry when the source declaration arrives and
574
+ * emits the initializing `assign` instead of a fresh declaration. */
575
+ readonly tdzPredeclared: Map<ts.Symbol, IrLocal>;
576
+ /** Nested function DECLARATIONS lowered eagerly by the forward-hoisting
577
+ * machinery (predeclareForwardFnDecl — a reference above the declaration
578
+ * in the same function, JS's function hoisting): the statement loop skips
579
+ * the source statement when it arrives. */
580
+ readonly hoistedFnDecls: Set<ts.FunctionDeclaration>;
581
+ /** `var` bindings hoisted to their function root (hoistVarBinding), keyed
582
+ * by the checker's merged symbol — every same-name `var` in one function
583
+ * is one symbol, so one slot. Module-scope vars live in globalsBySymbol
584
+ * instead. */
585
+ readonly hoistedVars: Map<ts.Symbol, IrLocal>;
586
+ /** Per-file `var` module globals whose type carries an undefined arm:
587
+ * lowerFileInit assigns them the interned undefined right after the
588
+ * run-once guard — JS hoists module vars to `undefined` at entry, so a
589
+ * function called above the declaration statement reads that, never a
590
+ * NULL slot. Filled by collectGlobals. */
591
+ readonly varGlobalEntryInits: Map<ts.SourceFile, IrGlobal[]>;
592
+ get ctx(): FnCtx;
593
+ get scopes(): Map<ts.Symbol, IrLocal>[];
594
+ /** Names of bodies the discovery pass reached; null lowers everything
595
+ * (the discovery pass itself). */
596
+ readonly reachable: ReadonlySet<string> | null;
597
+ /** Coverage remainder mode: the reachability gate inverts (see wantBody)
598
+ * and no module is built. */
599
+ readonly remainder: boolean;
600
+ /** Deferred collection diagnostics (failed signatures/class shapes) by
601
+ * declaration symbol: an unreached declaration must not fail the build,
602
+ * so its diagnostics wait until a reference makes them relevant. */
603
+ readonly deferredDiags: Map<ts.Symbol, ScrDiagnostic[]>;
604
+ /** Deferred classes by qualified IR name — for flush sites that only
605
+ * know the class name (typed receivers, module class retention). */
606
+ readonly deferredClassByName: Map<string, ts.Symbol>;
607
+ /** Symbols whose deferred diagnostics THIS pass flushed (handed to the
608
+ * coverage remainder as alreadyFlushed). */
609
+ readonly flushedSymbols: Set<ts.Symbol>;
610
+ readonly alreadyFlushed: ReadonlySet<ts.Symbol>;
611
+ /** The build's target platform ("win32" | "darwin" | "linux" | ...):
612
+ * selects the platform-keyed builtin surfaces (builtinModuleFnsOf /
613
+ * builtinModuleConstOf in surfaces.ts). */
614
+ readonly targetPlatform: string;
615
+ /** LowererMode.startupCrash — buildMain opens %main with the throw. */
616
+ readonly startupCrash: StartupCrash | null;
617
+ /** Symbols a POISONED declaration statement would have bound: the
618
+ * declaration's own diagnostic is already recorded, and no local/global
619
+ * registered, so later references fall through every resolution step —
620
+ * the fallthroughs report the inherited-blocker cascade (SC2004)
621
+ * instead of misattributing the reference. */
622
+ readonly blockedBindings: Set<ts.Symbol>;
623
+ /** True while collectProgram runs: resolution helpers must not flush
624
+ * deferred diagnostics (collection itself resolves symbols — extends
625
+ * clauses — and collection order must not decide what reports). */
626
+ collecting: boolean;
627
+ /** Non-null redirects pushDiag into a capture buffer (the deferred
628
+ * collection wrapper). */
629
+ diagSink: ScrDiagnostic[] | null;
630
+ /** Diagnostics converted into runtimeFence statements (JS sources —
631
+ * see lowerStmts): off the build, preserved here so coverage reporting
632
+ * can still name every deferred fence. */
633
+ readonly runtimeFences: ScrDiagnostic[];
634
+ /** --provenance-sources: diagnostics of ELIDED pure-annotated dead
635
+ * consts in fetched source modules (lowerStmts's elision rule) — off
636
+ * the build entirely (the statement lowers to its poisoned bindings and
637
+ * nothing throws), preserved for the coverage report's provenance
638
+ * section. */
639
+ readonly provenanceElided: ScrDiagnostic[];
640
+ /** --provenance-sources: per-file statement attribution (mirrors the
641
+ * stats counters, keyed by fileName) so the coverage report can answer
642
+ * "did the PACKAGE's statements compile static?" per provenance
643
+ * package. Only populated while the registry is active; the remainder
644
+ * pass skips it (attribution describes the build). */
645
+ readonly statsByFile: Map<string, {
646
+ total: number;
647
+ failed: number;
648
+ island: number;
649
+ }>;
650
+ /** Bumps the per-file attribution counter (no-op unless provenance is
651
+ * active and this is the emit/discovery lane — mirror the CALLER's
652
+ * suppressStats guard, this method only gates remainder). */
653
+ bumpFileStat(file: string, kind: "total" | "failed" | "island"): void;
654
+ constructor(program: ts.Program, entry: ts.SourceFile, moduleOrder: ts.SourceFile[], dynamic: boolean, mode?: LowererMode);
655
+ registerBuiltinErrorClasses(): void;
656
+ builtinErrorInfoOf(symbol: ts.Symbol | null | undefined): ClassInfo | null;
657
+ builtinEmitterInfoOf(symbol: ts.Symbol | null | undefined): ClassInfo | null;
658
+ builtinStreamInfoOf(symbol: ts.Symbol | null | undefined): ClassInfo | null;
659
+ /** Program-wide qualified name for a top-level declaration. */
660
+ qualify(sf: ts.SourceFile, name: string): string;
661
+ /** The IR name mapType gives class instance types — must agree with
662
+ * collectClassShape's registration. Namespace-nested classes carry the
663
+ * namespace path (nsPathPrefix), so `namespace A { export class C }`
664
+ * and a top-level `class C` never collide. Class EXPRESSIONS name by
665
+ * SOURCE POSITION (`%cx<start>.<name>`): deterministic across the
666
+ * discovery and emit passes (no counter can drift between them),
667
+ * program-unique through the file qualifier, and collision-free with
668
+ * user identifiers ('%'). */
669
+ readonly classNamer: (decl: ts.ClassLikeDeclaration) => string;
670
+ /** Follows import aliases to the original declaration's symbol. Every
671
+ * value reference resolves through here, so it doubles as the flush
672
+ * point for deferred collection diagnostics: resolving a reference to a
673
+ * broken declaration reports what collection deferred. */
674
+ resolveValueSymbol(ident: ts.Identifier): ts.Symbol | null;
675
+ /** A module's CJS export-table member symbol by NAME (the checker's
676
+ * module-symbol exports map — present in tsgo even where no expando
677
+ * property symbol exists at the attachment/use sites). */
678
+ cjsModuleExportSymbol(sf: ts.SourceFile, name: string): ts.Symbol | undefined;
679
+ /** The local VALUE symbol behind a CJS export-table property symbol —
680
+ * see resolveValueSymbol. Null when `symbol` is not such a property (or
681
+ * the property's value is not a plain identifier reference). */
682
+ private cjsExportValueSymbol;
683
+ /** The CLASS symbol a member-form CJS export declaration forwards to:
684
+ * `d` (an export property symbol's declaration) sits in a top-level
685
+ * `exports.C = <ident>` / `module.exports.C = <ident>` statement of a
686
+ * JS module, the statement is not discarded by a later table, and the
687
+ * identifier resolves to a class declaration. Null otherwise. */
688
+ cjsMemberExportClassSymbol(d: ts.Node): ts.Symbol | null;
689
+ /** The CommonJS JS module a DEFAULT-import binding's declaration loads
690
+ * (`import d from "./lib.cjs"`), or null: Node's ESM-CJS interop binds
691
+ * the default to module.exports — exactly a require binding — so those
692
+ * bindings ride the CJS namespace machinery below. ESM dependencies
693
+ * (any .ts, ESM-syntax .js/.mjs) answer null and keep the ESM default
694
+ * machinery. */
695
+ private cjsDefaultImportDepOf;
696
+ /** True when `expr` is an identifier bound by a top-level
697
+ * `const x = require("./local")` of a RELATIVE module — the CommonJS
698
+ * namespace binding — or by a DEFAULT import of a CommonJS JS module
699
+ * (`import d from "./lib.cjs"`: Node binds d to module.exports, the
700
+ * same value require answers). Member accesses on it resolve through
701
+ * the export table (property symbols → resolveValueSymbol); the bare
702
+ * value keeps the namespace-object fence, like ESM namespace imports
703
+ * of builtins. */
704
+ cjsLocalModuleBindingOf(expr: ts.Expression): boolean;
705
+ /** Assignment-target resolution: a function local (possibly captured) or
706
+ * a module global. tsc has already rejected writes to consts. */
707
+ resolveWritable(ident: ts.Identifier): {
708
+ id: string;
709
+ type: IrType;
710
+ } | null;
711
+ fnSigOf(ident: ts.Identifier): FnSig | null;
712
+ globalOf(ident: ts.Identifier): IrGlobal | null;
713
+ splitFiles(): FileParts[];
714
+ collectProgram(parts: FileParts[]): void;
715
+ /** Names every file's %init and registers the run-once guard globals
716
+ * (EVERY module, the entry included: an admissible import cycle can
717
+ * close back on the entry, whose init call must be the cache hit Node's
718
+ * revisit is — not a recursion) BEFORE any body lowers: function bodies
719
+ * and init bodies alike may contain require statements that lower to
720
+ * calls of these names. Runs in every pass so the ids are
721
+ * deterministic. */
722
+ prepareModuleInits(parts: FileParts[]): void;
723
+ /** The lowering of a CommonJS `require("./local")` occurrence: a call of
724
+ * the required module's run-once %init at exactly this statement's
725
+ * position — Node's inline evaluation, with the guard supplying the
726
+ * cache-hit behavior for every require after the first. Null when the
727
+ * specifier is not a relative program module (builtins load nothing;
728
+ * anything else kept its preflight fence). */
729
+ requireInitStmt(spec: string, node: ts.Node): IrStmt | null;
730
+ /** True when this body should lower: everything with no reachable set
731
+ * (discovery), the marked bodies in the emit pass, and exactly the
732
+ * UNMARKED bodies in the coverage remainder. */
733
+ wantBody(name: string): boolean;
734
+ collectNpmImports(parts: FileParts[]): void;
735
+ collectJsonImports(parts: FileParts[]): void;
736
+ run(): LowerResult;
737
+ /** True when `t` (recursively) names a class instance type with no
738
+ * registered ClassInfo — the shape of a JS class whose collection fenced.
739
+ * Used by run()'s global pruning; shapes/unions recurse with a seen-set
740
+ * (interned ids can nest). */
741
+ typeNamesUnregisteredClass(t: IrType, seen?: Set<string>): boolean;
742
+ /** Whether run() counts a signature-blocked declaration in
743
+ * stats.functionsSkipped: whole-program passes and the coverage
744
+ * remainder do; the reachability emit pass leaves the counting to the
745
+ * remainder (the declaration was never reached). */
746
+ countsSkips(): boolean;
747
+ /** The discovery pass: computes the set of body names the program's entry
748
+ * reaches. Seeds are the per-file init bodies (top-level statements always
749
+ * run); edges fire from RESOLUTION sites while a body lowers (noteEdge /
750
+ * noteVirtualEdge) — direct calls, closure creation (a taken closure may
751
+ * be called indirectly), `new`, super calls, accessor invocations, and
752
+ * virtual dispatch. Recording at resolution time (not off the produced
753
+ * IR) keeps edges from statements that later poison, so the callee's own
754
+ * diagnostics still surface — the collect-everything invariant. Generic
755
+ * instances ride the existing monomorphization queue (already
756
+ * demand-driven) and lifted lambdas lower inline with their enclosing
757
+ * body; both fire edges through the same hooks and are not units
758
+ * themselves. */
759
+ discover(): Set<string>;
760
+ /** Discovery hook (see discover): fires when lowering resolves a
761
+ * reference to a lowerable body. Inert in the emit pass. */
762
+ noteEdge(name: string): void;
763
+ /** Discovery hook for virtual dispatch: a virtualCall on `info`'s static
764
+ * class reaches the nearest declaration at/above it plus every override
765
+ * on a STRICT descendant (receivers of sibling branches can't flow into
766
+ * this call site; a virtualCall through their own static classes marks
767
+ * them). */
768
+ noteVirtualEdge(info: ClassInfo, method: string): void;
769
+ moduleArtifacts(functions: IrFunction[]): {
770
+ classes: IrClassDef[];
771
+ records: IrRecordShape[];
772
+ unions: IrUnionDef[];
773
+ };
774
+ /** All diagnostics land here; while a generic instance body is lowering,
775
+ * the instantiation context is appended so the user knows which concrete
776
+ * types made the (source-anchored) construct fail. */
777
+ pushDiag(diag: ScrDiagnostic): void;
778
+ unsupported(code: keyof typeof UNSUPPORTED & `SC${number}`, node: ts.Node, featureOverride?: string, hintOverride?: string): never;
779
+ /** The dynamic-family fence for an OPERATION on an `any`-origin
780
+ * checked-dynamic value that only the engine can execute (operators,
781
+ * iteration, computed member names, ...). Carries SC2011 — the same
782
+ * code as the `any` type fence — so the coverage report groups it with
783
+ * the dynamic-capable family and the two-tier retry knows the island
784
+ * lifts the site. Use exactly when the blocking operand IS dyn-typed
785
+ * and its checker type is `any`-flavored; genuine `unknown` keeps the
786
+ * SC1100-family fences (tsc constrains what unknown can do, so those
787
+ * sites are checker-error territory, not engine territory). */
788
+ anyOpFence(feature: string, node: ts.Node): never;
789
+ /** True when this expression's CHECKER type is `any`-flavored — the
790
+ * gate anyOpFence's call sites use to tell `any`-origin dyn values
791
+ * (the engine could run the operation) from genuine `unknown` ones. */
792
+ anyOrigin(node: ts.Node): boolean;
793
+ badType(node: ts.Node, type: ts.Type): never;
794
+ /** The lib fence (SC2020): a reached use of standard-library surface
795
+ * nothing lowers. Poisons the statement like every other rejection.
796
+ * `sym`, when given, picks the wording: surface declared only by the
797
+ * adopted @types/node is blamed at @types/node. */
798
+ noLowering(surface: string, node: ts.Node, hint?: string, sym?: ts.Symbol | null): never;
799
+ stdlibMemberFence(access: ts.PropertyAccessExpression): void;
800
+ typeOf(node: ts.Node): ts.Type;
801
+ /** mapType with this Lowerer's registries and (while a generic instance
802
+ * body lowers) type-parameter bindings threaded through. */
803
+ mapTypeOf(t: ts.Type): IrType | null;
804
+ /** True when a ?. token blocks this lowering — i.e. it is NOT the one an
805
+ * active optional-chain lowering is currently handling. Every receiver-
806
+ * typed lowering that supports chained receivers guards with this
807
+ * instead of a raw questionDotToken check. */
808
+ chainBlocked(...nodes: (ts.CallExpression | ts.PropertyAccessExpression | ts.ElementAccessExpression)[]): boolean;
809
+ /** formatIrType with this Lowerer's registries (records and unions expand
810
+ * to their structure in diagnostics). */
811
+ fmt(t: IrType): string;
812
+ /** isJsonSafeType with this Lowerer's registries — the shared fence for
813
+ * what JSON.stringify accepts and what a checked cast can validate. */
814
+ jsonSafe(t: IrType): boolean;
815
+ /** True when a type is a BARE undefined-armed union — the one JSON-unsafe
816
+ * shape whose rejections deserve their own wording: Node's stringify of
817
+ * bare undefined is not a string at all and JSON text never matches the
818
+ * arm, so exactness is unreachable and the fixes (narrow first / null arm
819
+ * / make it an optional record FIELD, where drop-and-absent semantics ARE
820
+ * Node's) are specific. Record fields don't count: an undefined-armed
821
+ * union in field position is JSON-safe (isJsonSafeType), so a record that
822
+ * still fails the fence does so for some other reason. */
823
+ bareUndefinedArmedUnion(t: IrType): boolean;
824
+ /** canCrossIslandBoundary with this Lowerer's registries — THE test
825
+ * behind every marshal/exit decision (the implicit coercions, jsvalIn,
826
+ * the checked island-exit cast). Rejections that follow a false answer
827
+ * speak through boundaryIntoIslandMsg / boundaryOutOfIslandMsg. */
828
+ boundarySafe(t: IrType): boolean;
829
+ /** canExitIslandToType with this Lowerer's registries — the EXIT
830
+ * direction's slightly wider test (bare undefined-armed unions of
831
+ * JSON-safe data arms exit; the engine's undefined takes the undefined
832
+ * arm before the JSON round trip). */
833
+ boundaryExitSafe(t: IrType): boolean;
834
+ isIslandExpr(node: ts.Expression): boolean;
835
+ /** True when this node's CHECKER type is `any[]`/`unknown[]` — the type
836
+ * tsc's Array.isArray predicate narrows readonly arrays to (its `arg is
837
+ * any[]` quirk), and what a union collapses to when such an arm absorbs
838
+ * its siblings. The VALUE behind it can still be a real static array
839
+ * (maybeNarrow's isArray bridge extracts the union's array arm), so
840
+ * receiver-typed dispatch falls back to the LOWERED type under this
841
+ * test. */
842
+ checkerAnyArray(node: ts.Expression): boolean;
843
+ /** Substitutes a bound type parameter anywhere inside mapType's recursion
844
+ * (`T`, `T[]`, `{ v: T }`, `(x: T) => T` all resolve). Inert outside
845
+ * generic instantiation. */
846
+ readonly typeParamResolver: (t: ts.Type) => IrType | null;
847
+ irTypeOf(node: ts.Node): IrType;
848
+ /** Exact-shape enforcement (SC2002). Records are monomorphic structs, so
849
+ * everywhere a value flows into a typed slot (call arg, initializer,
850
+ * assignment, field, return) the shapes must MATCH — TS's structural width
851
+ * subtyping (`{a, b}` where `{a}` is expected) has no runtime coercion.
852
+ * Non-record mismatches are not reachable through tsc-clean programs; the
853
+ * validator ICEs on them as the usual backstop. */
854
+ requireExactShape(node: ts.Node, actual: IrType, expected: IrType): void;
855
+ /** Unwraps a HYBRID (function-with-properties) record to its callable:
856
+ * a record whose shape carries the reserved `%call` func field reads
857
+ * that field; anything else returns unchanged. The consumer half of
858
+ * types.ts's chalk-shape mapping — call paths and func-slot coercions
859
+ * share it. */
860
+ hybridCallUnwrap(expr: IrExpr): IrExpr;
861
+ /** The tag of the union arm equal to `arm`, or -1 (unknown union / no
862
+ * such arm). Arm lists are canonical (typeKey-sorted) and interned, so
863
+ * this is THE tag for that (union, arm) pair program-wide — every wrap,
864
+ * narrow, and tag test agrees by construction. */
865
+ armTag(unionId: string, arm: IrType): number;
866
+ /** Implicit union construction. Wherever a value flows into a typed slot
867
+ * (initializer, assignment, call argument, return, field write, record
868
+ * literal field, ternary arm) whose expected type is a union and the
869
+ * value's type is one of its arms, wrap it in a `unionWrap` carrying the
870
+ * arm's canonical tag. Same-union values pass through untouched; anything
871
+ * else (including a DIFFERENT union) is left for requireExactShape, which
872
+ * rejects union mismatches with SC2003. */
873
+ coerceToExpected(expr: IrExpr, expected: IrType): IrExpr;
874
+ /** Copy-based structural WIDTH coercion — a `Full` record flowing into a
875
+ * narrower `{ id }` slot, or `Full[]` into `{ id }[]` (the Pick-typed
876
+ * display-table pattern): TS's width subtyping is free on erased types,
877
+ * but monomorphic structs must RESHAPE, so the value is rebuilt with the
878
+ * subset of fields copied — per element, via an interned helper, for
879
+ * arrays. A deliberate divergence from JS's aliasing (SEMANTICS.md 35,
880
+ * next to the marshal-copy stance): mutations through the narrowed value
881
+ * don't reach the original and vice versa. Exactly two flows coerce —
882
+ * record→record and record-array→record-array, each target field copied
883
+ * from a same-named source field whose type matches exactly or LIFTS
884
+ * into the target field's union (see recordWidthHelper); anything
885
+ * deeper keeps the exactness fences. Null when the pair isn't
886
+ * width-coercible. */
887
+ widthCoerce(expr: IrExpr, expected: IrType): IrExpr | null;
888
+ /** One step of the recursive width-lift relation: how a `src`-typed
889
+ * value enters a `dst`-typed slot under the copy-reshape family. The
890
+ * pure planning side — nothing interns here, so whole plans validate
891
+ * before any helper exists. The cases, in order:
892
+ * copy — exact same type (typeEquals), the field/element moves as is
893
+ * retag — union into union, every arm mapped (unionRetagMappable —
894
+ * identity arms, trap-less; record/array arms may width-lift
895
+ * into exactly one destination arm)
896
+ * wrap — a non-unit arm value into a union that contains it
897
+ * liftWrap — a record/array value into a union with NO identical arm
898
+ * but exactly ONE arm it width-lifts into (the findRoute
899
+ * rule applied at every level; several candidates are
900
+ * ambiguous and decline)
901
+ * width — record into a strict-subset record (recordWidthPlan,
902
+ * recursively — NESTED width)
903
+ * arr — array into array whose element pair lifts (per-element
904
+ * copy loop, arrayWidthHelper)
905
+ * Null when the pair isn't in the relation — callers keep their fences. */
906
+ widthLiftPlan(src: IrType, dst: IrType): WidthLift | null;
907
+ /** The build side of widthLiftPlan: the IrExpr converting `value` into
908
+ * `dst` under a plan the caller validated. Interns whatever helpers the
909
+ * lift needs (planned first, so the interns cannot fail — a failure here
910
+ * is a lowerer bug, not a user diagnostic). */
911
+ applyWidthLift(lift: WidthLift, value: IrExpr, dst: IrType, loc: SrcLoc): IrExpr;
912
+ /** Interned `%rec.width.<n>(r)` — builds the target shape from a source
913
+ * record by copying fields: every target field must exist on the source
914
+ * with the EXACT same type, or with a type that LIFTS under
915
+ * widthLiftPlan — an arm value wraps (`text: string` into
916
+ * `text?: string`), a whole union re-tags (unionRetagMappable), a field
917
+ * whose own record/array type needs narrowing reshapes RECURSIVELY
918
+ * (nested width — the copy stance applies per level), and a MISSING
919
+ * optional-flavored field completes to its undefined arm (the
920
+ * literal-completion rule). TUPLES width-coerce too, arity-exact (TS
921
+ * permits no other tuple width): per-position lifts, never completion.
922
+ * Index-signature shapes keep the exactness fences here (the overflow
923
+ * CAPTURE helper owns their reshapes). Null when the shapes don't
924
+ * relate that way. */
925
+ /** The pure planning half of recordWidthHelper — every target field's
926
+ * lift, or null when the pair isn't width-coercible. Callers that must
927
+ * validate a WHOLE plan before interning anything (the retag helper's
928
+ * per-arm width lifts) probe with this. */
929
+ recordWidthPlan(fromId: string, toId: string): Map<string, {
930
+ src: IrType;
931
+ lift: WidthLift;
932
+ } | {
933
+ absent: true;
934
+ utag: number;
935
+ }> | null;
936
+ recordWidthHelper(fromId: string, toId: string, loc: SrcLoc): string | null;
937
+ /** Interned `%arr.width.<n>(a)` — the per-element copy loop over
938
+ * widthLiftPlan's element lift: out = []; n = a.length; for (...)
939
+ * out.push(lift(a[i])); return out. Record elements reshape
940
+ * (recordWidthHelper), union elements wrap or re-tag (`number[]` into
941
+ * `(number | undefined)[]`), nested arrays recurse. Null when the
942
+ * element pair isn't width-liftable. */
943
+ /** Interned `%tup.arr.<n>(t)` — rebuilds a TUPLE as an ARRAY: positions
944
+ * read in order, each lifted into the element type under widthLiftPlan.
945
+ * Null unless the source shape really is a tuple whose every position
946
+ * lifts (records with named fields never relate to arrays). */
947
+ tupleArrayWidthHelper(fromId: string, toT: IrType & {
948
+ kind: "array";
949
+ }, loc: SrcLoc): string | null;
950
+ arrayWidthHelper(fromT: IrType & {
951
+ kind: "array";
952
+ }, toT: IrType & {
953
+ kind: "array";
954
+ }, loc: SrcLoc): string | null;
955
+ /** The planning half of objRecordWidthHelper — how a CLASS INSTANCE
956
+ * projects into a record shape (tsc's structural view of classes makes
957
+ * `new Point(0,0)` flow into `{x: number; y: number}` slots). Every
958
+ * target field must be a plain instance FIELD on the class (inherited
959
+ * included) whose type lifts, or a missing optional-flavored field
960
+ * completing to its undefined arm — but never a field the class
961
+ * satisfies through a METHOD or accessor (bound method references have
962
+ * no lowering; the plan declines instead of projecting a lie). Builtin
963
+ * runtime layouts (the Error/EventEmitter/stream chains) decline: their
964
+ * fields aren't plain emitted storage. */
965
+ objToRecordPlan(className: string, toId: string): Map<string, {
966
+ src: IrType;
967
+ lift: WidthLift;
968
+ } | {
969
+ absent: true;
970
+ utag: number;
971
+ }> | null;
972
+ /** Interned `%obj.width.<n>(o)` — builds a record from a class
973
+ * instance's fields under objToRecordPlan: the width-copy stance
974
+ * (divergence 305 — a fresh record, mutations don't alias, extra class
975
+ * members drop). */
976
+ objRecordWidthHelper(className: string, toId: string, loc: SrcLoc): string | null;
977
+ /** The planning half of recordClassWidthHelper — how a RECORD enters a
978
+ * class-instance slot. Construction IS the projection, so the class
979
+ * must be a pure parameter-property data class: its own trivial
980
+ * constructor (every parameter a parameter property, empty body), no
981
+ * other fields, no methods/accessors anywhere in the chain (a
982
+ * fabricated instance must carry no behavior the record lacks), no
983
+ * decoration, no base beyond a generic FAMILY ancestor (fieldless and
984
+ * methodless by construction). Each constructor parameter takes the
985
+ * same-named source field under widthLiftPlan, or — omittable params —
986
+ * the absent undefined arm. One entry per constructor parameter, in
987
+ * parameter order. */
988
+ recordToClassPlan(fromId: string, className: string): ({
989
+ field: string;
990
+ src: IrType;
991
+ lift: WidthLift;
992
+ } | {
993
+ absent: true;
994
+ })[] | null;
995
+ /** Interned `%cls.width.<n>(r)` — `new C(r.p1, ..., r.pn)` under
996
+ * recordToClassPlan: the record's fields become the trivial
997
+ * constructor's arguments (divergence 305's copy stance — a fresh
998
+ * instance, mutations don't alias, and `instanceof C` answers true
999
+ * where Node's plain object answers false). */
1000
+ recordClassWidthHelper(fromId: string, className: string, loc: SrcLoc): string | null;
1001
+ /** A CLASS VALUE's statics projected into a record shape (`var f:
1002
+ * ShapeFactory = Shape`): the record literal capturing static FIELDS as
1003
+ * copies of their globals and static METHODS as the zero-capture
1004
+ * closures `const f = C.m` builds (params all required — value-form
1005
+ * completion rules stay out of coercions). Inherited statics resolve
1006
+ * like JS's class-object prototype walk. Divergence 305's copy stance:
1007
+ * later writes to a writable static field don't flow into the record
1008
+ * (Node aliases the one class object). Null when any target field has
1009
+ * no projectable static. */
1010
+ classStaticsProjection(className: string, toId: string, loc: SrcLoc): IrExpr | null;
1011
+ /** Interned `%fn.width.<n>(f)` — the function-RETURN width adapter: a
1012
+ * zero-param `() => Wide[]` value flowing into a `() => Narrow[]` slot
1013
+ * (the createProxyServer getRoutes shape) wraps in a fresh closure that
1014
+ * calls the original and maps the result through the per-element record
1015
+ * width copy (%arr.width). The adapter is a factory lifted function
1016
+ * whose param the returned closure captures; each invocation of the
1017
+ * adapted value builds a FRESH array of narrowed records (the width
1018
+ * machinery's copy stance — callers see the values, not the identity).
1019
+ * Null when the return shapes aren't width-coercible; bounded to
1020
+ * zero-param signatures (the one observed site — widening needs a
1021
+ * param-forwarding story nothing drives yet). */
1022
+ funcReturnWidthAdapter(fromT: IrType & {
1023
+ kind: "func";
1024
+ }, toT: IrType & {
1025
+ kind: "func";
1026
+ }, loc: SrcLoc): string | null;
1027
+ /** Whether a `src`-typed VALUE converts into a `dst` slot through the
1028
+ * coercions coerceToExpected applies mechanically — the PURE probe
1029
+ * behind funcCoerceAdapter (nothing interns): exact types, arm wraps
1030
+ * into unions, whole-union re-tags (unionRetagMappable), checked
1031
+ * single-arm narrows, void into an undefined-armed union, and the dyn
1032
+ * boundary in both directions (dynFrom / dynCheck's JSON-safe domain).
1033
+ * Deliberately EXCLUDES the trap-only stranded conversions — an adapter
1034
+ * that could only ever throw is a fence, not a bridge. */
1035
+ coercibleValue(src: IrType, dst: IrType): boolean;
1036
+ /** Interned `%fn.adapt.<n>(f)` — the GENERAL function-value adapter: a
1037
+ * `fromT` function value flowing into a `toT` slot whose pieces differ
1038
+ * only by coercibleValue conversions. The slot's callers pass toT's
1039
+ * parameters: the wrapper takes them, converts the first
1040
+ * fromT.params.length into the wrapped function's own types (surplus
1041
+ * slot parameters are DROPPED — JS's extra-argument rule), calls it,
1042
+ * and converts the result back (a void slot drops the result; a void
1043
+ * result wraps as the slot union's undefined arm). Rest signatures on
1044
+ * either side decline (the pack shapes don't line up mechanically).
1045
+ * Null when any piece is outside coercibleValue — the exactness fences
1046
+ * stay. */
1047
+ funcCoerceAdapter(fromT: IrType & {
1048
+ kind: "func";
1049
+ }, toT: IrType & {
1050
+ kind: "func";
1051
+ }, loc: SrcLoc): string | null;
1052
+ /** The spawnSync-runner VALUE adapter's plan — a function returning the
1053
+ * opaque spawnRes flowing into a slot whose signature returns the
1054
+ * STRUCTURAL result record tsc accepted (`defaultRunner` into a
1055
+ * `CommandRunner` param: `{ status: number | null; stdout?: string;
1056
+ * stderr?: string; error?: Error }`). Parameters must agree pairwise;
1057
+ * each target field must be one of the spawnRes reads (status, stdout,
1058
+ * stderr, error) at its exact lowered type — string fields optionally
1059
+ * undefined-armed. Null when the pair isn't this shape. Pure: callers
1060
+ * probe before interning. */
1061
+ spawnResFnAdapterPlan(fromT: IrType & {
1062
+ kind: "func";
1063
+ }, toT: IrType & {
1064
+ kind: "func";
1065
+ }): {
1066
+ field: string;
1067
+ build: (r: IrExpr, loc: SrcLoc) => IrExpr;
1068
+ }[] | null;
1069
+ /** Interned `%fnval.spawnres.<n>(f)` — the runner-value adapter: a
1070
+ * fresh closure of the TARGET signature forwarding its arguments to the
1071
+ * captured function and converting the opaque spawnRes result into the
1072
+ * target's structural record (one eager read per declared field —
1073
+ * spawnResFnAdapterPlan's set). Divergence caveat: stdout/stderr read
1074
+ * as the captured text ("" when nothing was captured, e.g. stdio
1075
+ * "inherit") where Node stores null. */
1076
+ spawnResFnAdapter(fromT: IrType & {
1077
+ kind: "func";
1078
+ }, toT: IrType & {
1079
+ kind: "func";
1080
+ }, loc: SrcLoc): string | null;
1081
+ /** Interned `%union.retag.<n>(u)` — the runtime re-tag for a value of
1082
+ * union `fromId` flowing into a slot of union `toId`: a switch on the
1083
+ * source tag re-wraps the payload under its tag in the destination
1084
+ * (unionNarrow + unionWrap — the payload pointer moves, no copy, so
1085
+ * ref-arm identity is preserved across the re-tag). Arms map by
1086
+ * canonical type (typeEquals): every non-unit source arm must exist in
1087
+ * the destination, or the pair isn't mappable (null — the caller keeps
1088
+ * the SC2003 fence). A stranded UNIT arm (undefined/null with no
1089
+ * destination arm) is different: it means tsc's picture at the site was
1090
+ * NARROWER than the IR type — control-flow narrowing to a sub-union, or
1091
+ * a non-null assertion, both of which erase at lowering — so the arm is
1092
+ * exactly the possibility the checker proved (or the source asserted)
1093
+ * away. It compiles to a runtime trap case throwing a catchable
1094
+ * TypeError-shaped string, the lying-cast stance (SEMANTICS.md): sound
1095
+ * narrowing never reaches it, a lying `!` throws instead of smuggling
1096
+ * an unrepresentable unit into the destination. */
1097
+ /** True when unionRetagHelper can bridge the pair — every non-unit
1098
+ * source arm exists (typeEquals) in the destination, or width-lifts
1099
+ * into exactly one destination arm (widthLiftPlan — record and array
1100
+ * arms compose the re-tag with the per-arm reshape). Pure: callers that
1101
+ * must validate a WHOLE plan before interning anything (recordWidthHelper)
1102
+ * probe with this so a failed later field never orphans a helper. */
1103
+ unionRetagMappable(fromId: string, toId: string): boolean;
1104
+ /** A checker-NARROWED union flowing into a different union: `typeof r
1105
+ * === "string" || Buffer.isBuffer(r)` proves the record arm of r away,
1106
+ * then `{ data: r }` needs `Buffer | string | Rec` in a `Buffer | string`
1107
+ * slot. Control-flow narrowing to a sub-union erases at lowering, so the
1108
+ * IR value still carries the wide union — but the SITE's checker type
1109
+ * names exactly the arms still possible, and every one of those must
1110
+ * exist in both unions. The stranded arms compile to trap cases exactly
1111
+ * like stranded units (divergence 38's trust-the-checker stance): sound
1112
+ * narrowing never reaches them, a lying cast throws a catchable
1113
+ * TypeError instead of smuggling an unrepresentable arm. Null when the
1114
+ * site type isn't a genuine sub-union of the source (the SC2003 fence
1115
+ * stays). */
1116
+ narrowedRetagHelper(node: ts.Node, fromId: string, toId: string, loc: SrcLoc): string | null;
1117
+ /** The stranded-UNIT trap for PLAIN (non-union) slots: a null/undefined
1118
+ * value flowing into a non-nullable typed slot the checker approved —
1119
+ * `null!` and `null as any as T` casts, and the non-strict world's
1120
+ * legal `let s: string = null`. The compiled representation has no null
1121
+ * to carry, so the FLOW throws the catchable stranded TypeError
1122
+ * (divergence 38's stance: Node lets the impossible value ride until it
1123
+ * is used; the trap surfaces at the assignment instead). Unit sources
1124
+ * only — they are pure, so the nullary helper evaluates nothing. */
1125
+ strandedUnitTrap(expr: IrExpr, expected: IrType, loc: SrcLoc): IrExpr | null;
1126
+ /** The STRANDED-SOURCE trap: a checker-approved value flowing into a
1127
+ * union that cannot represent it (armTag < 0, no class widening, no
1128
+ * width lift). Only shapes that PROVE a lying assertion trap: unit
1129
+ * sources (null/undefined literals smuggled through `null!` / `as any`
1130
+ * casts), and record/array sources with ZERO same-family width-lift
1131
+ * candidates among the arms — an AMBIGUOUS lift (several candidates)
1132
+ * stays a compile fence, because honest code lands there. The interned
1133
+ * helper evaluates the operand (JS evaluates it too) and throws the
1134
+ * stranded-arm TypeError verbatim. Null when the shape doesn't prove
1135
+ * the lie. */
1136
+ strandedCoercionTrap(expr: IrExpr, expected: IrType & {
1137
+ kind: "union";
1138
+ }, loc: SrcLoc): IrExpr | null;
1139
+ unionRetagHelper(fromId: string, toId: string, loc: SrcLoc, trappable?: ReadonlySet<number>): string | null;
1140
+ /** Interned `%union.narrow.<n>(u)` — the CHECKED single-arm extraction
1141
+ * behind `x!` on union values: the asserted arm's payload comes out
1142
+ * (+1 for ref arms, like any unionNarrow), and every OTHER arm throws
1143
+ * the catchable TypeError — divergence 38's lying-assertion stance (an
1144
+ * unchecked unionNarrow would misread the payload where JS lets the
1145
+ * impossible value flow on). Null when the target isn't a non-unit arm
1146
+ * of the union — those uses keep their erasure/fences. */
1147
+ narrowedArmHelper(fromId: string, target: IrType, loc: SrcLoc): string | null;
1148
+ /** True when a static value can become ONE island value: jsval itself,
1149
+ * anything boundary-safe (the deep JSON marshal), a record whose fields
1150
+ * all can (built as an island OBJECT literal, field by field), or an
1151
+ * array of such (built as an island ARRAY, element by element). The
1152
+ * lift beyond boundarySafe exists for jsval-BEARING composites —
1153
+ * `{ role: string; content: any[] }[]` flowing into an `any[]` slot —
1154
+ * which have no JSON serialization (a handle isn't JSON) but an honest
1155
+ * per-field construction. Recursion terminates: recursive shapes are
1156
+ * rejected at mapping time. */
1157
+ jsvalLiftable(t: IrType): boolean;
1158
+ /** A jsval-typed expression carrying `e`'s value into the island —
1159
+ * jsvalLiftable's constructive side. Primitives and JSON-safe composites
1160
+ * keep the jsMarshal deep copy; jsval-bearing records and arrays go
1161
+ * through interned per-type builder helpers (%jsin.*), so the operand is
1162
+ * always evaluated exactly once (as the helper's argument). */
1163
+ jsvalLiftExpr(e: IrExpr, loc: SrcLoc): IrExpr;
1164
+ /** Interned `%jsin.union.<n>(u)` — the runtime tag switch marshaling a
1165
+ * union value INTO the island: unit arms become the engine's own
1166
+ * undefined/null (JS-exact — `{ instructions: undefined }` crossing in
1167
+ * has the property present and undefined, exactly what the source
1168
+ * spells), every other arm narrows and lifts as itself (strings by
1169
+ * value, JSON-safe composites as deep copies, typed arrays as engine
1170
+ * typed-array copies, URLs as engine URL instances). Caller must have
1171
+ * checked jsvalLiftable. */
1172
+ unionToJsvalHelper(unionId: string, loc: SrcLoc): string;
1173
+ /** Interned `%jsin.rec.<n>(r)` — builds an island OBJECT from a
1174
+ * jsval-bearing record: marshaled key strings, each field lifted through
1175
+ * jsvalLiftExpr (jsval fields pass as handles, JSON-safe fields deep-copy,
1176
+ * nested composites recurse through their own helpers). Caller must have
1177
+ * checked jsvalLiftable. */
1178
+ recordToJsvalHelper(shapeId: string, loc: SrcLoc): string;
1179
+ /** Interned `%jsin.arr.<n>(a)` — builds ONE island ARRAY from a native
1180
+ * array whose elements lift: out = []; for (...) out[i] = lift(a[i]);
1181
+ * return out. The index marshals by value like any number. Caller must
1182
+ * have checked jsvalLiftable of the element. */
1183
+ arrayToJsvalHelper(elem: IrType, loc: SrcLoc): string;
1184
+ /** Interned `%jsin.elems.<n>(a)` — a NATIVE array of island handles from
1185
+ * a native array whose elements lift: the `any[]`-slot coercion (each
1186
+ * element becomes one island value; the array stays static). Null when
1187
+ * the element doesn't lift. */
1188
+ arrayToJsvalArrayHelper(fromElem: IrType, loc: SrcLoc): string | null;
1189
+ jsvalIn(e: IrExpr, node: ts.Node): IrExpr;
1190
+ /** THE coercion path for values flowing into a typed slot: union arms
1191
+ * wrap implicitly (coerceToExpected), then the exact-type fence runs
1192
+ * (SC2002 for record shapes, SC2003 for unions). Every slot-directed
1193
+ * lowering goes through here (via lowerExprExpecting) or calls this
1194
+ * directly when the expression was already lowered. */
1195
+ coerceInto(node: ts.Node, expr: IrExpr, expected: IrType): IrExpr;
1196
+ /** The unit an 'any' expression PROVABLY holds on every run, or null
1197
+ * when no proof exists. Two spellings prove: the lowered value IS the
1198
+ * engine unit literal (`null as any`, an any-contextual `undefined`),
1199
+ * or the node is an identifier whose every declaration is a plain,
1200
+ * non-ambient `var`/`let`/`const` declarator under a variable STATEMENT
1201
+ * (catch bindings, for-of/for-in cursors, parameters, and imports all
1202
+ * fail this shape test — each receives values from elsewhere), each
1203
+ * initializer absent or unit-typed by the checker (a unit TYPE has
1204
+ * exactly one value, so syntax doesn't matter), and nothing in the
1205
+ * declaring file ever assigns it — bindingNeverReassigned, the same
1206
+ * file-scan proof the generic-binding machinery leans on (ESM import
1207
+ * bindings are read-only, so cross-file writes don't exist). A hoisted
1208
+ * `var` read before its unit-initialized statement holds undefined —
1209
+ * also a unit — so the mixed case reports both names. */
1210
+ provenUnitAnyOf(node: ts.Node, value: IrExpr): string | null;
1211
+ /** Lowers an expression that flows into a slot of a known expected type,
1212
+ * then applies the coercion path (coerceInto). An EMPTY array literal
1213
+ * takes the slot's array type directly — the caller-supplied `expected`
1214
+ * lowerArrayLiteral documents, for the positions where tsc's contextual
1215
+ * API answers nothing (binding-element defaults: `{ json = [] }`) and
1216
+ * the literal's own never[] would build the f64 representation. */
1217
+ lowerExprExpecting(node: ts.Expression, expected: IrType | undefined): IrExpr;
1218
+ /** A value flowing into an index-signature VALUE slot (an overflow
1219
+ * literal entry, a dynamic-keyed record write). dyn slots (`unknown`
1220
+ * signatures — ModelPricing's) take a DOM conversion: dyn values pass
1221
+ * through, JSON-safe static values convert with dynFrom (a deep copy —
1222
+ * the jsMarshal aliasing stance), everything else keeps the dyn-boundary
1223
+ * fence. Typed slots ride the ordinary coercion path (union slots wrap
1224
+ * arm values, exactness enforced). */
1225
+ intoIndexValueSlot(value: IrExpr, indexValue: IrType, node: ts.Node): IrExpr;
1226
+ /** IR-level `t | undefined` through the shared canonicalizer — the
1227
+ * declared result type of an index-signature read under
1228
+ * noUncheckedIndexedAccess. Null when the type cannot take the arm. */
1229
+ withUndefinedArmOf(t: IrType): IrType | null;
1230
+ /** True when a static type converts to a dyn DOM value (the dynFrom
1231
+ * walker's domain): JSON-safe, bytes<u8> (Uint8Array/Buffer — the DOM's
1232
+ * bytes kind, payload copied; stdin chunks into unknown-typed helpers),
1233
+ * an undefined-armed union whose other arms are JSON-safe — the
1234
+ * undefined arm becomes the undefined DOM singleton — or a BOXABLE
1235
+ * function type (the checked-dynamic function boundary: the closure
1236
+ * crosses as the DOM's callable kind, identity preserved). */
1237
+ dynConvertible(t: IrType): boolean;
1238
+ /** The value of a `return` statement. In an async function `return p`
1239
+ * where p is a promise flattens (JS: the returned promise's settlement
1240
+ * becomes the async function's result), so it lowers exactly as
1241
+ * `return await p` — the awaitExpr parks the fiber and re-throws
1242
+ * rejections, which IS the flattening. Everything else flows into the
1243
+ * function's return slot through the usual coercion path. */
1244
+ /** The value of `return <expr>` against the context's declared return —
1245
+ * or NULL for a bare return: `return undefined`/`return null` in a
1246
+ * void-returning function (`{ bar() { return undefined } }`, inferred
1247
+ * `() => null` shapes whose return maps to void) hands the caller JS's
1248
+ * undefined, which the void slot drops. Units are pure literals, so
1249
+ * nothing evaluates; unit-typed non-literals keep the fences. */
1250
+ lowerReturnValue(node: ts.Expression): IrExpr | null;
1251
+ /** `return <expr>` lowered as a STATEMENT against the declared return.
1252
+ * Void-returning contexts get the JS drop: a contextually void-typed
1253
+ * function may return a value (`fv = function() { return 0; }` into a
1254
+ * `() => void` slot) — the expression evaluates for its effects, the
1255
+ * caller never sees a value, so the return goes out bare. Async
1256
+ * void-inner returns still resolve a returned promise first. */
1257
+ lowerReturnStmt(node: ts.Expression, loc: SrcLoc): IrStmt;
1258
+ maybeNarrow(expr: IrExpr, node: ts.Node): IrExpr;
1259
+ lowerUnitComparison(left: IrExpr, right: IrExpr, negated: boolean, loc: SrcLoc): IrExpr | null;
1260
+ lowerNullishCoalesce(expr: ts.BinaryExpression, loc: SrcLoc): IrExpr;
1261
+ lowerOptionalChain(expr: ts.CallExpression | ts.PropertyAccessExpression | ts.ElementAccessExpression): IrExpr;
1262
+ finishOptionalChain(expr: ts.Expression, id: string, receiver: IrExpr, body: IrExpr, loc: SrcLoc): IrExpr;
1263
+ /** The union without `t`'s undefined arm (unchanged when there is none, or
1264
+ * when `t` isn't a union). The body-facing type of a defaulted parameter:
1265
+ * tsc types uses of `x: string | undefined = "hi"` as plain `string` inside
1266
+ * the body — the default removes exactly the undefined possibility. */
1267
+ stripUndefinedArm(t: IrType): IrType;
1268
+ /** The interned `T | undefined` union over a non-union arm type — the ABI
1269
+ * type of a defaulted parameter, and the result type of lookups that may
1270
+ * miss (process.env reads). "undefined" sorts last among all arm typeKeys,
1271
+ * so the sorted pair is always [t, undefined]. */
1272
+ withUndefinedArm(t: IrType): IrType;
1273
+ paramShape(param: ts.ParameterDeclaration): ParamShape;
1274
+ checkDefaultParamBodyType(param: ts.ParameterDeclaration, bodyType: IrType): void;
1275
+ paramShapes(params: readonly ts.ParameterDeclaration[]): ParamShape[];
1276
+ completeArgs(argNodes: readonly ts.Expression[], shapes: readonly ParamShape[], loc: SrcLoc, blame: ts.Node): IrExpr[];
1277
+ wrappedUndefined(type: IrType, loc: SrcLoc): IrExpr | null;
1278
+ /** The entry value of a binding JS initializes to `undefined` (an
1279
+ * initializer-less declaration, a hoisted `var` before its statement):
1280
+ * undefined-armed unions hold the interned undefined arm, and 'any'
1281
+ * slots hold the ENGINE's undefined — tsc's definite-assignment
1282
+ * analysis never guards `any` reads, so a jsval slot IS readable before
1283
+ * any assignment and must never stay a C-level NULL (a validated exit
1284
+ * or engine op on NULL is memory-unsafe, not a TypeError). Null for
1285
+ * every other type: tsc rejects their pre-assignment reads. */
1286
+ unassignedSlotInit(type: IrType, loc: SrcLoc): IrExpr | null;
1287
+ undefinedArgFor(type: IrType, loc: SrcLoc, blame: ts.Node): IrExpr;
1288
+ requireExactArityValue(blame: ts.Node, contextual: ts.Expression | null, shapes: readonly ParamShape[], funcType: IrType): void;
1289
+ bodyReturnType(isAsync: boolean, declared: IrType): IrType;
1290
+ genBodyReturnType(declared: IrType): IrType;
1291
+ declaredReturnType(decl: ts.SignatureDeclaration, blame: ts.Node): IrType;
1292
+ /** Runs one declaration's collection with diagnostics captured: on
1293
+ * poison, they DEFER under the declaration's symbol instead of failing
1294
+ * the build — an unreached broken declaration costs nothing; the first
1295
+ * reference flushes them (flushDeferred). A declaration with no name
1296
+ * symbol reports eagerly (nothing could ever reference it). */
1297
+ collectDeferring(symbolOf: () => ts.Symbol | undefined, collect: () => void): ts.Symbol | null;
1298
+ /** Pushes a symbol's deferred collection diagnostics: lowering resolved
1299
+ * a reference to it, so the declaration is part of what the entry runs.
1300
+ * The reference site then proceeds exactly as before (its own rejection
1301
+ * may follow) — reached-but-broken declarations report the same set of
1302
+ * diagnostics the eager collector historically produced. */
1303
+ flushDeferred(symbol: ts.Symbol): void;
1304
+ flushDeferredClass(className: string): void;
1305
+ collectSignature(decl: ts.FunctionDeclaration): void;
1306
+ collectSignatureInner(decl: ts.FunctionDeclaration): void;
1307
+ collectGenericSignature(decl: ts.FunctionDeclaration): void;
1308
+ genericFnOf(ident: ts.Identifier): GenericFnInfo | null;
1309
+ lowerGenericCall(expr: ts.CallExpression, info: GenericFnInfo): IrExpr;
1310
+ lowerGenericFnValue(ref: ts.Expression, info: GenericFnInfo): IrExpr;
1311
+ inferTypeParamBindings(expr: ts.CallExpression, info: GenericFnInfo, rsig: ts.Signature): Map<ts.Symbol, IrType>;
1312
+ lowerGenericInstance(info: GenericFnInfo, inst: GenericInstance): IrFunction;
1313
+ collectClassShape(decl: ts.ClassDeclaration): void;
1314
+ collectClassShapeInner(decl: ts.ClassLikeDeclaration, jsNameOverride?: string, inst?: {
1315
+ family: ClassInfo;
1316
+ name: string;
1317
+ bindings: Map<ts.Symbol, IrType>;
1318
+ typeArgsText: string;
1319
+ ordinal: number;
1320
+ }, mixin?: {
1321
+ base: ClassInfo;
1322
+ name: string;
1323
+ call: ts.CallExpression;
1324
+ bindings: Map<ts.Symbol, IrType>;
1325
+ context: string;
1326
+ ordinal: number;
1327
+ }): void;
1328
+ lowerClassExpressionInfo(expr: ts.ClassExpression): ClassInfo;
1329
+ lowerClassExpression(expr: ts.ClassExpression): IrExpr;
1330
+ findMethodOn(info: ClassInfo | null, name: string): {
1331
+ declarer: ClassInfo;
1332
+ sig: {
1333
+ params: ParamShape[];
1334
+ ret: IrType;
1335
+ abstract?: true;
1336
+ async?: true;
1337
+ };
1338
+ } | null;
1339
+ isSubclassOf(sub: string, sup: string): boolean;
1340
+ inHierarchy(info: ClassInfo): boolean;
1341
+ overrideBelow(info: ClassInfo, name: string): boolean;
1342
+ upcastTo(expr: IrExpr, className: string): IrExpr;
1343
+ /** True when `className` is the %Error root or any class inside its
1344
+ * hierarchy (builtin kinds and user `extends Error` subclasses). */
1345
+ errorHierarchyClassOf(className: string): boolean;
1346
+ classValueRef(info: ClassInfo, blame: ts.Node): IrExpr;
1347
+ /** Class EXPRESSIONS collected this run, in first-encounter order: the
1348
+ * emit pass lowers their members after the init bodies (declaration
1349
+ * members ride fp.classDecls; expressions register only when their
1350
+ * containing statement lowers). */
1351
+ readonly exprClasses: ClassInfo[];
1352
+ readonly exprClassInfoByNode: Map<ts.ClassExpression, ClassInfo>;
1353
+ /** Class expressions whose collection is IN FLIGHT — the reentrancy
1354
+ * guard for heritage-demanded collection (lowerClassExpressionInfo). */
1355
+ readonly collectingExprClasses: Set<ts.ClassExpression>;
1356
+ /** Static-init statements of class expressions inside the statement
1357
+ * currently lowering — lowerFileInit drains the buffer immediately
1358
+ * BEFORE that statement (JS's order for the supported whole-initializer
1359
+ * positions). */
1360
+ readonly pendingClassExprInits: IrStmt[];
1361
+ /** Discovery hook: registers a just-collected expression class's member
1362
+ * bodies as worklist units (the units map is otherwise built before
1363
+ * lowering starts). Null in the emit pass. */
1364
+ onExprClassCollected: ((info: ClassInfo) => void) | null;
1365
+ /** Mixin functions (`(Base: T) => class extends Base {…}`) by their
1366
+ * function-like node: recognized shape, or null for checked
1367
+ * non-qualifiers (lower-mixins.ts). */
1368
+ readonly mixinFnShapes: Map<ts.Node, MixinFnShape | null>;
1369
+ /** Mixin instantiations by CALL SITE (one class per once-evaluated call
1370
+ * — the class-expression identity rule); null marks a poisoned
1371
+ * instantiation so re-demands fence instead of half-collecting. */
1372
+ readonly mixinInstanceByCall: Map<ts.CallExpression, ClassInfo | null>;
1373
+ /** Mixin calls whose instantiation is IN FLIGHT — the cyclic-extends
1374
+ * backstop (the collectingExprClasses rule). */
1375
+ readonly mixinCollectingCalls: Set<ts.CallExpression>;
1376
+ /** Per mixin-class-node demand count: only the FIRST instantiation
1377
+ * counts statements toward coverage (the generic-instance rule). */
1378
+ readonly mixinOrdinals: Map<ts.ClassLikeDeclaration, number>;
1379
+ /** The mixin instantiation whose source is CURRENTLY collecting or
1380
+ * lowering: mapType resolves the inner class node's own instance type
1381
+ * (`this` inside members, self-referential fields) to THIS
1382
+ * instantiation — the shared AST means the checker keeps answering the
1383
+ * one class node for every instantiation, like generic bindings. */
1384
+ mixinTypeContext: {
1385
+ classNode: ts.ClassLikeDeclaration;
1386
+ className: string;
1387
+ } | null;
1388
+ /** PINNED mixin instantiations (const-binding / heritage call sites) by
1389
+ * their class node — the intersection resolver's candidate sets
1390
+ * (mixinIntersectionInstanceType). */
1391
+ readonly mixinInstancesByClassNode: Map<ts.ClassLikeDeclaration, ClassInfo[]>;
1392
+ mixinCallClassInfoOf(call: ts.CallExpression): ClassInfo | null;
1393
+ /** Generic classes (monomorphization by flow): declaration → the family's
1394
+ * instance table. Filled by collectClassShapeInner's family mode;
1395
+ * consulted by mapType's genericClassInstance hook. */
1396
+ readonly genericClassByDecl: Map<ts.ClassLikeDeclaration, GenericClassInfo>;
1397
+ /** Instantiations in demand order — the member-lowering worklist run()'s
1398
+ * monomorphization fixpoint drains (an instantiation's methods can
1399
+ * demand further instances of either kind). */
1400
+ readonly genericClassInstances: ClassInfo[];
1401
+ /** Discovery hook: a generic-class instantiation collected mid-lowering
1402
+ * (instantiations are demand-driven, not units — their members lower in
1403
+ * the instance drain). Null everywhere today; reserved for symmetry with
1404
+ * onExprClassCollected should instantiations ever need eager
1405
+ * registration. */
1406
+ onLateClassCollected: ((info: ClassInfo) => void) | null;
1407
+ genericClassInstanceType(decl: ts.ClassLikeDeclaration, ref: ts.Type): IrType | null;
1408
+ findStaticOn(info: ClassInfo | null, name: string): ReturnType<typeof findStaticOn>;
1409
+ staticShadowBelow(info: ClassInfo, name: string): boolean;
1410
+ ctorAbiEquals(sub: ClassInfo, sup: ClassInfo): boolean;
1411
+ exactClassOfReceiver(expr: ts.Expression): ClassInfo | null;
1412
+ lowerClassMembers(info: ClassInfo): IrFunction[];
1413
+ lowerStaticFieldInits(info: ClassInfo): IrStmt[];
1414
+ /** The method-like members (methods and accessors) of a class that have
1415
+ * lowerable bodies, with their collected method-map names. */
1416
+ classMethodMembers(info: ClassInfo): Generator<{
1417
+ mName: string;
1418
+ member: ts.MethodDeclaration | ts.AccessorDeclaration;
1419
+ }>;
1420
+ lowerClassCtor(info: ClassInfo): IrFunction;
1421
+ lowerClassMethodMember(info: ClassInfo, fnLike: ts.MethodDeclaration | ts.AccessorDeclaration): IrFunction | null;
1422
+ throwingSetterFn(info: ClassInfo, prop: string): IrFunction;
1423
+ fieldInitStmts(info: ClassInfo, thisLocal: IrLocal): IrStmt[];
1424
+ lowerDerivedCtorBody(info: ClassInfo, thisLocal: IrLocal, forward?: IrExpr[]): IrStmt[];
1425
+ superCallStmt(info: ClassInfo, thisLocal: IrLocal, args: IrExpr[], loc: SrcLoc): IrStmt;
1426
+ /** Declares the `this` param local, registered under the THIS_BINDING
1427
+ * sentinel so lexical-this capture in arrows uses the normal machinery. */
1428
+ declareThis(type: IrType): IrLocal;
1429
+ lowerFunction(decl: ts.FunctionDeclaration): IrFunction | null;
1430
+ collectGlobals(sf: ts.SourceFile, topStmts: ts.Statement[]): void;
1431
+ lowerFileInit(sf: ts.SourceFile, stmts: ts.Statement[], name: string): IrFunction;
1432
+ lowerDefaultExport(stmt: ts.ExportAssignment): IrStmt | null;
1433
+ buildMain(): IrFunction;
1434
+ declareLocal(nameNode: ts.Node, name: string, type: IrType, mutable: boolean): IrLocal;
1435
+ /** A function-scope local bound to NO ts.Symbol — the hidden ABI slot of a
1436
+ * defaulted parameter (the parameter's symbol binds to the separately-
1437
+ * declared body local; nothing in the source can name this one). */
1438
+ declareHiddenLocal(name: string, type: IrType): IrLocal;
1439
+ /** Declares a callee's parameter locals from its ParamShapes and builds
1440
+ * the DEFAULT-PARAM PROLOGUE. Required/optional/rest params bind their
1441
+ * symbol directly (one local of the ABI type). A defaulted param `x: T = e`
1442
+ * gets TWO locals: the hidden ABI slot (the incoming `T | undefined`
1443
+ * union) and the body local `x` of plain T, initialized by
1444
+ *
1445
+ * const x = <in> is undefined-arm ? e : narrow(<in>)
1446
+ *
1447
+ * — a lazily-branched ternary, so the default expression evaluates exactly
1448
+ * when the argument was omitted or undefined (JS's call-time rule), in the
1449
+ * callee scope, left-to-right across params (prologue order), and may
1450
+ * reference earlier params (their body locals are already bound) and
1451
+ * `this` in methods (param 0, declared before any of these). tsc rejects
1452
+ * self- and forward-references inside initializers. Must be called before
1453
+ * lowering the body; the returned prologue statements go first. */
1454
+ declareParams(rawDecls: readonly ts.ParameterDeclaration[], shapes: readonly ParamShape[]): {
1455
+ params: IrParam[];
1456
+ prologue: IrStmt[];
1457
+ };
1458
+ /** The binding for `symbol` inside context `ctx` — a scoped local or an
1459
+ * already-threaded capture entry. */
1460
+ bindingIn(ctx: FnCtx, symbol: ts.Symbol): IrLocal | null;
1461
+ /** Resolves an identifier to a local of the CURRENT function, creating
1462
+ * capture entries (and boxing the origin binding) when the name lives in
1463
+ * an enclosing function. Self-references of a named lambda are NOT
1464
+ * resolved here — callers check `isSelfReference` first. */
1465
+ resolveLocal(ident: ts.Identifier): IrLocal | null;
1466
+ /** Lexical `this` — the enclosing method's this-param, possibly captured
1467
+ * through arrows (function expressions/declarations reset `this` in JS;
1468
+ * their bodies never see an enclosing method's binding). */
1469
+ resolveThis(): IrLocal | null;
1470
+ resolveKey(symbol: ts.Symbol, blame?: ts.Node): IrLocal | null;
1471
+ isSelfReference(ident: ts.Identifier): boolean;
1472
+ lowerStmts(stmts: readonly ts.Statement[]): IrStmt[];
1473
+ noteBlockedBindings(stmt: ts.Statement): void;
1474
+ isBlockedBinding(symbol: ts.Symbol | null): boolean;
1475
+ /** The cascade rejection: an honest "inherits its declaration's blocker"
1476
+ * diagnostic (SC2004) when the symbol is a known-blocked binding, the
1477
+ * caller's own fallback otherwise. */
1478
+ rejectUnresolved(ident: ts.Identifier, fallback: string): never;
1479
+ rejectUnresolvedSymbol(symbol: ts.Symbol | null, name: string, node: ts.Node, fallback: string): never;
1480
+ lowerScopedBlock(stmt: ts.Statement): IrStmt[];
1481
+ /** Lowers inside a control-construct marker (loop/switch/labeled block/
1482
+ * try-with-finally/finally block) so the jump fences below know what a
1483
+ * break/continue/return crosses. `labels` carries the construct's JS
1484
+ * label names when the source statement was labeled — labeled jumps
1485
+ * resolve against them. */
1486
+ inCtl<T>(kind: "loop" | "switch" | "block" | "tryFinally" | "finallyBlock", fn: () => T, labels?: string[]): T;
1487
+ /** The label names a `lbl:` chain put on the statement currently being
1488
+ * lowered — set by lowerLabeled around lowering the labeled construct,
1489
+ * consumed exactly once by the construct's own lowering (takeLabels).
1490
+ * A lowering that never consumes them signals lowerLabeled to fence:
1491
+ * silently dropping a label would compile `break lbl` wrong. */
1492
+ pendingLabels: string[] | null;
1493
+ takeLabels(): string[] | undefined;
1494
+ rejectJumpCrossingFinally(kw: "break" | "continue" | "return", stmt: ts.Statement, label?: string): void;
1495
+ lowerStmt(stmt: ts.Statement): IrStmt | IrStmt[] | null;
1496
+ lowerVarStatement(stmt: ts.VariableStatement): IrStmt[];
1497
+ lowerDestructuringDecl(decl: ts.VariableDeclaration, isLet: boolean): IrStmt[];
1498
+ lowerDestructuringAssignParts(target: ts.ObjectLiteralExpression | ts.ArrayLiteralExpression, rhs: ts.Expression, loc: SrcLoc): {
1499
+ stmts: IrStmt[];
1500
+ value: IrExpr;
1501
+ };
1502
+ lowerBindingPattern(pattern: ts.ArrayBindingPattern | ts.ObjectBindingPattern, srcRef: () => IrExpr, srcType: IrType, isLet: boolean, out: IrStmt[]): void;
1503
+ checkBindingElement(el: ts.BindingElement, allowDefault?: boolean): void;
1504
+ bindPatternTarget(name: ts.BindingName, value: IrExpr, isLet: boolean, out: IrStmt[]): void;
1505
+ lowerVarDeclList(list: ts.VariableDeclarationList): IrStmt | null;
1506
+ lowerVarDecl(decl: ts.VariableDeclaration, isLet: boolean): IrStmt | null;
1507
+ lowerSwitch(stmt: ts.SwitchStatement): IrStmt;
1508
+ lowerTry(stmt: ts.TryStatement): IrStmt;
1509
+ lowerExprStatement(expr: ts.Expression): IrStmt;
1510
+ lowerForOf(stmt: ts.ForOfStatement): IrStmt;
1511
+ lowerForStatement(stmt: ts.ForStatement): IrStmt;
1512
+ lowerCondition(expr: ts.Expression): IrExpr;
1513
+ ensureBool(e: IrExpr, node: ts.Expression): IrExpr;
1514
+ requireTruthyUnion(unionId: string, node: ts.Expression): void;
1515
+ eqComparableUnion(unionId: string): boolean;
1516
+ lowerExpr(expr: ts.Expression): IrExpr;
1517
+ lowerIntrinsicProperty(expr: ts.PropertyAccessExpression): IrExpr | null;
1518
+ /** True for the STANDARD LIBRARY's source files: the shipped ambient
1519
+ * .d.ts files (core + overrides + fallback), a lib.*.d.ts bundled with the typescript
1520
+ * package (asked via program.isSourceFileDefaultLibrary, never by path
1521
+ * matching), or the ADOPTED @types/node surface standing in for the
1522
+ * fallback (see loadProgram — the lowering tables recognize the same
1523
+ * members by name + this provenance, and everything else those files
1524
+ * declare hits the SC2020-family fence). The file half of every
1525
+ * supported-surface provenance check. */
1526
+ readonly isStdlibFile: (sf: ts.SourceFile) => boolean;
1527
+ nodeTypesOnlySymbol(sym: ts.Symbol | null | undefined): boolean;
1528
+ /** True for an npm package's shipped declaration files — under
1529
+ * node_modules but NOT the standard library (typescript's own lib files
1530
+ * live under node_modules too), or inside a registered workspace-linked
1531
+ * package (a node_modules symlink whose realpath'd files carry no
1532
+ * node_modules segment — shared.ts). The provenance half of the npm
1533
+ * typing rule (package types are island handles) and of the per-package
1534
+ * requires-dynamic attribution. */
1535
+ readonly isNpmFile: (sf: ts.SourceFile) => boolean;
1536
+ npmPackageOf(type: ts.Type): string | null;
1537
+ npmMemberFence(access: ts.PropertyAccessExpression): void;
1538
+ npmPackageOfSymbol(sym: ts.Symbol | undefined): string | null;
1539
+ isStdlibMember(access: ts.PropertyAccessExpression): boolean;
1540
+ isStdlibSymbol(symbol: ts.Symbol | undefined): boolean;
1541
+ isStdlibGlobal(expr: ts.Expression, name: string): boolean;
1542
+ stdlibGlobalMember(access: ts.PropertyAccessExpression, name: string): string | null;
1543
+ lowerArrayLiteral(expr: ts.ArrayLiteralExpression, expected?: IrType & {
1544
+ kind: "array";
1545
+ }): IrExpr;
1546
+ lowerObjectLiteral(expr: ts.ObjectLiteralExpression): IrExpr;
1547
+ lowerShorthandValue(prop: ts.ShorthandPropertyAssignment): IrExpr;
1548
+ rejectThisInObjectMethod(node: ts.Node): void;
1549
+ lowerElementAccess(expr: ts.ElementAccessExpression): IrExpr;
1550
+ lowerRecordKeyRead(expr: ts.ElementAccessExpression, shapeId: string, shape: IrRecordShape): IrExpr;
1551
+ lowerElementWrite(expr: ts.BinaryExpression): IrStmt;
1552
+ ensureString(e: IrExpr, node: ts.Node): IrExpr;
1553
+ lowerTemplate(expr: ts.TemplateExpression): IrExpr;
1554
+ lowerAsExpression(expr: ts.AsExpression | ts.TypeAssertion): IrExpr;
1555
+ lowerPrefixUnary(expr: ts.PrefixUnaryExpression): IrExpr;
1556
+ lowerBinary(expr: ts.BinaryExpression): IrExpr;
1557
+ lowerCaughtTypeofTest(expr: ts.BinaryExpression, loc: SrcLoc): IrExpr | null;
1558
+ caughtRead(node: ts.Identifier, local: IrLocal, loc: SrcLoc): IrExpr;
1559
+ caughtLocalOf(node: ts.Expression): IrLocal | null;
1560
+ caughtToString(node: ts.Expression): IrExpr | null;
1561
+ lowerInstanceOf(expr: ts.BinaryExpression, loc: SrcLoc): IrExpr;
1562
+ lowerCall(expr: ts.CallExpression): IrExpr;
1563
+ isTopLevelFnSymbol(ident: ts.Identifier): boolean;
1564
+ lowerNestedFunctionDecl(stmt: ts.FunctionDeclaration): IrStmt;
1565
+ lambdaSignature(node: ts.ArrowFunction | ts.FunctionExpression | ts.FunctionDeclaration | ts.MethodDeclaration | ts.GetAccessorDeclaration | ts.SetAccessorDeclaration): {
1566
+ shapes: ParamShape[];
1567
+ funcType: IrType & {
1568
+ kind: "func";
1569
+ };
1570
+ };
1571
+ lowerLambda(node: ts.ArrowFunction | ts.FunctionExpression | ts.FunctionDeclaration | ts.MethodDeclaration | ts.GetAccessorDeclaration | ts.SetAccessorDeclaration): IrExpr;
1572
+ lowerArrayMethodCall(call: ts.CallExpression, access: ts.PropertyAccessExpression): IrExpr | null;
1573
+ lowerMapMethodCall(call: ts.CallExpression, access: ts.PropertyAccessExpression): IrExpr | null;
1574
+ lowerMapForEachCall(call: ts.CallExpression, receiver: IrExpr, mapT: IrType & {
1575
+ kind: "map";
1576
+ }): IrExpr;
1577
+ buildMapForEachFn(name: string, mapT: IrType & {
1578
+ kind: "map";
1579
+ }, arity: number, fnRet: IrType, loc: SrcLoc): IrFunction;
1580
+ lowerSetMethodCall(call: ts.CallExpression, access: ts.PropertyAccessExpression): IrExpr | null;
1581
+ lowerSetForEachCall(call: ts.CallExpression, receiver: IrExpr, setT: IrType & {
1582
+ kind: "set";
1583
+ }): IrExpr;
1584
+ buildSetForEachFn(name: string, setT: IrType & {
1585
+ kind: "set";
1586
+ }, arity: number, fnRet: IrType, loc: SrcLoc): IrFunction;
1587
+ lowerRegexLiteral(expr: ts.RegularExpressionLiteral): IrExpr;
1588
+ lowerRegexMethodCall(call: ts.CallExpression, access: ts.PropertyAccessExpression): IrExpr | null;
1589
+ lowerStringMethodCall(call: ts.CallExpression, access: ts.PropertyAccessExpression): IrExpr | null;
1590
+ lowerBytesNew(expr: ts.NewExpression, symbol: ts.Symbol | null | undefined): IrExpr | null;
1591
+ lowerBytesMethodCall(call: ts.CallExpression, access: ts.PropertyAccessExpression): IrExpr | null;
1592
+ lowerBufferStaticCall(call: ts.CallExpression, access: ts.PropertyAccessExpression): IrExpr | null;
1593
+ fieldTarget(access: ts.PropertyAccessExpression): FieldTarget | null;
1594
+ uniqueSymbolKeyOf(key: ts.Expression): {
1595
+ sym: ts.Symbol;
1596
+ fieldName: string;
1597
+ } | null;
1598
+ foldedStringKeyOf(expr: ts.Expression): string | null;
1599
+ accessorCall(className: string, member: string, obj: IrExpr, extraArgs: IrExpr[], ret: IrType, loc: SrcLoc): IrExpr;
1600
+ classIteratorOf(t: IrType): ClassIteratorInfo | null;
1601
+ classIteratorOpenCall(cit: ClassIteratorInfo, recv: IrExpr, loc: SrcLoc): IrExpr;
1602
+ classIteratorNextCall(cit: ClassIteratorInfo, itRef: IrExpr, loc: SrcLoc): IrExpr;
1603
+ classIteratorDrainCall(src: IrExpr, loc: SrcLoc, elemT?: IrType): IrExpr | null;
1604
+ classIteratorRestDrainCall(cit: ClassIteratorInfo, itVal: IrExpr, loc: SrcLoc): IrExpr;
1605
+ fieldGetExpr(target: FieldTarget, loc: SrcLoc, blame: ts.Node): IrExpr;
1606
+ fieldSetStmt(target: FieldTarget, value: IrExpr, loc: SrcLoc, blame: ts.Node): IrStmt;
1607
+ lowerFieldCompound(access: ts.PropertyAccessExpression | ts.ElementAccessExpression, op: CompoundOp, rhsNode: ts.Expression | null, loc: SrcLoc): IrStmt;
1608
+ errorMessageArg(args: readonly ts.Expression[], loc: SrcLoc, blame: ts.Node): IrExpr;
1609
+ inheritsBuiltinErrorCtor(info: ClassInfo): boolean;
1610
+ inheritsBuiltinEmitterCtor(info: ClassInfo): boolean;
1611
+ lowerNew(expr: ts.NewExpression): IrExpr;
1612
+ lowerFieldRead(expr: ts.PropertyAccessExpression): IrExpr | null;
1613
+ lowerUnionProperty(expr: ts.PropertyAccessExpression): IrExpr | null;
1614
+ lowerRecordFieldCall(call: ts.CallExpression, access: ts.PropertyAccessExpression): IrExpr | null;
1615
+ lowerObjectMethodCall(call: ts.CallExpression, access: ts.PropertyAccessExpression): IrExpr | null;
1616
+ lowerSuperMethodCall(call: ts.CallExpression, access: ts.PropertyAccessExpression): IrExpr;
1617
+ superThisRef(access: ts.PropertyAccessExpression): {
1618
+ thisRef: IrExpr;
1619
+ base: ClassInfo;
1620
+ };
1621
+ lowerSuperAccessorRead(access: ts.PropertyAccessExpression): IrExpr;
1622
+ lowerSuperAccessorWrite(access: ts.PropertyAccessExpression, rhs: ts.Expression, loc: SrcLoc): IrStmt;
1623
+ lowerComptime(expr: ts.CallExpression): IrExpr;
1624
+ comptimeBakeable(t: IrType): boolean;
1625
+ rejectComptimeCaptures(cb: ts.ArrowFunction | ts.FunctionExpression): void;
1626
+ comptimeValueToIr(value: unknown, expected: IrType, path: string, blame: ts.Node): IrExpr;
1627
+ isConsoleLog(call: ts.CallExpression): boolean;
1628
+ consoleCallMember(call: ts.CallExpression): "log" | "error" | "warn" | null;
1629
+ builtinImportOf(ident: ts.Identifier): {
1630
+ module: string;
1631
+ member: string;
1632
+ } | null;
1633
+ /** The namespace-import twin of builtinImportOf's provenance rule:
1634
+ * resolves an expression to the supported builtin MODULE whose members
1635
+ * it exposes — an identifier declared by `import * as ns from "node:fs"`
1636
+ * (through the symbol, so shadowing locals never match), or a nested
1637
+ * member access that IS a module in its own right (`fs.promises` — the
1638
+ * same object as node:fs/promises, Node's rule). Null otherwise. */
1639
+ builtinNamespaceModuleOf(expr: ts.Expression): string | null;
1640
+ /** A member access on a supported builtin namespace import —
1641
+ * `fs.readFileSync`, `path.sep`, `fs.promises.readFile` — as the same
1642
+ * { module, member } shape builtinImportOf gives named imports, so both
1643
+ * import forms key the same lowering tables. Null for everything else. */
1644
+ builtinMemberOf(access: ts.PropertyAccessExpression): {
1645
+ module: string;
1646
+ member: string;
1647
+ } | null;
1648
+ /** `ns.member(...)` on a builtin namespace import: exactly the named-
1649
+ * import dispatch — the module tables for lowered members, the module-
1650
+ * qualified per-member fence for the rest. Null for non-namespace
1651
+ * callees (the call chain keeps trying). */
1652
+ lowerNamespaceBuiltinCall(call: ts.CallExpression, access: ts.PropertyAccessExpression): IrExpr | null;
1653
+ /** `ns.member` on a builtin namespace import as a VALUE: constants
1654
+ * (path.sep, os.EOL) read as interned string literals; fs.constants
1655
+ * access-mode bits bake as numbers exactly like the named-import form;
1656
+ * functions have no closure representation (call sites only); members
1657
+ * with no lowering fence with the module-qualified name. Null for
1658
+ * non-namespace receivers (the property chain keeps trying). */
1659
+ lowerNamespaceBuiltinProperty(expr: ts.PropertyAccessExpression): IrExpr | null;
1660
+ lowerBuiltinModuleCall(expr: ts.CallExpression, bi: {
1661
+ module: string;
1662
+ member: string;
1663
+ }, fn: BuiltinModuleFn, loc: SrcLoc): IrExpr;
1664
+ lowerChildArgsArg(node: ts.Expression | undefined, loc: SrcLoc): IrExpr;
1665
+ lowerSpawnSyncCall(expr: ts.CallExpression, loc: SrcLoc): IrExpr;
1666
+ lowerSpawnCall(expr: ts.CallExpression, loc: SrcLoc): IrExpr;
1667
+ lowerExecSyncCall(expr: ts.CallExpression, shell: boolean, loc: SrcLoc): IrExpr;
1668
+ recordToEnvPairs(node: ts.Expression): IrExpr;
1669
+ envToPairsHelper(shapeId: string, loc: SrcLoc): string | null;
1670
+ lowerJsonMethodCall(call: ts.CallExpression, access: ts.PropertyAccessExpression): IrExpr | null;
1671
+ fencedBuiltinImportOf(ident: ts.Identifier): string | null;
1672
+ lowerCryptoComposedCall(call: ts.CallExpression, access: ts.PropertyAccessExpression): IrExpr | null;
1673
+ lowerUrlMethodCall(call: ts.CallExpression, access: ts.PropertyAccessExpression): IrExpr | null;
1674
+ lowerSearchParamsMethodCall(call: ts.CallExpression, access: ts.PropertyAccessExpression): IrExpr | null;
1675
+ lowerStatsMethodCall(call: ts.CallExpression, access: ts.PropertyAccessExpression): IrExpr | null;
1676
+ lowerChildMethodCall(call: ts.CallExpression, access: ts.PropertyAccessExpression): IrExpr | null;
1677
+ lowerAtomicsCall(call: ts.CallExpression, access: ts.PropertyAccessExpression): IrExpr | null;
1678
+ lowerNetModuleCall(expr: ts.CallExpression, bi: {
1679
+ module: string;
1680
+ member: string;
1681
+ }, loc: SrcLoc): IrExpr | null;
1682
+ lowerServerMethodCall(call: ts.CallExpression, access: ts.PropertyAccessExpression): IrExpr | null;
1683
+ lowerServerProperty(expr: ts.PropertyAccessExpression): IrExpr | null;
1684
+ lowerAssertModuleCall(expr: ts.CallExpression, bi: {
1685
+ module: string;
1686
+ member: string;
1687
+ }, loc: SrcLoc): IrExpr | null;
1688
+ lowerAssertDirectCall(expr: ts.CallExpression, loc: SrcLoc): IrExpr | null;
1689
+ lowerUtilModuleCall(expr: ts.CallExpression, bi: {
1690
+ module: string;
1691
+ member: string;
1692
+ }, loc: SrcLoc): IrExpr | null;
1693
+ lowerDgramDnsModuleCall(expr: ts.CallExpression, bi: {
1694
+ module: string;
1695
+ member: string;
1696
+ }, loc: SrcLoc): IrExpr | null;
1697
+ lowerDgramMethodCall(call: ts.CallExpression, access: ts.PropertyAccessExpression): IrExpr | null;
1698
+ lowerNodeTestModuleCall(expr: ts.CallExpression, bi: {
1699
+ module: string;
1700
+ member: string;
1701
+ }, loc: SrcLoc): IrExpr | null;
1702
+ lowerTestDirectCall(expr: ts.CallExpression, loc: SrcLoc): IrExpr | null;
1703
+ lowerTestMethodCall(call: ts.CallExpression, access: ts.PropertyAccessExpression): IrExpr | null;
1704
+ lowerTestCtxProperty(expr: ts.PropertyAccessExpression): IrExpr | null;
1705
+ lowerHttpHeadersElement(expr: ts.ElementAccessExpression): IrExpr | null;
1706
+ lowerJsonProperty(expr: ts.PropertyAccessExpression): IrExpr | null;
1707
+ lowerErrorCodeProperty(expr: ts.PropertyAccessExpression): IrExpr | null;
1708
+ lowerStringDecoderMethodCall(call: ts.CallExpression, access: ts.PropertyAccessExpression): IrExpr | null;
1709
+ lowerReadlineMethodCall(call: ts.CallExpression, access: ts.PropertyAccessExpression): IrExpr | null;
1710
+ lowerDcChannelMethodCall(call: ts.CallExpression, access: ts.PropertyAccessExpression): IrExpr | null;
1711
+ lowerAlsMethodCall(call: ts.CallExpression, access: ts.PropertyAccessExpression): IrExpr | null;
1712
+ lowerDcChannelProperty(access: ts.PropertyAccessExpression): IrExpr | null;
1713
+ lowerDcTracingChannelMethodCall(call: ts.CallExpression, access: ts.PropertyAccessExpression): IrExpr | null;
1714
+ lowerDcTracingChannelProperty(access: ts.PropertyAccessExpression): IrExpr | null;
1715
+ strdecHelper(op: "write" | "end", shapeId: string, loc: SrcLoc): string;
1716
+ lowerProcessProperty(expr: ts.PropertyAccessExpression): IrExpr | null;
1717
+ lowerFsConstantsProperty(expr: ts.PropertyAccessExpression): IrExpr | null;
1718
+ lowerHttp2ConstantsProperty(expr: ts.PropertyAccessExpression): IrExpr | null;
1719
+ http2ConstantBindingOf(ident: ts.Identifier): IrExpr | null;
1720
+ http2ConstantsDestructureDecl(nameNode: ts.Node, init: ts.Expression | undefined): boolean;
1721
+ lowerProcessStreamProperty(expr: ts.PropertyAccessExpression): IrExpr | null;
1722
+ isProcessEnv(node: ts.Expression): boolean;
1723
+ envValueType(): IrType;
1724
+ lowerProcessEnvGet(expr: ts.PropertyAccessExpression): IrExpr | null;
1725
+ lowerProcessMethodCall(call: ts.CallExpression, access: ts.PropertyAccessExpression): IrExpr | null;
1726
+ lowerProcessOptionalMethodCall(call: ts.CallExpression): IrExpr | null;
1727
+ lowerTimeoutMethodCall(call: ts.CallExpression, access: ts.PropertyAccessExpression): IrExpr | null;
1728
+ promisifiedExecFileDecl(nameNode: ts.Node, init: ts.Expression | undefined): boolean;
1729
+ lowerExecFileAsyncCall(expr: ts.CallExpression, loc: SrcLoc): IrExpr;
1730
+ execFileAsyncHelper(loc: SrcLoc): {
1731
+ name: string;
1732
+ shapeId: string;
1733
+ };
1734
+ envSnapshotHelper(shapeId: string, loc: SrcLoc): string | null;
1735
+ lowerNumberStaticCall(call: ts.CallExpression, access: ts.PropertyAccessExpression): IrExpr | null;
1736
+ lowerDateCall(call: ts.CallExpression, access: ts.PropertyAccessExpression): IrExpr | null;
1737
+ lowerTextCodecCall(call: ts.CallExpression, access: ts.PropertyAccessExpression): IrExpr | null;
1738
+ lowerStringStaticCall(call: ts.CallExpression, access: ts.PropertyAccessExpression): IrExpr | null;
1739
+ lowerStringLastIndexOfCall(call: ts.CallExpression, access: ts.PropertyAccessExpression): IrExpr | null;
1740
+ lowerFilterNarrowCall(call: ts.CallExpression, access: ts.PropertyAccessExpression): IrExpr | null;
1741
+ lowerPromiseMethodCall(call: ts.CallExpression, access: ts.PropertyAccessExpression): IrExpr | null;
1742
+ lowerPromiseStaticCall(call: ts.CallExpression, access: ts.PropertyAccessExpression): IrExpr | null;
1743
+ lowerNumberStaticProperty(expr: ts.PropertyAccessExpression): IrExpr | null;
1744
+ requireDynamicApi(feature: string, node: ts.Node): void;
1745
+ lowerMathProperty(expr: ts.PropertyAccessExpression): IrExpr | null;
1746
+ islandGlobalFnOf(ident: ts.Identifier): IslandFnEntry | null;
1747
+ lowerIslandMethodCall(call: ts.CallExpression, access: ts.PropertyAccessExpression): IrExpr | null;
1748
+ }