@scriptc/compiler 0.0.34 → 0.0.36

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 (424) hide show
  1. package/ambient/scriptc-node-fallback.d.ts +7 -6
  2. package/dist/backend/build-cache.d.ts +44 -0
  3. package/dist/backend/build-cache.js +241 -0
  4. package/dist/backend/build-cache.js.map +1 -0
  5. package/dist/backend/{emission/emit-async.d.ts → c/async.d.ts} +21 -30
  6. package/dist/backend/{emission/emit-async.js → c/async.js} +270 -286
  7. package/dist/backend/c/async.js.map +1 -0
  8. package/dist/backend/{emission/emitter.d.ts → c/c-emitter.d.ts} +6 -23
  9. package/dist/backend/{emission/emitter.js → c/c-emitter.js} +53 -107
  10. package/dist/backend/c/c-emitter.js.map +1 -0
  11. package/dist/backend/c/exprs.d.ts +8 -0
  12. package/dist/backend/c/exprs.js +7913 -0
  13. package/dist/backend/c/exprs.js.map +1 -0
  14. package/dist/backend/{emission/emit-island.d.ts → c/island.d.ts} +5 -5
  15. package/dist/backend/{emission/emit-island.js → c/island.js} +24 -22
  16. package/dist/backend/c/island.js.map +1 -0
  17. package/dist/backend/{emission → c}/may-throw.d.ts +1 -1
  18. package/dist/backend/{emission → c}/may-throw.js +1 -1
  19. package/dist/backend/c/may-throw.js.map +1 -0
  20. package/dist/backend/{emission/emit-shapes.d.ts → c/shapes.d.ts} +19 -19
  21. package/dist/backend/{emission/emit-shapes.js → c/shapes.js} +78 -87
  22. package/dist/backend/c/shapes.js.map +1 -0
  23. package/dist/backend/{emission/emit-stmts.d.ts → c/stmts.d.ts} +12 -12
  24. package/dist/backend/{emission/emit-stmts.js → c/stmts.js} +377 -343
  25. package/dist/backend/c/stmts.js.map +1 -0
  26. package/dist/backend/{emission/emit-types.d.ts → c/types.d.ts} +1 -1
  27. package/dist/backend/{emission/emit-types.js → c/types.js} +42 -286
  28. package/dist/backend/c/types.js.map +1 -0
  29. package/dist/backend/c/types.test.js +25 -0
  30. package/dist/backend/c/types.test.js.map +1 -0
  31. package/dist/backend/{emission/emit-walkers.d.ts → c/walkers.d.ts} +19 -41
  32. package/dist/backend/{emission/emit-walkers.js → c/walkers.js} +238 -298
  33. package/dist/backend/c/walkers.js.map +1 -0
  34. package/dist/backend/ffi-callbacks.d.ts +1 -1
  35. package/dist/backend/ffi-callbacks.js +4 -3
  36. package/dist/backend/ffi-callbacks.js.map +1 -1
  37. package/dist/backend/{library-identity.d.ts → library-identity-markers.d.ts} +0 -4
  38. package/dist/backend/{library-identity.js → library-identity-markers.js} +10 -9
  39. package/dist/backend/library-identity-markers.js.map +1 -0
  40. package/dist/backend/llvm/blocks.d.ts +4 -0
  41. package/dist/backend/llvm/blocks.js +29 -0
  42. package/dist/backend/llvm/blocks.js.map +1 -1
  43. package/dist/backend/llvm/classes.d.ts +2 -19
  44. package/dist/backend/llvm/classes.js +20 -52
  45. package/dist/backend/llvm/classes.js.map +1 -1
  46. package/dist/backend/llvm/common.d.ts +4 -0
  47. package/dist/backend/llvm/common.js +27 -0
  48. package/dist/backend/llvm/common.js.map +1 -0
  49. package/dist/backend/llvm/dyn.d.ts +3 -8
  50. package/dist/backend/llvm/dyn.js +152 -224
  51. package/dist/backend/llvm/dyn.js.map +1 -1
  52. package/dist/backend/llvm/emitter.d.ts +4 -1
  53. package/dist/backend/llvm/emitter.js +514 -9981
  54. package/dist/backend/llvm/emitter.js.map +1 -1
  55. package/dist/backend/llvm/expr-async.d.ts +4 -0
  56. package/dist/backend/llvm/expr-async.js +726 -0
  57. package/dist/backend/llvm/expr-async.js.map +1 -0
  58. package/dist/backend/llvm/expr-bytes.d.ts +13 -0
  59. package/dist/backend/llvm/expr-bytes.js +456 -0
  60. package/dist/backend/llvm/expr-bytes.js.map +1 -0
  61. package/dist/backend/llvm/expr-callbacks.d.ts +22 -0
  62. package/dist/backend/llvm/expr-callbacks.js +520 -0
  63. package/dist/backend/llvm/expr-callbacks.js.map +1 -0
  64. package/dist/backend/llvm/expr-calls.d.ts +2 -0
  65. package/dist/backend/llvm/expr-calls.js +618 -0
  66. package/dist/backend/llvm/expr-calls.js.map +1 -0
  67. package/dist/backend/llvm/expr-containers.d.ts +25 -0
  68. package/dist/backend/llvm/expr-containers.js +623 -0
  69. package/dist/backend/llvm/expr-containers.js.map +1 -0
  70. package/dist/backend/llvm/expr-context.d.ts +255 -0
  71. package/dist/backend/llvm/expr-context.js +2 -0
  72. package/dist/backend/llvm/expr-context.js.map +1 -0
  73. package/dist/backend/llvm/expr-control.d.ts +2 -0
  74. package/dist/backend/llvm/expr-control.js +473 -0
  75. package/dist/backend/llvm/expr-control.js.map +1 -0
  76. package/dist/backend/llvm/expr-dispatch.d.ts +4 -0
  77. package/dist/backend/llvm/expr-dispatch.js +151 -0
  78. package/dist/backend/llvm/expr-dispatch.js.map +1 -0
  79. package/dist/backend/llvm/expr-dynamic.d.ts +2 -0
  80. package/dist/backend/llvm/expr-dynamic.js +810 -0
  81. package/dist/backend/llvm/expr-dynamic.js.map +1 -0
  82. package/dist/backend/llvm/expr-island.d.ts +15 -0
  83. package/dist/backend/llvm/expr-island.js +690 -0
  84. package/dist/backend/llvm/expr-island.js.map +1 -0
  85. package/dist/backend/llvm/expr-primitives.d.ts +6 -0
  86. package/dist/backend/llvm/expr-primitives.js +622 -0
  87. package/dist/backend/llvm/expr-primitives.js.map +1 -0
  88. package/dist/backend/llvm/expr-records.d.ts +9 -0
  89. package/dist/backend/llvm/expr-records.js +299 -0
  90. package/dist/backend/llvm/expr-records.js.map +1 -0
  91. package/dist/backend/llvm/expr-stream-bridges.d.ts +13 -0
  92. package/dist/backend/llvm/expr-stream-bridges.js +396 -0
  93. package/dist/backend/llvm/expr-stream-bridges.js.map +1 -0
  94. package/dist/backend/llvm/expr-stream-callbacks.d.ts +12 -0
  95. package/dist/backend/llvm/expr-stream-callbacks.js +360 -0
  96. package/dist/backend/llvm/expr-stream-callbacks.js.map +1 -0
  97. package/dist/backend/llvm/lib-dispatch.d.ts +5 -0
  98. package/dist/backend/llvm/lib-dispatch.js +267 -0
  99. package/dist/backend/llvm/lib-dispatch.js.map +1 -0
  100. package/dist/backend/llvm/lib-filesystem.d.ts +6 -0
  101. package/dist/backend/llvm/lib-filesystem.js +594 -0
  102. package/dist/backend/llvm/lib-filesystem.js.map +1 -0
  103. package/dist/backend/llvm/lib-network.d.ts +2 -0
  104. package/dist/backend/llvm/lib-network.js +429 -0
  105. package/dist/backend/llvm/lib-network.js.map +1 -0
  106. package/dist/backend/llvm/lib-process.d.ts +5 -0
  107. package/dist/backend/llvm/lib-process.js +585 -0
  108. package/dist/backend/llvm/lib-process.js.map +1 -0
  109. package/dist/backend/llvm/lib-shared.d.ts +6 -0
  110. package/dist/backend/llvm/lib-shared.js +687 -0
  111. package/dist/backend/llvm/lib-shared.js.map +1 -0
  112. package/dist/backend/llvm/lib-stream.d.ts +2 -0
  113. package/dist/backend/llvm/lib-stream.js +470 -0
  114. package/dist/backend/llvm/lib-stream.js.map +1 -0
  115. package/dist/backend/llvm/shapes.d.ts +12 -2
  116. package/dist/backend/llvm/shapes.js +66 -307
  117. package/dist/backend/llvm/shapes.js.map +1 -1
  118. package/dist/backend/llvm/shapes.test.js +52 -0
  119. package/dist/backend/llvm/shapes.test.js.map +1 -0
  120. package/dist/backend/llvm/split.d.ts +43 -0
  121. package/dist/backend/llvm/split.js +227 -0
  122. package/dist/backend/llvm/split.js.map +1 -0
  123. package/dist/backend/llvm/split.test.d.ts +1 -0
  124. package/dist/backend/llvm/split.test.js +102 -0
  125. package/dist/backend/llvm/split.test.js.map +1 -0
  126. package/dist/backend/llvm/unsupported.d.ts +1 -1
  127. package/dist/backend/llvm/walkers.d.ts +2 -3
  128. package/dist/backend/llvm/walkers.js +164 -218
  129. package/dist/backend/llvm/walkers.js.map +1 -1
  130. package/dist/backend/native-codegen.d.ts +38 -0
  131. package/dist/backend/native-codegen.js +261 -0
  132. package/dist/backend/native-codegen.js.map +1 -0
  133. package/dist/backend/native-codegen.test.d.ts +1 -0
  134. package/dist/backend/native-codegen.test.js +188 -0
  135. package/dist/backend/native-codegen.test.js.map +1 -0
  136. package/dist/backend/native-link-info.d.ts +96 -0
  137. package/dist/backend/native-link-info.js +219 -0
  138. package/dist/backend/native-link-info.js.map +1 -0
  139. package/dist/backend/native-link-info.test.d.ts +1 -0
  140. package/dist/backend/native-link-info.test.js +134 -0
  141. package/dist/backend/native-link-info.test.js.map +1 -0
  142. package/dist/backend/{cc.d.ts → native-toolchain.d.ts} +139 -47
  143. package/dist/backend/{cc.js → native-toolchain.js} +1008 -910
  144. package/dist/backend/native-toolchain.js.map +1 -0
  145. package/dist/backend/native-toolchain.test.d.ts +1 -0
  146. package/dist/backend/{cc-cache.test.js → native-toolchain.test.js} +1297 -127
  147. package/dist/backend/native-toolchain.test.js.map +1 -0
  148. package/dist/backend/object-localize.js +1 -1
  149. package/dist/backend/object-localize.test.js +20 -0
  150. package/dist/backend/object-localize.test.js.map +1 -1
  151. package/dist/backend/runtime-abi.d.ts +10 -0
  152. package/dist/backend/runtime-abi.js +11 -0
  153. package/dist/backend/runtime-abi.js.map +1 -0
  154. package/dist/backend/runtime-pack.d.ts +137 -0
  155. package/dist/backend/runtime-pack.js +400 -0
  156. package/dist/backend/runtime-pack.js.map +1 -0
  157. package/dist/backend/runtime-pack.test.d.ts +1 -0
  158. package/dist/backend/runtime-pack.test.js +438 -0
  159. package/dist/backend/runtime-pack.test.js.map +1 -0
  160. package/dist/backend/targets.d.ts +30 -0
  161. package/dist/backend/targets.js +46 -0
  162. package/dist/backend/targets.js.map +1 -0
  163. package/dist/backend/targets.test.d.ts +1 -0
  164. package/dist/backend/targets.test.js +19 -0
  165. package/dist/backend/targets.test.js.map +1 -0
  166. package/dist/backend/vendor-archives.d.ts +41 -0
  167. package/dist/backend/vendor-archives.js +462 -0
  168. package/dist/backend/vendor-archives.js.map +1 -0
  169. package/dist/compat/fetch-profile.d.ts +0 -1
  170. package/dist/compat/fetch-profile.js +0 -1
  171. package/dist/compat/fetch-profile.js.map +1 -1
  172. package/dist/coverage/report.js +3 -3
  173. package/dist/coverage/report.js.map +1 -1
  174. package/dist/coverage/surface-manifest.js +25 -32
  175. package/dist/coverage/surface-manifest.js.map +1 -1
  176. package/dist/diagnostics/diagnostic.d.ts +11 -12
  177. package/dist/diagnostics/diagnostic.js +19 -17
  178. package/dist/diagnostics/diagnostic.js.map +1 -1
  179. package/dist/diagnostics/render.d.ts +1 -1
  180. package/dist/diagnostics/render.js +1 -1
  181. package/dist/diagnostics/render.js.map +1 -1
  182. package/dist/errors.d.ts +5 -0
  183. package/dist/errors.js +9 -0
  184. package/dist/errors.js.map +1 -0
  185. package/dist/executable/executable-cache.d.ts +86 -0
  186. package/dist/executable/executable-cache.js +398 -0
  187. package/dist/executable/executable-cache.js.map +1 -0
  188. package/dist/executable/executable-cache.test.d.ts +1 -0
  189. package/dist/executable/executable-cache.test.js +300 -0
  190. package/dist/executable/executable-cache.test.js.map +1 -0
  191. package/dist/ffi/{profile.d.ts → ffi-manifest.d.ts} +7 -2
  192. package/dist/ffi/{profile.js → ffi-manifest.js} +2 -1
  193. package/dist/ffi/ffi-manifest.js.map +1 -0
  194. package/dist/frontend/builtin-modules.d.ts +21 -0
  195. package/dist/frontend/builtin-modules.js +82 -0
  196. package/dist/frontend/builtin-modules.js.map +1 -0
  197. package/dist/frontend/cjs-lexer.d.ts +7 -0
  198. package/dist/frontend/cjs-lexer.js +15 -17
  199. package/dist/frontend/cjs-lexer.js.map +1 -1
  200. package/dist/frontend/dts-paths.d.ts +26 -0
  201. package/dist/frontend/dts-paths.js +41 -0
  202. package/dist/frontend/dts-paths.js.map +1 -0
  203. package/dist/frontend/input-tracker.d.ts +0 -2
  204. package/dist/frontend/input-tracker.js +1 -4
  205. package/dist/frontend/input-tracker.js.map +1 -1
  206. package/dist/frontend/lib-contract.d.ts +1 -5
  207. package/dist/frontend/lib-contract.js +1 -1
  208. package/dist/frontend/lib-contract.js.map +1 -1
  209. package/dist/frontend/lib-exports.d.ts +1 -1
  210. package/dist/frontend/lowering/call-position.d.ts +4 -0
  211. package/dist/frontend/lowering/call-position.js +7 -0
  212. package/dist/frontend/lowering/call-position.js.map +1 -0
  213. package/dist/frontend/lowering/callback-arg.d.ts +20 -0
  214. package/dist/frontend/lowering/callback-arg.js +44 -0
  215. package/dist/frontend/lowering/callback-arg.js.map +1 -0
  216. package/dist/frontend/lowering/lib-boundary.d.ts +1 -1
  217. package/dist/frontend/lowering/lib-boundary.js +34 -34
  218. package/dist/frontend/lowering/lib-boundary.js.map +1 -1
  219. package/dist/frontend/lowering/lower-assert.d.ts +3 -3
  220. package/dist/frontend/lowering/lower-assert.js +214 -241
  221. package/dist/frontend/lowering/lower-assert.js.map +1 -1
  222. package/dist/frontend/lowering/lower-builtins.d.ts +74 -146
  223. package/dist/frontend/lowering/lower-builtins.js +1126 -1234
  224. package/dist/frontend/lowering/lower-builtins.js.map +1 -1
  225. package/dist/frontend/lowering/lower-calls.d.ts +56 -188
  226. package/dist/frontend/lowering/lower-calls.js +1409 -1494
  227. package/dist/frontend/lowering/lower-calls.js.map +1 -1
  228. package/dist/frontend/lowering/lower-classes.d.ts +62 -125
  229. package/dist/frontend/lowering/lower-classes.js +832 -866
  230. package/dist/frontend/lowering/lower-classes.js.map +1 -1
  231. package/dist/frontend/lowering/lower-comptime.d.ts +5 -12
  232. package/dist/frontend/lowering/lower-comptime.js +32 -31
  233. package/dist/frontend/lowering/lower-comptime.js.map +1 -1
  234. package/dist/frontend/lowering/lower-containers.d.ts +35 -135
  235. package/dist/frontend/lowering/lower-containers.js +1394 -1715
  236. package/dist/frontend/lowering/lower-containers.js.map +1 -1
  237. package/dist/frontend/lowering/lower-dgram.d.ts +3 -7
  238. package/dist/frontend/lowering/lower-dgram.js +97 -111
  239. package/dist/frontend/lowering/lower-dgram.js.map +1 -1
  240. package/dist/frontend/lowering/lower-enums.d.ts +4 -4
  241. package/dist/frontend/lowering/lower-enums.js +30 -30
  242. package/dist/frontend/lowering/lower-enums.js.map +1 -1
  243. package/dist/frontend/lowering/{lower-emitter.d.ts → lower-event-emitter.d.ts} +7 -18
  244. package/dist/frontend/lowering/{lower-emitter.js → lower-event-emitter.js} +172 -174
  245. package/dist/frontend/lowering/lower-event-emitter.js.map +1 -0
  246. package/dist/frontend/lowering/lower-expando.d.ts +5 -5
  247. package/dist/frontend/lowering/lower-expando.js +40 -40
  248. package/dist/frontend/lowering/lower-expando.js.map +1 -1
  249. package/dist/frontend/lowering/lower-exprs.d.ts +56 -264
  250. package/dist/frontend/lowering/lower-exprs.js +1644 -1704
  251. package/dist/frontend/lowering/lower-exprs.js.map +1 -1
  252. package/dist/frontend/lowering/lower-generators.d.ts +6 -6
  253. package/dist/frontend/lowering/lower-generators.js +73 -72
  254. package/dist/frontend/lowering/lower-generators.js.map +1 -1
  255. package/dist/frontend/lowering/lower-inspect.d.ts +5 -17
  256. package/dist/frontend/lowering/lower-inspect.js +236 -238
  257. package/dist/frontend/lowering/lower-inspect.js.map +1 -1
  258. package/dist/frontend/lowering/lower-island.d.ts +34 -45
  259. package/dist/frontend/lowering/lower-island.js +440 -511
  260. package/dist/frontend/lowering/lower-island.js.map +1 -1
  261. package/dist/frontend/lowering/lower-mixins.d.ts +7 -10
  262. package/dist/frontend/lowering/lower-mixins.js +86 -86
  263. package/dist/frontend/lowering/lower-mixins.js.map +1 -1
  264. package/dist/frontend/lowering/lower-modules.d.ts +12 -18
  265. package/dist/frontend/lowering/lower-modules.js +284 -283
  266. package/dist/frontend/lowering/lower-modules.js.map +1 -1
  267. package/dist/frontend/lowering/lower-namespaces.d.ts +23 -49
  268. package/dist/frontend/lowering/lower-namespaces.js +123 -115
  269. package/dist/frontend/lowering/lower-namespaces.js.map +1 -1
  270. package/dist/frontend/lowering/lower-server.d.ts +18 -25
  271. package/dist/frontend/lowering/lower-server.js +899 -899
  272. package/dist/frontend/lowering/lower-server.js.map +1 -1
  273. package/dist/frontend/lowering/lower-stmts.d.ts +30 -149
  274. package/dist/frontend/lowering/lower-stmts.js +1176 -1229
  275. package/dist/frontend/lowering/lower-stmts.js.map +1 -1
  276. package/dist/frontend/lowering/lower-stream.d.ts +12 -12
  277. package/dist/frontend/lowering/lower-stream.js +300 -301
  278. package/dist/frontend/lowering/lower-stream.js.map +1 -1
  279. package/dist/frontend/lowering/lower-test.d.ts +5 -5
  280. package/dist/frontend/lowering/lower-test.js +82 -82
  281. package/dist/frontend/lowering/lower-test.js.map +1 -1
  282. package/dist/frontend/lowering/lowerer.d.ts +66 -20
  283. package/dist/frontend/lowering/lowerer.js +421 -198
  284. package/dist/frontend/lowering/lowerer.js.map +1 -1
  285. package/dist/frontend/lowering/pairs-snapshot.d.ts +11 -0
  286. package/dist/frontend/lowering/pairs-snapshot.js +85 -0
  287. package/dist/frontend/lowering/pairs-snapshot.js.map +1 -0
  288. package/dist/frontend/lowering/static-this.d.ts +6 -0
  289. package/dist/frontend/lowering/static-this.js +24 -0
  290. package/dist/frontend/lowering/static-this.js.map +1 -0
  291. package/dist/frontend/lowering/surfaces.d.ts +14 -33
  292. package/dist/frontend/lowering/surfaces.js +64 -64
  293. package/dist/frontend/lowering/surfaces.js.map +1 -1
  294. package/dist/frontend/npm-static-rewrite.js +6 -28
  295. package/dist/frontend/npm-static-rewrite.js.map +1 -1
  296. package/dist/frontend/npm-static.d.ts +0 -10
  297. package/dist/frontend/npm-static.js +4 -7
  298. package/dist/frontend/npm-static.js.map +1 -1
  299. package/dist/frontend/npm.d.ts +0 -24
  300. package/dist/frontend/npm.js +11 -85
  301. package/dist/frontend/npm.js.map +1 -1
  302. package/dist/frontend/program.d.ts +3 -1
  303. package/dist/frontend/program.js +51 -17
  304. package/dist/frontend/program.js.map +1 -1
  305. package/dist/frontend/provenance-registry.d.ts +0 -2
  306. package/dist/frontend/provenance-registry.js +0 -10
  307. package/dist/frontend/provenance-registry.js.map +1 -1
  308. package/dist/frontend/provenance.js +4 -7
  309. package/dist/frontend/provenance.js.map +1 -1
  310. package/dist/frontend/resolve.d.ts +7 -2
  311. package/dist/frontend/resolve.js +12 -17
  312. package/dist/frontend/resolve.js.map +1 -1
  313. package/dist/frontend/resolve.test.d.ts +1 -0
  314. package/dist/frontend/resolve.test.js +29 -0
  315. package/dist/frontend/resolve.test.js.map +1 -0
  316. package/dist/frontend/ts7/adapter.d.ts +2 -2
  317. package/dist/frontend/ts7/adapter.js +1 -1
  318. package/dist/frontend/ts7/adapter.js.map +1 -1
  319. package/dist/frontend/ts7/checker.d.ts +40 -2
  320. package/dist/frontend/ts7/checker.js +182 -54
  321. package/dist/frontend/ts7/checker.js.map +1 -1
  322. package/dist/frontend/ts7/enums.js +2 -1
  323. package/dist/frontend/ts7/enums.js.map +1 -1
  324. package/dist/frontend/ts7/{program.js → program-adapter.js} +7 -6
  325. package/dist/frontend/ts7/program-adapter.js.map +1 -0
  326. package/dist/frontend/ts7/world-check.d.ts +1 -3
  327. package/dist/frontend/ts7/world-check.js +3 -1
  328. package/dist/frontend/ts7/world-check.js.map +1 -1
  329. package/dist/frontend/tsc-codes.d.ts +8 -0
  330. package/dist/frontend/tsc-codes.js +109 -0
  331. package/dist/frontend/tsc-codes.js.map +1 -0
  332. package/dist/frontend/{types.d.ts → type-mapper.d.ts} +2 -25
  333. package/dist/frontend/{types.js → type-mapper.js} +31 -52
  334. package/dist/frontend/type-mapper.js.map +1 -0
  335. package/dist/frontend/workspace-registry.d.ts +26 -0
  336. package/dist/frontend/workspace-registry.js +71 -0
  337. package/dist/frontend/workspace-registry.js.map +1 -0
  338. package/dist/index.d.ts +115 -30
  339. package/dist/index.js +650 -146
  340. package/dist/index.js.map +1 -1
  341. package/dist/ir/analysis.d.ts +37 -0
  342. package/dist/ir/analysis.js +118 -0
  343. package/dist/ir/analysis.js.map +1 -0
  344. package/dist/ir/analysis.test.d.ts +1 -0
  345. package/dist/ir/analysis.test.js +21 -0
  346. package/dist/ir/analysis.test.js.map +1 -0
  347. package/dist/ir/build.d.ts +9 -0
  348. package/dist/ir/build.js +33 -0
  349. package/dist/ir/build.js.map +1 -0
  350. package/dist/ir/integer-loops.d.ts +1 -1
  351. package/dist/ir/{nodes.d.ts → ir.d.ts} +60 -26
  352. package/dist/ir/{nodes.js → ir.js} +173 -141
  353. package/dist/ir/ir.js.map +1 -0
  354. package/dist/ir/ir.test.d.ts +1 -0
  355. package/dist/ir/ir.test.js +17 -0
  356. package/dist/ir/ir.test.js.map +1 -0
  357. package/dist/ir/serialize.d.ts +1 -1
  358. package/dist/ir/serialize.js +2 -1
  359. package/dist/ir/serialize.js.map +1 -1
  360. package/dist/ir/validate.d.ts +1 -1
  361. package/dist/ir/validate.js +16 -5
  362. package/dist/ir/validate.js.map +1 -1
  363. package/dist/library/cache-primitives.d.ts +24 -0
  364. package/dist/library/cache-primitives.js +83 -0
  365. package/dist/library/cache-primitives.js.map +1 -0
  366. package/dist/library/cache-reset.test.d.ts +1 -0
  367. package/dist/library/cache-reset.test.js +47 -0
  368. package/dist/library/cache-reset.test.js.map +1 -0
  369. package/dist/library/compiler-self-identity.d.ts +23 -0
  370. package/dist/library/compiler-self-identity.js +84 -0
  371. package/dist/library/compiler-self-identity.js.map +1 -0
  372. package/dist/library/fence-eval.d.ts +3 -1
  373. package/dist/library/fence-eval.js +5 -1
  374. package/dist/library/fence-eval.js.map +1 -1
  375. package/dist/library/int-infer.d.ts +1 -36
  376. package/dist/library/int-infer.js +17 -17
  377. package/dist/library/int-infer.js.map +1 -1
  378. package/dist/library/{early-cache.d.ts → library-cache.d.ts} +1 -1
  379. package/dist/library/{early-cache.js → library-cache.js} +37 -111
  380. package/dist/library/library-cache.js.map +1 -0
  381. package/dist/library/library-cache.test.d.ts +1 -0
  382. package/dist/library/{early-cache.test.js → library-cache.test.js} +2 -2
  383. package/dist/library/library-cache.test.js.map +1 -0
  384. package/dist/library/{profile.d.ts → library-profile.d.ts} +4 -7
  385. package/dist/library/{profile.js → library-profile.js} +18 -11
  386. package/dist/library/library-profile.js.map +1 -0
  387. package/dist/library/semantic-source.js +2 -1
  388. package/dist/library/semantic-source.js.map +1 -1
  389. package/dist/library/sidecar.d.ts +5 -2
  390. package/dist/library/sidecar.js +11 -5
  391. package/dist/library/sidecar.js.map +1 -1
  392. package/dist/startup-cache.d.ts +6 -0
  393. package/dist/startup-cache.js +6 -0
  394. package/dist/startup-cache.js.map +1 -0
  395. package/package.json +7 -2
  396. package/surface-manifest.json +1 -1
  397. package/dist/backend/cc-cache.test.js.map +0 -1
  398. package/dist/backend/cc.js.map +0 -1
  399. package/dist/backend/emission/emit-async.js.map +0 -1
  400. package/dist/backend/emission/emit-exprs.d.ts +0 -13
  401. package/dist/backend/emission/emit-exprs.js +0 -7407
  402. package/dist/backend/emission/emit-exprs.js.map +0 -1
  403. package/dist/backend/emission/emit-island.js.map +0 -1
  404. package/dist/backend/emission/emit-shapes.js.map +0 -1
  405. package/dist/backend/emission/emit-stmts.js.map +0 -1
  406. package/dist/backend/emission/emit-types.js.map +0 -1
  407. package/dist/backend/emission/emit-walkers.js.map +0 -1
  408. package/dist/backend/emission/emitter.js.map +0 -1
  409. package/dist/backend/emission/may-throw.js.map +0 -1
  410. package/dist/backend/library-identity.js.map +0 -1
  411. package/dist/ffi/profile.js.map +0 -1
  412. package/dist/frontend/lowering/lower-emitter.js.map +0 -1
  413. package/dist/frontend/shared.d.ts +0 -82
  414. package/dist/frontend/shared.js +0 -308
  415. package/dist/frontend/shared.js.map +0 -1
  416. package/dist/frontend/ts7/program.js.map +0 -1
  417. package/dist/frontend/types.js.map +0 -1
  418. package/dist/ir/nodes.js.map +0 -1
  419. package/dist/library/early-cache.js.map +0 -1
  420. package/dist/library/early-cache.test.js.map +0 -1
  421. package/dist/library/profile.js.map +0 -1
  422. /package/dist/backend/{cc-cache.test.d.ts → c/types.test.d.ts} +0 -0
  423. /package/dist/{library/early-cache.test.d.ts → backend/llvm/shapes.test.d.ts} +0 -0
  424. /package/dist/frontend/ts7/{program.d.ts → program-adapter.d.ts} +0 -0
