@scriptc/compiler 0.0.35 → 0.1.1

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