@scriptc/compiler 0.0.35 → 0.1.1

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 (439) hide show
  1. package/ambient/scriptc-node-fallback.d.ts +14 -11
  2. package/ambient/scriptc-overrides.d.ts +0 -7
  3. package/ambient/scriptc.d.ts +1 -1
  4. package/dist/backend/build-cache.d.ts +44 -0
  5. package/dist/backend/build-cache.js +241 -0
  6. package/dist/backend/build-cache.js.map +1 -0
  7. package/dist/backend/{emission/emit-async.d.ts → c/async.d.ts} +21 -30
  8. package/dist/backend/{emission/emit-async.js → c/async.js} +270 -286
  9. package/dist/backend/c/async.js.map +1 -0
  10. package/dist/backend/{emission/emitter.d.ts → c/c-emitter.d.ts} +6 -23
  11. package/dist/backend/{emission/emitter.js → c/c-emitter.js} +53 -107
  12. package/dist/backend/c/c-emitter.js.map +1 -0
  13. package/dist/backend/c/exprs.d.ts +8 -0
  14. package/dist/backend/c/exprs.js +7937 -0
  15. package/dist/backend/c/exprs.js.map +1 -0
  16. package/dist/backend/{emission/emit-island.d.ts → c/island.d.ts} +5 -5
  17. package/dist/backend/{emission/emit-island.js → c/island.js} +24 -22
  18. package/dist/backend/c/island.js.map +1 -0
  19. package/dist/backend/{emission → c}/may-throw.d.ts +1 -1
  20. package/dist/backend/{emission → c}/may-throw.js +4 -1
  21. package/dist/backend/c/may-throw.js.map +1 -0
  22. package/dist/backend/{emission/emit-shapes.d.ts → c/shapes.d.ts} +19 -19
  23. package/dist/backend/{emission/emit-shapes.js → c/shapes.js} +78 -87
  24. package/dist/backend/c/shapes.js.map +1 -0
  25. package/dist/backend/{emission/emit-stmts.d.ts → c/stmts.d.ts} +12 -12
  26. package/dist/backend/{emission/emit-stmts.js → c/stmts.js} +395 -343
  27. package/dist/backend/c/stmts.js.map +1 -0
  28. package/dist/backend/{emission/emit-types.d.ts → c/types.d.ts} +1 -1
  29. package/dist/backend/{emission/emit-types.js → c/types.js} +42 -286
  30. package/dist/backend/c/types.js.map +1 -0
  31. package/dist/backend/c/types.test.js +25 -0
  32. package/dist/backend/c/types.test.js.map +1 -0
  33. package/dist/backend/{emission/emit-walkers.d.ts → c/walkers.d.ts} +19 -41
  34. package/dist/backend/{emission/emit-walkers.js → c/walkers.js} +242 -304
  35. package/dist/backend/c/walkers.js.map +1 -0
  36. package/dist/backend/external-c.d.ts +33 -0
  37. package/dist/backend/external-c.js +51 -0
  38. package/dist/backend/external-c.js.map +1 -0
  39. package/dist/backend/ffi-callbacks.d.ts +1 -1
  40. package/dist/backend/ffi-callbacks.js +4 -3
  41. package/dist/backend/ffi-callbacks.js.map +1 -1
  42. package/dist/backend/{library-identity.d.ts → library-identity-markers.d.ts} +0 -4
  43. package/dist/backend/{library-identity.js → library-identity-markers.js} +10 -9
  44. package/dist/backend/library-identity-markers.js.map +1 -0
  45. package/dist/backend/link-plan.d.ts +37 -0
  46. package/dist/backend/link-plan.js +26 -0
  47. package/dist/backend/link-plan.js.map +1 -0
  48. package/dist/backend/linker.d.ts +22 -0
  49. package/dist/backend/linker.js +236 -0
  50. package/dist/backend/linker.js.map +1 -0
  51. package/dist/backend/llvm/blocks.d.ts +4 -0
  52. package/dist/backend/llvm/blocks.js +29 -0
  53. package/dist/backend/llvm/blocks.js.map +1 -1
  54. package/dist/backend/llvm/classes.d.ts +2 -19
  55. package/dist/backend/llvm/classes.js +20 -52
  56. package/dist/backend/llvm/classes.js.map +1 -1
  57. package/dist/backend/llvm/common.d.ts +4 -0
  58. package/dist/backend/llvm/common.js +27 -0
  59. package/dist/backend/llvm/common.js.map +1 -0
  60. package/dist/backend/llvm/dyn.d.ts +3 -8
  61. package/dist/backend/llvm/dyn.js +159 -224
  62. package/dist/backend/llvm/dyn.js.map +1 -1
  63. package/dist/backend/llvm/emitter.d.ts +4 -1
  64. package/dist/backend/llvm/emitter.js +548 -9988
  65. package/dist/backend/llvm/emitter.js.map +1 -1
  66. package/dist/backend/llvm/expr-async.d.ts +4 -0
  67. package/dist/backend/llvm/expr-async.js +726 -0
  68. package/dist/backend/llvm/expr-async.js.map +1 -0
  69. package/dist/backend/llvm/expr-bytes.d.ts +13 -0
  70. package/dist/backend/llvm/expr-bytes.js +456 -0
  71. package/dist/backend/llvm/expr-bytes.js.map +1 -0
  72. package/dist/backend/llvm/expr-callbacks.d.ts +22 -0
  73. package/dist/backend/llvm/expr-callbacks.js +520 -0
  74. package/dist/backend/llvm/expr-callbacks.js.map +1 -0
  75. package/dist/backend/llvm/expr-calls.d.ts +2 -0
  76. package/dist/backend/llvm/expr-calls.js +618 -0
  77. package/dist/backend/llvm/expr-calls.js.map +1 -0
  78. package/dist/backend/llvm/expr-containers.d.ts +25 -0
  79. package/dist/backend/llvm/expr-containers.js +637 -0
  80. package/dist/backend/llvm/expr-containers.js.map +1 -0
  81. package/dist/backend/llvm/expr-context.d.ts +255 -0
  82. package/dist/backend/llvm/expr-context.js +2 -0
  83. package/dist/backend/llvm/expr-context.js.map +1 -0
  84. package/dist/backend/llvm/expr-control.d.ts +2 -0
  85. package/dist/backend/llvm/expr-control.js +473 -0
  86. package/dist/backend/llvm/expr-control.js.map +1 -0
  87. package/dist/backend/llvm/expr-dispatch.d.ts +4 -0
  88. package/dist/backend/llvm/expr-dispatch.js +153 -0
  89. package/dist/backend/llvm/expr-dispatch.js.map +1 -0
  90. package/dist/backend/llvm/expr-dynamic.d.ts +2 -0
  91. package/dist/backend/llvm/expr-dynamic.js +810 -0
  92. package/dist/backend/llvm/expr-dynamic.js.map +1 -0
  93. package/dist/backend/llvm/expr-island.d.ts +15 -0
  94. package/dist/backend/llvm/expr-island.js +690 -0
  95. package/dist/backend/llvm/expr-island.js.map +1 -0
  96. package/dist/backend/llvm/expr-primitives.d.ts +6 -0
  97. package/dist/backend/llvm/expr-primitives.js +642 -0
  98. package/dist/backend/llvm/expr-primitives.js.map +1 -0
  99. package/dist/backend/llvm/expr-records.d.ts +9 -0
  100. package/dist/backend/llvm/expr-records.js +299 -0
  101. package/dist/backend/llvm/expr-records.js.map +1 -0
  102. package/dist/backend/llvm/expr-stream-bridges.d.ts +13 -0
  103. package/dist/backend/llvm/expr-stream-bridges.js +420 -0
  104. package/dist/backend/llvm/expr-stream-bridges.js.map +1 -0
  105. package/dist/backend/llvm/expr-stream-callbacks.d.ts +12 -0
  106. package/dist/backend/llvm/expr-stream-callbacks.js +360 -0
  107. package/dist/backend/llvm/expr-stream-callbacks.js.map +1 -0
  108. package/dist/backend/llvm/lib-dispatch.d.ts +5 -0
  109. package/dist/backend/llvm/lib-dispatch.js +267 -0
  110. package/dist/backend/llvm/lib-dispatch.js.map +1 -0
  111. package/dist/backend/llvm/lib-filesystem.d.ts +6 -0
  112. package/dist/backend/llvm/lib-filesystem.js +594 -0
  113. package/dist/backend/llvm/lib-filesystem.js.map +1 -0
  114. package/dist/backend/llvm/lib-network.d.ts +2 -0
  115. package/dist/backend/llvm/lib-network.js +429 -0
  116. package/dist/backend/llvm/lib-network.js.map +1 -0
  117. package/dist/backend/llvm/lib-process.d.ts +5 -0
  118. package/dist/backend/llvm/lib-process.js +585 -0
  119. package/dist/backend/llvm/lib-process.js.map +1 -0
  120. package/dist/backend/llvm/lib-shared.d.ts +6 -0
  121. package/dist/backend/llvm/lib-shared.js +687 -0
  122. package/dist/backend/llvm/lib-shared.js.map +1 -0
  123. package/dist/backend/llvm/lib-stream.d.ts +2 -0
  124. package/dist/backend/llvm/lib-stream.js +470 -0
  125. package/dist/backend/llvm/lib-stream.js.map +1 -0
  126. package/dist/backend/llvm/shapes.d.ts +12 -2
  127. package/dist/backend/llvm/shapes.js +66 -307
  128. package/dist/backend/llvm/shapes.js.map +1 -1
  129. package/dist/backend/llvm/shapes.test.js +52 -0
  130. package/dist/backend/llvm/shapes.test.js.map +1 -0
  131. package/dist/backend/llvm/unsupported.d.ts +1 -1
  132. package/dist/backend/llvm/walkers.d.ts +2 -3
  133. package/dist/backend/llvm/walkers.js +195 -222
  134. package/dist/backend/llvm/walkers.js.map +1 -1
  135. package/dist/backend/native-codegen.d.ts +45 -0
  136. package/dist/backend/native-codegen.js +275 -0
  137. package/dist/backend/native-codegen.js.map +1 -0
  138. package/dist/backend/native-codegen.test.js +226 -0
  139. package/dist/backend/native-codegen.test.js.map +1 -0
  140. package/dist/backend/native-link-info.d.ts +96 -0
  141. package/dist/backend/native-link-info.js +243 -0
  142. package/dist/backend/native-link-info.js.map +1 -0
  143. package/dist/backend/native-link-info.test.d.ts +1 -0
  144. package/dist/backend/native-link-info.test.js +134 -0
  145. package/dist/backend/native-link-info.test.js.map +1 -0
  146. package/dist/backend/{cc.d.ts → native-toolchain.d.ts} +54 -34
  147. package/dist/backend/{cc.js → native-toolchain.js} +231 -810
  148. package/dist/backend/native-toolchain.js.map +1 -0
  149. package/dist/backend/native-toolchain.test.d.ts +1 -0
  150. package/dist/backend/{cc-cache.test.js → native-toolchain.test.js} +219 -7
  151. package/dist/backend/native-toolchain.test.js.map +1 -0
  152. package/dist/backend/object-localize.js +1 -1
  153. package/dist/backend/runtime-abi.d.ts +10 -0
  154. package/dist/backend/runtime-abi.js +11 -0
  155. package/dist/backend/runtime-abi.js.map +1 -0
  156. package/dist/backend/runtime-pack-targets.test.d.ts +1 -0
  157. package/dist/backend/runtime-pack-targets.test.js +54 -0
  158. package/dist/backend/runtime-pack-targets.test.js.map +1 -0
  159. package/dist/backend/runtime-pack.d.ts +112 -0
  160. package/dist/backend/runtime-pack.js +305 -0
  161. package/dist/backend/runtime-pack.js.map +1 -0
  162. package/dist/backend/runtime-pack.test.d.ts +1 -0
  163. package/dist/backend/runtime-pack.test.js +473 -0
  164. package/dist/backend/runtime-pack.test.js.map +1 -0
  165. package/dist/backend/targets.d.ts +76 -0
  166. package/dist/backend/targets.js +262 -0
  167. package/dist/backend/targets.js.map +1 -0
  168. package/dist/backend/targets.test.d.ts +1 -0
  169. package/dist/backend/targets.test.js +41 -0
  170. package/dist/backend/targets.test.js.map +1 -0
  171. package/dist/backend/vendor-archives.d.ts +41 -0
  172. package/dist/backend/vendor-archives.js +462 -0
  173. package/dist/backend/vendor-archives.js.map +1 -0
  174. package/dist/compat/fetch-profile.d.ts +0 -1
  175. package/dist/compat/fetch-profile.js +0 -1
  176. package/dist/compat/fetch-profile.js.map +1 -1
  177. package/dist/coverage/report.js +3 -3
  178. package/dist/coverage/report.js.map +1 -1
  179. package/dist/coverage/surface-manifest.js +35 -33
  180. package/dist/coverage/surface-manifest.js.map +1 -1
  181. package/dist/diagnostics/diagnostic.d.ts +11 -12
  182. package/dist/diagnostics/diagnostic.js +19 -17
  183. package/dist/diagnostics/diagnostic.js.map +1 -1
  184. package/dist/diagnostics/render.d.ts +1 -1
  185. package/dist/diagnostics/render.js +1 -1
  186. package/dist/diagnostics/render.js.map +1 -1
  187. package/dist/errors.d.ts +5 -0
  188. package/dist/errors.js +9 -0
  189. package/dist/errors.js.map +1 -0
  190. package/dist/executable/{early-cache.d.ts → executable-cache.d.ts} +2 -2
  191. package/dist/executable/{early-cache.js → executable-cache.js} +36 -98
  192. package/dist/executable/executable-cache.js.map +1 -0
  193. package/dist/executable/executable-cache.test.d.ts +1 -0
  194. package/dist/executable/{early-cache.test.js → executable-cache.test.js} +3 -3
  195. package/dist/executable/executable-cache.test.js.map +1 -0
  196. package/dist/ffi/{profile.js → ffi-manifest.js} +1 -1
  197. package/dist/ffi/ffi-manifest.js.map +1 -0
  198. package/dist/frontend/builtin-modules.d.ts +21 -0
  199. package/dist/frontend/builtin-modules.js +82 -0
  200. package/dist/frontend/builtin-modules.js.map +1 -0
  201. package/dist/frontend/cjs-lexer.d.ts +7 -0
  202. package/dist/frontend/cjs-lexer.js +15 -17
  203. package/dist/frontend/cjs-lexer.js.map +1 -1
  204. package/dist/frontend/dts-paths.d.ts +26 -0
  205. package/dist/frontend/dts-paths.js +41 -0
  206. package/dist/frontend/dts-paths.js.map +1 -0
  207. package/dist/frontend/input-tracker.d.ts +0 -2
  208. package/dist/frontend/input-tracker.js +1 -4
  209. package/dist/frontend/input-tracker.js.map +1 -1
  210. package/dist/frontend/lib-contract.d.ts +1 -5
  211. package/dist/frontend/lib-contract.js +1 -1
  212. package/dist/frontend/lib-contract.js.map +1 -1
  213. package/dist/frontend/lib-exports.d.ts +1 -1
  214. package/dist/frontend/lowering/array-values.d.ts +8 -0
  215. package/dist/frontend/lowering/array-values.js +60 -0
  216. package/dist/frontend/lowering/array-values.js.map +1 -0
  217. package/dist/frontend/lowering/call-position.d.ts +4 -0
  218. package/dist/frontend/lowering/call-position.js +7 -0
  219. package/dist/frontend/lowering/call-position.js.map +1 -0
  220. package/dist/frontend/lowering/callback-arg.d.ts +20 -0
  221. package/dist/frontend/lowering/callback-arg.js +44 -0
  222. package/dist/frontend/lowering/callback-arg.js.map +1 -0
  223. package/dist/frontend/lowering/lib-boundary.d.ts +1 -1
  224. package/dist/frontend/lowering/lib-boundary.js +34 -34
  225. package/dist/frontend/lowering/lib-boundary.js.map +1 -1
  226. package/dist/frontend/lowering/lower-array-sort.d.ts +22 -0
  227. package/dist/frontend/lowering/lower-array-sort.js +619 -0
  228. package/dist/frontend/lowering/lower-array-sort.js.map +1 -0
  229. package/dist/frontend/lowering/lower-assert.d.ts +3 -3
  230. package/dist/frontend/lowering/lower-assert.js +214 -241
  231. package/dist/frontend/lowering/lower-assert.js.map +1 -1
  232. package/dist/frontend/lowering/lower-builtins.d.ts +74 -146
  233. package/dist/frontend/lowering/lower-builtins.js +1285 -1233
  234. package/dist/frontend/lowering/lower-builtins.js.map +1 -1
  235. package/dist/frontend/lowering/lower-calls.d.ts +59 -192
  236. package/dist/frontend/lowering/lower-calls.js +1644 -1506
  237. package/dist/frontend/lowering/lower-calls.js.map +1 -1
  238. package/dist/frontend/lowering/lower-classes.d.ts +62 -125
  239. package/dist/frontend/lowering/lower-classes.js +832 -866
  240. package/dist/frontend/lowering/lower-classes.js.map +1 -1
  241. package/dist/frontend/lowering/lower-comptime.d.ts +5 -12
  242. package/dist/frontend/lowering/lower-comptime.js +32 -31
  243. package/dist/frontend/lowering/lower-comptime.js.map +1 -1
  244. package/dist/frontend/lowering/lower-containers.d.ts +35 -135
  245. package/dist/frontend/lowering/lower-containers.js +1984 -2227
  246. package/dist/frontend/lowering/lower-containers.js.map +1 -1
  247. package/dist/frontend/lowering/lower-dgram.d.ts +3 -7
  248. package/dist/frontend/lowering/lower-dgram.js +97 -111
  249. package/dist/frontend/lowering/lower-dgram.js.map +1 -1
  250. package/dist/frontend/lowering/lower-enums.d.ts +4 -4
  251. package/dist/frontend/lowering/lower-enums.js +30 -30
  252. package/dist/frontend/lowering/lower-enums.js.map +1 -1
  253. package/dist/frontend/lowering/{lower-emitter.d.ts → lower-event-emitter.d.ts} +7 -18
  254. package/dist/frontend/lowering/{lower-emitter.js → lower-event-emitter.js} +172 -174
  255. package/dist/frontend/lowering/lower-event-emitter.js.map +1 -0
  256. package/dist/frontend/lowering/lower-expando.d.ts +5 -5
  257. package/dist/frontend/lowering/lower-expando.js +40 -40
  258. package/dist/frontend/lowering/lower-expando.js.map +1 -1
  259. package/dist/frontend/lowering/lower-exprs.d.ts +60 -264
  260. package/dist/frontend/lowering/lower-exprs.js +2361 -1765
  261. package/dist/frontend/lowering/lower-exprs.js.map +1 -1
  262. package/dist/frontend/lowering/lower-generators.d.ts +6 -6
  263. package/dist/frontend/lowering/lower-generators.js +73 -72
  264. package/dist/frontend/lowering/lower-generators.js.map +1 -1
  265. package/dist/frontend/lowering/lower-inspect.d.ts +5 -17
  266. package/dist/frontend/lowering/lower-inspect.js +273 -261
  267. package/dist/frontend/lowering/lower-inspect.js.map +1 -1
  268. package/dist/frontend/lowering/lower-island.d.ts +39 -49
  269. package/dist/frontend/lowering/lower-island.js +447 -513
  270. package/dist/frontend/lowering/lower-island.js.map +1 -1
  271. package/dist/frontend/lowering/lower-mixins.d.ts +7 -10
  272. package/dist/frontend/lowering/lower-mixins.js +85 -85
  273. package/dist/frontend/lowering/lower-mixins.js.map +1 -1
  274. package/dist/frontend/lowering/lower-modules.d.ts +12 -18
  275. package/dist/frontend/lowering/lower-modules.js +284 -283
  276. package/dist/frontend/lowering/lower-modules.js.map +1 -1
  277. package/dist/frontend/lowering/lower-namespaces.d.ts +23 -49
  278. package/dist/frontend/lowering/lower-namespaces.js +123 -115
  279. package/dist/frontend/lowering/lower-namespaces.js.map +1 -1
  280. package/dist/frontend/lowering/lower-server.d.ts +18 -25
  281. package/dist/frontend/lowering/lower-server.js +909 -899
  282. package/dist/frontend/lowering/lower-server.js.map +1 -1
  283. package/dist/frontend/lowering/lower-stmts.d.ts +30 -149
  284. package/dist/frontend/lowering/lower-stmts.js +1463 -1285
  285. package/dist/frontend/lowering/lower-stmts.js.map +1 -1
  286. package/dist/frontend/lowering/lower-stream.d.ts +12 -12
  287. package/dist/frontend/lowering/lower-stream.js +300 -301
  288. package/dist/frontend/lowering/lower-stream.js.map +1 -1
  289. package/dist/frontend/lowering/lower-test.d.ts +5 -5
  290. package/dist/frontend/lowering/lower-test.js +82 -82
  291. package/dist/frontend/lowering/lower-test.js.map +1 -1
  292. package/dist/frontend/lowering/lowerer.d.ts +134 -22
  293. package/dist/frontend/lowering/lowerer.js +1277 -126
  294. package/dist/frontend/lowering/lowerer.js.map +1 -1
  295. package/dist/frontend/lowering/pairs-snapshot.d.ts +11 -0
  296. package/dist/frontend/lowering/pairs-snapshot.js +85 -0
  297. package/dist/frontend/lowering/pairs-snapshot.js.map +1 -0
  298. package/dist/frontend/lowering/static-this.d.ts +6 -0
  299. package/dist/frontend/lowering/static-this.js +24 -0
  300. package/dist/frontend/lowering/static-this.js.map +1 -0
  301. package/dist/frontend/lowering/surfaces.d.ts +24 -35
  302. package/dist/frontend/lowering/surfaces.js +78 -66
  303. package/dist/frontend/lowering/surfaces.js.map +1 -1
  304. package/dist/frontend/npm-static-rewrite.js +6 -28
  305. package/dist/frontend/npm-static-rewrite.js.map +1 -1
  306. package/dist/frontend/npm-static.d.ts +0 -10
  307. package/dist/frontend/npm-static.js +4 -7
  308. package/dist/frontend/npm-static.js.map +1 -1
  309. package/dist/frontend/npm.d.ts +0 -24
  310. package/dist/frontend/npm.js +11 -85
  311. package/dist/frontend/npm.js.map +1 -1
  312. package/dist/frontend/program.d.ts +3 -1
  313. package/dist/frontend/program.js +9 -4
  314. package/dist/frontend/program.js.map +1 -1
  315. package/dist/frontend/provenance-registry.d.ts +0 -2
  316. package/dist/frontend/provenance-registry.js +0 -10
  317. package/dist/frontend/provenance-registry.js.map +1 -1
  318. package/dist/frontend/provenance.js +4 -7
  319. package/dist/frontend/provenance.js.map +1 -1
  320. package/dist/frontend/resolve.d.ts +7 -2
  321. package/dist/frontend/resolve.js +12 -17
  322. package/dist/frontend/resolve.js.map +1 -1
  323. package/dist/frontend/resolve.test.d.ts +1 -0
  324. package/dist/frontend/resolve.test.js +29 -0
  325. package/dist/frontend/resolve.test.js.map +1 -0
  326. package/dist/frontend/ts7/adapter.d.ts +2 -2
  327. package/dist/frontend/ts7/adapter.js +1 -1
  328. package/dist/frontend/ts7/adapter.js.map +1 -1
  329. package/dist/frontend/ts7/checker.js +2 -36
  330. package/dist/frontend/ts7/checker.js.map +1 -1
  331. package/dist/frontend/ts7/enums.js +2 -1
  332. package/dist/frontend/ts7/enums.js.map +1 -1
  333. package/dist/frontend/ts7/{program.js → program-adapter.js} +7 -6
  334. package/dist/frontend/ts7/program-adapter.js.map +1 -0
  335. package/dist/frontend/ts7/world-check.d.ts +1 -3
  336. package/dist/frontend/ts7/world-check.js +3 -1
  337. package/dist/frontend/ts7/world-check.js.map +1 -1
  338. package/dist/frontend/tsc-codes.d.ts +8 -0
  339. package/dist/frontend/tsc-codes.js +109 -0
  340. package/dist/frontend/tsc-codes.js.map +1 -0
  341. package/dist/frontend/{types.d.ts → type-mapper.d.ts} +2 -25
  342. package/dist/frontend/{types.js → type-mapper.js} +12 -11
  343. package/dist/frontend/type-mapper.js.map +1 -0
  344. package/dist/frontend/workspace-registry.d.ts +26 -0
  345. package/dist/frontend/workspace-registry.js +71 -0
  346. package/dist/frontend/workspace-registry.js.map +1 -0
  347. package/dist/index.d.ts +113 -31
  348. package/dist/index.js +536 -128
  349. package/dist/index.js.map +1 -1
  350. package/dist/ir/analysis.d.ts +37 -0
  351. package/dist/ir/analysis.js +118 -0
  352. package/dist/ir/analysis.js.map +1 -0
  353. package/dist/ir/analysis.test.d.ts +1 -0
  354. package/dist/ir/analysis.test.js +21 -0
  355. package/dist/ir/analysis.test.js.map +1 -0
  356. package/dist/ir/build.d.ts +9 -0
  357. package/dist/ir/build.js +33 -0
  358. package/dist/ir/build.js.map +1 -0
  359. package/dist/ir/integer-loops.d.ts +1 -1
  360. package/dist/ir/{nodes.d.ts → ir.d.ts} +119 -37
  361. package/dist/ir/{nodes.js → ir.js} +170 -166
  362. package/dist/ir/ir.js.map +1 -0
  363. package/dist/ir/ir.test.d.ts +1 -0
  364. package/dist/ir/ir.test.js +17 -0
  365. package/dist/ir/ir.test.js.map +1 -0
  366. package/dist/ir/serialize.d.ts +2 -2
  367. package/dist/ir/serialize.js +3 -2
  368. package/dist/ir/serialize.js.map +1 -1
  369. package/dist/ir/validate.d.ts +1 -1
  370. package/dist/ir/validate.js +93 -41
  371. package/dist/ir/validate.js.map +1 -1
  372. package/dist/library/cache-primitives.d.ts +24 -0
  373. package/dist/library/cache-primitives.js +83 -0
  374. package/dist/library/cache-primitives.js.map +1 -0
  375. package/dist/library/cache-reset.test.d.ts +1 -0
  376. package/dist/library/cache-reset.test.js +47 -0
  377. package/dist/library/cache-reset.test.js.map +1 -0
  378. package/dist/library/{implementation-identity.js → compiler-self-identity.js} +1 -1
  379. package/dist/library/compiler-self-identity.js.map +1 -0
  380. package/dist/library/fence-eval.d.ts +3 -1
  381. package/dist/library/fence-eval.js +8 -2
  382. package/dist/library/fence-eval.js.map +1 -1
  383. package/dist/library/int-infer.d.ts +1 -36
  384. package/dist/library/int-infer.js +29 -18
  385. package/dist/library/int-infer.js.map +1 -1
  386. package/dist/library/int-infer.test.js +4 -4
  387. package/dist/library/{early-cache.d.ts → library-cache.d.ts} +1 -1
  388. package/dist/library/{early-cache.js → library-cache.js} +34 -89
  389. package/dist/library/library-cache.js.map +1 -0
  390. package/dist/library/library-cache.test.d.ts +1 -0
  391. package/dist/library/{early-cache.test.js → library-cache.test.js} +7 -7
  392. package/dist/library/library-cache.test.js.map +1 -0
  393. package/dist/library/{profile.d.ts → library-profile.d.ts} +4 -7
  394. package/dist/library/{profile.js → library-profile.js} +18 -11
  395. package/dist/library/library-profile.js.map +1 -0
  396. package/dist/library/semantic-source.js +2 -1
  397. package/dist/library/semantic-source.js.map +1 -1
  398. package/dist/library/sidecar.d.ts +5 -2
  399. package/dist/library/sidecar.js +11 -5
  400. package/dist/library/sidecar.js.map +1 -1
  401. package/dist/startup-cache.d.ts +11 -3
  402. package/dist/startup-cache.js +17 -2
  403. package/dist/startup-cache.js.map +1 -1
  404. package/package.json +19 -2
  405. package/surface-manifest.json +5 -5
  406. package/dist/backend/cc-cache.test.js.map +0 -1
  407. package/dist/backend/cc.js.map +0 -1
  408. package/dist/backend/emission/emit-async.js.map +0 -1
  409. package/dist/backend/emission/emit-exprs.d.ts +0 -13
  410. package/dist/backend/emission/emit-exprs.js +0 -7407
  411. package/dist/backend/emission/emit-exprs.js.map +0 -1
  412. package/dist/backend/emission/emit-island.js.map +0 -1
  413. package/dist/backend/emission/emit-shapes.js.map +0 -1
  414. package/dist/backend/emission/emit-stmts.js.map +0 -1
  415. package/dist/backend/emission/emit-types.js.map +0 -1
  416. package/dist/backend/emission/emit-walkers.js.map +0 -1
  417. package/dist/backend/emission/emitter.js.map +0 -1
  418. package/dist/backend/emission/may-throw.js.map +0 -1
  419. package/dist/backend/library-identity.js.map +0 -1
  420. package/dist/executable/early-cache.js.map +0 -1
  421. package/dist/executable/early-cache.test.js.map +0 -1
  422. package/dist/ffi/profile.js.map +0 -1
  423. package/dist/frontend/lowering/lower-emitter.js.map +0 -1
  424. package/dist/frontend/shared.d.ts +0 -82
  425. package/dist/frontend/shared.js +0 -308
  426. package/dist/frontend/shared.js.map +0 -1
  427. package/dist/frontend/ts7/program.js.map +0 -1
  428. package/dist/frontend/types.js.map +0 -1
  429. package/dist/ir/nodes.js.map +0 -1
  430. package/dist/library/early-cache.js.map +0 -1
  431. package/dist/library/early-cache.test.js.map +0 -1
  432. package/dist/library/implementation-identity.js.map +0 -1
  433. package/dist/library/profile.js.map +0 -1
  434. /package/dist/backend/{cc-cache.test.d.ts → c/types.test.d.ts} +0 -0
  435. /package/dist/{executable/early-cache.test.d.ts → backend/llvm/shapes.test.d.ts} +0 -0
  436. /package/dist/{library/early-cache.test.d.ts → backend/native-codegen.test.d.ts} +0 -0
  437. /package/dist/ffi/{profile.d.ts → ffi-manifest.d.ts} +0 -0
  438. /package/dist/frontend/ts7/{program.d.ts → program-adapter.d.ts} +0 -0
  439. /package/dist/library/{implementation-identity.d.ts → compiler-self-identity.d.ts} +0 -0