@@ -1,84 +1,24 @@
1
- import { DYN_HANDLE_KINDS, isRefCounted, typeEquals, typeKey } from "../../ir/nodes.js";
2
- import { cDecl, cStringLiteral, cType, elemAccess, releaseCallC, retainCallC, vAdapters } from "./emit-types.js";
1
+ import { InternalCompilerError } from "../../errors.js";
2
+ import { DYN_HANDLE_KINDS, isRefCounted, typeEquals, typeKey } from "../../ir/ir.js";
3
+ import { dynDesc, undefinedArmTag } from "../../ir/analysis.js";
4
+ import { cDecl, cStringLiteral, cType, elemAccess, releaseCallC, retainCallC, vAdapters } from "./types.js";
3
5
  import { mangleField, mangleRecordNew, mangleRecordStruct } from "../mangle.js";
4
- import { OVERFLOW_MEMBER } from "./emit-shapes.js";
5
- /** Short human description of a dynCheck target for error messages
6
- * ("expected number | string at $.items[2]"). Records read as "object" —
7
- * the path already says where; the full shape would bloat messages. */
8
- export function dynDesc(E, t) {
9
- switch (t.kind) {
10
- case "f64":
11
- return "number";
12
- case "string":
13
- return "string";
14
- case "bool":
15
- return "boolean";
16
- case "record":
17
- // Tuples read as "array": that IS the JSON representation the
18
- // caller must supply (arity failures carry their own message).
19
- return E.recordsById.get(t.shapeId)?.tuple ? "array" : "object";
20
- case "array":
21
- return "array";
22
- case "nullT":
23
- return "null";
24
- // Reachable through optional-flavored record fields ("expected
25
- // string | undefined at $.a" — honest: the fix is a string value OR
26
- // omitting the key).
27
- case "undefinedT":
28
- return "undefined";
29
- // dyn fields accept any dyn value — only reachable in messages as a
30
- // sibling of a failing field, never as the failure itself.
31
- case "dyn":
32
- return "unknown";
33
- case "bytes":
34
- return "Uint8Array";
35
- // The %Error extraction (an instanceof-Error narrow / cast on an
36
- // unknown value): the failure names the class, like caughtCheck's.
37
- case "object":
38
- return t.className.replace(/^%/, "");
39
- case "union": {
40
- const def = E.unionsById.get(t.unionId);
41
- if (!def)
42
- throw new Error(`emitter bug: dynDesc of unknown union ${t.unionId}`);
43
- return def.arms.map((a) => E.dynDesc(a)).join(" | ");
44
- }
45
- // Function targets (the checked-dynamic function boundary): the
46
- // failure names the expected callability, not the full signature —
47
- // the path already says where.
48
- case "func":
49
- return "function";
50
- // Map/Set-valued index signatures (Record<string, Map<K, V>>): only
51
- // reachable through the keyed-read miss trap's message — no dynCheck
52
- // ever expects one.
53
- case "map":
54
- return "Map";
55
- case "set":
56
- return "Set";
57
- default: {
58
- // Runtime HANDLE targets name the class ("expected
59
- // IncomingMessage at $, got string").
60
- const h = DYN_HANDLE_KINDS.get(t.kind);
61
- if (h)
62
- return h.cls;
63
- throw new Error(`emitter bug: dynDesc of non-JSON type ${t.kind}`);
64
- }
65
- }
66
- }
6
+ import { OVERFLOW_MEMBER } from "./shapes.js";
67
7
  /** The per-union ToBoolean helper (interned per unionId): switch on the
68
8
  * runtime tag — unit arms false, f64 arms 0/NaN-falsy, string arms
69
9
  * empty-falsy, bool arms by payload, ref arms always true (JS objects),
70
10
  * jsval arms answered by the engine. Borrows the operand. */