@@ -1,3 +1,4 @@
1
+ import { InternalCompilerError } from "../../errors.js";
1
2
  /* The node:assert lowering (a spoke module like lower-dgram.ts): the
2
3
  * callable module form (`assert(x)` through a default import or a CJS
3
4
  * require binding), ok, the strict/deep equality quartet, fail, throws,
@@ -22,10 +23,12 @@
22
23
  * signature records, dyn/unknown) fences at the call site instead of
23
24
  * miscomparing. */
24
25
  import * as ts from "../ts7/adapter.js";
26
+ import { resultIsDiscarded } from "./call-position.js";
25
27
  import { jsFuncNameOf, own } from "./lowerer.js";
26
28
  import { NARROW_FIRST } from "./surfaces.js";
27
29
  import { typeReachesItself } from "./lower-inspect.js";
28
- import { BOOL, CAUGHT, DYN, DYN_HANDLE_KINDS, F64, REGEX, RUNTIME_ERROR_CLASSES, STRING, VOID, isUnitType, typeEquals, typeKey } from "../../ir/nodes.js";
30
+ import { BOOL, CAUGHT, DYN, DYN_HANDLE_KINDS, F64, REGEX, RUNTIME_ERROR_CLASSES, STRING, VOID, isUnitType, typeEquals, typeKey } from "../../ir/ir.js";
31
+ import { boolLit, countedFor, numLit, strLit, varRef } from "../../ir/build.js";
29
32
  /** node:assert/strict binds the loose NAMES to the strict comparisons —
30
33
  * Node's own aliasing (`strict.equal === assert.strictEqual`). */