71
- export function unionTruthyHelper(E, unionId) {
72
- const existing = E.unionTruthyFns.get(unionId);
11
+ export function unionTruthyHelper(emitter, unionId) {
12
+ const existing = emitter.unionTruthyFns.get(unionId);
73
13
  if (existing)
74
14
  return existing;
75
- const def = E.unionsById.get(unionId);
15
+ const def = emitter.unionsById.get(unionId);
76
16
  if (!def)
77
- throw new Error(`emitter bug: truthiness of unknown union ${unionId}`);
78
- const name = `sc_ut_${E.unionTruthyFns.size}`;
79
- E.unionTruthyFns.set(unionId, name);
17
+ throw new InternalCompilerError(`emitter bug: truthiness of unknown union ${unionId}`);
18
+ const name = `sc_ut_${emitter.unionTruthyFns.size}`;
19
+ emitter.unionTruthyFns.set(unionId, name);
80
20
  const sig = `static bool ${name}(ScrUnion *v)`;
81
- E.walkerProtos.push(`${sig}; /* ToBoolean ${unionId} */`);
21
+ emitter.walkerProtos.push(`${sig}; /* ToBoolean ${unionId} */`);
82
22
  const d = [`${sig} { /* ToBoolean ${unionId} */`, ` switch (v->tag) {`];
83
23
  def.arms.forEach((arm, i) => {
84
24
  switch (arm.kind) {
@@ -105,7 +45,7 @@ export function unionTruthyHelper(E, unionId) {
105
45
  }
106
46
  });
107
47
  d.push(` default: scr_trap("scriptc: internal error: invalid union tag\\n");`, ` }`, `}`, ``);
108
- E.walkerDefs.push(...d);
48
+ emitter.walkerDefs.push(...d);
109
49
  return name;
110
50
  }
111
51
  /** The per-union strict-equality helper (interned per unionId, with a
@@ -115,19 +55,19 @@ export function unionTruthyHelper(E, unionId) {
115
55
  * (NaN equals NaN, +0 differs from -0) under the sameValue flag,
116
56
  * strings by bytes, bools by value, ref arms by POINTER identity (JS
117
57
  * object equality). Borrows both operands. */
118
- export function unionEqHelper(E, unionId, sameValue) {
58
+ export function unionEqHelper(emitter, unionId, sameValue) {
119
59
  const key = sameValue ? `sv:${unionId}` : unionId;
120
- const existing = E.unionEqFns.get(key);
60
+ const existing = emitter.unionEqFns.get(key);
121
61
  if (existing)
122
62
  return existing;
123
- const def = E.unionsById.get(unionId);
63
+ const def = emitter.unionsById.get(unionId);
124
64
  if (!def)
125
- throw new Error(`emitter bug: equality of unknown union ${unionId}`);
126
- const name = `sc_ue_${E.unionEqFns.size}`;
127
- E.unionEqFns.set(key, name);
65
+ throw new InternalCompilerError(`emitter bug: equality of unknown union ${unionId}`);
66
+ const name = `sc_ue_${emitter.unionEqFns.size}`;
67
+ emitter.unionEqFns.set(key, name);
128
68
  const what = sameValue ? "SameValue" : "strict equality";
129
69
  const sig = `static bool ${name}(ScrUnion *a, ScrUnion *b)`;
130
- E.walkerProtos.push(`${sig}; /* ${what} ${unionId} */`);
70
+ emitter.walkerProtos.push(`${sig}; /* ${what} ${unionId} */`);
131
71
  const d = [
132
72
  `${sig} { /* ${what} ${unionId} */`,
133
73
  ` if (a->tag != b->tag) return false;`,
@@ -156,7 +96,7 @@ export function unionEqHelper(E, unionId, sameValue) {
156
96
  }
157
97
  });
158
98
  d.push(` default: scr_trap("scriptc: internal error: invalid union tag\\n");`, ` }`, `}`, ``);
159
- E.walkerDefs.push(...d);
99
+ emitter.walkerDefs.push(...d);
160
100
  return name;
161
101
  }
162
102
  /** The per-union ToString helper (interned per unionId): switch on the
@@ -165,23 +105,23 @@ export function unionEqHelper(E, unionId, sameValue) {
165
105
  * formatters (String(x) semantics). Ref arms never arrive (the frontend
166
106
  * fences unions with object arms from string conversion — JS would print
167
107
  * "[object Object]"). Borrows the operand; the result is owned (+1). */
168
- export function unionToStrHelper(E, unionId) {
169
- const existing = E.unionToStrFns.get(unionId);
108
+ export function unionToStrHelper(emitter, unionId) {
109
+ const existing = emitter.unionToStrFns.get(unionId);
170
110
  if (existing)
171
111
  return existing;
172
- const def = E.unionsById.get(unionId);
112
+ const def = emitter.unionsById.get(unionId);
173
113
  if (!def)
174
- throw new Error(`emitter bug: ToString of unknown union ${unionId}`);
175
- const name = `sc_us_${E.unionToStrFns.size}`;
176
- E.unionToStrFns.set(unionId, name);
114
+ throw new InternalCompilerError(`emitter bug: ToString of unknown union ${unionId}`);
115
+ const name = `sc_us_${emitter.unionToStrFns.size}`;
116
+ emitter.unionToStrFns.set(unionId, name);
177
117
  const sig = `static ScrStr *${name}(ScrUnion *v)`;
178
- E.walkerProtos.push(`${sig}; /* ToString ${unionId} */`);
118
+ emitter.walkerProtos.push(`${sig}; /* ToString ${unionId} */`);
179
119
  const d = [`${sig} { /* ToString ${unionId} */`, ` switch (v->tag) {`];
180
120
  def.arms.forEach((arm, i) => {
181
121
  switch (arm.kind) {
182
122
  case "undefinedT":
183
123
  case "nullT": {
184
- const lit = E.internLiteral(arm.kind === "undefinedT" ? "undefined" : "null");
124
+ const lit = emitter.internLiteral(arm.kind === "undefinedT" ? "undefined" : "null");
185
125
  d.push(` case ${i}: return scr_str_retain((ScrStr *)&${lit});`);
186
126
  break;
187
127
  }
@@ -197,16 +137,16 @@ export function unionToStrHelper(E, unionId) {
197
137
  case "bytes": {
198
138
  // Buffer.toString() IS the utf8 decode (Node's default
199
139
  // encoding) — the `Buffer | string` chunk idiom.
200
- const enc = E.internLiteral("utf8");
140
+ const enc = emitter.internLiteral("utf8");
201
141
  d.push(` case ${i}: return scr_bytes_to_str((ScrBytes *)scr_union_peek(v), (ScrStr *)&${enc});`);
202
142
  break;
203
143
  }
204
144
  default:
205
- throw new Error(`emitter bug: ToString of union with a ${arm.kind} arm (frontend fences these)`);
145
+ throw new InternalCompilerError(`emitter bug: ToString of union with a ${arm.kind} arm (frontend fences these)`);
206
146
  }
207
147
  });
208
148
  d.push(` default: scr_trap("scriptc: internal error: invalid union tag\\n");`, ` }`, `}`, ``);
209
- E.walkerDefs.push(...d);
149
+ emitter.walkerDefs.push(...d);
210
150
  return name;
211
151
  }
212
152
  /** The per-union array-join helper (interned per unionId): Array.prototype
@@ -216,20 +156,20 @@ export function unionToStrHelper(E, unionId) {
216
156
  * f64/bool via the JS-exact formatters). The frontend admits only unions
217
157
  * of f64/string/bool/unit arms here. Borrows the array and separator;
218
158
  * the result is owned (+1). */
219
- export function unionJoinHelper(E, unionId) {
220
- const existing = E.unionJoinFns.get(unionId);
159
+ export function unionJoinHelper(emitter, unionId) {
160
+ const existing = emitter.unionJoinFns.get(unionId);
221
161
  if (existing)
222
162
  return existing;
223
- const def = E.unionsById.get(unionId);
163
+ const def = emitter.unionsById.get(unionId);
224
164
  if (!def)
225
- throw new Error(`emitter bug: join of unknown union ${unionId}`);
226
- const name = `sc_uj_${E.unionJoinFns.size}`;
227
- E.unionJoinFns.set(unionId, name);
228
- const toStr = unionToStrHelper(E, unionId);
165
+ throw new InternalCompilerError(`emitter bug: join of unknown union ${unionId}`);
166
+ const name = `sc_uj_${emitter.unionJoinFns.size}`;
167
+ emitter.unionJoinFns.set(unionId, name);
168
+ const toStr = unionToStrHelper(emitter, unionId);
229
169
  const unitTags = def.arms.flatMap((a, i) => a.kind === "undefinedT" || a.kind === "nullT" ? [i] : []);
230
170
  const sig = `static ScrStr *${name}(ScrArr *a, ScrStr *sep)`;
231
- E.walkerProtos.push(`${sig}; /* join ${unionId} */`);
232
- E.walkerDefs.push(`${sig} { /* Array#join over ${unionId}: nullish arms print empty */`, ` ScrJsonBuf b;`, ` scr_jb_init(&b);`, ` size_t n = (size_t)scr_arr_len(a);`, ` for (size_t i = 0; i < n; i++) {`, ` if (i) for (size_t j = 0; j < sep->len; j++) scr_jb_putc(&b, sep->data[j]);`, ` ScrUnion *u = (ScrUnion *)scr_arr_get_ref(a, (double)i);`, ...(unitTags.length > 0
171
+ emitter.walkerProtos.push(`${sig}; /* join ${unionId} */`);
172
+ emitter.walkerDefs.push(`${sig} { /* Array#join over ${unionId}: nullish arms print empty */`, ` ScrJsonBuf b;`, ` scr_jb_init(&b);`, ` size_t n = (size_t)scr_arr_len(a);`, ` for (size_t i = 0; i < n; i++) {`, ` if (i) for (size_t j = 0; j < sep->len; j++) scr_jb_putc(&b, sep->data[j]);`, ` ScrUnion *u = (ScrUnion *)scr_arr_get_ref(a, (double)i);`, ...(unitTags.length > 0
233
173
  ? [` if (${unitTags.map((t) => `u->tag == ${t}`).join(" || ")}) { scr_union_release(u); continue; }`]
234
174
  : []), ` ScrStr *s = ${toStr}(u);`, ` for (size_t j = 0; j < s->len; j++) scr_jb_putc(&b, s->data[j]);`, ` scr_str_release(s);`, ` scr_union_release(u);`, ` }`, ` return scr_jb_finish(&b);`, `}`, ``);
235
175
  return name;
@@ -241,13 +181,13 @@ export function unionJoinHelper(E, unionId) {
241
181
  * with ","; null/undefined ELEMENTS print empty, nested arrays flatten
242
182
  * through the recursion — JS-exact), plain objects as
243
183
  * "[object Object]". The operand is borrowed; the result is owned (+1). */
244
- export function dynToStrHelper(E) {
245
- if (E.dynToStrFn)
246
- return E.dynToStrFn;
184
+ export function dynToStrHelper(emitter) {
185
+ if (emitter.dynToStrFn)
186
+ return emitter.dynToStrFn;
247
187
  const name = "sc_ds";
248
- E.dynToStrFn = name;
249
- E.walkerProtos.push(`static void ${name}_buf(ScrJsonBuf *b, const ScrDyn *d); /* String(unknown) walker */`, `static ScrStr *${name}(const ScrDyn *d); /* String(unknown) */`);
250
- E.walkerDefs.push(`static void ${name}_buf(ScrJsonBuf *b, const ScrDyn *d) { /* String(unknown), recursive */`, ` switch (d->kind) {`, ` case SCR_DYN_UNDEF: scr_jb_puts(b, "undefined"); break;`, ` case SCR_DYN_NULL: scr_jb_puts(b, "null"); break;`, ` case SCR_DYN_BOOL: scr_jb_puts(b, d->v.b ? "true" : "false"); break;`, ` case SCR_DYN_NUM: {`, ` ScrStr *s = scr_f64_to_scrstr(d->v.num); /* String(n): NaN/Infinity spelled out, not JSON null */`, ` for (size_t i = 0; i < s->len; i++) scr_jb_putc(b, s->data[i]);`, ` scr_str_release(s);`, ` break;`, ` }`, ` case SCR_DYN_STR:`, ` for (size_t i = 0; i < d->v.str->len; i++) scr_jb_putc(b, d->v.str->data[i]);`, ` break;`, ` case SCR_DYN_ARR:`, ` /* Array.prototype.toString: join(",") — null/undefined ELEMENTS`, ` * print empty (unlike top level), nested arrays flatten. */`, ` for (size_t i = 0; i < d->v.arr.len; i++) {`, ` if (i > 0) scr_jb_putc(b, ',');`, ` const ScrDyn *e = d->v.arr.items[i];`, ` if (e->kind == SCR_DYN_UNDEF || e->kind == SCR_DYN_NULL) continue;`, ` ${name}_buf(b, e);`, ` }`, ` break;`, ` case SCR_DYN_OBJ:`, ` if (scr_dyn_obj_get(d, "%error", 6)) {`, ` /* The checked-dynamic tree's error encoding (caughtToDyn): Error.prototype`, ` * .toString over the encoded name/message — Node's String(err),`, ` * which carries no stack either. */`, ` const ScrDyn *en = scr_dyn_obj_get(d, "name", 4);`, ` const ScrDyn *em = scr_dyn_obj_get(d, "message", 7);`, ` const ScrStr *ens = (en && en->kind == SCR_DYN_STR) ? en->v.str : NULL;`, ` const ScrStr *ems = (em && em->kind == SCR_DYN_STR) ? em->v.str : NULL;`, ` if (ens) for (size_t i = 0; i < ens->len; i++) scr_jb_putc(b, ens->data[i]);`, ` if (ens && ens->len && ems && ems->len) scr_jb_puts(b, ": ");`, ` if (ems) for (size_t i = 0; i < ems->len; i++) scr_jb_putc(b, ems->data[i]);`, ` break;`, ` }`, ` scr_jb_puts(b, "[object Object]");`, ` break;`, ` case SCR_DYN_BYTES: {`, ` /* Buffer-flavored values (stream chunks) coerce utf8 (Node's`, ` * Buffer.toString); plain Uint8Array joins its elements. */`, ` if (d->buffer) {`, ` ScrStr *enc = scr_str_new("utf8", 4);`, ` ScrStr *txt = scr_bytes_to_str(d->v.bytes, enc);`, ` scr_str_release(enc);`, ` for (size_t i = 0; i < txt->len; i++) scr_jb_putc(b, txt->data[i]);`, ` scr_str_release(txt);`, ` break;`, ` }`, ` for (size_t i = 0; i < d->v.bytes->len; i++) {`, ` if (i > 0) scr_jb_putc(b, ',');`, ` char n[16];`, ` snprintf(n, sizeof n, "%u", (unsigned)d->v.bytes->data[i]);`, ` scr_jb_puts(b, n);`, ` }`, ` break;`, ` }`, ` case SCR_DYN_FUNC:`, ` /* Function.prototype.toString: the SOURCE is gone in a compiled`, ` * program, so the native-code form — exactly what JS engines`, ` * print for their own non-JS functions. */`, ` scr_jb_puts(b, "function ");`, ` if (d->v.fn.name) scr_jb_puts(b, d->v.fn.name);`, ` scr_jb_puts(b, "() { [native code] }");`, ` break;`, ` case SCR_DYN_HANDLE:`, ` /* Object.prototype.toString — Node's String() over these`, ` * classes (IncomingMessage/ServerResponse/Socket). */`, ` scr_jb_puts(b, "[object Object]");`, ` break;`, ` case SCR_DYN_PROMISE:`, ` /* Object.prototype.toString with the Promise @@toStringTag. */`, ` scr_jb_puts(b, "[object Promise]");`, ` break;`, ` case SCR_DYN_JSVAL:`, ` /* Island-held: the engine's own ToString (a bridged failure`, ` * leaves the exception pending and appends nothing). */`, ` scr_dyn_isl_tostr_buf(b, d);`, ` break;`, ` case SCR_DYN_TYPED_REF: {`, ` ScrDyn *sc_materialized = scr_dyn_typed_ref_materialize(d);`, ` ${name}_buf(b, sc_materialized);`, ` scr_dyn_release(sc_materialized);`, ` break;`, ` }`, ` }`, `}`, `static ScrStr *${name}(const ScrDyn *d) { /* String(unknown) -> owned (+1) */`, ` if (d->kind == SCR_DYN_STR) return scr_str_retain(d->v.str);`, ` ScrJsonBuf b;`, ` scr_jb_init(&b);`, ` ${name}_buf(&b, d);`, ` return scr_jb_finish(&b);`, `}`, ``);
188
+ emitter.dynToStrFn = name;
189
+ emitter.walkerProtos.push(`static void ${name}_buf(ScrJsonBuf *b, const ScrDyn *d); /* String(unknown) walker */`, `static ScrStr *${name}(const ScrDyn *d); /* String(unknown) */`);
190
+ emitter.walkerDefs.push(`static void ${name}_buf(ScrJsonBuf *b, const ScrDyn *d) { /* String(unknown), recursive */`, ` switch (d->kind) {`, ` case SCR_DYN_UNDEF: scr_jb_puts(b, "undefined"); break;`, ` case SCR_DYN_NULL: scr_jb_puts(b, "null"); break;`, ` case SCR_DYN_BOOL: scr_jb_puts(b, d->v.b ? "true" : "false"); break;`, ` case SCR_DYN_NUM: {`, ` ScrStr *s = scr_f64_to_scrstr(d->v.num); /* String(n): NaN/Infinity spelled out, not JSON null */`, ` for (size_t i = 0; i < s->len; i++) scr_jb_putc(b, s->data[i]);`, ` scr_str_release(s);`, ` break;`, ` }`, ` case SCR_DYN_STR:`, ` for (size_t i = 0; i < d->v.str->len; i++) scr_jb_putc(b, d->v.str->data[i]);`, ` break;`, ` case SCR_DYN_ARR:`, ` /* Array.prototype.toString: join(",") — null/undefined ELEMENTS`, ` * print empty (unlike top level), nested arrays flatten. */`, ` for (size_t i = 0; i < d->v.arr.len; i++) {`, ` if (i > 0) scr_jb_putc(b, ',');`, ` const ScrDyn *e = d->v.arr.items[i];`, ` if (e->kind == SCR_DYN_UNDEF || e->kind == SCR_DYN_NULL) continue;`, ` ${name}_buf(b, e);`, ` }`, ` break;`, ` case SCR_DYN_OBJ:`, ` if (scr_dyn_obj_get(d, "%error", 6)) {`, ` /* The checked-dynamic tree's error encoding (caughtToDyn): Error.prototype`, ` * .toString over the encoded name/message — Node's String(err),`, ` * which carries no stack either. */`, ` const ScrDyn *en = scr_dyn_obj_get(d, "name", 4);`, ` const ScrDyn *em = scr_dyn_obj_get(d, "message", 7);`, ` const ScrStr *ens = (en && en->kind == SCR_DYN_STR) ? en->v.str : NULL;`, ` const ScrStr *ems = (em && em->kind == SCR_DYN_STR) ? em->v.str : NULL;`, ` if (ens) for (size_t i = 0; i < ens->len; i++) scr_jb_putc(b, ens->data[i]);`, ` if (ens && ens->len && ems && ems->len) scr_jb_puts(b, ": ");`, ` if (ems) for (size_t i = 0; i < ems->len; i++) scr_jb_putc(b, ems->data[i]);`, ` break;`, ` }`, ` scr_jb_puts(b, "[object Object]");`, ` break;`, ` case SCR_DYN_BYTES: {`, ` /* Buffer-flavored values (stream chunks) coerce utf8 (Node's`, ` * Buffer.toString); plain Uint8Array joins its elements. */`, ` if (d->buffer) {`, ` ScrStr *enc = scr_str_new("utf8", 4);`, ` ScrStr *txt = scr_bytes_to_str(d->v.bytes, enc);`, ` scr_str_release(enc);`, ` for (size_t i = 0; i < txt->len; i++) scr_jb_putc(b, txt->data[i]);`, ` scr_str_release(txt);`, ` break;`, ` }`, ` for (size_t i = 0; i < d->v.bytes->len; i++) {`, ` if (i > 0) scr_jb_putc(b, ',');`, ` char n[16];`, ` snprintf(n, sizeof n, "%u", (unsigned)d->v.bytes->data[i]);`, ` scr_jb_puts(b, n);`, ` }`, ` break;`, ` }`, ` case SCR_DYN_FUNC:`, ` /* Function.prototype.toString: the SOURCE is gone in a compiled`, ` * program, so the native-code form — exactly what JS engines`, ` * print for their own non-JS functions. */`, ` scr_jb_puts(b, "function ");`, ` if (d->v.fn.name) scr_jb_puts(b, d->v.fn.name);`, ` scr_jb_puts(b, "() { [native code] }");`, ` break;`, ` case SCR_DYN_HANDLE:`, ` /* Object.prototype.toString — Node's String() over these`, ` * classes (IncomingMessage/ServerResponse/Socket). */`, ` scr_jb_puts(b, "[object Object]");`, ` break;`, ` case SCR_DYN_PROMISE:`, ` /* Object.prototype.toString with the Promise @@toStringTag. */`, ` scr_jb_puts(b, "[object Promise]");`, ` break;`, ` case SCR_DYN_JSVAL:`, ` /* Island-held: the engine's own ToString (a bridged failure`, ` * leaves the exception pending and appends nothing). */`, ` scr_dyn_isl_tostr_buf(b, d);`, ` break;`, ` case SCR_DYN_TYPED_REF: {`, ` ScrDyn *sc_materialized = scr_dyn_typed_ref_materialize(d);`, ` ${name}_buf(b, sc_materialized);`, ` scr_dyn_release(sc_materialized);`, ` break;`, ` }`, ` }`, `}`, `static ScrStr *${name}(const ScrDyn *d) { /* String(unknown) -> owned (+1) */`, ` if (d->kind == SCR_DYN_STR) return scr_str_retain(d->v.str);`, ` ScrJsonBuf b;`, ` scr_jb_init(&b);`, ` ${name}_buf(&b, d);`, ` return scr_jb_finish(&b);`, `}`, ``);
251
191
  return name;
252
192
  }
253
193
  /** The caught→dyn converter (interned once, type-independent): a catch
@@ -260,14 +200,14 @@ export function dynToStrHelper(E) {
260
200
  * closures, unions — and non-Error hierarchy objects, type-erased at
261
201
  * runtime) becomes an EMPTY dyn object (SEMANTICS.md 67). Borrows the
262
202
  * snapshot; the result is a fresh tree (+1). Never throws. */
263
- export function caughtToDynHelper(E) {
264
- if (E.caughtToDynFn)
265
- return E.caughtToDynFn;
203
+ export function caughtToDynHelper(emitter) {
204
+ if (emitter.caughtToDynFn)
205
+ return emitter.caughtToDynFn;
266
206
  const name = "sc_cd";
267
- E.caughtToDynFn = name;
207
+ emitter.caughtToDynFn = name;
268
208
  const sig = `static ScrDyn *${name}(const ScrCaught *c)`;
269
- E.walkerProtos.push(`${sig}; /* caught -> unknown */`);
270
- E.walkerDefs.push(`${sig} { /* caught -> unknown (+1, fresh tree) */`, ` switch (c->kind) {`, ` case SCR_EXC_F64: return scr_dyn_new_num(c->f64);`, ` case SCR_EXC_BOOL: return scr_dyn_new_bool(c->b);`, ` case SCR_EXC_STR: return scr_dyn_new_str((ScrStr *)c->payload); /* _new_str retains */`, ` case SCR_EXC_OBJ:`, ` if (scr_error_is(c->payload)) {`, ` /* The identity-cached crossing (scr_json.c): the SAME error`, ` * instance boxes to ONE dyn node however it crosses, so a`, ` * caught dyn compares reference-equal to the thrown error's`, ` * other boxings, like Node. */`, ` return scr_dyn_from_error((const ScrError *)c->payload);`, ` }`, ` /* FALLTHROUGH: a non-Error hierarchy object is type-erased */`, ` case SCR_EXC_REF:`, ` /* A thrown dyn value passes back BY REFERENCE (identity with`, ` * every other holder of the node — the traced-throw shape). */`, ` if (c->retain_fn == scr_dyn_retain_v) return scr_dyn_retain((ScrDyn *)c->payload);`, ` /* FALLTHROUGH */`, ` default:`, ` /* non-dyn REF and non-Error objects: the "[object Object]"`, ` * approximation — truthy, typeof "object", fields unreadable. */`, ` return scr_dyn_new_obj();`, ` }`, `}`, ``);
209
+ emitter.walkerProtos.push(`${sig}; /* caught -> unknown */`);
210
+ emitter.walkerDefs.push(`${sig} { /* caught -> unknown (+1, fresh tree) */`, ` switch (c->kind) {`, ` case SCR_EXC_F64: return scr_dyn_new_num(c->f64);`, ` case SCR_EXC_BOOL: return scr_dyn_new_bool(c->b);`, ` case SCR_EXC_STR: return scr_dyn_new_str((ScrStr *)c->payload); /* _new_str retains */`, ` case SCR_EXC_OBJ:`, ` if (scr_error_is(c->payload)) {`, ` /* The identity-cached crossing (scr_json.c): the SAME error`, ` * instance boxes to ONE dyn node however it crosses, so a`, ` * caught dyn compares reference-equal to the thrown error's`, ` * other boxings, like Node. */`, ` return scr_dyn_from_error((const ScrError *)c->payload);`, ` }`, ` /* FALLTHROUGH: a non-Error hierarchy object is type-erased */`, ` case SCR_EXC_REF:`, ` /* A thrown dyn value passes back BY REFERENCE (identity with`, ` * every other holder of the node — the traced-throw shape). */`, ` if (c->retain_fn == scr_dyn_retain_v) return scr_dyn_retain((ScrDyn *)c->payload);`, ` /* FALLTHROUGH */`, ` default:`, ` /* non-dyn REF and non-Error objects: the "[object Object]"`, ` * approximation — truthy, typeof "object", fields unreadable. */`, ` return scr_dyn_new_obj();`, ` }`, `}`, ``);
271
211
  return name;
272
212
  }
273
213
  /** The pretty-print re-indenter (interned once, type-independent):
@@ -280,25 +220,25 @@ export function caughtToDynHelper(E) {
280
220
  * commas, and colons inside JSON strings untouched. Compact input is
281
221
  * BORROWED; the result is a fresh string (+1). An empty indent (space 0,
282
222
  * "", null) never reaches here — the frontend drops the property. */
283
- export function jsonIndentHelper(E) {
284
- if (E.jsonIndentFn)
285
- return E.jsonIndentFn;
223
+ export function jsonIndentHelper(emitter) {
224
+ if (emitter.jsonIndentFn)
225
+ return emitter.jsonIndentFn;
286
226
  const name = "sc_ji";
287
- E.jsonIndentFn = name;
227
+ emitter.jsonIndentFn = name;
288
228
  const sig = `static ScrStr *${name}(ScrStr *compact, const char *indent, size_t ilen)`;
289
- E.walkerProtos.push(`${sig}; /* stringify space re-indent */`);
290
- E.walkerDefs.push(`${sig} { /* stringify space re-indent (Node's gap algorithm) */`, ` ScrJsonBuf b;`, ` scr_jb_init(&b);`, ` const char *s = compact->data;`, ` size_t n = compact->len;`, ` size_t depth = 0;`, ` bool instr = false;`, `#define SCR_JI_INDENT() do { \\`, ` scr_jb_putc(&b, '\\n'); \\`, ` for (size_t td = 0; td < depth; td++) \\`, ` for (size_t tk = 0; tk < ilen; tk++) scr_jb_putc(&b, indent[tk]); \\`, ` } while (0)`, ` for (size_t i = 0; i < n; i++) {`, ` char c = s[i];`, ` if (instr) {`, ` scr_jb_putc(&b, c);`, ` if (c == '\\\\' && i + 1 < n) { scr_jb_putc(&b, s[++i]); }`, ` else if (c == '"') instr = false;`, ` continue;`, ` }`, ` switch (c) {`, ` case '"': instr = true; scr_jb_putc(&b, c); break;`, ` case '{': case '[':`, ` scr_jb_putc(&b, c);`, ` if (i + 1 < n && s[i + 1] == (c == '{' ? '}' : ']')) {`, ` scr_jb_putc(&b, s[++i]); /* empty {} / [] stay inline, like Node */`, ` break;`, ` }`, ` depth++;`, ` SCR_JI_INDENT();`, ` break;`, ` case '}': case ']':`, ` depth--;`, ` SCR_JI_INDENT();`, ` scr_jb_putc(&b, c);`, ` break;`, ` case ',':`, ` scr_jb_putc(&b, ',');`, ` SCR_JI_INDENT();`, ` break;`, ` case ':':`, ` scr_jb_putc(&b, ':');`, ` scr_jb_putc(&b, ' ');`, ` break;`, ` default:`, ` scr_jb_putc(&b, c);`, ` }`, ` }`, `#undef SCR_JI_INDENT`, ` return scr_jb_finish(&b);`, `}`, ``);
229
+ emitter.walkerProtos.push(`${sig}; /* stringify space re-indent */`);
230
+ emitter.walkerDefs.push(`${sig} { /* stringify space re-indent (Node's gap algorithm) */`, ` ScrJsonBuf b;`, ` scr_jb_init(&b);`, ` const char *s = compact->data;`, ` size_t n = compact->len;`, ` size_t depth = 0;`, ` bool instr = false;`, `#define SCR_JI_INDENT() do { \\`, ` scr_jb_putc(&b, '\\n'); \\`, ` for (size_t td = 0; td < depth; td++) \\`, ` for (size_t tk = 0; tk < ilen; tk++) scr_jb_putc(&b, indent[tk]); \\`, ` } while (0)`, ` for (size_t i = 0; i < n; i++) {`, ` char c = s[i];`, ` if (instr) {`, ` scr_jb_putc(&b, c);`, ` if (c == '\\\\' && i + 1 < n) { scr_jb_putc(&b, s[++i]); }`, ` else if (c == '"') instr = false;`, ` continue;`, ` }`, ` switch (c) {`, ` case '"': instr = true; scr_jb_putc(&b, c); break;`, ` case '{': case '[':`, ` scr_jb_putc(&b, c);`, ` if (i + 1 < n && s[i + 1] == (c == '{' ? '}' : ']')) {`, ` scr_jb_putc(&b, s[++i]); /* empty {} / [] stay inline, like Node */`, ` break;`, ` }`, ` depth++;`, ` SCR_JI_INDENT();`, ` break;`, ` case '}': case ']':`, ` depth--;`, ` SCR_JI_INDENT();`, ` scr_jb_putc(&b, c);`, ` break;`, ` case ',':`, ` scr_jb_putc(&b, ',');`, ` SCR_JI_INDENT();`, ` break;`, ` case ':':`, ` scr_jb_putc(&b, ':');`, ` scr_jb_putc(&b, ' ');`, ` break;`, ` default:`, ` scr_jb_putc(&b, c);`, ` }`, ` }`, `#undef SCR_JI_INDENT`, ` return scr_jb_finish(&b);`, `}`, ``);
291
231
  return name;
292
232
  }
293
- export function jsonWriteHelper(E, t) {
233
+ export function jsonWriteHelper(emitter, t) {
294
234
  const key = typeKey(t);
295
- const existing = E.jsonWriters.get(key);
235
+ const existing = emitter.jsonWriters.get(key);
296
236
  if (existing)
297
237
  return existing;
298
- const name = `sc_jw_${E.jsonWriters.size}`;
299
- E.jsonWriters.set(key, name);
238
+ const name = `sc_jw_${emitter.jsonWriters.size}`;
239
+ emitter.jsonWriters.set(key, name);
300
240
  const sig = `static void ${name}(ScrJsonBuf *b, ${cDecl(t, "v")})`;
301
- E.walkerProtos.push(`${sig}; /* stringify ${key} */`);
241
+ emitter.walkerProtos.push(`${sig}; /* stringify ${key} */`);
302
242
  const d = [`${sig} { /* stringify ${key} */`];
303
243
  switch (t.kind) {
304
244
  case "f64":
@@ -311,17 +251,17 @@ export function jsonWriteHelper(E, t) {
311
251
  d.push(` scr_jb_put_json_str(b, v);`);
312
252
  break;
313
253
  case "record": {
314
- const shape = E.recordsById.get(t.shapeId);
254
+ const shape = emitter.recordsById.get(t.shapeId);
315
255
  if (!shape)
316
- throw new Error(`emitter bug: jsonStringify of unknown shape ${t.shapeId}`);
256
+ throw new InternalCompilerError(`emitter bug: jsonStringify of unknown shape ${t.shapeId}`);
317
257
  // CYCLE-CAPABLE shapes (recursive record types — the collector-
318
258
  // fixpoint set) bracket the walk with the circular-detection
319
259
  // stack: a value already being serialized above throws V8's exact
320
260
  // circular-structure TypeError (scr_jb_enter). Edge labels stamp
321
261
  // only before members whose walk can re-enter (cycle-capable
322
262
  // types); acyclic shapes pay nothing.
323
- const cyclic = E.traceAdapterC(t) !== null;
324
- const edgeable = (ft) => cyclic && E.traceAdapterC(ft) !== null;
263
+ const cyclic = emitter.traceAdapterC(t) !== null;
264
+ const edgeable = (ft) => cyclic && emitter.traceAdapterC(ft) !== null;
325
265
  if (cyclic)
326
266
  d.push(` if (!scr_jb_enter(b, v, ${shape.tuple ? "true" : "false"})) return; /* circular: pending TypeError */`);
327
267
  // A tuple serializes as a JSON ARRAY in index order — JS-exact
@@ -335,7 +275,7 @@ export function jsonWriteHelper(E, t) {
335
275
  d.push(` scr_jb_putc(b, ',');`);
336
276
  if (edgeable(f.type))
337
277
  d.push(` scr_jb_edge_idx(b, ${i});`);
338
- d.push(` ${E.jsonWriteHelper(f.type)}(b, v->${mangleField(f.name)});`);
278
+ d.push(` ${emitter.jsonWriteHelper(f.type)}(b, v->${mangleField(f.name)});`);
339
279
  });
340
280
  d.push(` scr_jb_putc(b, ']');`);
341
281
  if (cyclic)
@@ -354,7 +294,7 @@ export function jsonWriteHelper(E, t) {
354
294
  const order = shape.declaredOrder ?? shape.fields.map((f) => f.name);
355
295
  const inOrder = new Set(order);
356
296
  if (shape.fields.some((f) => !inOrder.has(f.name) && !f.name.startsWith("%"))) {
357
- throw new Error(`emitter bug: declaredOrder of shape ${t.shapeId} omits a non-internal field`);
297
+ throw new InternalCompilerError(`emitter bug: declaredOrder of shape ${t.shapeId} omits a non-internal field`);
358
298
  }
359
299
  const byName = new Map(shape.fields.map((f) => [f.name, f]));
360
300
  const emitFields = order.map((n) => byName.get(n)).filter((f) => f !== undefined);
@@ -364,7 +304,7 @@ export function jsonWriteHelper(E, t) {
364
304
  // flag); all-required shapes keep the static prefix labels. An
365
305
  // overflow portion forces the dynamic path too (entry count is
366
306
  // runtime state).
367
- const droppable = emitFields.some((f) => E.undefinedArmTag(f.type) >= 0) || !!shape.indexValue;
307
+ const droppable = emitFields.some((f) => undefinedArmTag(f.type, emitter.unionsById) >= 0) || !!shape.indexValue;
368
308
  d.push(` scr_jb_putc(b, '{');`);
369
309
  if (!droppable) {
370
310
  emitFields.forEach((f, i) => {
@@ -374,14 +314,14 @@ export function jsonWriteHelper(E, t) {
374
314
  d.push(` scr_jb_edge_prop(b, ${cStringLiteral(Buffer.from(f.name, "utf8"))});`);
375
315
  // Refcounted fields are BORROWED straight off the struct (the
376
316
  // record itself is borrowed for the whole call).
377
- d.push(` ${E.jsonWriteHelper(f.type)}(b, v->${mangleField(f.name)});`);
317
+ d.push(` ${emitter.jsonWriteHelper(f.type)}(b, v->${mangleField(f.name)});`);
378
318
  });
379
319
  }
380
320
  else {
381
321
  d.push(` bool first = true;`);
382
322
  for (const f of emitFields) {
383
323
  const label = cStringLiteral(Buffer.from(`"${f.name}":`, "utf8"));
384
- const utag = E.undefinedArmTag(f.type);
324
+ const utag = undefinedArmTag(f.type, emitter.unionsById);
385
325
  const pad = utag >= 0 ? " " : " ";
386
326
  if (utag >= 0) {
387
327
  d.push(` if (v->${mangleField(f.name)}->tag != ${utag}) { /* undefined-valued field: dropped, like Node */`);
@@ -391,7 +331,7 @@ export function jsonWriteHelper(E, t) {
391
331
  d.push(`${pad}scr_jb_puts(b, ${label});`);
392
332
  if (edgeable(f.type))
393
333
  d.push(`${pad}scr_jb_edge_prop(b, ${cStringLiteral(Buffer.from(f.name, "utf8"))});`);
394
- d.push(`${pad}${E.jsonWriteHelper(f.type)}(b, v->${mangleField(f.name)});`);
334
+ d.push(`${pad}${emitter.jsonWriteHelper(f.type)}(b, v->${mangleField(f.name)});`);
395
335
  if (utag >= 0)
396
336
  d.push(` }`);
397
337
  }
@@ -419,8 +359,8 @@ export function jsonWriteHelper(E, t) {
419
359
  }
420
360
  const skipUndef = iv.kind === "dyn"
421
361
  ? `e->kind == SCR_DYN_UNDEF`
422
- : E.undefinedArmTag(iv) >= 0
423
- ? `e->tag == ${E.undefinedArmTag(iv)}`
362
+ : undefinedArmTag(iv, emitter.unionsById) >= 0
363
+ ? `e->tag == ${undefinedArmTag(iv, emitter.unionsById)}`
424
364
  : null;
425
365
  if (skipUndef) {
426
366
  d.push(` if (${skipUndef}) { /* undefined-valued entry: dropped, like Node */`);
@@ -435,7 +375,7 @@ export function jsonWriteHelper(E, t) {
435
375
  d.push(` scr_jb_putc(b, ':');`);
436
376
  if (edgeable(iv))
437
377
  d.push(` scr_jb_edge_key(b, k);`);
438
- d.push(` ${E.jsonWriteHelper(iv)}(b, e);`);
378
+ d.push(` ${emitter.jsonWriteHelper(iv)}(b, e);`);
439
379
  d.push(` scr_str_release(k);`);
440
380
  if (isRefCounted(iv))
441
381
  d.push(` ${releaseCallC(iv, "e")};`);
@@ -459,10 +399,10 @@ export function jsonWriteHelper(E, t) {
459
399
  break;
460
400
  case "array": {
461
401
  const elem = t.elem;
462
- const w = E.jsonWriteHelper(elem);
402
+ const w = emitter.jsonWriteHelper(elem);
463
403
  // A cycle-capable array (elements can point back at it) joins the
464
404
  // circular-detection stack exactly like a cycle-capable record.
465
- const cyclic = E.traceAdapterC(t) !== null;
405
+ const cyclic = emitter.traceAdapterC(t) !== null;
466
406
  if (cyclic)
467
407
  d.push(` if (!scr_jb_enter(b, v, true)) return; /* circular: pending TypeError */`);
468
408
  d.push(` scr_jb_putc(b, '[');`);
@@ -489,9 +429,9 @@ export function jsonWriteHelper(E, t) {
489
429
  break;
490
430
  }
491
431
  case "union": {
492
- const def = E.unionsById.get(t.unionId);
432
+ const def = emitter.unionsById.get(t.unionId);
493
433
  if (!def)
494
- throw new Error(`emitter bug: jsonStringify of unknown union ${t.unionId}`);
434
+ throw new InternalCompilerError(`emitter bug: jsonStringify of unknown union ${t.unionId}`);
495
435
  d.push(` switch (v->tag) {`);
496
436
  def.arms.forEach((arm, i) => {
497
437
  if (arm.kind === "nullT") {
@@ -509,7 +449,7 @@ export function jsonWriteHelper(E, t) {
509
449
  d.push(` scr_trap("scriptc: internal error: stringify reached an undefined arm\\n");`);
510
450
  return;
511
451
  }
512
- const w = E.jsonWriteHelper(arm);
452
+ const w = emitter.jsonWriteHelper(arm);
513
453
  if (arm.kind === "f64") {
514
454
  d.push(` case ${i}: ${w}(b, scr_union_get_f64(v)); break;`);
515
455
  }
@@ -526,10 +466,10 @@ export function jsonWriteHelper(E, t) {
526
466
  break;
527
467
  }
528
468
  default:
529
- throw new Error(`emitter bug: jsonStringify of non-JSON type ${t.kind}`);
469
+ throw new InternalCompilerError(`emitter bug: jsonStringify of non-JSON type ${t.kind}`);
530
470
  }
531
471
  d.push(`}`, ``);
532
- E.walkerDefs.push(...d);
472
+ emitter.walkerDefs.push(...d);
533
473
  return name;
534
474
  }
535
475
  /** The emitted match predicate for one dynCheck target type:
@@ -537,15 +477,15 @@ export function jsonWriteHelper(E, t) {
537
477
  * Never throws, builds nothing; union builders use it to try arms in
538
478
  * canonical order (first FULL match wins). Records are width-tolerant
539
479
  * here too: extra keys are ignored, only declared fields are examined. */
540
- export function dynMatchHelper(E, t) {
480
+ export function dynMatchHelper(emitter, t) {
541
481
  const key = typeKey(t);
542
- const existing = E.dynMatchers.get(key);
482
+ const existing = emitter.dynMatchers.get(key);
543
483
  if (existing)
544
484
  return existing;
545
- const name = `sc_dm_${E.dynMatchers.size}`;
546
- E.dynMatchers.set(key, name);
485
+ const name = `sc_dm_${emitter.dynMatchers.size}`;
486
+ emitter.dynMatchers.set(key, name);
547
487
  const sig = `static bool ${name}(const ScrDyn *d)`;
548
- E.walkerProtos.push(`${sig}; /* matches ${key} */`);
488
+ emitter.walkerProtos.push(`${sig}; /* matches ${key} */`);
549
489
  const d = [`${sig} { /* matches ${key} */`];
550
490
  if (isRefCounted(t) && t.kind !== "dyn") {
551
491
  const keyLit = cStringLiteral(Buffer.from(key, "utf8"));
@@ -583,13 +523,13 @@ export function dynMatchHelper(E, t) {
583
523
  case "bytes":
584
524
  // A Uint8Array target (the checked-dynamic tree carries u8 payloads only).
585
525
  if (t.elem !== "u8")
586
- throw new Error(`emitter bug: dynMatch of bytes<${t.elem}>`);
526
+ throw new InternalCompilerError(`emitter bug: dynMatch of bytes<${t.elem}>`);
587
527
  d.push(` return d->kind == SCR_DYN_BYTES;`);
588
528
  break;
589
529
  case "record": {
590
- const shape = E.recordsById.get(t.shapeId);
530
+ const shape = emitter.recordsById.get(t.shapeId);
591
531
  if (!shape)
592
- throw new Error(`emitter bug: dynCheck of unknown shape ${t.shapeId}`);
532
+ throw new InternalCompilerError(`emitter bug: dynCheck of unknown shape ${t.shapeId}`);
593
533
  // A tuple matches a JSON ARRAY of EXACTLY its arity whose elements
594
534
  // match positionally (arity is part of the type — width tolerance
595
535
  // is an object-key concept and does not apply).
@@ -597,7 +537,7 @@ export function dynMatchHelper(E, t) {
597
537
  const byIndex = [...shape.fields].sort((a, b) => Number(a.name) - Number(b.name));
598
538
  d.push(` if (d->kind != SCR_DYN_ARR || d->v.arr.len != ${byIndex.length}) return false;`);
599
539
  byIndex.forEach((f, i) => {
600
- d.push(` if (!${E.dynMatchHelper(f.type)}(d->v.arr.items[${i}])) return false;`);
540
+ d.push(` if (!${emitter.dynMatchHelper(f.type)}(d->v.arr.items[${i}])) return false;`);
601
541
  });
602
542
  d.push(` return true;`);
603
543
  break;
@@ -613,13 +553,13 @@ export function dynMatchHelper(E, t) {
613
553
  const keyLit = cStringLiteral(Buffer.from(f.name, "utf8"));
614
554
  const keyLen = Buffer.byteLength(f.name, "utf8");
615
555
  d.push(` m = scr_dyn_obj_get(d, ${keyLit}, ${keyLen});`);
616
- if (E.undefinedArmTag(f.type) >= 0) {
556
+ if (undefinedArmTag(f.type, emitter.unionsById) >= 0) {
617
557
  // Optional-flavored field: a MISSING key is the undefined arm
618
558
  // (a match); a PRESENT key must fit the union as usual.
619
- d.push(` if (m && !${E.dynMatchHelper(f.type)}(m)) return false;`);
559
+ d.push(` if (m && !${emitter.dynMatchHelper(f.type)}(m)) return false;`);
620
560
  }
621
561
  else {
622
- d.push(` if (!m || !${E.dynMatchHelper(f.type)}(m)) return false;`);
562
+ d.push(` if (!m || !${emitter.dynMatchHelper(f.type)}(m)) return false;`);
623
563
  }
624
564
  }
625
565
  // Index-signature shapes: UNDECLARED keys must fit the overflow
@@ -638,14 +578,14 @@ export function dynMatchHelper(E, t) {
638
578
  d.push(` const ScrDynEntry *e = &d->v.obj.entries[i];`);
639
579
  if (shape.fields.length > 0)
640
580
  d.push(` if (${skip}) continue;`);
641
- d.push(` if (!${E.dynMatchHelper(shape.indexValue)}(e->value)) return false;`);
581
+ d.push(` if (!${emitter.dynMatchHelper(shape.indexValue)}(e->value)) return false;`);
642
582
  d.push(` }`);
643
583
  }
644
584
  d.push(` return true;`);
645
585
  break;
646
586
  }
647
587
  case "array": {
648
- const m = E.dynMatchHelper(t.elem);
588
+ const m = emitter.dynMatchHelper(t.elem);
649
589
  d.push(` if (d->kind != SCR_DYN_ARR) return false;`);
650
590
  d.push(` for (size_t i = 0; i < d->v.arr.len; i++) {`);
651
591
  d.push(` if (!${m}(d->v.arr.items[i])) return false;`);
@@ -654,23 +594,23 @@ export function dynMatchHelper(E, t) {
654
594
  break;
655
595
  }
656
596
  case "union": {
657
- const def = E.unionsById.get(t.unionId);
597
+ const def = emitter.unionsById.get(t.unionId);
658
598
  if (!def)
659
- throw new Error(`emitter bug: dynCheck of unknown union ${t.unionId}`);
599
+ throw new InternalCompilerError(`emitter bug: dynCheck of unknown union ${t.unionId}`);
660
600
  // The undefined arm participates: parsed JSON never contains
661
601
  // undefined (a MISSING record key was the arm's only source), but
662
602
  // the checked-dynamic tree can hold the undefined value now — overflow entries
663
603
  // under `unknown` index signatures — and it matches exactly the
664
604
  // undefined arm.
665
- const arms = def.arms.map((a) => `${E.dynMatchHelper(a)}(d)`);
605
+ const arms = def.arms.map((a) => `${emitter.dynMatchHelper(a)}(d)`);
666
606
  d.push(` return ${arms.join(" || ")};`);
667
607
  break;
668
608
  }
669
609
  default:
670
- throw new Error(`emitter bug: dynMatch of non-JSON type ${t.kind}`);
610
+ throw new InternalCompilerError(`emitter bug: dynMatch of non-JSON type ${t.kind}`);
671
611
  }
672
612
  d.push(`}`, ``);
673
- E.walkerDefs.push(...d);
613
+ emitter.walkerDefs.push(...d);
674
614
  return name;
675
615
  }
676
616
  /** The emitted keyed read on a dyn value:
@@ -688,16 +628,16 @@ export function dynMatchHelper(E, t) {
688
628
  * is undefined." (or "…null."), the property form "Cannot destructure
689
629
  * property 'PROP' of 'SPELL' …" when firstProp is non-NULL — V8's exact
690
630
  * strings, source spelling included. Non-nullish values pass silently. */
691
- export function dynDestrCheckHelper(E) {
631
+ export function dynDestrCheckHelper(emitter) {
692
632
  const memoKey = "%dynDestrCheck";
693
- const existing = E.dynBuilders.get(memoKey);
633
+ const existing = emitter.dynBuilders.get(memoKey);
694
634
  if (existing)
695
635
  return existing;
696
636
  const name = "sc_dyn_destr_check";
697
- E.dynBuilders.set(memoKey, name);
637
+ emitter.dynBuilders.set(memoKey, name);
698
638
  const sig = `static void ${name}(const ScrDyn *d, const char *spell, const char *firstProp)`;
699
- E.walkerProtos.push(`${sig}; /* destructuring RequireObjectCoercible */`);
700
- E.walkerDefs.push(`${sig} { /* destructuring RequireObjectCoercible */`, ` if (d->kind != SCR_DYN_UNDEF && d->kind != SCR_DYN_NULL) return;`, ` ScrJsonBuf b;`, ` scr_jb_init(&b);`, ` if (firstProp) {`, ` scr_jb_puts(&b, "Cannot destructure property '");`, ` scr_jb_puts(&b, firstProp);`, ` scr_jb_puts(&b, "' of '");`, ` scr_jb_puts(&b, spell);`, ` scr_jb_puts(&b, "' as it is ");`, ` } else {`, ` scr_jb_puts(&b, "Cannot destructure '");`, ` scr_jb_puts(&b, spell);`, ` scr_jb_puts(&b, "' as it is ");`, ` }`, ` scr_jb_puts(&b, d->kind == SCR_DYN_UNDEF ? "undefined." : "null.");`, ` scr_throw_error(SCR_ERR_TYPE, scr_jb_finish(&b));`, `}`, ``);
639
+ emitter.walkerProtos.push(`${sig}; /* destructuring RequireObjectCoercible */`);
640
+ emitter.walkerDefs.push(`${sig} { /* destructuring RequireObjectCoercible */`, ` if (d->kind != SCR_DYN_UNDEF && d->kind != SCR_DYN_NULL) return;`, ` ScrJsonBuf b;`, ` scr_jb_init(&b);`, ` if (firstProp) {`, ` scr_jb_puts(&b, "Cannot destructure property '");`, ` scr_jb_puts(&b, firstProp);`, ` scr_jb_puts(&b, "' of '");`, ` scr_jb_puts(&b, spell);`, ` scr_jb_puts(&b, "' as it is ");`, ` } else {`, ` scr_jb_puts(&b, "Cannot destructure '");`, ` scr_jb_puts(&b, spell);`, ` scr_jb_puts(&b, "' as it is ");`, ` }`, ` scr_jb_puts(&b, d->kind == SCR_DYN_UNDEF ? "undefined." : "null.");`, ` scr_throw_error(SCR_ERR_TYPE, scr_jb_finish(&b));`, `}`, ``);
701
641
  return name;
702
642
  }
703
643
  /** GetIterator + first-N steps over a dyn value (the dynIterN node), as
@@ -709,27 +649,27 @@ export function dynDestrCheckHelper(E) {
709
649
  * "function …" — each with the "(cannot read property
710
650
  * Symbol(Symbol.iterator))" tail). Returns a fresh +1 dyn array of
711
651
  * exactly n elements, undefined-padded past the end. */
712
- export function dynIterNHelper(E) {
652
+ export function dynIterNHelper(emitter) {
713
653
  const memoKey = "%dynIterN";
714
- const existing = E.dynBuilders.get(memoKey);
654
+ const existing = emitter.dynBuilders.get(memoKey);
715
655
  if (existing)
716
656
  return existing;
717
657
  const name = "sc_dyn_iter_n";
718
- E.dynBuilders.set(memoKey, name);
658
+ emitter.dynBuilders.set(memoKey, name);
719
659
  const sig = `static ScrDyn *${name}(const ScrDyn *d, size_t n)`;
720
- E.walkerProtos.push(`${sig}; /* destructuring GetIterator + N steps */`);
721
- E.walkerDefs.push(`${sig} { /* destructuring GetIterator + N steps */`, ` if (d->kind == SCR_DYN_TYPED_REF) {`, ` ScrDyn *sc_materialized = scr_dyn_typed_ref_materialize(d);`, ` ScrDyn *sc_out = ${name}(sc_materialized, n);`, ` scr_dyn_release(sc_materialized);`, ` return sc_out;`, ` }`, ` if (d->kind == SCR_DYN_JSVAL) {`, ` /* An engine array IS iterable — the not-iterable TypeError below`, ` * would be a wrong claim. Loud fence (lane dyn-routing-ops). */`, ` scr_dyn_isl_fence(d, "iteration");`, ` return NULL;`, ` }`, ` if (d->kind != SCR_DYN_ARR && d->kind != SCR_DYN_STR && d->kind != SCR_DYN_BYTES) {`, ` ScrJsonBuf b;`, ` scr_jb_init(&b);`, ` switch (d->kind) {`, ` case SCR_DYN_UNDEF: scr_jb_puts(&b, "undefined"); break;`, ` case SCR_DYN_NULL: scr_jb_puts(&b, "object null"); break;`, ` case SCR_DYN_BOOL: scr_jb_puts(&b, d->v.b ? "boolean true" : "boolean false"); break;`, ` case SCR_DYN_NUM: {`, ` scr_jb_puts(&b, "number ");`, ` ScrStr *s = scr_f64_to_scrstr(d->v.num);`, ` for (size_t i = 0; i < s->len; i++) scr_jb_putc(&b, s->data[i]);`, ` scr_str_release(s);`, ` break;`, ` }`, ` case SCR_DYN_FUNC: scr_jb_puts(&b, "function"); break;`, ` default: scr_jb_puts(&b, "object"); break;`, ` }`, ` scr_jb_puts(&b, " is not iterable (cannot read property Symbol(Symbol.iterator))");`, ` scr_throw_error(SCR_ERR_TYPE, scr_jb_finish(&b));`, ` return NULL;`, ` }`, ` ScrDyn *out = scr_dyn_new_arr();`, ` for (size_t i = 0; i < n; i++) {`, ` ScrDyn *item = NULL;`, ` if (d->kind == SCR_DYN_ARR) {`, ` item = i < d->v.arr.len ? scr_dyn_retain(d->v.arr.items[i]) : scr_dyn_retain(scr_dyn_undefined());`, ` } else if (d->kind == SCR_DYN_BYTES) {`, ` item = i < d->v.bytes->len ? scr_dyn_new_num((double)d->v.bytes->data[i]) : scr_dyn_retain(scr_dyn_undefined());`, ` } else {`, ` /* String iteration: whole code POINTS (astral chars arrive`, ` * unsplit — the string iterator, not charAt). */`, ` double len = scr_str_utf16_len(d->v.str);`, ` double at = 0;`, ` for (size_t step = 0; step < i && at < len; step++) {`, ` ScrStr *cp = scr_str_cp_at(d->v.str, at);`, ` at += scr_str_utf16_len(cp);`, ` scr_str_release(cp);`, ` }`, ` if (at < len) {`, ` ScrStr *cp = scr_str_cp_at(d->v.str, at);`, ` item = scr_dyn_new_str(cp);`, ` scr_str_release(cp);`, ` } else {`, ` item = scr_dyn_retain(scr_dyn_undefined());`, ` }`, ` }`, ` scr_dyn_arr_push(out, item); /* push takes ownership */`, ` }`, ` return out;`, `}`, ``);
660
+ emitter.walkerProtos.push(`${sig}; /* destructuring GetIterator + N steps */`);
661
+ emitter.walkerDefs.push(`${sig} { /* destructuring GetIterator + N steps */`, ` if (d->kind == SCR_DYN_TYPED_REF) {`, ` ScrDyn *sc_materialized = scr_dyn_typed_ref_materialize(d);`, ` ScrDyn *sc_out = ${name}(sc_materialized, n);`, ` scr_dyn_release(sc_materialized);`, ` return sc_out;`, ` }`, ` if (d->kind == SCR_DYN_JSVAL) {`, ` /* An engine array IS iterable — the not-iterable TypeError below`, ` * would be a wrong claim. Loud fence (lane dyn-routing-ops). */`, ` scr_dyn_isl_fence(d, "iteration");`, ` return NULL;`, ` }`, ` if (d->kind != SCR_DYN_ARR && d->kind != SCR_DYN_STR && d->kind != SCR_DYN_BYTES) {`, ` ScrJsonBuf b;`, ` scr_jb_init(&b);`, ` switch (d->kind) {`, ` case SCR_DYN_UNDEF: scr_jb_puts(&b, "undefined"); break;`, ` case SCR_DYN_NULL: scr_jb_puts(&b, "object null"); break;`, ` case SCR_DYN_BOOL: scr_jb_puts(&b, d->v.b ? "boolean true" : "boolean false"); break;`, ` case SCR_DYN_NUM: {`, ` scr_jb_puts(&b, "number ");`, ` ScrStr *s = scr_f64_to_scrstr(d->v.num);`, ` for (size_t i = 0; i < s->len; i++) scr_jb_putc(&b, s->data[i]);`, ` scr_str_release(s);`, ` break;`, ` }`, ` case SCR_DYN_FUNC: scr_jb_puts(&b, "function"); break;`, ` default: scr_jb_puts(&b, "object"); break;`, ` }`, ` scr_jb_puts(&b, " is not iterable (cannot read property Symbol(Symbol.iterator))");`, ` scr_throw_error(SCR_ERR_TYPE, scr_jb_finish(&b));`, ` return NULL;`, ` }`, ` ScrDyn *out = scr_dyn_new_arr();`, ` for (size_t i = 0; i < n; i++) {`, ` ScrDyn *item = NULL;`, ` if (d->kind == SCR_DYN_ARR) {`, ` item = i < d->v.arr.len ? scr_dyn_retain(d->v.arr.items[i]) : scr_dyn_retain(scr_dyn_undefined());`, ` } else if (d->kind == SCR_DYN_BYTES) {`, ` item = i < d->v.bytes->len ? scr_dyn_new_num((double)d->v.bytes->data[i]) : scr_dyn_retain(scr_dyn_undefined());`, ` } else {`, ` /* String iteration: whole code POINTS (astral chars arrive`, ` * unsplit — the string iterator, not charAt). */`, ` double len = scr_str_utf16_len(d->v.str);`, ` double at = 0;`, ` for (size_t step = 0; step < i && at < len; step++) {`, ` ScrStr *cp = scr_str_cp_at(d->v.str, at);`, ` at += scr_str_utf16_len(cp);`, ` scr_str_release(cp);`, ` }`, ` if (at < len) {`, ` ScrStr *cp = scr_str_cp_at(d->v.str, at);`, ` item = scr_dyn_new_str(cp);`, ` scr_str_release(cp);`, ` } else {`, ` item = scr_dyn_retain(scr_dyn_undefined());`, ` }`, ` }`, ` scr_dyn_arr_push(out, item); /* push takes ownership */`, ` }`, ` return out;`, `}`, ``);
722
662
  return name;
723
663
  }
724
- export function dynKeyGetHelper(E) {
664
+ export function dynKeyGetHelper(emitter) {
725
665
  const memoKey = "%dynKeyGet";
726
- const existing = E.dynBuilders.get(memoKey);
666
+ const existing = emitter.dynBuilders.get(memoKey);
727
667
  if (existing)
728
668
  return existing;
729
669
  const name = "sc_dyn_key_get";
730
- E.dynBuilders.set(memoKey, name);
670
+ emitter.dynBuilders.set(memoKey, name);
731
671
  const sig = `static ScrDyn *${name}(ScrDyn *d, ScrStr *k, bool opt)`;
732
- E.walkerProtos.push(`${sig}; /* d[k] on dyn */`);
672
+ emitter.walkerProtos.push(`${sig}; /* d[k] on dyn */`);
733
673
  const d = [`${sig} { /* d[k] on dyn */`];
734
674
  d.push(` if (d->kind == SCR_DYN_UNDEF || d->kind == SCR_DYN_NULL) {`);
735
675
  d.push(` if (opt) return scr_dyn_retain(scr_dyn_undefined());`);
@@ -815,7 +755,7 @@ export function dynKeyGetHelper(E) {
815
755
  d.push(` }`);
816
756
  d.push(` return scr_dyn_retain(scr_dyn_undefined());`);
817
757
  d.push(`}`, ``);
818
- E.walkerDefs.push(...d);
758
+ emitter.walkerDefs.push(...d);
819
759
  return name;
820
760
  }
821
761
  /** The emitted checked builder for one dynCheck target type:
@@ -826,16 +766,16 @@ export function dynKeyGetHelper(E) {
826
766
  * Recursive calls propagate a pending exception by releasing the
827
767
  * partially-built value and returning — the same pending-check discipline
828
768
  * emitted function bodies follow. */
829
- export function dynCheckHelper(E, t) {
769
+ export function dynCheckHelper(emitter, t) {
830
770
  const key = typeKey(t);
831
- const existing = E.dynBuilders.get(key);
771
+ const existing = emitter.dynBuilders.get(key);
832
772
  if (existing)
833
773
  return existing;
834
- const name = `sc_dc_${E.dynBuilders.size}`;
835
- E.dynBuilders.set(key, name);
774
+ const name = `sc_dc_${emitter.dynBuilders.size}`;
775
+ emitter.dynBuilders.set(key, name);
836
776
  const sig = `static ${cType(t)}${cType(t).endsWith("*") ? "" : " "}${name}(const ScrDyn *d, const ScrDynPath *path)`;
837
- E.walkerProtos.push(`${sig}; /* check ${key} */`);
838
- const want = cStringLiteral(Buffer.from(E.dynDesc(t), "utf8"));
777
+ emitter.walkerProtos.push(`${sig}; /* check ${key} */`);
778
+ const want = cStringLiteral(Buffer.from(dynDesc(t, emitter.recordsById, emitter.unionsById), "utf8"));
839
779
  const d = [`${sig} { /* check ${key} */`];
840
780
  if (isRefCounted(t) && t.kind !== "dyn") {
841
781
  const keyLit = cStringLiteral(Buffer.from(key, "utf8"));
@@ -849,9 +789,9 @@ export function dynCheckHelper(E, t) {
849
789
  }
850
790
  d.push(` ScrDyn *sc_materialized = scr_dyn_typed_ref_materialize(d);`, ` ${cDecl(t, "sc_out")} = ${name}(sc_materialized, path);`, ` scr_dyn_release(sc_materialized);`);
851
791
  if (t.kind === "record") {
852
- const shape = E.recordsById.get(t.shapeId);
792
+ const shape = emitter.recordsById.get(t.shapeId);
853
793
  if (!shape) {
854
- throw new Error(`emitter bug: cached typed-ref cast of unknown shape ${t.shapeId}`);
794
+ throw new InternalCompilerError(`emitter bug: cached typed-ref cast of unknown shape ${t.shapeId}`);
855
795
  }
856
796
  d.push(` if (sc_out && sc_cached) {`);
857
797
  for (const field of shape.fields) {
@@ -893,7 +833,7 @@ export function dynCheckHelper(E, t) {
893
833
  // `u as Uint8Array`: kind check, then a fresh COPY out (the
894
834
  // boundary's aliasing stance in both directions).
895
835
  if (t.elem !== "u8")
896
- throw new Error(`emitter bug: dynCheck of bytes<${t.elem}>`);
836
+ throw new InternalCompilerError(`emitter bug: dynCheck of bytes<${t.elem}>`);
897
837
  d.push(` if (d->kind != SCR_DYN_BYTES) { scr_dyn_check_fail(path, ${want}, d); return NULL; }`);
898
838
  d.push(` return scr_dyn_bytes_copy_out(d);`);
899
839
  break;
@@ -906,15 +846,15 @@ export function dynCheckHelper(E, t) {
906
846
  // compare reference-equal (the tracing suite's shape); alien
907
847
  // %error objects rebuild once and cache the pair.
908
848
  if (t.className !== "%Error") {
909
- throw new Error(`emitter bug: dynCheck of class ${t.className} (only %Error extracts from the checked-dynamic tree)`);
849
+ throw new InternalCompilerError(`emitter bug: dynCheck of class ${t.className} (only %Error extracts from the checked-dynamic tree)`);
910
850
  }
911
851
  d.push(` if (d->kind != SCR_DYN_OBJ || !scr_dyn_obj_get(d, "%error", 6)) { scr_dyn_check_fail(path, ${want}, d); return NULL; }`);
912
852
  d.push(` return scr_error_from_dyn(d);`);
913
853
  break;
914
854
  case "record": {
915
- const shape = E.recordsById.get(t.shapeId);
855
+ const shape = emitter.recordsById.get(t.shapeId);
916
856
  if (!shape)
917
- throw new Error(`emitter bug: dynCheck of unknown shape ${t.shapeId}`);
857
+ throw new InternalCompilerError(`emitter bug: dynCheck of unknown shape ${t.shapeId}`);
918
858
  const rel = (v) => releaseCallC(t, v);
919
859
  // Tuple targets: a JSON ARRAY of exactly the arity, validated and
920
860
  // extracted positionally with index paths ("$.pairs[3][1]").
@@ -927,7 +867,7 @@ export function dynCheckHelper(E, t) {
927
867
  byIndex.forEach((f, i) => {
928
868
  d.push(` {`);
929
869
  d.push(` ScrDynPath p = { path, NULL, ${i} };`);
930
- d.push(` r->${mangleField(f.name)} = ${E.dynCheckHelper(f.type)}(d->v.arr.items[${i}], &p);`);
870
+ d.push(` r->${mangleField(f.name)} = ${emitter.dynCheckHelper(f.type)}(d->v.arr.items[${i}], &p);`);
931
871
  d.push(` if (scr_exc_pending()) { ${rel("r")}; return NULL; }`);
932
872
  d.push(` }`);
933
873
  });
@@ -939,14 +879,14 @@ export function dynCheckHelper(E, t) {
939
879
  for (const f of shape.fields) {
940
880
  const keyLit = cStringLiteral(Buffer.from(f.name, "utf8"));
941
881
  const keyLen = Buffer.byteLength(f.name, "utf8");
942
- const fieldWant = cStringLiteral(Buffer.from(E.dynDesc(f.type), "utf8"));
882
+ const fieldWant = cStringLiteral(Buffer.from(dynDesc(f.type, emitter.recordsById, emitter.unionsById), "utf8"));
943
883
  // Width tolerance: only declared fields are looked up — extra JSON
944
884
  // keys are simply never examined (check-and-extract, not shape
945
885
  // equality). A missing field fails as "got undefined" — except
946
886
  // optional-flavored fields (undefined-armed unions), where the
947
887
  // missing key IS the undefined arm: the interned immortal
948
888
  // instance, no retain owed (rc == SIZE_MAX).
949
- const utag = f.type.kind === "union" ? E.undefinedArmTag(f.type) : -1;
889
+ const utag = f.type.kind === "union" ? undefinedArmTag(f.type, emitter.unionsById) : -1;
950
890
  d.push(` {`);
951
891
  d.push(` ScrDynPath p = { path, ${keyLit}, 0 };`);
952
892
  d.push(` const ScrDyn *m = scr_dyn_obj_get(d, ${keyLit}, ${keyLen});`);
@@ -955,20 +895,20 @@ export function dynCheckHelper(E, t) {
955
895
  // one IS the undefined dyn value (JS's missing-property read).
956
896
  // Go through the dyn builder so a Web-stream typed-ref capsule
957
897
  // cannot escape inside a checked record field.
958
- d.push(` r->${mangleField(f.name)} = ${E.dynCheckHelper(f.type)}(m ? m : scr_dyn_undefined(), &p);`);
898
+ d.push(` r->${mangleField(f.name)} = ${emitter.dynCheckHelper(f.type)}(m ? m : scr_dyn_undefined(), &p);`);
959
899
  }
960
900
  else if (utag >= 0 && f.type.kind === "union") {
961
- const unit = E.unitInstanceRef(f.type.unionId, utag);
901
+ const unit = emitter.unitInstanceRef(f.type.unionId, utag);
962
902
  d.push(` if (!m) {`);
963
903
  d.push(` r->${mangleField(f.name)} = ${unit}; /* absent key -> the undefined arm */`);
964
904
  d.push(` } else {`);
965
- d.push(` r->${mangleField(f.name)} = ${E.dynCheckHelper(f.type)}(m, &p);`);
905
+ d.push(` r->${mangleField(f.name)} = ${emitter.dynCheckHelper(f.type)}(m, &p);`);
966
906
  d.push(` if (scr_exc_pending()) { ${rel("r")}; return NULL; }`);
967
907
  d.push(` }`);
968
908
  }
969
909
  else {
970
910
  d.push(` if (!m) { scr_dyn_check_fail(&p, ${fieldWant}, NULL); ${rel("r")}; return NULL; }`);
971
- d.push(` r->${mangleField(f.name)} = ${E.dynCheckHelper(f.type)}(m, &p);`);
911
+ d.push(` r->${mangleField(f.name)} = ${emitter.dynCheckHelper(f.type)}(m, &p);`);
972
912
  d.push(` if (scr_exc_pending()) { ${rel("r")}; return NULL; }`);
973
913
  }
974
914
  d.push(` }`);
@@ -995,7 +935,7 @@ export function dynCheckHelper(E, t) {
995
935
  }
996
936
  else {
997
937
  d.push(` ScrDynPath p = { path, e->key, 0 };`);
998
- d.push(` ${cDecl(iv, "ev")} = ${E.dynCheckHelper(iv)}(e->value, &p);`);
938
+ d.push(` ${cDecl(iv, "ev")} = ${emitter.dynCheckHelper(iv)}(e->value, &p);`);
999
939
  d.push(` if (scr_exc_pending()) { ${rel("r")}; return NULL; }`);
1000
940
  }
1001
941
  d.push(` ScrStr *ek = scr_str_new(e->key, e->key_len);`);
@@ -1013,9 +953,9 @@ export function dynCheckHelper(E, t) {
1013
953
  }
1014
954
  case "array": {
1015
955
  const elem = t.elem;
1016
- const c = E.dynCheckHelper(elem);
956
+ const c = emitter.dynCheckHelper(elem);
1017
957
  d.push(` if (d->kind != SCR_DYN_ARR) { scr_dyn_check_fail(path, ${want}, d); return NULL; }`);
1018
- d.push(` ScrArr *a = ${E.arrNewC(elem, "d->v.arr.len")};`);
958
+ d.push(` ScrArr *a = ${emitter.arrNewC(elem, "d->v.arr.len")};`);
1019
959
  d.push(` for (size_t i = 0; i < d->v.arr.len; i++) {`);
1020
960
  d.push(` ScrDynPath p = { path, NULL, i };`);
1021
961
  d.push(` ${cDecl(elem, "e")} = ${c}(d->v.arr.items[i], &p);`);
@@ -1026,14 +966,14 @@ export function dynCheckHelper(E, t) {
1026
966
  break;
1027
967
  }
1028
968
  case "union": {
1029
- const def = E.unionsById.get(t.unionId);
969
+ const def = emitter.unionsById.get(t.unionId);
1030
970
  if (!def)
1031
- throw new Error(`emitter bug: dynCheck of unknown union ${t.unionId}`);
971
+ throw new InternalCompilerError(`emitter bug: dynCheck of unknown union ${t.unionId}`);
1032
972
  // Arms in CANONICAL order, first FULL match wins (discriminated
1033
973
  // unions disambiguate naturally: the arm whose declared fields all
1034
974
  // fit). The matched arm's builder can no longer fail.
1035
975
  def.arms.forEach((arm, i) => {
1036
- const m = E.dynMatchHelper(arm);
976
+ const m = emitter.dynMatchHelper(arm);
1037
977
  if (arm.kind === "undefinedT") {
1038
978
  // Parsed JSON never matches here (no undefined in JSON text —
1039
979
  // a MISSING record key builds this arm in the record builder
@@ -1041,7 +981,7 @@ export function dynCheckHelper(E, t) {
1041
981
  // `unknown` index-signature overflows and builds the interned
1042
982
  // unit instance exactly like null.
1043
983
  d.push(` if (${m}(d)) {`);
1044
- d.push(` return ${E.unitInstanceRef(t.unionId, i)};`);
984
+ d.push(` return ${emitter.unitInstanceRef(t.unionId, i)};`);
1045
985
  d.push(` }`);
1046
986
  return;
1047
987
  }
@@ -1050,11 +990,11 @@ export function dynCheckHelper(E, t) {
1050
990
  // immortal instance (rc == SIZE_MAX — RC entry points and the
1051
991
  // collector both skip it, so no retain is owed).
1052
992
  d.push(` if (${m}(d)) {`);
1053
- d.push(` return ${E.unitInstanceRef(t.unionId, i)};`);
993
+ d.push(` return ${emitter.unitInstanceRef(t.unionId, i)};`);
1054
994
  d.push(` }`);
1055
995
  return;
1056
996
  }
1057
- const c = E.dynCheckHelper(arm);
997
+ const c = emitter.dynCheckHelper(arm);
1058
998
  d.push(` if (${m}(d)) {`);
1059
999
  if (arm.kind === "f64") {
1060
1000
  d.push(` return scr_union_new_f64(${i}, ${c}(d, path));`);
@@ -1064,7 +1004,7 @@ export function dynCheckHelper(E, t) {
1064
1004
  }
1065
1005
  else {
1066
1006
  const rc = vAdapters(arm);
1067
- d.push(` return scr_union_new_ref(${i}, ${c}(d, path), &${rc.retain}, &${rc.release}, ${E.traceArgC(arm)});`);
1007
+ d.push(` return scr_union_new_ref(${i}, ${c}(d, path), &${rc.retain}, &${rc.release}, ${emitter.traceArgC(arm)});`);
1068
1008
  }
1069
1009
  d.push(` }`);
1070
1010
  });
@@ -1113,7 +1053,7 @@ export function dynCheckHelper(E, t) {
1113
1053
  // wrapper, retained); anything else wraps in the per-target
1114
1054
  // adapter closure, whose caps[0] obj-box owns the dyn value
1115
1055
  // (untraced — cycles through dyn never collect, SEMANTICS.md).
1116
- const adapter = dynFuncAdapterHelper(E, t);
1056
+ const adapter = dynFuncAdapterHelper(emitter, t);
1117
1057
  const sigLit = cStringLiteral(Buffer.from(key, "utf8"));
1118
1058
  d.push(` if (d->kind != SCR_DYN_FUNC) { scr_dyn_check_fail(path, ${want}, d); return NULL; }`);
1119
1059
  d.push(` if (strcmp(d->v.fn.sig, ${sigLit}) == 0) return scr_closure_retain(d->v.fn.clo);`);
@@ -1134,11 +1074,11 @@ export function dynCheckHelper(E, t) {
1134
1074
  d.push(` return (${cType(t).trim()})scr_dyn_handle_unbox(d, ${h.tag}, path, ${want});`);
1135
1075
  break;
1136
1076
  }
1137
- throw new Error(`emitter bug: dynCheck of non-JSON type ${t.kind}`);
1077
+ throw new InternalCompilerError(`emitter bug: dynCheck of non-JSON type ${t.kind}`);
1138
1078
  }
1139
1079
  }
1140
1080
  d.push(`}`, ``);
1141
- E.walkerDefs.push(...d);
1081
+ emitter.walkerDefs.push(...d);
1142
1082
  return name;
1143
1083
  }
1144
1084
  /** The emitted static→dyn converter for one type:
@@ -1148,15 +1088,15 @@ export function dynCheckHelper(E, t) {
1148
1088
  * plus undefined-armed unions (the undefined arm becomes the undefined
1149
1089
  * dyn singleton) and index-signature records (whose overflow entries
1150
1090
  * copy over). The operand is borrowed. Never throws. */
1151
- export function toDynHelper(E, t) {
1091
+ export function toDynHelper(emitter, t) {
1152
1092
  const key = typeKey(t);
1153
- const existing = E.toDynFns.get(key);
1093
+ const existing = emitter.toDynFns.get(key);
1154
1094
  if (existing)
1155
1095
  return existing;
1156
- const name = `sc_td_${E.toDynFns.size}`;
1157
- E.toDynFns.set(key, name);
1096
+ const name = `sc_td_${emitter.toDynFns.size}`;
1097
+ emitter.toDynFns.set(key, name);
1158
1098
  const sig = `static ScrDyn *${name}(${cDecl(t, "v")})`;
1159
- E.walkerProtos.push(`${sig}; /* to-dyn ${key} */`);
1099
+ emitter.walkerProtos.push(`${sig}; /* to-dyn ${key} */`);
1160
1100
  const d = [`${sig} { /* to-dyn ${key} */`];
1161
1101
  let sourceAccessor = null;
1162
1102
  switch (t.kind) {
@@ -1180,7 +1120,7 @@ export function toDynHelper(E, t) {
1180
1120
  case "object":
1181
1121
  // %Error only (canConvertToDyn's gate): the checked-dynamic tree's error encoding.
1182
1122
  if (t.className !== "%Error") {
1183
- throw new Error(`emitter bug: to-dyn of class ${t.className}`);
1123
+ throw new InternalCompilerError(`emitter bug: to-dyn of class ${t.className}`);
1184
1124
  }
1185
1125
  d.push(` return scr_dyn_from_error(v);`);
1186
1126
  break;
@@ -1194,23 +1134,23 @@ export function toDynHelper(E, t) {
1194
1134
  // Function-valued record/array fields (EventListenerObject's
1195
1135
  // handleEvent method) box through the same identity-preserving
1196
1136
  // closure bridge as a bare dynFrom function.
1197
- d.push(` return ${dynFuncBoxHelper(E, t)}(v, NULL);`);
1137
+ d.push(` return ${dynFuncBoxHelper(emitter, t)}(v, NULL);`);
1198
1138
  break;
1199
1139
  case "bytes":
1200
1140
  // bytes<u8> → the checked-dynamic tree's bytes kind, payload COPIED (the boundary
1201
1141
  // stance; stdin chunks into unknown-typed helpers).
1202
1142
  if (t.elem !== "u8")
1203
- throw new Error(`emitter bug: to-dyn of bytes<${t.elem}>`);
1143
+ throw new InternalCompilerError(`emitter bug: to-dyn of bytes<${t.elem}>`);
1204
1144
  d.push(` return scr_dyn_new_bytes_copy(v);`);
1205
1145
  break;
1206
1146
  case "record": {
1207
- const shape = E.recordsById.get(t.shapeId);
1147
+ const shape = emitter.recordsById.get(t.shapeId);
1208
1148
  if (!shape)
1209
- throw new Error(`emitter bug: to-dyn of unknown shape ${t.shapeId}`);
1149
+ throw new InternalCompilerError(`emitter bug: to-dyn of unknown shape ${t.shapeId}`);
1210
1150
  // CYCLE-CAPABLE shapes guard the deep copy: a cyclic value has no
1211
1151
  // finite dyn copy, so enter TRAPS on re-entry (SEMANTICS.md — Node
1212
1152
  // shares the reference instead of copying).
1213
- const cyclicRec = E.traceAdapterC(t) !== null;
1153
+ const cyclicRec = emitter.traceAdapterC(t) !== null;
1214
1154
  if (cyclicRec)
1215
1155
  d.push(` scr_dyn_from_enter(v);`);
1216
1156
  if (shape.tuple) {
@@ -1218,7 +1158,7 @@ export function toDynHelper(E, t) {
1218
1158
  const byIndex = [...shape.fields].sort((a, b) => Number(a.name) - Number(b.name));
1219
1159
  d.push(` ScrDyn *d = scr_dyn_new_arr();`);
1220
1160
  for (const f of byIndex) {
1221
- d.push(` scr_dyn_arr_push(d, ${E.toDynHelper(f.type)}(v->${mangleField(f.name)}));`);
1161
+ d.push(` scr_dyn_arr_push(d, ${emitter.toDynHelper(f.type)}(v->${mangleField(f.name)}));`);
1222
1162
  }
1223
1163
  if (cyclicRec)
1224
1164
  d.push(` scr_dyn_from_leave();`);
@@ -1232,7 +1172,7 @@ export function toDynHelper(E, t) {
1232
1172
  name: `${name}_source_access`,
1233
1173
  release: rc.release,
1234
1174
  };
1235
- E.walkerProtos.push(`static ScrDyn *${sourceAccessor.name}(void *v, bool materialize); /* live listener source ${key} */`);
1175
+ emitter.walkerProtos.push(`static ScrDyn *${sourceAccessor.name}(void *v, bool materialize); /* live listener source ${key} */`);
1236
1176
  d.push(` ScrDyn *d = scr_dyn_new_obj_with_identity(v, &${rc.retain}, &${sourceAccessor.name});`);
1237
1177
  }
1238
1178
  else {
@@ -1255,7 +1195,7 @@ export function toDynHelper(E, t) {
1255
1195
  for (const f of dynFields) {
1256
1196
  const keyLit = cStringLiteral(Buffer.from(f.name, "utf8"));
1257
1197
  const keyLen = Buffer.byteLength(f.name, "utf8");
1258
- d.push(` scr_dyn_obj_set(d, ${keyLit}, ${keyLen}, ${E.toDynHelper(f.type)}(v->${mangleField(f.name)}));`);
1198
+ d.push(` scr_dyn_obj_set(d, ${keyLit}, ${keyLen}, ${emitter.toDynHelper(f.type)}(v->${mangleField(f.name)}));`);
1259
1199
  }
1260
1200
  }
1261
1201
  if (shape.indexValue) {
@@ -1278,7 +1218,7 @@ export function toDynHelper(E, t) {
1278
1218
  }
1279
1219
  else {
1280
1220
  d.push(` ${cDecl(iv, "e")} = (${cType(iv).trim()})scr_map_get_str_ref(${m}, k);`);
1281
- d.push(` scr_dyn_obj_set(d, k->data, k->len, ${E.toDynHelper(iv)}(e));`);
1221
+ d.push(` scr_dyn_obj_set(d, k->data, k->len, ${emitter.toDynHelper(iv)}(e));`);
1282
1222
  d.push(` ${releaseCallC(iv, "e")};`);
1283
1223
  }
1284
1224
  d.push(` scr_str_release(k);`);
@@ -1294,7 +1234,7 @@ export function toDynHelper(E, t) {
1294
1234
  case "array": {
1295
1235
  const elem = t.elem;
1296
1236
  // Cycle-capable arrays guard the deep copy like records above.
1297
- const cyclicArr = E.traceAdapterC(t) !== null;
1237
+ const cyclicArr = emitter.traceAdapterC(t) !== null;
1298
1238
  if (cyclicArr)
1299
1239
  d.push(` scr_dyn_from_enter(v);`);
1300
1240
  d.push(` ScrDyn *d = scr_dyn_new_arr();`);
@@ -1307,7 +1247,7 @@ export function toDynHelper(E, t) {
1307
1247
  }
1308
1248
  else {
1309
1249
  d.push(` ${cDecl(elem, "e")} = (${cType(elem).trim()})scr_arr_get_ref(v, (double)i);`);
1310
- d.push(` scr_dyn_arr_push(d, ${E.toDynHelper(elem)}(e));`);
1250
+ d.push(` scr_dyn_arr_push(d, ${emitter.toDynHelper(elem)}(e));`);
1311
1251
  d.push(` ${releaseCallC(elem, "e")};`);
1312
1252
  }
1313
1253
  d.push(` }`);
@@ -1317,9 +1257,9 @@ export function toDynHelper(E, t) {
1317
1257
  break;
1318
1258
  }
1319
1259
  case "union": {
1320
- const def = E.unionsById.get(t.unionId);
1260
+ const def = emitter.unionsById.get(t.unionId);
1321
1261
  if (!def)
1322
- throw new Error(`emitter bug: to-dyn of unknown union ${t.unionId}`);
1262
+ throw new InternalCompilerError(`emitter bug: to-dyn of unknown union ${t.unionId}`);
1323
1263
  d.push(` switch (v->tag) {`);
1324
1264
  def.arms.forEach((arm, i) => {
1325
1265
  if (arm.kind === "undefinedT") {
@@ -1337,10 +1277,10 @@ export function toDynHelper(E, t) {
1337
1277
  else if (arm.kind === "func") {
1338
1278
  // A boxable function arm crosses through the checked-dynamic
1339
1279
  // function boundary (the dynFrom func special case, sans name).
1340
- d.push(` case ${i}: return ${dynFuncBoxHelper(E, arm)}((ScrClosure *)scr_union_peek(v), NULL);`);
1280
+ d.push(` case ${i}: return ${dynFuncBoxHelper(emitter, arm)}((ScrClosure *)scr_union_peek(v), NULL);`);
1341
1281
  }
1342
1282
  else {
1343
- d.push(` case ${i}: return ${E.toDynHelper(arm)}((${cType(arm).trim()})scr_union_peek(v));`);
1283
+ d.push(` case ${i}: return ${emitter.toDynHelper(arm)}((${cType(arm).trim()})scr_union_peek(v));`);
1344
1284
  }
1345
1285
  });
1346
1286
  d.push(` default: scr_trap("scriptc: internal error: invalid union tag\\n");`);
@@ -1357,7 +1297,7 @@ export function toDynHelper(E, t) {
1357
1297
  d.push(` return scr_dyn_new_promise(v);`);
1358
1298
  break;
1359
1299
  }
1360
- d.push(` return scr_dyn_new_promise_adapting(v, &${promiseDynAdapterHelper(E, t.inner)});`);
1300
+ d.push(` return scr_dyn_new_promise_adapting(v, &${promiseDynAdapterHelper(emitter, t.inner)});`);
1361
1301
  break;
1362
1302
  }
1363
1303
  default: {
@@ -1369,13 +1309,13 @@ export function toDynHelper(E, t) {
1369
1309
  d.push(` return scr_dyn_new_handle(v, ${h.tag});`);
1370
1310
  break;
1371
1311
  }
1372
- throw new Error(`emitter bug: to-dyn of unsupported type ${t.kind}`);
1312
+ throw new InternalCompilerError(`emitter bug: to-dyn of unsupported type ${t.kind}`);
1373
1313
  }
1374
1314
  }
1375
1315
  d.push(`}`, ``);
1376
- E.walkerDefs.push(...d);
1316
+ emitter.walkerDefs.push(...d);
1377
1317
  if (sourceAccessor) {
1378
- E.walkerDefs.push(`static ScrDyn *${sourceAccessor.name}(void *v, bool materialize) {`, ` if (materialize) return ${name}((${cType(t).trim()})v);`, ` ${sourceAccessor.release}(v);`, ` return NULL;`, `}`, ``);
1318
+ emitter.walkerDefs.push(`static ScrDyn *${sourceAccessor.name}(void *v, bool materialize) {`, ` if (materialize) return ${name}((${cType(t).trim()})v);`, ` ${sourceAccessor.release}(v);`, ` return NULL;`, `}`, ``);
1379
1319
  }
1380
1320
  return name;
1381
1321
  }
@@ -1385,15 +1325,15 @@ export function toDynHelper(E, t) {
1385
1325
  * value, and fulfill dst with it (scr_dyn_new_promise_adapting's
1386
1326
  * callback; rejections never reach an adapter — the runtime copies them
1387
1327
  * raw). Interned per inner typeKey. */
1388
- export function promiseDynAdapterHelper(E, inner) {
1328
+ function promiseDynAdapterHelper(emitter, inner) {
1389
1329
  const key = typeKey(inner);
1390
- const existing = E.promiseDynAdapters.get(key);
1330
+ const existing = emitter.promiseDynAdapters.get(key);
1391
1331
  if (existing)
1392
1332
  return existing;
1393
- const name = `sc_pda_${E.promiseDynAdapters.size}`;
1394
- E.promiseDynAdapters.set(key, name);
1333
+ const name = `sc_pda_${emitter.promiseDynAdapters.size}`;
1334
+ emitter.promiseDynAdapters.set(key, name);
1395
1335
  const sig = `static void ${name}(ScrPromise *dst, ScrPromise *src)`;
1396
- E.walkerProtos.push(`${sig}; /* dyn-box settle adapter for promise<${key}> */`);
1336
+ emitter.walkerProtos.push(`${sig}; /* dyn-box settle adapter for promise<${key}> */`);
1397
1337
  const d = [`${sig} { /* dyn-box settle adapter for promise<${key}> */`];
1398
1338
  const fulfill = (expr) => ` scr_promise_fulfill_ref(dst, ${expr}, scr_dyn_retain_v, scr_dyn_release_v, NULL);`;
1399
1339
  switch (inner.kind) {
@@ -1423,7 +1363,7 @@ export function promiseDynAdapterHelper(E, inner) {
1423
1363
  // nested promises, handles): extract (+1 via the stored retain),
1424
1364
  // convert through the shared to-dyn spelling, release the extract.
1425
1365
  d.push(` ${cDecl(inner, "pv")} = (${cType(inner).trim()})scr_promise_payload_ref(src);`);
1426
- d.push(` ScrDyn *dv = ${toDynExprC(E, inner, "pv")};`);
1366
+ d.push(` ScrDyn *dv = ${toDynExprC(emitter, inner, "pv")};`);
1427
1367
  if (isRefCounted(inner))
1428
1368
  d.push(` ${releaseCallC(inner, "pv")};`);
1429
1369
  d.push(fulfill(`dv`));
@@ -1431,10 +1371,10 @@ export function promiseDynAdapterHelper(E, inner) {
1431
1371
  }
1432
1372
  }
1433
1373
  d.push(`}`, ``);
1434
- E.walkerDefs.push(...d);
1374
+ emitter.walkerDefs.push(...d);
1435
1375
  return name;
1436
1376
  }
1437
- /* ── the checked-dynamic function boundary (nodes.ts) ─────────────────
1377
+ /* ── the checked-dynamic function boundary (ir.ts) ─────────────────
1438
1378
  * Three interned per-signature helpers:
1439
1379
  *
1440
1380
  * sc_dfk_<n> — the CALL THUNK a dyn-boxed closure carries: validate
@@ -1459,27 +1399,27 @@ export function promiseDynAdapterHelper(E, inner) {
1459
1399
  * result uniformly), funcs box (anonymous — the static name is gone by
1460
1400
  * the time a value flows through an adapter; SEMANTICS.md), everything
1461
1401
  * else rides the toDyn converter. `expr` is BORROWED in every arm. */
1462
- function toDynExprC(E, t, expr) {
1402
+ function toDynExprC(emitter, t, expr) {
1463
1403
  if (t.kind === "dyn")
1464
1404
  return `scr_dyn_retain(${expr})`;
1465
1405
  if (t.kind === "func")
1466
- return `${E.dynFuncBoxHelper(t)}(${expr}, NULL)`;
1406
+ return `${emitter.dynFuncBoxHelper(t)}(${expr}, NULL)`;
1467
1407
  // An island value wraps by reference (scalar-normalizing) — the
1468
1408
  // jsval-returning callback shape of the routed-dispatch lane.
1469
1409
  if (t.kind === "jsval")
1470
1410
  return `scr_dyn_from_jsval(${expr})`;
1471
- return `${E.toDynHelper(t)}(${expr})`;
1411
+ return `${emitter.toDynHelper(t)}(${expr})`;
1472
1412
  }
1473
1413
  /** The call thunk for one closure signature (see the block comment). */
1474
- export function dynFuncThunkHelper(E, t) {
1414
+ function dynFuncThunkHelper(emitter, t) {
1475
1415
  const key = typeKey(t);
1476
- const existing = E.dynFuncThunks.get(key);
1416
+ const existing = emitter.dynFuncThunks.get(key);
1477
1417
  if (existing)
1478
1418
  return existing;
1479
- const name = `sc_dfk_${E.dynFuncThunks.size}`;
1480
- E.dynFuncThunks.set(key, name);
1419
+ const name = `sc_dfk_${emitter.dynFuncThunks.size}`;
1420
+ emitter.dynFuncThunks.set(key, name);
1481
1421
  const sig = `static ScrDyn *${name}(ScrClosure *c, ScrDyn *const *args, size_t argc)`;
1482
- E.walkerProtos.push(`${sig}; /* dyn call thunk for ${key} */`);
1422
+ emitter.walkerProtos.push(`${sig}; /* dyn call thunk for ${key} */`);
1483
1423
  const d = [`${sig} { /* dyn call thunk for ${key} */`];
1484
1424
  if (t.params.length === 0)
1485
1425
  d.push(` (void)args;`);
@@ -1507,7 +1447,7 @@ export function dynFuncThunkHelper(E, t) {
1507
1447
  }
1508
1448
  else {
1509
1449
  d.push(` ScrDynPath pp = { NULL, NULL, ${i} };`);
1510
- d.push(` a${i} = ${E.dynCheckHelper(p)}(ad, &pp);`);
1450
+ d.push(` a${i} = ${emitter.dynCheckHelper(p)}(ad, &pp);`);
1511
1451
  const undo = t.params
1512
1452
  .slice(0, i)
1513
1453
  .flatMap((q, j) => (isRefCounted(q) ? [`${releaseCallC(q, `a${j}`)};`] : []));
@@ -1542,44 +1482,44 @@ export function dynFuncThunkHelper(E, t) {
1542
1482
  else {
1543
1483
  d.push(` ${cDecl(t.ret, "r")} = ${call};`);
1544
1484
  d.push(` if (scr_exc_pending()) return NULL;`);
1545
- d.push(` ScrDyn *out = ${toDynExprC(E, t.ret, "r")};`);
1485
+ d.push(` ScrDyn *out = ${toDynExprC(emitter, t.ret, "r")};`);
1546
1486
  if (isRefCounted(t.ret))
1547
1487
  d.push(` ${releaseCallC(t.ret, "r")};`);
1548
1488
  d.push(` return out;`);
1549
1489
  }
1550
1490
  d.push(`}`, ``);
1551
- E.walkerDefs.push(...d);
1491
+ emitter.walkerDefs.push(...d);
1552
1492
  return name;
1553
1493
  }
1554
1494
  /** The box builder dynFrom emits for one closure signature. */
1555
- export function dynFuncBoxHelper(E, t) {
1495
+ export function dynFuncBoxHelper(emitter, t) {
1556
1496
  const key = typeKey(t);
1557
- const existing = E.dynFuncBoxes.get(key);
1497
+ const existing = emitter.dynFuncBoxes.get(key);
1558
1498
  if (existing)
1559
1499
  return existing;
1560
- const name = `sc_dfb_${E.dynFuncBoxes.size}`;
1561
- E.dynFuncBoxes.set(key, name);
1500
+ const name = `sc_dfb_${emitter.dynFuncBoxes.size}`;
1501
+ emitter.dynFuncBoxes.set(key, name);
1562
1502
  const sig = `static ScrDyn *${name}(ScrClosure *v, const char *fname)`;
1563
- E.walkerProtos.push(`${sig}; /* box ${key} into dyn */`);
1564
- const thunk = dynFuncThunkHelper(E, t);
1503
+ emitter.walkerProtos.push(`${sig}; /* box ${key} into dyn */`);
1504
+ const thunk = dynFuncThunkHelper(emitter, t);
1565
1505
  const sigLit = cStringLiteral(Buffer.from(key, "utf8"));
1566
- E.walkerDefs.push(`${sig} { /* box ${key} into dyn */`, ` return scr_dyn_new_func(scr_closure_retain(v), &${thunk}, ${t.params.length}, ${sigLit}, fname);`, `}`, ``);
1506
+ emitter.walkerDefs.push(`${sig} { /* box ${key} into dyn */`, ` return scr_dyn_new_func(scr_closure_retain(v), &${thunk}, ${t.params.length}, ${sigLit}, fname);`, `}`, ``);
1567
1507
  return name;
1568
1508
  }
1569
1509
  /** The adapter closure body for one TARGET signature: the emitted C
1570
1510
  * function a func-targeted dynCheck wraps a non-identical boxed
1571
1511
  * signature in. caps[0] is an untraced obj-box owning the dyn function
1572
1512
  * value. */
1573
- export function dynFuncAdapterHelper(E, t) {
1513
+ function dynFuncAdapterHelper(emitter, t) {
1574
1514
  const key = typeKey(t);
1575
- const existing = E.dynFuncAdapters.get(key);
1515
+ const existing = emitter.dynFuncAdapters.get(key);
1576
1516
  if (existing)
1577
1517
  return existing;
1578
- const name = `sc_dfa_${E.dynFuncAdapters.size}`;
1579
- E.dynFuncAdapters.set(key, name);
1518
+ const name = `sc_dfa_${emitter.dynFuncAdapters.size}`;
1519
+ emitter.dynFuncAdapters.set(key, name);
1580
1520
  const params = ["ScrClosure *sc_env", ...t.params.map((p, i) => cDecl(p, `a${i}`))].join(", ");
1581
1521
  const sig = `static ${cType(t.ret)}${cType(t.ret).endsWith("*") ? "" : " "}${name}(${params})`;
1582
- E.walkerProtos.push(`${sig}; /* dyn fn adapter to ${key} */`);
1522
+ emitter.walkerProtos.push(`${sig}; /* dyn fn adapter to ${key} */`);
1583
1523
  const dummy = t.ret.kind === "void" ? "" : t.ret.kind === "f64" ? "0" : t.ret.kind === "bool" ? "false" : "NULL";
1584
1524
  const d = [`${sig} { /* dyn fn adapter to ${key} */`];
1585
1525
  d.push(` ScrDyn *sc_fn = (ScrDyn *)scr_box_get_ref(sc_env->caps[0]); /* +1 */`);
@@ -1588,7 +1528,7 @@ export function dynFuncAdapterHelper(E, t) {
1588
1528
  if (t.params.length > 0) {
1589
1529
  d.push(` ScrDyn *sc_args[${t.params.length}];`);
1590
1530
  t.params.forEach((p, i) => {
1591
- d.push(` sc_args[${i}] = ${toDynExprC(E, p, `a${i}`)};`);
1531
+ d.push(` sc_args[${i}] = ${toDynExprC(emitter, p, `a${i}`)};`);
1592
1532
  if (isRefCounted(p))
1593
1533
  d.push(` ${releaseCallC(p, `a${i}`)};`);
1594
1534
  });
@@ -1610,12 +1550,12 @@ export function dynFuncAdapterHelper(E, t) {
1610
1550
  // Validate the dyn result into the target's return type — a lying
1611
1551
  // wrapper throws the catchable TypeError here (path "$"), exactly
1612
1552
  // the dynCheck stance; the dummy result rides the pending unwind.
1613
- d.push(` ${cDecl(t.ret, "out")} = ${E.dynCheckHelper(t.ret)}(sc_r, NULL);`);
1553
+ d.push(` ${cDecl(t.ret, "out")} = ${emitter.dynCheckHelper(t.ret)}(sc_r, NULL);`);
1614
1554
  d.push(` scr_dyn_release(sc_r);`);
1615
1555
  d.push(` return out;`);
1616
1556
  }
1617
1557
  d.push(`}`, ``);
1618
- E.walkerDefs.push(...d);
1558
+ emitter.walkerDefs.push(...d);
1619
1559
  return name;
1620
1560
  }
1621
1561
  /** The emitted dynamic-keyed READ helper for one (shape, result type):
@@ -1627,19 +1567,19 @@ export function dynFuncAdapterHelper(E, t) {
1627
1567
  * arm (T undefined-armed union), or TRAPS with the key text (the array
1628
1568
  * OOB policy — the checker claimed T and no undefined is representable).
1629
1569
  * Borrows both; refcounted results are owned (+1). */
1630
- export function recordKeyGetHelper(E, shapeId, t, overflowOnly = false) {
1570
+ export function recordKeyGetHelper(emitter, shapeId, t, overflowOnly = false) {
1631
1571
  const key = `${shapeId}|${typeKey(t)}${overflowOnly ? "|ovf" : ""}`;
1632
- const existing = E.recordKeyGetFns.get(key);
1572
+ const existing = emitter.recordKeyGetFns.get(key);
1633
1573
  if (existing)
1634
1574
  return existing;
1635
- const shape = E.recordsById.get(shapeId);
1575
+ const shape = emitter.recordsById.get(shapeId);
1636
1576
  if (!shape)
1637
- throw new Error(`emitter bug: keyed read of unknown shape ${shapeId}`);
1638
- const name = `sc_rkg_${E.recordKeyGetFns.size}`;
1639
- E.recordKeyGetFns.set(key, name);
1577
+ throw new InternalCompilerError(`emitter bug: keyed read of unknown shape ${shapeId}`);
1578
+ const name = `sc_rkg_${emitter.recordKeyGetFns.size}`;
1579
+ emitter.recordKeyGetFns.set(key, name);
1640
1580
  const struct = mangleRecordStruct(shapeId);
1641
1581
  const sig = `static ${cType(t)}${cType(t).endsWith("*") ? "" : " "}${name}(${struct} *r, ScrStr *k)`;
1642
- E.walkerProtos.push(`${sig}; /* r[k] on ${shapeId} as ${typeKey(t)} */`);
1582
+ emitter.walkerProtos.push(`${sig}; /* r[k] on ${shapeId} as ${typeKey(t)} */`);
1643
1583
  const d = [`${sig} { /* r[k] on ${shapeId} as ${typeKey(t)} */`];
1644
1584
  // How a value of type `vt` (a field, or the overflow hit) surfaces as T.
1645
1585
  const surface = (vt, expr, owned) => {
@@ -1648,27 +1588,27 @@ export function recordKeyGetHelper(E, shapeId, t, overflowOnly = false) {
1648
1588
  }
1649
1589
  if (t.kind === "dyn") {
1650
1590
  // toDyn borrows — an owned operand would leak; callers pass borrowed.
1651
- return `${E.toDynHelper(vt)}(${expr})`;
1591
+ return `${emitter.toDynHelper(vt)}(${expr})`;
1652
1592
  }
1653
1593
  if (t.kind === "union") {
1654
- const def = E.unionsById.get(t.unionId);
1594
+ const def = emitter.unionsById.get(t.unionId);
1655
1595
  const tag = def?.arms.findIndex((a) => typeEquals(a, vt)) ?? -1;
1656
1596
  if (tag < 0)
1657
- throw new Error(`emitter bug: keyed read arm for ${typeKey(vt)} in ${typeKey(t)}`);
1597
+ throw new InternalCompilerError(`emitter bug: keyed read arm for ${typeKey(vt)} in ${typeKey(t)}`);
1658
1598
  if (vt.kind === "f64")
1659
1599
  return `scr_union_new_f64(${tag}, ${expr})`;
1660
1600
  if (vt.kind === "bool")
1661
1601
  return `scr_union_new_bool(${tag}, ${expr})`;
1662
1602
  const rc = vAdapters(vt);
1663
1603
  const payload = owned ? expr : retainCallC(vt, expr);
1664
- return `scr_union_new_ref(${tag}, ${payload}, &${rc.retain}, &${rc.release}, ${E.traceArgC(vt)})`;
1604
+ return `scr_union_new_ref(${tag}, ${payload}, &${rc.retain}, &${rc.release}, ${emitter.traceArgC(vt)})`;
1665
1605
  }
1666
- throw new Error(`emitter bug: keyed read cannot surface ${typeKey(vt)} as ${typeKey(t)}`);
1606
+ throw new InternalCompilerError(`emitter bug: keyed read cannot surface ${typeKey(vt)} as ${typeKey(t)}`);
1667
1607
  };
1668
1608
  // overflowOnly (a literal key naming no declared field): the declared
1669
1609
  // switch can never hit — only the overflow answers.
1670
1610
  for (const f of overflowOnly ? [] : shape.fields) {
1671
- const lit = E.internLiteral(f.name);
1611
+ const lit = emitter.internLiteral(f.name);
1672
1612
  d.push(` if (scr_str_eq(k, (ScrStr *)&${lit})) { /* ${f.name} */`);
1673
1613
  d.push(` return ${surface(f.type, `r->${mangleField(f.name)}`, false)};`);
1674
1614
  d.push(` }`);
@@ -1693,7 +1633,7 @@ export function recordKeyGetHelper(E, shapeId, t, overflowOnly = false) {
1693
1633
  d.push(` return ${surface(iv, "hit", true)};`);
1694
1634
  }
1695
1635
  else {
1696
- throw new Error(`emitter bug: keyed read overflow ${typeKey(iv)} as ${typeKey(t)}`);
1636
+ throw new InternalCompilerError(`emitter bug: keyed read overflow ${typeKey(iv)} as ${typeKey(t)}`);
1697
1637
  }
1698
1638
  d.push(` }`);
1699
1639
  }
@@ -1702,17 +1642,17 @@ export function recordKeyGetHelper(E, shapeId, t, overflowOnly = false) {
1702
1642
  if (t.kind === "dyn") {
1703
1643
  d.push(` return scr_dyn_retain(scr_dyn_undefined());`);
1704
1644
  }
1705
- else if (t.kind === "union" && E.undefinedArmTag(t) >= 0) {
1706
- d.push(` return ${E.unitInstanceRef(t.unionId, E.undefinedArmTag(t))};`);
1645
+ else if (t.kind === "union" && undefinedArmTag(t, emitter.unionsById) >= 0) {
1646
+ d.push(` return ${emitter.unitInstanceRef(t.unionId, undefinedArmTag(t, emitter.unionsById))};`);
1707
1647
  }
1708
1648
  else {
1709
1649
  // JS would answer undefined; T has no way to say it (the checker
1710
1650
  // claimed T without noUncheckedIndexedAccess) — trap like an array
1711
1651
  // OOB read instead of corrupting a typed slot (SEMANTICS.md).
1712
- d.push(` scr_trap_fmt("scriptc: TypeError: record has no key '%.*s' (typed '${E.dynDesc(t)}' — no undefined is representable)\\n", (int)k->len, k->data);`);
1652
+ d.push(` scr_trap_fmt("scriptc: TypeError: record has no key '%.*s' (typed '${dynDesc(t, emitter.recordsById, emitter.unionsById)}' — no undefined is representable)\\n", (int)k->len, k->data);`);
1713
1653
  }
1714
1654
  d.push(`}`, ``);
1715
- E.walkerDefs.push(...d);
1655
+ emitter.walkerDefs.push(...d);
1716
1656
  return name;
1717
1657
  }
1718
1658
  /** The emitted dynamic-keyed WRITE helper for one index-signature shape:
@@ -1723,32 +1663,32 @@ export function recordKeyGetHelper(E, shapeId, t, overflowOnly = false) {
1723
1663
  * anything, the documented divergence; typed values store directly),
1724
1664
  * an undeclared key inserts/replaces in the overflow map. Borrows r and
1725
1665
  * k; OWNS v (+1 moves in — released on the validation-failure path). */
1726
- export function recordKeySetHelper(E, shapeId) {
1727
- const existing = E.recordKeySetFns.get(shapeId);
1666
+ export function recordKeySetHelper(emitter, shapeId) {
1667
+ const existing = emitter.recordKeySetFns.get(shapeId);
1728
1668
  if (existing)
1729
1669
  return existing;
1730
- const shape = E.recordsById.get(shapeId);
1670
+ const shape = emitter.recordsById.get(shapeId);
1731
1671
  // Signature-free shapes dispatch over their (one-typed) declared
1732
1672
  // fields and TRAP on a miss (scr_record_key_miss — JS would add the
1733
1673
  // property, which a monomorphic struct cannot); overflow shapes keep
1734
1674
  // the map insert tail.
1735
1675
  const iv = shape?.indexValue ?? shape?.fields[0]?.type;
1736
1676
  if (!shape || !iv)
1737
- throw new Error(`emitter bug: keyed write on field-free non-overflow shape ${shapeId}`);
1738
- const name = `sc_rks_${E.recordKeySetFns.size}`;
1739
- E.recordKeySetFns.set(shapeId, name);
1677
+ throw new InternalCompilerError(`emitter bug: keyed write on field-free non-overflow shape ${shapeId}`);
1678
+ const name = `sc_rks_${emitter.recordKeySetFns.size}`;
1679
+ emitter.recordKeySetFns.set(shapeId, name);
1740
1680
  const struct = mangleRecordStruct(shapeId);
1741
1681
  const sig = `static void ${name}(${struct} *r, ScrStr *k, ${cDecl(iv, "v")})`;
1742
- E.walkerProtos.push(`${sig}; /* r[k] = v on ${shapeId} */`);
1682
+ emitter.walkerProtos.push(`${sig}; /* r[k] = v on ${shapeId} */`);
1743
1683
  const d = [`${sig} { /* r[k] = v on ${shapeId} */`];
1744
1684
  for (const f of shape.fields) {
1745
- const lit = E.internLiteral(f.name);
1685
+ const lit = emitter.internLiteral(f.name);
1746
1686
  const member = `r->${mangleField(f.name)}`;
1747
1687
  d.push(` if (scr_str_eq(k, (ScrStr *)&${lit})) { /* ${f.name} */`);
1748
1688
  if (iv.kind === "dyn" && shape.indexValue) {
1749
1689
  const keyLit = cStringLiteral(Buffer.from(f.name, "utf8"));
1750
1690
  d.push(` ScrDynPath p = { NULL, ${keyLit}, 0 };`);
1751
- d.push(` ${cDecl(f.type, "nv")} = ${E.dynCheckHelper(f.type)}(v, &p);`);
1691
+ d.push(` ${cDecl(f.type, "nv")} = ${emitter.dynCheckHelper(f.type)}(v, &p);`);
1752
1692
  d.push(` scr_dyn_release(v);`);
1753
1693
  d.push(` if (scr_exc_pending()) return; /* mismatched write: TypeError, field untouched */`);
1754
1694
  d.push(` ${isRefCounted(f.type) ? `if (${member}) ${releaseCallC(f.type, member)};` : `(void)0;`}`);
@@ -1782,7 +1722,7 @@ export function recordKeySetHelper(E, shapeId) {
1782
1722
  }
1783
1723
  }
1784
1724
  d.push(`}`, ``);
1785
- E.walkerDefs.push(...d);
1725
+ emitter.walkerDefs.push(...d);
1786
1726
  return name;
1787
1727
  }
1788
- //# sourceMappingURL=emit-walkers.js.map
1728
+ //# sourceMappingURL=walkers.js.map