31
34
  const STRICT_ALIASES = {
@@ -43,59 +46,58 @@ function canonicalAssertMember(module, member) {
43
46
  }
44
47
  /** VOID/never results are usable as statements and concise arrow bodies
45
48
  * only (the lower-dgram stance): nothing downstream can consume them. */
46
- function requireStatementPosition(L, call, what) {
47
- if (ts.isExpressionStatement(call.parent) || ts.isArrowFunction(call.parent))
49
+ function requireStatementPosition(lowerer, call, what) {
50
+ if (resultIsDiscarded(call))
48
51
  return;
49
- L.noLowering(`using the result of ${what}`, call, "the result is void — call it as its own statement");
52
+ lowerer.noLowering(`using the result of ${what}`, call, "the result is void — call it as its own statement");
50
53
  }
51
54
  /** The optional trailing message argument: Node accepts a string or an
52
55
  * Error (throwing the Error itself) — the STRING form lowers; a literal
53
56
  * `undefined` counts as omitted (Node's `message == null` test). Returns
54
57
  * the libCall's (msg, hasMsg) pair — a "" dummy when omitted, so the
55
58
  * runtime can distinguish an omitted message from an empty one. */
56
- function lowerMessageArg(L, node, loc) {
57
- const flag = (value) => ({ kind: "boolLit", value, type: BOOL, loc });
59
+ function lowerMessageArg(lowerer, node, loc) {
58
60
  if (!node || (ts.isIdentifier(node) && node.text === "undefined")) {
59
- return { msg: { kind: "strLit", value: "", type: STRING, loc }, hasMsg: flag(false) };
61
+ return { msg: { kind: "strLit", value: "", type: STRING, loc }, hasMsg: boolLit(false, loc) };
60
62
  }
61
- const msg = L.lowerExpr(node);
63
+ const msg = lowerer.lowerExpr(node);
62
64
  if (msg.type.kind !== "string") {
63
- L.noLowering(`assert messages of type '${L.fmt(msg.type)}'`, node, "only string messages lower (Node also accepts an Error to throw — construct and throw it directly)");
65
+ lowerer.noLowering(`assert messages of type '${lowerer.fmt(msg.type)}'`, node, "only string messages lower (Node also accepts an Error to throw — construct and throw it directly)");
64
66
  }
65
- return { msg, hasMsg: flag(true) };
67
+ return { msg, hasMsg: boolLit(true, loc) };
66
68
  }
67
69
  /** The module-function dispatch — the spoke's entry, called from both the
68
70
  * named-import and namespace/default-import call paths. Null for other
69
71
  * modules and for members with no lowering (the module tables' fence
70
72
  * takes over, module-qualified with the surfaces.ts hints). */
71
- export function lowerAssertModuleCall(L, expr, bi, loc) {
73
+ export function lowerAssertModuleCall(lowerer, expr, bi, loc) {
72
74
  if (bi.module !== "assert" && bi.module !== "assert/strict")
73
75
  return null;
74
76
  switch (canonicalAssertMember(bi.module, bi.member)) {
75
77
  case "ok":
76
- return lowerAssertOk(L, expr, loc);
78
+ return lowerAssertOk(lowerer, expr, loc);
77
79
  case "strictEqual":
78
- return lowerAssertEqual(L, expr, loc, false, false);
80
+ return lowerAssertEqual(lowerer, expr, loc, false, false);
79
81
  case "notStrictEqual":
80
- return lowerAssertEqual(L, expr, loc, true, false);
82
+ return lowerAssertEqual(lowerer, expr, loc, true, false);
81
83
  case "deepStrictEqual":
82
- return lowerAssertEqual(L, expr, loc, false, true);
84
+ return lowerAssertEqual(lowerer, expr, loc, false, true);
83
85
  case "notDeepStrictEqual":
84
- return lowerAssertEqual(L, expr, loc, true, true);
86
+ return lowerAssertEqual(lowerer, expr, loc, true, true);
85
87
  case "fail":
86
- return lowerAssertFail(L, expr, loc);
88
+ return lowerAssertFail(lowerer, expr, loc);
87
89
  case "match":
88
- return lowerAssertMatch(L, expr, loc, false);
90
+ return lowerAssertMatch(lowerer, expr, loc, false);
89
91
  case "doesNotMatch":
90
- return lowerAssertMatch(L, expr, loc, true);
92
+ return lowerAssertMatch(lowerer, expr, loc, true);
91
93
  case "throws":
92
- return lowerAssertThrows(L, expr, loc);
94
+ return lowerAssertThrows(lowerer, expr, loc);
93
95
  case "rejects":
94
- return lowerAssertRejects(L, expr, loc, false);
96
+ return lowerAssertRejects(lowerer, expr, loc, false);
95
97
  case "doesNotReject":
96
- return lowerAssertRejects(L, expr, loc, true);
98
+ return lowerAssertRejects(lowerer, expr, loc, true);
97
99
  case "ifError":
98
- return lowerAssertIfError(L, expr, loc);
100
+ return lowerAssertIfError(lowerer, expr, loc);
99
101
  default:
100
102
  return null;
101
103
  }
@@ -106,32 +108,32 @@ export function lowerAssertModuleCall(L, expr, bi, loc) {
106
108
  * module object is assert.ok itself. A NAMESPACE import binding is not
107
109
  * callable in Node (ES namespace objects throw TypeError), so that form
108
110
  * fences instead of compiling a crash. Null for non-assert callees. */
109
- export function lowerAssertDirectCall(L, expr, loc) {
111
+ export function lowerAssertDirectCall(lowerer, expr, loc) {
110
112
  const callee = expr.expression;
111
113
  if (!ts.isIdentifier(callee))
112
114
  return null;
113
- const module = L.builtinNamespaceModuleOf(callee);
115
+ const module = lowerer.builtinNamespaceModuleOf(callee);
114
116
  if (module !== "assert" && module !== "assert/strict")
115
117
  return null;
116
- const calleeSym = L.checker.getSymbolAtLocation(callee);
117
- const decl = calleeSym ? L.checker.declarationsOf(calleeSym)[0] : undefined;
118
+ const calleeSym = lowerer.checker.getSymbolAtLocation(callee);
119
+ const decl = calleeSym ? lowerer.checker.declarationsOf(calleeSym)[0] : undefined;
118
120
  if (decl && ts.isNamespaceImport(decl)) {
119
- L.unsupported("SC1013", expr, "calling a module namespace object (Node throws TypeError there — " +
121
+ lowerer.unsupported("SC1013", expr, "calling a module namespace object (Node throws TypeError there — " +
120
122
  'use the default import: import assert from "node:assert")');
121
123
  }
122
- return lowerAssertOk(L, expr, loc);
124
+ return lowerAssertOk(lowerer, expr, loc);
123
125
  }
124
126
  /** assert(value[, message]) / assert.ok(value[, message]): the truthiness
125
127
  * test over any condition-testable type; the generated message carries the
126
128
  * call's SOURCE TEXT (Node re-reads the file at runtime — the frontend has
127
129
  * the same bytes at compile time). */
128
- function lowerAssertOk(L, expr, loc) {
129
- requireStatementPosition(L, expr, expr.expression.getText());
130
+ function lowerAssertOk(lowerer, expr, loc) {
131
+ requireStatementPosition(lowerer, expr, expr.expression.getText());
130
132
  if (expr.arguments.length < 1 || expr.arguments.length > 2) {
131
- L.noLowering(`${expr.expression.getText()} with ${expr.arguments.length} arguments`, expr, "the supported forms are assert(value) and assert(value, message)");
133
+ lowerer.noLowering(`${expr.expression.getText()} with ${expr.arguments.length} arguments`, expr, "the supported forms are assert(value) and assert(value, message)");
132
134
  }
133
135
  const valueNode = expr.arguments[0];
134
- const pass = L.ensureBool(L.lowerExpr(valueNode), valueNode);
136
+ const pass = lowerer.ensureBool(lowerer.lowerExpr(valueNode), valueNode);
135
137
  const msgNode = expr.arguments[1];
136
138
  if (!msgNode || (ts.isIdentifier(msgNode) && msgNode.text === "undefined")) {
137
139
  // Node reads the CALLSITE LINE and slices the expression out of it
@@ -142,16 +144,16 @@ function lowerAssertOk(L, expr, loc) {
142
144
  const msg = { kind: "strLit", value: generated, type: STRING, loc };
143
145
  return { kind: "libCall", fn: "assert.ok", args: [pass, msg], type: VOID, loc };
144
146
  }
145
- const { msg } = lowerMessageArg(L, msgNode, loc);
147
+ const { msg } = lowerMessageArg(lowerer, msgNode, loc);
146
148
  return { kind: "libCall", fn: "assert.ok", args: [pass, msg], type: VOID, loc };
147
149
  }
148
150
  /** assert.fail([message]): an unconditional AssertionError — "Failed"
149
151
  * when the message is omitted (Node's internal default). Lowers as
150
152
  * assert.ok over a false literal. */
151
- function lowerAssertFail(L, expr, loc) {
152
- requireStatementPosition(L, expr, "assert.fail");
153
+ function lowerAssertFail(lowerer, expr, loc) {
154
+ requireStatementPosition(lowerer, expr, "assert.fail");
153
155
  if (expr.arguments.length > 1) {
154
- L.noLowering(`assert.fail with ${expr.arguments.length} arguments`, expr, "the supported form is fail(message?) — the deprecated fail(actual, expected, ...) has no lowering");
156
+ lowerer.noLowering(`assert.fail with ${expr.arguments.length} arguments`, expr, "the supported form is fail(message?) — the deprecated fail(actual, expected, ...) has no lowering");
155
157
  }
156
158
  let msg;
157
159
  const msgNode = expr.arguments[0];
@@ -159,7 +161,7 @@ function lowerAssertFail(L, expr, loc) {
159
161
  msg = { kind: "strLit", value: "Failed", type: STRING, loc };
160
162
  }
161
163
  else {
162
- msg = lowerMessageArg(L, msgNode, loc).msg;
164
+ msg = lowerMessageArg(lowerer, msgNode, loc).msg;
163
165
  }
164
166
  const falseLit = { kind: "boolLit", value: false, type: BOOL, loc };
165
167
  return { kind: "libCall", fn: "assert.ok", args: [falseLit, msg], type: VOID, loc };
@@ -170,11 +172,11 @@ function lowerAssertFail(L, expr, loc) {
170
172
  * deepStrictEqual synthesizes the per-type structural comparison. Objects
171
173
  * under strictEqual (reference equality), mixed static types, and unions
172
174
  * fence — honestly, never a miscompare. */
173
- function lowerAssertEqual(L, expr, loc, negated, deep) {
175
+ function lowerAssertEqual(lowerer, expr, loc, negated, deep) {
174
176
  const surface = `assert.${deep ? (negated ? "notDeepStrictEqual" : "deepStrictEqual") : negated ? "notStrictEqual" : "strictEqual"}`;
175
- requireStatementPosition(L, expr, surface);
177
+ requireStatementPosition(lowerer, expr, surface);
176
178
  if (expr.arguments.length < 2 || expr.arguments.length > 3) {
177
- L.noLowering(`${surface} with ${expr.arguments.length} arguments`, expr);
179
+ lowerer.noLowering(`${surface} with ${expr.arguments.length} arguments`, expr);
178
180
  }
179
181
  // A context-free EMPTY array literal on either side has no element type
180
182
  // of its own (`deepStrictEqual(ee.listeners('x'), [])` — the checker
@@ -190,15 +192,14 @@ function lowerAssertEqual(L, expr, loc, negated, deep) {
190
192
  let a;
191
193
  let b;
192
194
  if (emptyArrayLit(aNode) && !emptyArrayLit(bNode)) {
193
- b = L.lowerExpr(bNode);
194
- a = adoptedEmpty(b.type) ?? L.lowerExpr(aNode);
195
+ b = lowerer.lowerExpr(bNode);
196
+ a = adoptedEmpty(b.type) ?? lowerer.lowerExpr(aNode);
195
197
  }
196
198
  else {
197
- a = L.lowerExpr(aNode);
198
- b = emptyArrayLit(bNode) ? (adoptedEmpty(a.type) ?? L.lowerExpr(bNode)) : L.lowerExpr(bNode);
199
+ a = lowerer.lowerExpr(aNode);
200
+ b = emptyArrayLit(bNode) ? (adoptedEmpty(a.type) ?? lowerer.lowerExpr(bNode)) : lowerer.lowerExpr(bNode);
199
201
  }
200
- const { msg, hasMsg } = lowerMessageArg(L, expr.arguments[2], loc);
201
- const flag = (value) => ({ kind: "boolLit", value, type: BOOL, loc });
202
+ const { msg, hasMsg } = lowerMessageArg(lowerer, expr.arguments[2], loc);
202
203
  // CHECKED-DYNAMIC operands (dyn-vs-dyn, dyn-vs-static): both sides
203
204
  // cross into the checked-dynamic tree and one runtime entry answers the whole quartet —
204
205
  // SameValue for the strict pair (boxed-closure identity for
@@ -224,7 +225,7 @@ function lowerAssertEqual(L, expr, loc, negated, deep) {
224
225
  k === "f64" ||
225
226
  k === "string" ||
226
227
  k === "bool" ||
227
- (k === "func" && L.dynConvertible(e.type)) ||
228
+ (k === "func" && lowerer.dynConvertible(e.type)) ||
228
229
  // Runtime handles cross by REFERENCE (identity preserved), so the
229
230
  // strict compare is honest: assert.strictEqual(this, server) —
230
231
  // the ambient-receiver suite shape. The runtime's deep arm
@@ -240,14 +241,14 @@ function lowerAssertEqual(L, expr, loc, negated, deep) {
240
241
  // code — Node's deepStrictEqual over Errors. Island round trips
241
242
  // re-encode and lose the identity (SEMANTICS.md).
242
243
  (k === "object" && e.type.kind === "object" && e.type.className === "%Error") ||
243
- (deep && k !== "bytes" && k !== "object" && L.dynConvertible(e.type));
244
+ (deep && k !== "bytes" && k !== "object" && lowerer.dynConvertible(e.type));
244
245
  if (!ok) {
245
246
  const hint = !deep && (k === "record" || k === "array" || k === "map" || k === "set" || k === "union")
246
247
  ? "strictEqual on objects is reference equality, which does not survive the unknown boundary (values copy when they cross) — deepStrictEqual compares structure, or narrow the unknown side first"
247
248
  : k === "bytes"
248
249
  ? "the unknown boundary cannot carry the Buffer-vs-Uint8Array brand Node compares — narrow the unknown side to a typed array and compare those"
249
250
  : "the static side must convert into the checked-dynamic tree (numbers, strings, booleans, null/undefined, boxable functions, or JSON-safe structures under the deep forms) — narrow the unknown side instead";
250
- L.noLowering(`${surface} of 'unknown' and '${L.fmt(e.type)}' values`, node, hint);
251
+ lowerer.noLowering(`${surface} of 'unknown' and '${lowerer.fmt(e.type)}' values`, node, hint);
251
252
  }
252
253
  // A boxed closure takes its best-effort JS name from the source
253
254
  // node (the coerceInto convention) — the failure message renders
@@ -258,7 +259,7 @@ function lowerAssertEqual(L, expr, loc, negated, deep) {
258
259
  return {
259
260
  kind: "libCall",
260
261
  fn: "assert.eqDyn",
261
- args: [box(a, aNode), box(b, bNode), flag(negated), flag(deep), msg, hasMsg],
262
+ args: [box(a, aNode), box(b, bNode), boolLit(negated, loc), boolLit(deep, loc), msg, hasMsg],
262
263
  type: VOID,
263
264
  loc,
264
265
  };
@@ -281,7 +282,7 @@ function lowerAssertEqual(L, expr, loc, negated, deep) {
281
282
  return {
282
283
  kind: "libCall",
283
284
  fn: scalarFn,
284
- args: [a, b, flag(negated), flag(deep), msg, hasMsg],
285
+ args: [a, b, boolLit(negated, loc), boolLit(deep, loc), msg, hasMsg],
285
286
  type: VOID,
286
287
  loc,
287
288
  };
@@ -297,35 +298,35 @@ function lowerAssertEqual(L, expr, loc, negated, deep) {
297
298
  // the call through a binding whose DECLARED constructor differs from the
298
299
  // value's runtime one compares by the declared brand (SEMANTICS.md).
299
300
  if (a.type.kind === "bytes" && typeEquals(a.type, b.type)) {
300
- const brandA = bytesBrandOf(L, expr.arguments[0]);
301
- const brandB = bytesBrandOf(L, expr.arguments[1]);
301
+ const brandA = bytesBrandOf(lowerer, expr.arguments[0]);
302
+ const brandB = bytesBrandOf(lowerer, expr.arguments[1]);
302
303
  if (!deep) {
303
304
  // Brands shape only the failure HEADER (same-structure vs
304
305
  // reference-equal expectation); an unclassifiable side defers to the
305
306
  // content probe.
306
- const brandsEq = flag(brandA === null || brandB === null || brandA === brandB);
307
+ const brandsEq = boolLit(brandA === null || brandB === null || brandA === brandB, loc);
307
308
  return {
308
309
  kind: "libCall",
309
310
  fn: "assert.refEqBytes",
310
- args: [a, b, flag(negated), brandsEq, msg, hasMsg],
311
+ args: [a, b, boolLit(negated, loc), brandsEq, msg, hasMsg],
311
312
  type: VOID,
312
313
  loc,
313
314
  };
314
315
  }
315
316
  if (brandA === null || brandB === null) {
316
- L.noLowering(`${surface} of typed-array values whose constructor is not in the static type`, brandA === null ? expr.arguments[0] : expr.arguments[1], "Node's deep equality compares prototypes (a Buffer is never deep-equal to a plain Uint8Array) — annotate the value so its constructor is visible");
317
+ lowerer.noLowering(`${surface} of typed-array values whose constructor is not in the static type`, brandA === null ? expr.arguments[0] : expr.arguments[1], "Node's deep equality compares prototypes (a Buffer is never deep-equal to a plain Uint8Array) — annotate the value so its constructor is visible");
317
318
  }
318
319
  const verdict = {
319
320
  kind: "libCall",
320
321
  fn: "assert.bytesDeepEq",
321
- args: [a, b, flag(brandA === brandB)],
322
+ args: [a, b, boolLit(brandA === brandB, loc)],
322
323
  type: BOOL,
323
324
  loc,
324
325
  };
325
326
  return {
326
327
  kind: "libCall",
327
328
  fn: "assert.deepResult",
328
- args: [verdict, flag(negated), msg, hasMsg],
329
+ args: [verdict, boolLit(negated, loc), msg, hasMsg],
329
330
  type: VOID,
330
331
  loc,
331
332
  };
@@ -340,7 +341,7 @@ function lowerAssertEqual(L, expr, loc, negated, deep) {
340
341
  return {
341
342
  kind: "libCall",
342
343
  fn: "assert.refEqFn",
343
- args: [a, b, flag(negated), msg, hasMsg],
344
+ args: [a, b, boolLit(negated, loc), msg, hasMsg],
344
345
  type: VOID,
345
346
  loc,
346
347
  };
@@ -351,32 +352,32 @@ function lowerAssertEqual(L, expr, loc, negated, deep) {
351
352
  : a.type.kind !== b.type.kind
352
353
  ? "both sides must share one static scalar type (number, string, or boolean)"
353
354
  : "strictEqual on objects is reference equality — deepStrictEqual compares structure";
354
- L.noLowering(`${surface} of '${L.fmt(a.type)}' and '${L.fmt(b.type)}' values`, expr, hint);
355
+ lowerer.noLowering(`${surface} of '${lowerer.fmt(a.type)}' and '${lowerer.fmt(b.type)}' values`, expr, hint);
355
356
  }
356
357
  // Deep equality: identical static types, structurally comparable.
357
358
  if (!typeEquals(a.type, b.type)) {
358
- L.noLowering(`${surface} of '${L.fmt(a.type)}' and '${L.fmt(b.type)}' values`, expr, "deep equality lowers when both sides have the SAME static type — annotate or narrow one side");
359
+ lowerer.noLowering(`${surface} of '${lowerer.fmt(a.type)}' and '${lowerer.fmt(b.type)}' values`, expr, "deep equality lowers when both sides have the SAME static type — annotate or narrow one side");
359
360
  }
360
361
  if (isUnitType(a.type)) {
361
362
  // undefined vs undefined / null vs null: trivially deep-equal.
362
363
  return {
363
364
  kind: "libCall",
364
365
  fn: "assert.deepResult",
365
- args: [flag(true), flag(negated), msg, hasMsg],
366
+ args: [boolLit(true, loc), boolLit(negated, loc), msg, hasMsg],
366
367
  type: VOID,
367
368
  loc,
368
369
  };
369
370
  }
370
- const unsupported = deepUnsupportedReason(L, a.type, new Set());
371
+ const unsupported = deepUnsupportedReason(lowerer, a.type, new Set());
371
372
  if (unsupported !== null) {
372
- L.noLowering(`${surface} of '${L.fmt(a.type)}' values`, expr, unsupported);
373
+ lowerer.noLowering(`${surface} of '${lowerer.fmt(a.type)}' values`, expr, unsupported);
373
374
  }
374
- const helper = deepEqHelper(L, a.type, loc);
375
+ const helper = deepEqHelper(lowerer, a.type, loc);
375
376
  const verdict = { kind: "call", callee: helper, args: [a, b], type: BOOL, loc };
376
377
  return {
377
378
  kind: "libCall",
378
379
  fn: "assert.deepResult",
379
- args: [verdict, flag(negated), msg, hasMsg],
380
+ args: [verdict, boolLit(negated, loc), msg, hasMsg],
380
381
  type: VOID,
381
382
  loc,
382
383
  };
@@ -384,18 +385,18 @@ function lowerAssertEqual(L, expr, loc, negated, deep) {
384
385
  /** assert.match / assert.doesNotMatch: the regex test with Node's
385
386
  * generated message (regex source + getter-ordered flags, the inspected
386
387
  * input). */
387
- function lowerAssertMatch(L, expr, loc, negated) {
388
+ function lowerAssertMatch(lowerer, expr, loc, negated) {
388
389
  const surface = negated ? "assert.doesNotMatch" : "assert.match";
389
- requireStatementPosition(L, expr, surface);
390
+ requireStatementPosition(lowerer, expr, surface);
390
391
  if (expr.arguments.length < 2 || expr.arguments.length > 3) {
391
- L.noLowering(`${surface} with ${expr.arguments.length} arguments`, expr);
392
+ lowerer.noLowering(`${surface} with ${expr.arguments.length} arguments`, expr);
392
393
  }
393
- const s = L.lowerExprExpecting(expr.arguments[0], STRING);
394
- const re = L.lowerExpr(expr.arguments[1]);
394
+ const s = lowerer.lowerExprExpecting(expr.arguments[0], STRING);
395
+ const re = lowerer.lowerExpr(expr.arguments[1]);
395
396
  if (re.type.kind !== "regex") {
396
- L.noLowering(`${surface} with a non-regex pattern`, expr.arguments[1], "the second argument must be a regular expression");
397
+ lowerer.noLowering(`${surface} with a non-regex pattern`, expr.arguments[1], "the second argument must be a regular expression");
397
398
  }
398
- const { msg, hasMsg } = lowerMessageArg(L, expr.arguments[2], loc);
399
+ const { msg, hasMsg } = lowerMessageArg(lowerer, expr.arguments[2], loc);
399
400
  const neg = { kind: "boolLit", value: negated, type: BOOL, loc };
400
401
  return { kind: "libCall", fn: "assert.match", args: [s, re, neg, msg, hasMsg], type: VOID, loc };
401
402
  }
@@ -407,10 +408,10 @@ function regexFlagsGetterOrder(flags) {
407
408
  }
408
409
  /** Is `className` the runtime %Error root or a class inside its
409
410
  * hierarchy (builtin kinds and user subclasses alike)? */
410
- function inErrorHierarchy(L, className) {
411
+ function inErrorHierarchy(lowerer, className) {
411
412
  if (className === "%Error" || RUNTIME_ERROR_CLASSES.has(className))
412
413
  return true;
413
- for (let c = L.classes.get(className)?.base ?? null; c; c = c.base) {
414
+ for (let c = lowerer.classes.get(className)?.base ?? null; c; c = c.base) {
414
415
  if (c.def.name === "%Error")
415
416
  return true;
416
417
  }
@@ -420,23 +421,23 @@ function inErrorHierarchy(L, className) {
420
421
  * regex test over String(error), an error-class identifier → instanceof,
421
422
  * an object LITERAL over name/message/code (string or regex values) →
422
423
  * the per-key shape comparison. Anything else fences honestly. */
423
- function classifyThrowsExpected(L, surface, node, loc) {
424
- const expectedT = L.mapTypeOf(L.typeOf(node));
424
+ function classifyThrowsExpected(lowerer, surface, node, loc) {
425
+ const expectedT = lowerer.mapTypeOf(lowerer.typeOf(node));
425
426
  if (expectedT?.kind === "string") {
426
- const m = lowerMessageArg(L, node, loc);
427
+ const m = lowerMessageArg(lowerer, node, loc);
427
428
  return { form: "message", msg: m.msg, hasMsg: m.hasMsg };
428
429
  }
429
430
  if (expectedT?.kind === "regex") {
430
- return { form: "regex", value: L.lowerExpr(node) };
431
+ return { form: "regex", value: lowerer.lowerExpr(node) };
431
432
  }
432
- const sym = ts.isIdentifier(node) ? L.resolveValueSymbol(node) : null;
433
- const info = (sym && L.builtinErrorInfoOf(sym)) ?? (sym && L.classBySymbol.get(sym)) ?? null;
433
+ const sym = ts.isIdentifier(node) ? lowerer.resolveValueSymbol(node) : null;
434
+ const info = (sym && lowerer.builtinErrorInfoOf(sym)) ?? (sym && lowerer.classBySymbol.get(sym)) ?? null;
434
435
  // A rebindable decorated name: the runtime expectation is the decoration
435
436
  // result's interval, not the declaration's — no static class check.
436
437
  if (info?.classDecorators?.valueGlobalId !== undefined) {
437
- L.unsupported("SC1090", node, "assert.throws/rejects against a decorated class whose decorators may replace it");
438
+ lowerer.unsupported("SC1090", node, "assert.throws/rejects against a decorated class whose decorators may replace it");
438
439
  }
439
- if (info && L.inHierarchy(info)) {
440
+ if (info && lowerer.inHierarchy(info)) {
440
441
  const rec = RUNTIME_ERROR_CLASSES.get(info.def.name);
441
442
  return {
442
443
  form: "class",
@@ -449,7 +450,7 @@ function classifyThrowsExpected(L, surface, node, loc) {
449
450
  obj = obj.expression;
450
451
  if (ts.isObjectLiteralExpression(obj)) {
451
452
  if (obj.properties.length === 0) {
452
- L.noLowering(`${surface} with an empty expected object`, obj, "Node rejects this (the error 'may not be an empty object') — name at least one of name/message/code");
453
+ lowerer.noLowering(`${surface} with an empty expected object`, obj, "Node rejects this (the error 'may not be an empty object') — name at least one of name/message/code");
453
454
  }
454
455
  // Duplicate keys keep the LAST value (JS object-literal semantics);
455
456
  // property order is preserved for argument evaluation.
@@ -457,15 +458,15 @@ function classifyThrowsExpected(L, surface, node, loc) {
457
458
  for (const prop of obj.properties) {
458
459
  const named = ts.isPropertyAssignment(prop) || ts.isShorthandPropertyAssignment(prop) ? prop : null;
459
460
  if (!named || !(ts.isIdentifier(named.name) || ts.isStringLiteral(named.name))) {
460
- L.noLowering(`${surface} with this expected-object property form`, prop, "plain `key: value` properties are the lowered form");
461
+ lowerer.noLowering(`${surface} with this expected-object property form`, prop, "plain `key: value` properties are the lowered form");
461
462
  }
462
463
  const keyName = named.name.text;
463
464
  const id = own(SHAPE_KEY_IDS, keyName);
464
465
  if (id === undefined) {
465
- L.noLowering(`${surface} comparing the '${keyName}' property of the thrown error`, prop, "the static error surface carries name, message, and code — compare other properties in a catch block");
466
+ lowerer.noLowering(`${surface} comparing the '${keyName}' property of the thrown error`, prop, "the static error surface carries name, message, and code — compare other properties in a catch block");
466
467
  }
467
468
  const valueNode = ts.isPropertyAssignment(named) ? named.initializer : named.name;
468
- const value = L.lowerExpr(valueNode);
469
+ const value = lowerer.lowerExpr(valueNode);
469
470
  if (value.type.kind === "string") {
470
471
  byId.set(id, { id, kind: "str", value, enameBake: null });
471
472
  }
@@ -479,7 +480,7 @@ function classifyThrowsExpected(L, surface, node, loc) {
479
480
  byId.set(id, { id, kind: "re", value, enameBake: bake });
480
481
  }
481
482
  else {
482
- L.noLowering(`${surface} expected-object values of type '${L.fmt(value.type)}'`, valueNode, "string and regular-expression values are the lowered comparisons");
483
+ lowerer.noLowering(`${surface} expected-object values of type '${lowerer.fmt(value.type)}'`, valueNode, "string and regular-expression values are the lowered comparisons");
483
484
  }
484
485
  }
485
486
  return { form: "shape", keys: [...byId.values()] };
@@ -489,12 +490,12 @@ function classifyThrowsExpected(L, surface, node, loc) {
489
490
  // the runtime compares per Node's expectsError key walk. A
490
491
  // checked-dynamic expected rides directly; a static %Error boxes.
491
492
  if (expectedT?.kind === "dyn") {
492
- const value = L.lowerExpr(node);
493
+ const value = lowerer.lowerExpr(node);
493
494
  if (value.type.kind === "dyn")
494
495
  return { form: "errValue", value };
495
496
  }
496
497
  if (expectedT?.kind === "object" && expectedT.className === "%Error") {
497
- const value = L.lowerExpr(node);
498
+ const value = lowerer.lowerExpr(node);
498
499
  if (value.type.kind === "object") {
499
500
  return { form: "errValue", value: { kind: "dynFrom", value, type: DYN, loc } };
500
501
  }
@@ -505,8 +506,8 @@ function classifyThrowsExpected(L, surface, node, loc) {
505
506
  // the expected's own keys only, so a convertible record crosses as its
506
507
  // dyn object. Records carrying regex members are not convertible and
507
508
  // keep the fence (the runtime walk would deep-compare, not test).
508
- if (expectedT?.kind === "record" && L.dynConvertible(expectedT)) {
509
- const value = L.lowerExpr(node);
509
+ if (expectedT?.kind === "record" && lowerer.dynConvertible(expectedT)) {
510
+ const value = lowerer.lowerExpr(node);
510
511
  // JS-lane locals holding object literals lower to dyn already; a
511
512
  // typed record crosses through dynFrom.
512
513
  if (value.type.kind === "dyn")
@@ -515,7 +516,7 @@ function classifyThrowsExpected(L, surface, node, loc) {
515
516
  return { form: "errValue", value: { kind: "dynFrom", value, type: DYN, loc } };
516
517
  }
517
518
  }
518
- L.noLowering(`${surface} with this expected-error shape`, node, "an error CLASS (Error/TypeError/... or a class extending them), an error instance, a message string, " +
519
+ lowerer.noLowering(`${surface} with this expected-error shape`, node, "an error CLASS (Error/TypeError/... or a class extending them), an error instance, a message string, " +
519
520
  "a regular expression, or an object literal over name/message/code are the lowered forms");
520
521
  }
521
522
  /** assert.throws(fn[, expected][, message]): the zero-parameter callback
@@ -529,17 +530,17 @@ function classifyThrowsExpected(L, surface, node, loc) {
529
530
  * non-Error thrown value under any expectation propagates
530
531
  * (SEMANTICS.md 104 — Node builds an AssertionError from its
531
532
  * inspection). */
532
- function lowerAssertThrows(L, expr, loc) {
533
- requireStatementPosition(L, expr, "assert.throws");
533
+ function lowerAssertThrows(lowerer, expr, loc) {
534
+ requireStatementPosition(lowerer, expr, "assert.throws");
534
535
  if (expr.arguments.length < 1 || expr.arguments.length > 3) {
535
- L.noLowering(`assert.throws with ${expr.arguments.length} arguments`, expr, "the supported forms are throws(fn), throws(fn, expected), and throws(fn, expected, message)");
536
+ lowerer.noLowering(`assert.throws with ${expr.arguments.length} arguments`, expr, "the supported forms are throws(fn), throws(fn, expected), and throws(fn, expected, message)");
536
537
  }
537
- const fn = L.lowerExpr(expr.arguments[0]);
538
+ const fn = lowerer.lowerExpr(expr.arguments[0]);
538
539
  if (fn.type.kind !== "func" || fn.type.params.length !== 0) {
539
- L.noLowering("assert.throws with this callback shape", expr.arguments[0], "the callback must be a zero-parameter function");
540
+ lowerer.noLowering("assert.throws with this callback shape", expr.arguments[0], "the callback must be a zero-parameter function");
540
541
  }
541
- const { expected, msg, hasMsg } = throwsArguments(L, "assert.throws", expr, loc);
542
- const helper = assertThrowsHelper(L, "throws", fn.type, false, expected, loc);
542
+ const { expected, msg, hasMsg } = throwsArguments(lowerer, "assert.throws", expr, loc);
543
+ const helper = assertThrowsHelper(lowerer, "throws", fn.type, false, expected, loc);
543
544
  return { kind: "call", callee: helper, args: [fn, msg, hasMsg, ...expectedArgs(expected)], type: VOID, loc };
544
545
  }
545
546
  /** assert.rejects / assert.doesNotReject: the async twins. The first
@@ -552,26 +553,26 @@ function lowerAssertThrows(L, expr, loc) {
552
553
  * doesNotReject rethrows a NON-matching rejection and throws Node's
553
554
  * "Got unwanted rejection" AssertionError on a match (regex
554
555
  * expectations fence — the runtime predicate is throw-shaped). */
555
- function lowerAssertRejects(L, expr, loc, doesNot) {
556
+ function lowerAssertRejects(lowerer, expr, loc, doesNot) {
556
557
  const surface = doesNot ? "assert.doesNotReject" : "assert.rejects";
557
558
  if (expr.arguments.length < 1 || expr.arguments.length > 3) {
558
- L.noLowering(`${surface} with ${expr.arguments.length} arguments`, expr, `the supported forms are ${doesNot ? "doesNotReject" : "rejects"}(fn), (fn, expected), and (fn, expected, message)`);
559
+ lowerer.noLowering(`${surface} with ${expr.arguments.length} arguments`, expr, `the supported forms are ${doesNot ? "doesNotReject" : "rejects"}(fn), (fn, expected), and (fn, expected, message)`);
559
560
  }
560
- const recv = L.lowerExpr(expr.arguments[0]);
561
+ const recv = lowerer.lowerExpr(expr.arguments[0]);
561
562
  const recvIsPromise = recv.type.kind === "promise";
562
563
  if (!recvIsPromise &&
563
564
  (recv.type.kind !== "func" || recv.type.params.length !== 0 || recv.type.ret.kind !== "promise")) {
564
- L.noLowering(`${surface} with this first argument`, expr.arguments[0], "an async (promise-returning) zero-parameter function or a promise are the lowered forms " +
565
+ lowerer.noLowering(`${surface} with this first argument`, expr.arguments[0], "an async (promise-returning) zero-parameter function or a promise are the lowered forms " +
565
566
  "(a bare thenable — an object with a then method — has no lowering: wrap it, e.g. Promise.resolve().then(() => thenable))");
566
567
  }
567
- const { expected, msg, hasMsg } = throwsArguments(L, surface, expr, loc);
568
+ const { expected, msg, hasMsg } = throwsArguments(lowerer, surface, expr, loc);
568
569
  if (doesNot && (expected.form === "shape" || expected.form === "errValue")) {
569
570
  // Node itself rejects this form (ERR_INVALID_ARG_TYPE: "expected"
570
571
  // must be a function or RegExp) — the fence is the compile-time
571
572
  // statement of the same rule.
572
- L.noLowering(`${surface} with an object-shape expectation`, expr.arguments[1], "Node rejects this form (doesNotReject takes a class or RegExp) — use a class, a regex, or a bare call");
573
+ lowerer.noLowering(`${surface} with an object-shape expectation`, expr.arguments[1], "Node rejects this form (doesNotReject takes a class or RegExp) — use a class, a regex, or a bare call");
573
574
  }
574
- const helper = assertThrowsHelper(L, doesNot ? "dnr" : "rejects", recv.type, recvIsPromise, expected, loc);
575
+ const helper = assertThrowsHelper(lowerer, doesNot ? "dnr" : "rejects", recv.type, recvIsPromise, expected, loc);
575
576
  return {
576
577
  kind: "call",
577
578
  callee: helper,
@@ -583,20 +584,20 @@ function lowerAssertRejects(L, expr, loc, doesNot) {
583
584
  /** The shared expected/message argument split (arguments 2 and 3): a
584
585
  * string expected IS the message and excludes a third argument (Node
585
586
  * throws ERR_INVALID_ARG_TYPE there). */
586
- function throwsArguments(L, surface, expr, loc) {
587
+ function throwsArguments(lowerer, surface, expr, loc) {
587
588
  const expectedNode = expr.arguments[1];
588
589
  // A literal `undefined` expected counts as omitted (Node reads the
589
590
  // message from the THIRD argument in that spelling).
590
591
  const expected = expectedNode && !(ts.isIdentifier(expectedNode) && expectedNode.text === "undefined")
591
- ? classifyThrowsExpected(L, surface, expectedNode, loc)
592
+ ? classifyThrowsExpected(lowerer, surface, expectedNode, loc)
592
593
  : { form: "bare" };
593
594
  if (expected.form === "message") {
594
595
  if (expr.arguments.length === 3) {
595
- L.noLowering(`${surface} with a string expected argument AND a message`, expr.arguments[2], "Node rejects this form (the string IS the message) — use an expected shape second");
596
+ lowerer.noLowering(`${surface} with a string expected argument AND a message`, expr.arguments[2], "Node rejects this form (the string IS the message) — use an expected shape second");
596
597
  }
597
598
  return { expected, msg: expected.msg, hasMsg: expected.hasMsg };
598
599
  }
599
- const { msg, hasMsg } = lowerMessageArg(L, expr.arguments[2], loc);
600
+ const { msg, hasMsg } = lowerMessageArg(lowerer, expr.arguments[2], loc);
600
601
  return { expected, msg, hasMsg };
601
602
  }
602
603
  /** The extra call-site arguments a form carries into its helper, in the
@@ -634,7 +635,7 @@ function expectedArgs(expected) {
634
635
  * return. doesNotReject inverts: a MATCHING Error throws "Got unwanted
635
636
  * rejection", everything else rethrows the original reason. A non-Error
636
637
  * thrown value under any expectation propagates (SEMANTICS.md 104). */
637
- function assertThrowsHelper(L, mode, recvType, recvIsPromise, expected, loc) {
638
+ function assertThrowsHelper(lowerer, mode, recvType, recvIsPromise, expected, loc) {
638
639
  const sig = expected.form === "class"
639
640
  ? `class:${expected.className}`
640
641
  : expected.form === "regex"
@@ -645,16 +646,12 @@ function assertThrowsHelper(L, mode, recvType, recvIsPromise, expected, loc) {
645
646
  ? "errval"
646
647
  : "bare";
647
648
  const key = `assert.${mode}:${recvIsPromise ? "p" : "f"}:${typeKey(recvType)}:${sig}`;
648
- const existing = L.assertHelpers.get(key);
649
+ const existing = lowerer.assertHelpers.get(key);
649
650
  if (existing)
650
651
  return existing;
651
- const name = `%assert.${mode}.${L.assertHelpers.size}`;
652
- L.assertHelpers.set(key, name);
653
- const ref = (localId, type) => ({ kind: "varRef", localId, type, loc });
654
- const flag = (value) => ({ kind: "boolLit", value, type: BOOL, loc });
655
- const str = (value) => ({ kind: "strLit", value, type: STRING, loc });
656
- const num = (value) => ({ kind: "numLit", value, type: F64, loc });
657
- const caughtRef = () => ref("e.0", CAUGHT);
652
+ const name = `%assert.${mode}.${lowerer.assertHelpers.size}`;
653
+ lowerer.assertHelpers.set(key, name);
654
+ const caughtRef = () => varRef("e.0", CAUGHT, loc);
658
655
  const errT = { kind: "object", className: "%Error" };
659
656
  const narrowed = () => ({ kind: "caughtNarrow", value: caughtRef(), type: errT, loc });
660
657
  const isInstance = (className) => ({
@@ -665,8 +662,8 @@ function assertThrowsHelper(L, mode, recvType, recvIsPromise, expected, loc) {
665
662
  expr: { kind: "libCall", fn, args, type: VOID, loc },
666
663
  loc,
667
664
  });
668
- const m = () => ref("m.0", STRING);
669
- const hm = () => ref("hm.0", BOOL);
665
+ const m = () => varRef("m.0", STRING, loc);
666
+ const hm = () => varRef("hm.0", BOOL, loc);
670
667
  const doReturn = { kind: "return", value: null, loc };
671
668
  const rethrow = { kind: "rethrow", localId: "e.0", loc };
672
669
  const ifStmt = (cond, then) => ({ kind: "if", cond, then, else_: null, loc });
@@ -697,8 +694,8 @@ function assertThrowsHelper(L, mode, recvType, recvIsPromise, expected, loc) {
697
694
  const stmts = [lib("assert.shapeBegin", [narrowed()])];
698
695
  expected.keys.forEach((k, i) => {
699
696
  stmts.push(lib(k.kind === "str" ? "assert.shapeStr" : "assert.shapeRe", [
700
- num(k.id),
701
- ref(shapeParamIds[i], k.kind === "str" ? STRING : REGEX),
697
+ numLit(k.id, loc),
698
+ varRef(shapeParamIds[i], k.kind === "str" ? STRING : REGEX, loc),
702
699
  ]));
703
700
  });
704
701
  return stmts;
@@ -709,18 +706,18 @@ function assertThrowsHelper(L, mode, recvType, recvIsPromise, expected, loc) {
709
706
  // name drops the detail (a documented sliver).
710
707
  const ename = (() => {
711
708
  if (expected.form === "class")
712
- return { e: str(expected.displayName), has: true };
709
+ return { e: strLit(expected.displayName, loc), has: true };
713
710
  if (expected.form === "shape") {
714
711
  const i = expected.keys.findIndex((k) => k.id === 2);
715
712
  if (i >= 0) {
716
713
  const k = expected.keys[i];
717
714
  if (k.kind === "str")
718
- return { e: ref(shapeParamIds[i], STRING), has: true };
715
+ return { e: varRef(shapeParamIds[i], STRING, loc), has: true };
719
716
  if (k.enameBake !== null)
720
- return { e: str(k.enameBake), has: true };
717
+ return { e: strLit(k.enameBake, loc), has: true };
721
718
  }
722
719
  }
723
- return { e: str(""), has: false };
720
+ return { e: strLit("", loc), has: false };
724
721
  })();
725
722
  let catchBody;
726
723
  if (mode === "dnr") {
@@ -746,7 +743,7 @@ function assertThrowsHelper(L, mode, recvType, recvIsPromise, expected, loc) {
746
743
  ifStmt({
747
744
  kind: "libCall",
748
745
  fn: "assert.regexErrTest",
749
- args: [ref("re.0", REGEX), narrowed()],
746
+ args: [varRef("re.0", REGEX, loc), narrowed()],
750
747
  type: BOOL,
751
748
  loc,
752
749
  }, [lib("assert.unwantedRejection", [narrowed(), m(), hm()])]),
@@ -757,7 +754,7 @@ function assertThrowsHelper(L, mode, recvType, recvIsPromise, expected, loc) {
757
754
  default:
758
755
  // Node itself rejects shape expectations here (ERR_INVALID_ARG_TYPE)
759
756
  // — the call site fences before reaching this helper.
760
- throw new Error("assert helper: doesNotReject shape forms fence at the call site");
757
+ throw new InternalCompilerError("assert helper: doesNotReject shape forms fence at the call site");
761
758
  }
762
759
  }
763
760
  else {
@@ -770,7 +767,7 @@ function assertThrowsHelper(L, mode, recvType, recvIsPromise, expected, loc) {
770
767
  catchBody = [
771
768
  ifStmt(isInstance(expected.className), [doReturn]),
772
769
  ifStmt(isInstance("%Error"), [
773
- lib("assert.throwsMismatch", [str(expected.displayName), narrowed(), m(), hm()]),
770
+ lib("assert.throwsMismatch", [strLit(expected.displayName, loc), narrowed(), m(), hm()]),
774
771
  ]),
775
772
  // A non-Error thrown value: propagate (SEMANTICS.md 104; the
776
773
  // mismatch throw above never falls through — its pending
@@ -781,7 +778,7 @@ function assertThrowsHelper(L, mode, recvType, recvIsPromise, expected, loc) {
781
778
  case "regex":
782
779
  catchBody = [
783
780
  ifStmt(isInstance("%Error"), [
784
- lib("assert.throwsRegex", [ref("re.0", REGEX), narrowed(), m(), hm()]),
781
+ lib("assert.throwsRegex", [varRef("re.0", REGEX, loc), narrowed(), m(), hm()]),
785
782
  doReturn,
786
783
  ]),
787
784
  rethrow,
@@ -805,7 +802,7 @@ function assertThrowsHelper(L, mode, recvType, recvIsPromise, expected, loc) {
805
802
  catchBody = [
806
803
  lib("assert.expectsErrDyn", [
807
804
  { kind: "caughtToDyn", value: caughtRef(), type: DYN, loc },
808
- ref("ev.0", DYN),
805
+ varRef("ev.0", DYN, loc),
809
806
  m(),
810
807
  hm(),
811
808
  ]),
@@ -821,7 +818,7 @@ function assertThrowsHelper(L, mode, recvType, recvIsPromise, expected, loc) {
821
818
  tryBody = [
822
819
  {
823
820
  kind: "exprStmt",
824
- expr: { kind: "callValue", callee: ref("f.0", fnT), args: [], type: fnT.ret, loc },
821
+ expr: { kind: "callValue", callee: varRef("f.0", fnT, loc), args: [], type: fnT.ret, loc },
825
822
  loc,
826
823
  },
827
824
  ];
@@ -829,7 +826,7 @@ function assertThrowsHelper(L, mode, recvType, recvIsPromise, expected, loc) {
829
826
  else {
830
827
  let awaited;
831
828
  if (recvIsPromise) {
832
- awaited = ref("f.0", recvType);
829
+ awaited = varRef("f.0", recvType, loc);
833
830
  }
834
831
  else {
835
832
  const fnT = recvType;
@@ -838,10 +835,10 @@ function assertThrowsHelper(L, mode, recvType, recvIsPromise, expected, loc) {
838
835
  body.push({
839
836
  kind: "varDecl",
840
837
  localId: "pr.0",
841
- init: { kind: "callValue", callee: ref("f.0", fnT), args: [], type: promT, loc },
838
+ init: { kind: "callValue", callee: varRef("f.0", fnT, loc), args: [], type: promT, loc },
842
839
  loc,
843
840
  });
844
- awaited = ref("pr.0", promT);
841
+ awaited = varRef("pr.0", promT, loc);
845
842
  }
846
843
  const inner = awaited.type.inner;
847
844
  tryBody = [
@@ -850,10 +847,10 @@ function assertThrowsHelper(L, mode, recvType, recvIsPromise, expected, loc) {
850
847
  }
851
848
  body.push({ kind: "tryCatch", tryBody, catchBody, catchLocalId: "e.0", finallyBody: null, loc });
852
849
  if (mode !== "dnr") {
853
- body.push(lib("assert.throwsNone", [flag(mode === "rejects"), ename.e, flag(ename.has), m(), hm()]));
850
+ body.push(lib("assert.throwsNone", [boolLit(mode === "rejects", loc), ename.e, boolLit(ename.has, loc), m(), hm()]));
854
851
  }
855
852
  body.push(doReturn);
856
- L.liftedFns.push({
853
+ lowerer.liftedFns.push({
857
854
  name,
858
855
  params,
859
856
  returnType: VOID,
@@ -869,7 +866,7 @@ function assertThrowsHelper(L, mode, recvType, recvIsPromise, expected, loc) {
869
866
  * "unit" for null/undefined (can never throw — the evaluated expression
870
867
  * alone suffices), a libCall name for scalars and %Error-hierarchy
871
868
  * objects, null for everything else (the caller fences). */
872
- function ifErrorLibFn(L, t) {
869
+ function ifErrorLibFn(lowerer, t) {
873
870
  switch (t.kind) {
874
871
  case "undefinedT":
875
872
  case "nullT":
@@ -881,7 +878,7 @@ function ifErrorLibFn(L, t) {
881
878
  case "bool":
882
879
  return "assert.ifErrorBool";
883
880
  case "object":
884
- return inErrorHierarchy(L, t.className) ? "assert.ifErrorErr" : null;
881
+ return inErrorHierarchy(lowerer, t.className) ? "assert.ifErrorErr" : null;
885
882
  default:
886
883
  return null;
887
884
  }
@@ -893,13 +890,13 @@ function ifErrorLibFn(L, t) {
893
890
  * evaluated expression alone; scalars and %Error-hierarchy objects
894
891
  * throw through the typed runtime entries; unions dispatch per arm in
895
892
  * an interned helper. Anything else fences. */
896
- function lowerAssertIfError(L, expr, loc) {
897
- requireStatementPosition(L, expr, "assert.ifError");
893
+ function lowerAssertIfError(lowerer, expr, loc) {
894
+ requireStatementPosition(lowerer, expr, "assert.ifError");
898
895
  if (expr.arguments.length !== 1) {
899
- L.noLowering(`assert.ifError with ${expr.arguments.length} arguments`, expr, "the supported form is ifError(value)");
896
+ lowerer.noLowering(`assert.ifError with ${expr.arguments.length} arguments`, expr, "the supported form is ifError(value)");
900
897
  }
901
898
  const argNode = expr.arguments[0];
902
- const argT = L.mapTypeOf(L.typeOf(argNode));
899
+ const argT = lowerer.mapTypeOf(lowerer.typeOf(argNode));
903
900
  if (argT && isUnitType(argT)) {
904
901
  // null/undefined can never throw, and a unit-typed expression has no
905
902
  // standalone runtime value to evaluate — a passing assert.ok is the
@@ -915,9 +912,9 @@ function lowerAssertIfError(L, expr, loc) {
915
912
  loc,
916
913
  };
917
914
  }
918
- const v = L.lowerExpr(argNode);
919
- const fence = (t) => L.noLowering(`assert.ifError over '${L.fmt(t)}' values`, argNode, "numbers, strings, booleans, Errors, null/undefined, and unions of those are the lowered forms");
920
- const direct = ifErrorLibFn(L, v.type);
915
+ const v = lowerer.lowerExpr(argNode);
916
+ const fence = (t) => lowerer.noLowering(`assert.ifError over '${lowerer.fmt(t)}' values`, argNode, "numbers, strings, booleans, Errors, null/undefined, and unions of those are the lowered forms");
917
+ const direct = ifErrorLibFn(lowerer, v.type);
921
918
  if (direct === "unit") {
922
919
  // A unit-typed value that mapped through some other checker spelling:
923
920
  // the same no-op (unreachable in practice — the mapTypeOf branch
@@ -945,36 +942,36 @@ function lowerAssertIfError(L, expr, loc) {
945
942
  if (v.type.kind !== "union")
946
943
  fence(v.type);
947
944
  const unionT = v.type;
948
- const def = L.unions.get(unionT.unionId);
945
+ const def = lowerer.unions.get(unionT.unionId);
949
946
  if (!def)
950
947
  fence(v.type);
951
948
  for (const arm of def.arms) {
952
- if (ifErrorLibFn(L, arm) === null)
949
+ if (ifErrorLibFn(lowerer, arm) === null)
953
950
  fence(arm);
954
951
  }
955
- const helper = ifErrorHelper(L, unionT, loc);
952
+ const helper = ifErrorHelper(lowerer, unionT, loc);
956
953
  return { kind: "call", callee: helper, args: [v], type: VOID, loc };
957
954
  }
958
955
  /** The interned per-union ifError helper `%assert.iferr.<n>(v): void` —
959
956
  * one tag test per arm: unit arms return quietly, every other arm
960
957
  * narrows and throws through its typed runtime entry. */
961
- function ifErrorHelper(L, t, loc) {
958
+ function ifErrorHelper(lowerer, t, loc) {
962
959
  const key = `assert.iferr:${typeKey(t)}`;
963
- const existing = L.assertHelpers.get(key);
960
+ const existing = lowerer.assertHelpers.get(key);
964
961
  if (existing)
965
962
  return existing;
966
- const name = `%assert.iferr.${L.assertHelpers.size}`;
967
- L.assertHelpers.set(key, name);
968
- const def = L.unions.get(t.unionId);
963
+ const name = `%assert.iferr.${lowerer.assertHelpers.size}`;
964
+ lowerer.assertHelpers.set(key, name);
965
+ const def = lowerer.unions.get(t.unionId);
969
966
  if (!def)
970
- throw new Error(`assert.ifError over unknown union ${t.unionId}`);
967
+ throw new InternalCompilerError(`assert.ifError over unknown union ${t.unionId}`);
971
968
  const v = () => ({ kind: "varRef", localId: "v.0", type: t, loc });
972
969
  const doReturn = { kind: "return", value: null, loc };
973
970
  const body = [];
974
971
  def.arms.forEach((arm, tag) => {
975
- const fn = ifErrorLibFn(L, arm);
972
+ const fn = ifErrorLibFn(lowerer, arm);
976
973
  if (fn === null)
977
- throw new Error("assert.ifError helper over an unfenced arm");
974
+ throw new InternalCompilerError("assert.ifError helper over an unfenced arm");
978
975
  const then = fn === "unit"
979
976
  ? [doReturn]
980
977
  : [
@@ -1000,7 +997,7 @@ function ifErrorHelper(L, t, loc) {
1000
997
  });
1001
998
  });
1002
999
  body.push(doReturn); // unreachable: some arm always matches
1003
- L.liftedFns.push({
1000
+ lowerer.liftedFns.push({
1004
1001
  name,
1005
1002
  params: [{ localId: "v.0", name: "v", type: t }],
1006
1003
  returnType: VOID,
@@ -1021,8 +1018,8 @@ const BYTES_BRANDS = new Set([
1021
1018
  "Int8Array", "Int16Array", "Int32Array", "Float32Array", "Float64Array",
1022
1019
  "BigInt64Array", "BigUint64Array", "DataView",
1023
1020
  ]);
1024
- function bytesBrandOf(L, node) {
1025
- const tname = L.checker.typeToString(L.checker.getBaseTypeOfLiteralType(L.typeOf(node)));
1021
+ function bytesBrandOf(lowerer, node) {
1022
+ const tname = lowerer.checker.typeToString(lowerer.checker.getBaseTypeOfLiteralType(lowerer.typeOf(node)));
1026
1023
  const head = /^[A-Za-z_$][A-Za-z0-9_$]*/.exec(tname)?.[0] ?? "";
1027
1024
  if (head === "Buffer" || head === "NonSharedBuffer")
1028
1025
  return "Buffer";
@@ -1033,7 +1030,7 @@ function bytesBrandOf(L, node) {
1033
1030
  * fence names the FIRST unsupported constituent — never a silent
1034
1031
  * miscompare. Recursive record shapes terminate through `visiting`
1035
1032
  * (a shape being checked is assumed fine; its own walk decides). */
1036
- function deepUnsupportedReason(L, t, visiting) {
1033
+ function deepUnsupportedReason(lowerer, t, visiting) {
1037
1034
  switch (t.kind) {
1038
1035
  case "f64":
1039
1036
  case "string":
@@ -1042,40 +1039,40 @@ function deepUnsupportedReason(L, t, visiting) {
1042
1039
  case "nullT":
1043
1040
  return null;
1044
1041
  case "array":
1045
- return deepUnsupportedReason(L, t.elem, visiting);
1042
+ return deepUnsupportedReason(lowerer, t.elem, visiting);
1046
1043
  case "record": {
1047
1044
  if (visiting.has(t.shapeId))
1048
1045
  return null;
1049
1046
  visiting.add(t.shapeId);
1050
- const shape = L.shapes.get(t.shapeId);
1047
+ const shape = lowerer.shapes.get(t.shapeId);
1051
1048
  if (!shape)
1052
1049
  return "this record shape has no deep comparison";
1053
1050
  if (shape.indexValue !== undefined) {
1054
1051
  return "index-signature records have no deep comparison (their key sets are dynamic)";
1055
1052
  }
1056
1053
  for (const f of shape.fields) {
1057
- const why = deepUnsupportedReason(L, f.type, visiting);
1054
+ const why = deepUnsupportedReason(lowerer, f.type, visiting);
1058
1055
  if (why !== null)
1059
1056
  return why;
1060
1057
  }
1061
1058
  return null;
1062
1059
  }
1063
1060
  case "map": {
1064
- const keyWhy = deepUnsupportedReason(L, t.key, visiting);
1061
+ const keyWhy = deepUnsupportedReason(lowerer, t.key, visiting);
1065
1062
  if (keyWhy !== null)
1066
1063
  return keyWhy;
1067
- return deepUnsupportedReason(L, t.value, visiting);
1064
+ return deepUnsupportedReason(lowerer, t.value, visiting);
1068
1065
  }
1069
1066
  case "set":
1070
1067
  return t.elem.kind === "f64" || t.elem.kind === "string" || t.elem.kind === "bool"
1071
1068
  ? null
1072
1069
  : "Sets of non-scalar elements have no deep comparison (Node matches object members structurally)";
1073
1070
  case "union": {
1074
- const def = L.unions.get(t.unionId);
1071
+ const def = lowerer.unions.get(t.unionId);
1075
1072
  if (!def)
1076
1073
  return "this union has no deep comparison";
1077
1074
  for (const arm of def.arms) {
1078
- const why = deepUnsupportedReason(L, arm, visiting);
1075
+ const why = deepUnsupportedReason(lowerer, arm, visiting);
1079
1076
  if (why !== null)
1080
1077
  return why;
1081
1078
  }
@@ -1098,7 +1095,7 @@ function deepUnsupportedReason(L, t, visiting) {
1098
1095
  case "object":
1099
1096
  return "class instances have no deep comparison (Node compares prototypes and own properties)";
1100
1097
  default:
1101
- return `'${L.fmt(t)}' values have no deep comparison`;
1098
+ return `'${lowerer.fmt(t)}' values have no deep comparison`;
1102
1099
  }
1103
1100
  }
1104
1101
  /** The interned per-type deep-equality helper `%assert.deq.<n>(a, b):
@@ -1107,28 +1104,25 @@ function deepUnsupportedReason(L, t, visiting) {
1107
1104
  * tag+payload unions, SameValueZero-keyed Maps with deep values, scalar
1108
1105
  * Sets by membership. Registered in the cache BEFORE the body builds, so
1109
1106
  * recursive record shapes call themselves by name. */
1110
- function deepEqHelper(L, t, loc) {
1107
+ function deepEqHelper(lowerer, t, loc) {
1111
1108
  const key = `assert.deq:${typeKey(t)}`;
1112
- const existing = L.assertHelpers.get(key);
1109
+ const existing = lowerer.assertHelpers.get(key);
1113
1110
  if (existing)
1114
1111
  return existing;
1115
- const name = `%assert.deq.${L.assertHelpers.size}`;
1116
- L.assertHelpers.set(key, name);
1117
- const ref = (localId, type) => ({ kind: "varRef", localId, type, loc });
1118
- const a = () => ref("a.0", t);
1119
- const b = () => ref("b.0", t);
1120
- const num = (value) => ({ kind: "numLit", value, type: F64, loc });
1121
- const boolLit = (value) => ({ kind: "boolLit", value, type: BOOL, loc });
1112
+ const name = `%assert.deq.${lowerer.assertHelpers.size}`;
1113
+ lowerer.assertHelpers.set(key, name);
1114
+ const a = () => varRef("a.0", t, loc);
1115
+ const b = () => varRef("b.0", t, loc);
1122
1116
  const ret = (value) => ({ kind: "return", value, loc });
1123
- const retFalse = ret(boolLit(false));
1117
+ const retFalse = ret(boolLit(false, loc));
1124
1118
  const not = (operand) => ({ kind: "unary", op: "!", operand, type: BOOL, loc });
1125
1119
  const neq = (left, right) => ({ kind: "bin", op: "!==", left, right, type: BOOL, loc });
1126
1120
  /** if (cond) return false; */
1127
1121
  const bailIf = (cond) => ({ kind: "if", cond, then: [retFalse], else_: null, loc });
1128
1122
  /** Deep-compare two same-typed exprs through the per-type helper. */
1129
1123
  const deq = (elemT, x, y) => isUnitType(elemT)
1130
- ? boolLit(true)
1131
- : { kind: "call", callee: deepEqHelper(L, elemT, loc), args: [x, y], type: BOOL, loc };
1124
+ ? boolLit(true, loc)
1125
+ : { kind: "call", callee: deepEqHelper(lowerer, elemT, loc), args: [x, y], type: BOOL, loc };
1132
1126
  let locals = [
1133
1127
  { id: "a.0", name: "a", type: t, mutable: false },
1134
1128
  { id: "b.0", name: "b", type: t, mutable: false },
@@ -1156,22 +1150,15 @@ function deepEqHelper(L, t, loc) {
1156
1150
  locals.push({ id: "i.0", name: "i", type: F64, mutable: true });
1157
1151
  body = [
1158
1152
  bailIf(neq(len(a()), len(b()))),
1159
- {
1160
- kind: "for",
1161
- init: { kind: "varDecl", localId: "i.0", init: num(0), loc },
1162
- cond: { kind: "bin", op: "<", left: ref("i.0", F64), right: len(a()), type: BOOL, loc },
1163
- update: { kind: "assign", localId: "i.0", value: { kind: "bin", op: "+", left: ref("i.0", F64), right: num(1), type: F64, loc }, loc },
1164
- body: [bailIf(not(deq(t.elem, at(a(), ref("i.0", F64)), at(b(), ref("i.0", F64)))))],
1165
- loc,
1166
- },
1167
- ret(boolLit(true)),
1153
+ countedFor(loc, len(a()), (i) => [bailIf(not(deq(t.elem, at(a(), i), at(b(), i))))]),
1154
+ ret(boolLit(true, loc)),
1168
1155
  ];
1169
1156
  break;
1170
1157
  }
1171
1158
  case "record": {
1172
- const shape = L.shapes.get(t.shapeId);
1159
+ const shape = lowerer.shapes.get(t.shapeId);
1173
1160
  if (!shape)
1174
- throw new Error(`assert deep-equal of unknown shape ${t.shapeId}`);
1161
+ throw new InternalCompilerError(`assert deep-equal of unknown shape ${t.shapeId}`);
1175
1162
  const get = (obj, field, type) => ({ kind: "recordGet", obj, shapeId: t.shapeId, field, type, loc });
1176
1163
  body = [];
1177
1164
  for (const f of shape.fields) {
@@ -1179,13 +1166,13 @@ function deepEqHelper(L, t, loc) {
1179
1166
  continue; // a unit field is equal by type
1180
1167
  body.push(bailIf(not(deq(f.type, get(a(), f.name, f.type), get(b(), f.name, f.type)))));
1181
1168
  }
1182
- body.push(ret(boolLit(true)));
1169
+ body.push(ret(boolLit(true, loc)));
1183
1170
  break;
1184
1171
  }
1185
1172
  case "union": {
1186
- const def = L.unions.get(t.unionId);
1173
+ const def = lowerer.unions.get(t.unionId);
1187
1174
  if (!def)
1188
- throw new Error(`assert deep-equal of unknown union ${t.unionId}`);
1175
+ throw new InternalCompilerError(`assert deep-equal of unknown union ${t.unionId}`);
1189
1176
  const isTag = (v, tag, negated) => ({ kind: "unionIsTag", unionId: t.unionId, tag, negated, value: v, type: BOOL, loc });
1190
1177
  const narrow = (v, tag, armT) => ({ kind: "unionNarrow", unionId: t.unionId, tag, value: v, type: armT, loc });
1191
1178
  body = [];
@@ -1208,67 +1195,53 @@ function deepEqHelper(L, t, loc) {
1208
1195
  const mi = (method, receiver, args, type) => ({ kind: "mapIntrinsic", method, receiver, args, type, loc });
1209
1196
  const valueT = t.value;
1210
1197
  const hasUndefArm = valueT.kind === "union" &&
1211
- (L.unions.get(valueT.unionId)?.arms.some((arm) => arm.kind === "undefinedT") ?? false);
1212
- const getT = hasUndefArm ? valueT : L.withUndefinedArm(valueT);
1198
+ (lowerer.unions.get(valueT.unionId)?.arms.some((arm) => arm.kind === "undefinedT") ?? false);
1199
+ const getT = hasUndefArm ? valueT : lowerer.withUndefinedArm(valueT);
1213
1200
  locals.push({ id: "i.0", name: "i", type: F64, mutable: true }, { id: "k.0", name: "k", type: t.key, mutable: false }, { id: "av.0", name: "av", type: valueT, mutable: false }, { id: "bv.0", name: "bv", type: getT, mutable: false });
1214
- const i = () => ref("i.0", F64);
1215
- const k = () => ref("k.0", t.key);
1201
+ const i = () => varRef("i.0", F64, loc);
1202
+ const k = () => varRef("k.0", t.key, loc);
1216
1203
  // The b-side value: get() answers `V | undefined`; has() already
1217
1204
  // proved presence, so a plain V narrows through the value arm.
1218
1205
  const bValue = getT === valueT
1219
- ? ref("bv.0", getT)
1206
+ ? varRef("bv.0", getT, loc)
1220
1207
  : {
1221
1208
  kind: "unionNarrow",
1222
1209
  unionId: getT.unionId,
1223
- tag: L.armTag(getT.unionId, valueT),
1224
- value: ref("bv.0", getT),
1210
+ tag: lowerer.armTag(getT.unionId, valueT),
1211
+ value: varRef("bv.0", getT, loc),
1225
1212
  type: valueT,
1226
1213
  loc,
1227
1214
  };
1228
1215
  body = [
1229
1216
  bailIf(neq(mi("size", a(), [], F64), mi("size", b(), [], F64))),
1230
- {
1231
- kind: "for",
1232
- init: { kind: "varDecl", localId: "i.0", init: num(0), loc },
1233
- cond: { kind: "bin", op: "<", left: i(), right: mi("iterCount", a(), [], F64), type: BOOL, loc },
1234
- update: { kind: "assign", localId: "i.0", value: { kind: "bin", op: "+", left: i(), right: num(1), type: F64, loc }, loc },
1235
- body: [
1236
- { kind: "if", cond: not(mi("iterLive", a(), [i()], BOOL)), then: [{ kind: "continue", loc }], else_: null, loc },
1237
- { kind: "varDecl", localId: "k.0", init: mi("iterKey", a(), [i()], t.key), loc },
1238
- bailIf(not(mi("has", b(), [k()], BOOL))),
1239
- { kind: "varDecl", localId: "av.0", init: mi("iterValue", a(), [i()], valueT), loc },
1240
- { kind: "varDecl", localId: "bv.0", init: mi("get", b(), [k()], getT), loc },
1241
- bailIf(not(deq(valueT, ref("av.0", valueT), bValue))),
1242
- ],
1243
- loc,
1244
- },
1245
- ret(boolLit(true)),
1217
+ countedFor(loc, mi("iterCount", a(), [], F64), () => [
1218
+ { kind: "if", cond: not(mi("iterLive", a(), [i()], BOOL)), then: [{ kind: "continue", loc }], else_: null, loc },
1219
+ { kind: "varDecl", localId: "k.0", init: mi("iterKey", a(), [i()], t.key), loc },
1220
+ bailIf(not(mi("has", b(), [k()], BOOL))),
1221
+ { kind: "varDecl", localId: "av.0", init: mi("iterValue", a(), [i()], valueT), loc },
1222
+ { kind: "varDecl", localId: "bv.0", init: mi("get", b(), [k()], getT), loc },
1223
+ bailIf(not(deq(valueT, varRef("av.0", valueT, loc), bValue))),
1224
+ ]),
1225
+ ret(boolLit(true, loc)),
1246
1226
  ];
1247
1227
  break;
1248
1228
  }
1249
1229
  case "set": {
1250
1230
  const si = (method, receiver, args, type) => ({ kind: "setIntrinsic", method, receiver, args, type, loc });
1251
1231
  locals.push({ id: "i.0", name: "i", type: F64, mutable: true });
1252
- const i = () => ref("i.0", F64);
1232
+ const i = () => varRef("i.0", F64, loc);
1253
1233
  body = [
1254
1234
  bailIf(neq(si("size", a(), [], F64), si("size", b(), [], F64))),
1255
- {
1256
- kind: "for",
1257
- init: { kind: "varDecl", localId: "i.0", init: num(0), loc },
1258
- cond: { kind: "bin", op: "<", left: i(), right: si("iterCount", a(), [], F64), type: BOOL, loc },
1259
- update: { kind: "assign", localId: "i.0", value: { kind: "bin", op: "+", left: i(), right: num(1), type: F64, loc }, loc },
1260
- body: [
1261
- { kind: "if", cond: not(si("iterLive", a(), [i()], BOOL)), then: [{ kind: "continue", loc }], else_: null, loc },
1262
- bailIf(not(si("has", b(), [si("iterKey", a(), [i()], t.elem)], BOOL))),
1263
- ],
1264
- loc,
1265
- },
1266
- ret(boolLit(true)),
1235
+ countedFor(loc, si("iterCount", a(), [], F64), () => [
1236
+ { kind: "if", cond: not(si("iterLive", a(), [i()], BOOL)), then: [{ kind: "continue", loc }], else_: null, loc },
1237
+ bailIf(not(si("has", b(), [si("iterKey", a(), [i()], t.elem)], BOOL))),
1238
+ ]),
1239
+ ret(boolLit(true, loc)),
1267
1240
  ];
1268
1241
  break;
1269
1242
  }
1270
1243
  default:
1271
- throw new Error(`assert deep-equal helper over unexpected type ${typeKey(t)}`);
1244
+ throw new InternalCompilerError(`assert deep-equal helper over unexpected type ${typeKey(t)}`);
1272
1245
  }
1273
1246
  // CYCLE-CAPABLE containers (recursive record types and their arrays/
1274
1247
  // maps) wrap the structural walk in the runtime PAIR MEMO: identical
@@ -1277,9 +1250,9 @@ function deepEqHelper(L, t, loc) {
1277
1250
  // structures compare true instead of recursing forever. The walk moves
1278
1251
  // into a sibling function; `name` becomes the memo wrapper every caller
1279
1252
  // (recursion included) enters through.
1280
- if ((t.kind === "record" || t.kind === "array" || t.kind === "map") && typeReachesItself(L, t)) {
1253
+ if ((t.kind === "record" || t.kind === "array" || t.kind === "map") && typeReachesItself(lowerer, t)) {
1281
1254
  const walkName = `${name}.walk`;
1282
- L.liftedFns.push({
1255
+ lowerer.liftedFns.push({
1283
1256
  name: walkName,
1284
1257
  params: [
1285
1258
  { localId: "a.0", name: "a", type: t },
@@ -1296,20 +1269,20 @@ function deepEqHelper(L, t, loc) {
1296
1269
  { id: "eq.0", name: "eq", type: BOOL, mutable: false },
1297
1270
  ];
1298
1271
  body = [
1299
- { kind: "if", cond: { kind: "bin", op: "===", left: a(), right: b(), type: BOOL, loc }, then: [ret(boolLit(true))], else_: null, loc },
1272
+ { kind: "if", cond: { kind: "bin", op: "===", left: a(), right: b(), type: BOOL, loc }, then: [ret(boolLit(true, loc))], else_: null, loc },
1300
1273
  {
1301
1274
  kind: "if",
1302
1275
  cond: { kind: "libCall", fn: "assert.deqEnter", args: [a(), b()], type: BOOL, loc },
1303
- then: [ret(boolLit(true))],
1276
+ then: [ret(boolLit(true, loc))],
1304
1277
  else_: null,
1305
1278
  loc,
1306
1279
  },
1307
1280
  { kind: "varDecl", localId: "eq.0", init: { kind: "call", callee: walkName, args: [a(), b()], type: BOOL, loc }, loc },
1308
1281
  { kind: "exprStmt", expr: { kind: "libCall", fn: "assert.deqLeave", args: [], type: VOID, loc }, loc },
1309
- ret(ref("eq.0", BOOL)),
1282
+ ret(varRef("eq.0", BOOL, loc)),
1310
1283
  ];
1311
1284
  }
1312
- L.liftedFns.push({
1285
+ lowerer.liftedFns.push({
1313
1286
  name,
1314
1287
  params: [
1315
1288
  { localId: "a.0", name: "a", type: t },