@geastack/compiler 1.0.15

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 (966) hide show
  1. package/LICENSE +202 -0
  2. package/README.md +149 -0
  3. package/dist/cli-analyze.d.ts +1 -0
  4. package/dist/cli-analyze.js +61 -0
  5. package/dist/cli-coverage.d.ts +1 -0
  6. package/dist/cli-coverage.js +329 -0
  7. package/dist/cli-emit.d.ts +10 -0
  8. package/dist/cli-emit.js +398 -0
  9. package/dist/cli-module-graph.d.ts +18 -0
  10. package/dist/cli-module-graph.js +123 -0
  11. package/dist/cli-package-source.d.ts +5 -0
  12. package/dist/cli-package-source.js +116 -0
  13. package/dist/cli-project.d.ts +2 -0
  14. package/dist/cli-project.js +60 -0
  15. package/dist/cli.d.ts +2 -0
  16. package/dist/cli.js +199 -0
  17. package/dist/compiler.d.ts +228 -0
  18. package/dist/compiler.js +1029 -0
  19. package/dist/conversion/algebra.d.ts +218 -0
  20. package/dist/conversion/algebra.js +155 -0
  21. package/dist/conversion/build.d.ts +67 -0
  22. package/dist/conversion/build.js +1378 -0
  23. package/dist/conversion/derive.d.ts +37 -0
  24. package/dist/conversion/derive.js +260 -0
  25. package/dist/conversion/graph-validation.d.ts +8 -0
  26. package/dist/conversion/graph-validation.js +97 -0
  27. package/dist/conversion/native-callable-adapter.d.ts +13 -0
  28. package/dist/conversion/native-callable-adapter.js +53 -0
  29. package/dist/conversion/native-class-reference.d.ts +12 -0
  30. package/dist/conversion/native-class-reference.js +39 -0
  31. package/dist/conversion/native-payload-transport.d.ts +25 -0
  32. package/dist/conversion/native-payload-transport.js +33 -0
  33. package/dist/conversion/native-selection.d.ts +49 -0
  34. package/dist/conversion/native-selection.js +135 -0
  35. package/dist/conversion/native-sum.d.ts +42 -0
  36. package/dist/conversion/native-sum.js +115 -0
  37. package/dist/conversion/nodes.d.ts +55 -0
  38. package/dist/conversion/nodes.js +91 -0
  39. package/dist/conversion/operand-view.d.ts +14 -0
  40. package/dist/conversion/operand-view.js +20 -0
  41. package/dist/conversion/record-view.d.ts +157 -0
  42. package/dist/conversion/record-view.js +273 -0
  43. package/dist/conversion/registry.d.ts +217 -0
  44. package/dist/conversion/registry.js +1 -0
  45. package/dist/diagnostics/model.d.ts +76 -0
  46. package/dist/diagnostics/model.js +60 -0
  47. package/dist/diagnostics/sweep.d.ts +31 -0
  48. package/dist/diagnostics/sweep.js +112 -0
  49. package/dist/identity/ids.d.ts +179 -0
  50. package/dist/identity/ids.js +212 -0
  51. package/dist/ir/absent-class-arm.d.ts +48 -0
  52. package/dist/ir/absent-class-arm.js +157 -0
  53. package/dist/ir/borrow-effects.d.ts +23 -0
  54. package/dist/ir/borrow-effects.js +151 -0
  55. package/dist/ir/borrowed-call-arguments.d.ts +40 -0
  56. package/dist/ir/borrowed-call-arguments.js +117 -0
  57. package/dist/ir/build.d.ts +168 -0
  58. package/dist/ir/build.js +459 -0
  59. package/dist/ir/call-dispatch.d.ts +38 -0
  60. package/dist/ir/call-dispatch.js +502 -0
  61. package/dist/ir/call-entry.d.ts +142 -0
  62. package/dist/ir/call-entry.js +386 -0
  63. package/dist/ir/callable-class-flow.d.ts +27 -0
  64. package/dist/ir/callable-class-flow.js +1386 -0
  65. package/dist/ir/callable-field-slots.d.ts +22 -0
  66. package/dist/ir/callable-field-slots.js +166 -0
  67. package/dist/ir/callable-identity-demand.d.ts +52 -0
  68. package/dist/ir/callable-identity-demand.js +460 -0
  69. package/dist/ir/callable-member-candidates.d.ts +9 -0
  70. package/dist/ir/callable-member-candidates.js +39 -0
  71. package/dist/ir/callable-records.d.ts +21 -0
  72. package/dist/ir/callable-records.js +411 -0
  73. package/dist/ir/captures.d.ts +26 -0
  74. package/dist/ir/captures.js +335 -0
  75. package/dist/ir/certificate.d.ts +45 -0
  76. package/dist/ir/certificate.js +47 -0
  77. package/dist/ir/certify/carrier-keys.d.ts +73 -0
  78. package/dist/ir/certify/carrier-keys.js +221 -0
  79. package/dist/ir/certify/function-source.d.ts +4 -0
  80. package/dist/ir/certify/function-source.js +28 -0
  81. package/dist/ir/certify/has-property-key.d.ts +88 -0
  82. package/dist/ir/certify/has-property-key.js +116 -0
  83. package/dist/ir/certify/instanceof-key.d.ts +24 -0
  84. package/dist/ir/certify/instanceof-key.js +35 -0
  85. package/dist/ir/certify/property-access-keys.d.ts +172 -0
  86. package/dist/ir/certify/property-access-keys.js +291 -0
  87. package/dist/ir/certify/property-access.d.ts +3 -0
  88. package/dist/ir/certify/property-access.js +597 -0
  89. package/dist/ir/certify/runtime-helper.d.ts +3 -0
  90. package/dist/ir/certify/runtime-helper.js +326 -0
  91. package/dist/ir/certify/typeof-operand.d.ts +14 -0
  92. package/dist/ir/certify/typeof-operand.js +16 -0
  93. package/dist/ir/certify.d.ts +123 -0
  94. package/dist/ir/certify.js +481 -0
  95. package/dist/ir/class-evaluation.d.ts +26 -0
  96. package/dist/ir/class-evaluation.js +50 -0
  97. package/dist/ir/class-static-fields.d.ts +60 -0
  98. package/dist/ir/class-static-fields.js +108 -0
  99. package/dist/ir/construct-entry.d.ts +26 -0
  100. package/dist/ir/construct-entry.js +117 -0
  101. package/dist/ir/dead-values.d.ts +90 -0
  102. package/dist/ir/dead-values.js +184 -0
  103. package/dist/ir/deferral.d.ts +99 -0
  104. package/dist/ir/deferral.js +409 -0
  105. package/dist/ir/dense-loops.d.ts +230 -0
  106. package/dist/ir/dense-loops.js +697 -0
  107. package/dist/ir/dominance.d.ts +82 -0
  108. package/dist/ir/dominance.js +268 -0
  109. package/dist/ir/emission-representations.d.ts +71 -0
  110. package/dist/ir/emission-representations.js +350 -0
  111. package/dist/ir/facts.d.ts +218 -0
  112. package/dist/ir/facts.js +181 -0
  113. package/dist/ir/fixed-data-definition.d.ts +19 -0
  114. package/dist/ir/fixed-data-definition.js +49 -0
  115. package/dist/ir/generator-split.d.ts +38 -0
  116. package/dist/ir/generator-split.js +329 -0
  117. package/dist/ir/hoist.d.ts +55 -0
  118. package/dist/ir/hoist.js +375 -0
  119. package/dist/ir/instantiation.d.ts +61 -0
  120. package/dist/ir/instantiation.js +137 -0
  121. package/dist/ir/integer-storage.d.ts +170 -0
  122. package/dist/ir/integer-storage.js +822 -0
  123. package/dist/ir/integers.d.ts +161 -0
  124. package/dist/ir/integers.js +539 -0
  125. package/dist/ir/integrity-restrictions.d.ts +50 -0
  126. package/dist/ir/integrity-restrictions.js +118 -0
  127. package/dist/ir/local-iterators.d.ts +4 -0
  128. package/dist/ir/local-iterators.js +27 -0
  129. package/dist/ir/lower-allocation.d.ts +4 -0
  130. package/dist/ir/lower-allocation.js +325 -0
  131. package/dist/ir/lower-completion.d.ts +15 -0
  132. package/dist/ir/lower-completion.js +25 -0
  133. package/dist/ir/lower-destructuring.d.ts +5 -0
  134. package/dist/ir/lower-destructuring.js +693 -0
  135. package/dist/ir/lower-element.d.ts +29 -0
  136. package/dist/ir/lower-element.js +111 -0
  137. package/dist/ir/lower-exceptions.d.ts +47 -0
  138. package/dist/ir/lower-exceptions.js +92 -0
  139. package/dist/ir/lower-flow.d.ts +137 -0
  140. package/dist/ir/lower-flow.js +600 -0
  141. package/dist/ir/lower-graph.d.ts +218 -0
  142. package/dist/ir/lower-graph.js +687 -0
  143. package/dist/ir/lower-invocation.d.ts +4 -0
  144. package/dist/ir/lower-invocation.js +514 -0
  145. package/dist/ir/lower-narrow.d.ts +53 -0
  146. package/dist/ir/lower-narrow.js +320 -0
  147. package/dist/ir/lower-operands.d.ts +272 -0
  148. package/dist/ir/lower-operands.js +461 -0
  149. package/dist/ir/lower-property.d.ts +21 -0
  150. package/dist/ir/lower-property.js +132 -0
  151. package/dist/ir/lower-protocol.d.ts +11 -0
  152. package/dist/ir/lower-protocol.js +118 -0
  153. package/dist/ir/lower-short-circuit.d.ts +41 -0
  154. package/dist/ir/lower-short-circuit.js +63 -0
  155. package/dist/ir/lower.d.ts +82 -0
  156. package/dist/ir/lower.js +1346 -0
  157. package/dist/ir/model.d.ts +1474 -0
  158. package/dist/ir/model.js +6 -0
  159. package/dist/ir/native-absent-property.d.ts +3 -0
  160. package/dist/ir/native-absent-property.js +13 -0
  161. package/dist/ir/native-array-transport.d.ts +7 -0
  162. package/dist/ir/native-array-transport.js +46 -0
  163. package/dist/ir/native-callable-bind.d.ts +9 -0
  164. package/dist/ir/native-callable-bind.js +30 -0
  165. package/dist/ir/native-carrier-predicate.d.ts +34 -0
  166. package/dist/ir/native-carrier-predicate.js +49 -0
  167. package/dist/ir/native-class-accessor.d.ts +18 -0
  168. package/dist/ir/native-class-accessor.js +52 -0
  169. package/dist/ir/native-class-construction.d.ts +16 -0
  170. package/dist/ir/native-class-construction.js +71 -0
  171. package/dist/ir/native-class-initialization.d.ts +15 -0
  172. package/dist/ir/native-class-initialization.js +56 -0
  173. package/dist/ir/native-class-origins.d.ts +13 -0
  174. package/dist/ir/native-class-origins.js +237 -0
  175. package/dist/ir/native-dictionary-transport.d.ts +6 -0
  176. package/dist/ir/native-dictionary-transport.js +37 -0
  177. package/dist/ir/native-enumeration.d.ts +14 -0
  178. package/dist/ir/native-enumeration.js +26 -0
  179. package/dist/ir/native-equality.d.ts +10 -0
  180. package/dist/ir/native-equality.js +18 -0
  181. package/dist/ir/native-field-owner.d.ts +37 -0
  182. package/dist/ir/native-field-owner.js +183 -0
  183. package/dist/ir/native-fixed-layout.d.ts +41 -0
  184. package/dist/ir/native-fixed-layout.js +232 -0
  185. package/dist/ir/native-host-construction.d.ts +53 -0
  186. package/dist/ir/native-host-construction.js +62 -0
  187. package/dist/ir/native-key-query.d.ts +4 -0
  188. package/dist/ir/native-key-query.js +38 -0
  189. package/dist/ir/native-merge-transport.d.ts +25 -0
  190. package/dist/ir/native-merge-transport.js +71 -0
  191. package/dist/ir/native-record-index-transport.d.ts +11 -0
  192. package/dist/ir/native-record-index-transport.js +34 -0
  193. package/dist/ir/native-record-index.d.ts +12 -0
  194. package/dist/ir/native-record-index.js +27 -0
  195. package/dist/ir/native-reflect-field.d.ts +5 -0
  196. package/dist/ir/native-reflect-field.js +33 -0
  197. package/dist/ir/native-sequence-transport.d.ts +7 -0
  198. package/dist/ir/native-sequence-transport.js +53 -0
  199. package/dist/ir/numeric-intrinsics.d.ts +13 -0
  200. package/dist/ir/numeric-intrinsics.js +57 -0
  201. package/dist/ir/object-value-conversions.d.ts +20 -0
  202. package/dist/ir/object-value-conversions.js +50 -0
  203. package/dist/ir/physical-class-reflection.d.ts +9 -0
  204. package/dist/ir/physical-class-reflection.js +57 -0
  205. package/dist/ir/presence-proof.d.ts +42 -0
  206. package/dist/ir/presence-proof.js +490 -0
  207. package/dist/ir/program-facts.d.ts +106 -0
  208. package/dist/ir/program-facts.js +319 -0
  209. package/dist/ir/proven-branches.d.ts +16 -0
  210. package/dist/ir/proven-branches.js +219 -0
  211. package/dist/ir/queries.d.ts +41 -0
  212. package/dist/ir/queries.js +213 -0
  213. package/dist/ir/reflection-demand.d.ts +64 -0
  214. package/dist/ir/reflection-demand.js +1394 -0
  215. package/dist/ir/refusal.d.ts +43 -0
  216. package/dist/ir/refusal.js +28 -0
  217. package/dist/ir/shake.d.ts +37 -0
  218. package/dist/ir/shake.js +1078 -0
  219. package/dist/ir/static-callables.d.ts +11 -0
  220. package/dist/ir/static-callables.js +163 -0
  221. package/dist/ir/string-layout-reuse.d.ts +13 -0
  222. package/dist/ir/string-layout-reuse.js +39 -0
  223. package/dist/ir/string-length-reuse.d.ts +8 -0
  224. package/dist/ir/string-length-reuse.js +47 -0
  225. package/dist/ir/transfer.d.ts +78 -0
  226. package/dist/ir/transfer.js +270 -0
  227. package/dist/ir/type-query-results.d.ts +25 -0
  228. package/dist/ir/type-query-results.js +96 -0
  229. package/dist/ir/typed-property-access.d.ts +100 -0
  230. package/dist/ir/typed-property-access.js +161 -0
  231. package/dist/ir/verify.d.ts +19 -0
  232. package/dist/ir/verify.js +355 -0
  233. package/dist/plugins/apple/constructors.d.ts +112 -0
  234. package/dist/plugins/apple/constructors.js +217 -0
  235. package/dist/plugins/apple/host.d.ts +181 -0
  236. package/dist/plugins/apple/host.js +262 -0
  237. package/dist/plugins/apple/jsx.d.ts +2 -0
  238. package/dist/plugins/apple/jsx.js +293 -0
  239. package/dist/plugins/apple/members.d.ts +16 -0
  240. package/dist/plugins/apple/members.js +190 -0
  241. package/dist/plugins/apple/plugin.d.ts +2 -0
  242. package/dist/plugins/apple/plugin.js +156 -0
  243. package/dist/plugins/gea/component-classes.d.ts +25 -0
  244. package/dist/plugins/gea/component-classes.js +162 -0
  245. package/dist/plugins/gea/component-inline.d.ts +13 -0
  246. package/dist/plugins/gea/component-inline.js +532 -0
  247. package/dist/plugins/gea/constructors.d.ts +23 -0
  248. package/dist/plugins/gea/constructors.js +100 -0
  249. package/dist/plugins/gea/contract.d.ts +150 -0
  250. package/dist/plugins/gea/contract.js +195 -0
  251. package/dist/plugins/gea/element-ref.d.ts +31 -0
  252. package/dist/plugins/gea/element-ref.js +45 -0
  253. package/dist/plugins/gea/host.d.ts +520 -0
  254. package/dist/plugins/gea/host.js +762 -0
  255. package/dist/plugins/gea/lower.d.ts +6 -0
  256. package/dist/plugins/gea/lower.js +195 -0
  257. package/dist/plugins/gea/members.d.ts +22 -0
  258. package/dist/plugins/gea/members.js +221 -0
  259. package/dist/plugins/gea/plugin.d.ts +22 -0
  260. package/dist/plugins/gea/plugin.js +307 -0
  261. package/dist/plugins/gea/prelude.d.ts +78 -0
  262. package/dist/plugins/gea/prelude.js +153 -0
  263. package/dist/plugins/gea/producer.d.ts +5 -0
  264. package/dist/plugins/gea/producer.js +52 -0
  265. package/dist/plugins/gea/reactive-slots.d.ts +49 -0
  266. package/dist/plugins/gea/reactive-slots.js +578 -0
  267. package/dist/plugins/gea/render-bridge.d.ts +6 -0
  268. package/dist/plugins/gea/render-bridge.js +281 -0
  269. package/dist/plugins/gea/slots.d.ts +15 -0
  270. package/dist/plugins/gea/slots.js +36 -0
  271. package/dist/plugins/gea/template-analysis.d.ts +151 -0
  272. package/dist/plugins/gea/template-analysis.js +346 -0
  273. package/dist/plugins/gea/user-agent-styles.d.ts +9 -0
  274. package/dist/plugins/gea/user-agent-styles.js +94 -0
  275. package/dist/plugins/installed.d.ts +19 -0
  276. package/dist/plugins/installed.js +21 -0
  277. package/dist/plugins/load.d.ts +7 -0
  278. package/dist/plugins/load.js +207 -0
  279. package/dist/plugins/model.d.ts +735 -0
  280. package/dist/plugins/model.js +47 -0
  281. package/dist/plugins/webgl/host.d.ts +77 -0
  282. package/dist/plugins/webgl/host.js +162 -0
  283. package/dist/plugins/webgl/plugin.d.ts +40 -0
  284. package/dist/plugins/webgl/plugin.js +99 -0
  285. package/dist/preflight/obligations.d.ts +206 -0
  286. package/dist/preflight/obligations.js +36 -0
  287. package/dist/preflight/report.d.ts +20 -0
  288. package/dist/preflight/report.js +61 -0
  289. package/dist/preflight/run.d.ts +39 -0
  290. package/dist/preflight/run.js +403 -0
  291. package/dist/project-preparation.d.ts +33 -0
  292. package/dist/project-preparation.js +314 -0
  293. package/dist/projection/abi.d.ts +82 -0
  294. package/dist/projection/abi.js +349 -0
  295. package/dist/projection/apply-arguments.d.ts +12 -0
  296. package/dist/projection/apply-arguments.js +20 -0
  297. package/dist/projection/bindings.d.ts +250 -0
  298. package/dist/projection/bindings.js +340 -0
  299. package/dist/projection/callee.d.ts +196 -0
  300. package/dist/projection/callee.js +444 -0
  301. package/dist/projection/class-property-presence.d.ts +28 -0
  302. package/dist/projection/class-property-presence.js +58 -0
  303. package/dist/projection/class-prototype.d.ts +5 -0
  304. package/dist/projection/class-prototype.js +23 -0
  305. package/dist/projection/class-storage.d.ts +26 -0
  306. package/dist/projection/class-storage.js +236 -0
  307. package/dist/projection/classes.d.ts +283 -0
  308. package/dist/projection/classes.js +944 -0
  309. package/dist/projection/coercions.d.ts +20 -0
  310. package/dist/projection/coercions.js +33 -0
  311. package/dist/projection/dispatch.d.ts +167 -0
  312. package/dist/projection/dispatch.js +379 -0
  313. package/dist/projection/fields.d.ts +123 -0
  314. package/dist/projection/fields.js +383 -0
  315. package/dist/projection/instance-test.d.ts +78 -0
  316. package/dist/projection/instance-test.js +156 -0
  317. package/dist/projection/slots.d.ts +146 -0
  318. package/dist/projection/slots.js +663 -0
  319. package/dist/projection/synthesized-abi.d.ts +61 -0
  320. package/dist/projection/synthesized-abi.js +94 -0
  321. package/dist/representation/array-index.d.ts +14 -0
  322. package/dist/representation/array-index.js +17 -0
  323. package/dist/representation/callable-object.d.ts +3 -0
  324. package/dist/representation/callable-object.js +6 -0
  325. package/dist/representation/collections.d.ts +84 -0
  326. package/dist/representation/collections.js +139 -0
  327. package/dist/representation/derive.d.ts +159 -0
  328. package/dist/representation/derive.js +2546 -0
  329. package/dist/representation/difference.d.ts +30 -0
  330. package/dist/representation/difference.js +240 -0
  331. package/dist/representation/field-descriptor-policy.d.ts +19 -0
  332. package/dist/representation/field-descriptor-policy.js +39 -0
  333. package/dist/representation/function-constructor.d.ts +13 -0
  334. package/dist/representation/function-constructor.js +9 -0
  335. package/dist/representation/host-abi.d.ts +32 -0
  336. package/dist/representation/host-abi.js +97 -0
  337. package/dist/representation/host-templates.d.ts +67 -0
  338. package/dist/representation/host-templates.js +94 -0
  339. package/dist/representation/intersection.d.ts +84 -0
  340. package/dist/representation/intersection.js +149 -0
  341. package/dist/representation/literal-destination.d.ts +43 -0
  342. package/dist/representation/literal-destination.js +133 -0
  343. package/dist/representation/merge.d.ts +18 -0
  344. package/dist/representation/merge.js +83 -0
  345. package/dist/representation/model.d.ts +1160 -0
  346. package/dist/representation/model.js +1019 -0
  347. package/dist/representation/numeric-index.d.ts +13 -0
  348. package/dist/representation/numeric-index.js +29 -0
  349. package/dist/representation/object-shape.d.ts +109 -0
  350. package/dist/representation/object-shape.js +123 -0
  351. package/dist/representation/optional.d.ts +12 -0
  352. package/dist/representation/optional.js +87 -0
  353. package/dist/representation/plan.d.ts +60 -0
  354. package/dist/representation/plan.js +78 -0
  355. package/dist/representation/policies.d.ts +589 -0
  356. package/dist/representation/policies.js +107 -0
  357. package/dist/representation/primitive-domain.d.ts +1 -0
  358. package/dist/representation/primitive-domain.js +1 -0
  359. package/dist/representation/primitives.d.ts +44 -0
  360. package/dist/representation/primitives.js +78 -0
  361. package/dist/representation/publish.d.ts +49 -0
  362. package/dist/representation/publish.js +648 -0
  363. package/dist/representation/record-fields.d.ts +96 -0
  364. package/dist/representation/record-fields.js +116 -0
  365. package/dist/representation/template-object.d.ts +11 -0
  366. package/dist/representation/template-object.js +26 -0
  367. package/dist/representation/union.d.ts +30 -0
  368. package/dist/representation/union.js +324 -0
  369. package/dist/representation/value-records.d.ts +3 -0
  370. package/dist/representation/value-records.js +307 -0
  371. package/dist/representation/verify.d.ts +17 -0
  372. package/dist/representation/verify.js +221 -0
  373. package/dist/semantics/alias-this-field-declaration-transform.d.ts +4 -0
  374. package/dist/semantics/alias-this-field-declaration-transform.js +207 -0
  375. package/dist/semantics/ambient-type-realization-transform.d.ts +62 -0
  376. package/dist/semantics/ambient-type-realization-transform.js +168 -0
  377. package/dist/semantics/ambient.d.ts +24 -0
  378. package/dist/semantics/ambient.js +119 -0
  379. package/dist/semantics/borrowed-builtin-call-bind-source-transform.d.ts +4 -0
  380. package/dist/semantics/borrowed-builtin-call-bind-source-transform.js +341 -0
  381. package/dist/semantics/callable-origins.d.ts +46 -0
  382. package/dist/semantics/callable-origins.js +354 -0
  383. package/dist/semantics/class-alias.d.ts +7 -0
  384. package/dist/semantics/class-alias.js +37 -0
  385. package/dist/semantics/class-heritage.d.ts +34 -0
  386. package/dist/semantics/class-heritage.js +104 -0
  387. package/dist/semantics/commonjs-wrapper.d.ts +69 -0
  388. package/dist/semantics/commonjs-wrapper.js +231 -0
  389. package/dist/semantics/constructor-slot-subclasses.d.ts +28 -0
  390. package/dist/semantics/constructor-slot-subclasses.js +112 -0
  391. package/dist/semantics/declaration-overlay-transform.d.ts +35 -0
  392. package/dist/semantics/declaration-overlay-transform.js +2157 -0
  393. package/dist/semantics/define-property-source-transform.d.ts +4 -0
  394. package/dist/semantics/define-property-source-transform.js +437 -0
  395. package/dist/semantics/diagnostic-source-preparation.d.ts +24 -0
  396. package/dist/semantics/diagnostic-source-preparation.js +82 -0
  397. package/dist/semantics/documentation-ranges.d.ts +22 -0
  398. package/dist/semantics/documentation-ranges.js +36 -0
  399. package/dist/semantics/dynamic-fallback.d.ts +86 -0
  400. package/dist/semantics/dynamic-fallback.js +249 -0
  401. package/dist/semantics/frontend-timing.d.ts +6 -0
  402. package/dist/semantics/frontend-timing.js +35 -0
  403. package/dist/semantics/frontend.d.ts +504 -0
  404. package/dist/semantics/frontend.js +1157 -0
  405. package/dist/semantics/host-declaration-provenance.d.ts +11 -0
  406. package/dist/semantics/host-declaration-provenance.js +18 -0
  407. package/dist/semantics/host-methods.d.ts +24 -0
  408. package/dist/semantics/host-methods.js +74 -0
  409. package/dist/semantics/host-protocols.d.ts +429 -0
  410. package/dist/semantics/host-protocols.js +1501 -0
  411. package/dist/semantics/inherited-accessor.d.ts +7 -0
  412. package/dist/semantics/inherited-accessor.js +48 -0
  413. package/dist/semantics/interface-families.d.ts +70 -0
  414. package/dist/semantics/interface-families.js +180 -0
  415. package/dist/semantics/interface-implementors.d.ts +53 -0
  416. package/dist/semantics/interface-implementors.js +87 -0
  417. package/dist/semantics/jsdoc-namepath-transform.d.ts +4 -0
  418. package/dist/semantics/jsdoc-namepath-transform.js +85 -0
  419. package/dist/semantics/model/coverage.d.ts +68 -0
  420. package/dist/semantics/model/coverage.js +73 -0
  421. package/dist/semantics/model/edges.d.ts +103 -0
  422. package/dist/semantics/model/edges.js +20 -0
  423. package/dist/semantics/model/graph.d.ts +55 -0
  424. package/dist/semantics/model/graph.js +129 -0
  425. package/dist/semantics/model/operands.d.ts +159 -0
  426. package/dist/semantics/model/operands.js +26 -0
  427. package/dist/semantics/model/operations.d.ts +496 -0
  428. package/dist/semantics/model/operations.js +2 -0
  429. package/dist/semantics/model/primitive-domain.d.ts +26 -0
  430. package/dist/semantics/model/primitive-domain.js +38 -0
  431. package/dist/semantics/model/selected-signature.d.ts +261 -0
  432. package/dist/semantics/model/selected-signature.js +55 -0
  433. package/dist/semantics/model/structural-type-table.d.ts +93 -0
  434. package/dist/semantics/model/structural-type-table.js +237 -0
  435. package/dist/semantics/model/structural-types.d.ts +367 -0
  436. package/dist/semantics/model/structural-types.js +200 -0
  437. package/dist/semantics/module-resolution.d.ts +23 -0
  438. package/dist/semantics/module-resolution.js +227 -0
  439. package/dist/semantics/new-callee-class-tag-source-transform.d.ts +4 -0
  440. package/dist/semantics/new-callee-class-tag-source-transform.js +64 -0
  441. package/dist/semantics/node-project.d.ts +13 -0
  442. package/dist/semantics/node-project.js +107 -0
  443. package/dist/semantics/node-source-hooks.d.ts +1 -0
  444. package/dist/semantics/node-source-hooks.js +63 -0
  445. package/dist/semantics/normalize/absent-globals.d.ts +143 -0
  446. package/dist/semantics/normalize/absent-globals.js +191 -0
  447. package/dist/semantics/normalize/arguments-objects.d.ts +43 -0
  448. package/dist/semantics/normalize/arguments-objects.js +60 -0
  449. package/dist/semantics/normalize/asserted-arm-absence.d.ts +28 -0
  450. package/dist/semantics/normalize/asserted-arm-absence.js +61 -0
  451. package/dist/semantics/normalize/assignment-patterns.d.ts +70 -0
  452. package/dist/semantics/normalize/assignment-patterns.js +147 -0
  453. package/dist/semantics/normalize/bag-absence.d.ts +8 -0
  454. package/dist/semantics/normalize/bag-absence.js +42 -0
  455. package/dist/semantics/normalize/binding-fixpoint.d.ts +36 -0
  456. package/dist/semantics/normalize/binding-fixpoint.js +140 -0
  457. package/dist/semantics/normalize/callback-parameter-contracts.d.ts +16 -0
  458. package/dist/semantics/normalize/callback-parameter-contracts.js +91 -0
  459. package/dist/semantics/normalize/cells/agreement.d.ts +46 -0
  460. package/dist/semantics/normalize/cells/agreement.js +34 -0
  461. package/dist/semantics/normalize/cells/candidates.d.ts +17 -0
  462. package/dist/semantics/normalize/cells/candidates.js +35 -0
  463. package/dist/semantics/normalize/cells/facts.d.ts +19 -0
  464. package/dist/semantics/normalize/cells/facts.js +90 -0
  465. package/dist/semantics/normalize/cells/index.d.ts +10 -0
  466. package/dist/semantics/normalize/cells/index.js +6 -0
  467. package/dist/semantics/normalize/cells/model.d.ts +98 -0
  468. package/dist/semantics/normalize/cells/model.js +2 -0
  469. package/dist/semantics/normalize/cells/policies/bag.d.ts +44 -0
  470. package/dist/semantics/normalize/cells/policies/bag.js +114 -0
  471. package/dist/semantics/normalize/cells/policies/collection.d.ts +42 -0
  472. package/dist/semantics/normalize/cells/policies/collection.js +218 -0
  473. package/dist/semantics/normalize/cells/policies/field.d.ts +28 -0
  474. package/dist/semantics/normalize/cells/policies/field.js +40 -0
  475. package/dist/semantics/normalize/cells/policies/index.d.ts +49 -0
  476. package/dist/semantics/normalize/cells/policies/index.js +58 -0
  477. package/dist/semantics/normalize/cells/policies/local.d.ts +18 -0
  478. package/dist/semantics/normalize/cells/policies/local.js +37 -0
  479. package/dist/semantics/normalize/cells/policies/parameter.d.ts +28 -0
  480. package/dist/semantics/normalize/cells/policies/parameter.js +39 -0
  481. package/dist/semantics/normalize/cells/policies/return.d.ts +26 -0
  482. package/dist/semantics/normalize/cells/policies/return.js +45 -0
  483. package/dist/semantics/normalize/cells/policies/shared.d.ts +33 -0
  484. package/dist/semantics/normalize/cells/policies/shared.js +45 -0
  485. package/dist/semantics/normalize/cells/policy.d.ts +72 -0
  486. package/dist/semantics/normalize/cells/policy.js +18 -0
  487. package/dist/semantics/normalize/cells/registry.d.ts +14 -0
  488. package/dist/semantics/normalize/cells/registry.js +17 -0
  489. package/dist/semantics/normalize/census-refusal.d.ts +62 -0
  490. package/dist/semantics/normalize/census-refusal.js +27 -0
  491. package/dist/semantics/normalize/census.d.ts +109 -0
  492. package/dist/semantics/normalize/census.js +667 -0
  493. package/dist/semantics/normalize/collection-bindings.d.ts +278 -0
  494. package/dist/semantics/normalize/collection-bindings.js +677 -0
  495. package/dist/semantics/normalize/commonjs-module-record.d.ts +21 -0
  496. package/dist/semantics/normalize/commonjs-module-record.js +289 -0
  497. package/dist/semantics/normalize/commonjs-require.d.ts +13 -0
  498. package/dist/semantics/normalize/commonjs-require.js +1527 -0
  499. package/dist/semantics/normalize/contribution.d.ts +63 -0
  500. package/dist/semantics/normalize/contribution.js +172 -0
  501. package/dist/semantics/normalize/dead-typeof-guards.d.ts +64 -0
  502. package/dist/semantics/normalize/dead-typeof-guards.js +152 -0
  503. package/dist/semantics/normalize/deferred-intrinsic-protocols.d.ts +57 -0
  504. package/dist/semantics/normalize/deferred-intrinsic-protocols.js +109 -0
  505. package/dist/semantics/normalize/derived-expression-type.d.ts +1070 -0
  506. package/dist/semantics/normalize/derived-expression-type.js +3463 -0
  507. package/dist/semantics/normalize/evaluation-order.d.ts +16 -0
  508. package/dist/semantics/normalize/evaluation-order.js +37 -0
  509. package/dist/semantics/normalize/field-bindings.d.ts +167 -0
  510. package/dist/semantics/normalize/field-bindings.js +1125 -0
  511. package/dist/semantics/normalize/flow/array-element-continuation.d.ts +27 -0
  512. package/dist/semantics/normalize/flow/array-element-continuation.js +1452 -0
  513. package/dist/semantics/normalize/flow/callable-array-origins.d.ts +42 -0
  514. package/dist/semantics/normalize/flow/callable-array-origins.js +318 -0
  515. package/dist/semantics/normalize/flow/callable-completions.d.ts +45 -0
  516. package/dist/semantics/normalize/flow/callable-completions.js +82 -0
  517. package/dist/semantics/normalize/flow/callable-reach.d.ts +237 -0
  518. package/dist/semantics/normalize/flow/callable-reach.js +7174 -0
  519. package/dist/semantics/normalize/flow/class-family-member-read.d.ts +16 -0
  520. package/dist/semantics/normalize/flow/class-family-member-read.js +992 -0
  521. package/dist/semantics/normalize/flow/collection-value-continuation.d.ts +21 -0
  522. package/dist/semantics/normalize/flow/collection-value-continuation.js +192 -0
  523. package/dist/semantics/normalize/flow/component-solver.d.ts +199 -0
  524. package/dist/semantics/normalize/flow/component-solver.js +587 -0
  525. package/dist/semantics/normalize/flow/computed-key-set.d.ts +84 -0
  526. package/dist/semantics/normalize/flow/computed-key-set.js +660 -0
  527. package/dist/semantics/normalize/flow/export-importers.d.ts +24 -0
  528. package/dist/semantics/normalize/flow/export-importers.js +269 -0
  529. package/dist/semantics/normalize/flow/host-text-sink.d.ts +25 -0
  530. package/dist/semantics/normalize/flow/host-text-sink.js +87 -0
  531. package/dist/semantics/normalize/flow/intrinsic-array-callback-frames.d.ts +84 -0
  532. package/dist/semantics/normalize/flow/intrinsic-array-callback-frames.js +180 -0
  533. package/dist/semantics/normalize/flow/intrinsic-data-definition.d.ts +35 -0
  534. package/dist/semantics/normalize/flow/intrinsic-data-definition.js +140 -0
  535. package/dist/semantics/normalize/flow/invocation-facts.d.ts +98 -0
  536. package/dist/semantics/normalize/flow/invocation-facts.js +257 -0
  537. package/dist/semantics/normalize/flow/member-call-forwarding.d.ts +122 -0
  538. package/dist/semantics/normalize/flow/member-call-forwarding.js +835 -0
  539. package/dist/semantics/normalize/flow/model.d.ts +357 -0
  540. package/dist/semantics/normalize/flow/model.js +177 -0
  541. package/dist/semantics/normalize/flow/native-collection-protocol.d.ts +24 -0
  542. package/dist/semantics/normalize/flow/native-collection-protocol.js +252 -0
  543. package/dist/semantics/normalize/flow/node-path-token.d.ts +3 -0
  544. package/dist/semantics/normalize/flow/node-path-token.js +53 -0
  545. package/dist/semantics/normalize/flow/object-binding-continuation.d.ts +11 -0
  546. package/dist/semantics/normalize/flow/object-binding-continuation.js +42 -0
  547. package/dist/semantics/normalize/flow/origin-authority.d.ts +56 -0
  548. package/dist/semantics/normalize/flow/origin-authority.js +2 -0
  549. package/dist/semantics/normalize/flow/owned-class-receivers.d.ts +35 -0
  550. package/dist/semantics/normalize/flow/owned-class-receivers.js +191 -0
  551. package/dist/semantics/normalize/flow/parameter-values.d.ts +27 -0
  552. package/dist/semantics/normalize/flow/parameter-values.js +251 -0
  553. package/dist/semantics/normalize/flow/proof-hypotheses.d.ts +66 -0
  554. package/dist/semantics/normalize/flow/proof-hypotheses.js +162 -0
  555. package/dist/semantics/normalize/flow/record-alias-closure.d.ts +27 -0
  556. package/dist/semantics/normalize/flow/record-alias-closure.js +298 -0
  557. package/dist/semantics/normalize/flow/seeded-origins.d.ts +43 -0
  558. package/dist/semantics/normalize/flow/seeded-origins.js +54 -0
  559. package/dist/semantics/normalize/flow/source-class-data.d.ts +132 -0
  560. package/dist/semantics/normalize/flow/source-class-data.js +838 -0
  561. package/dist/semantics/normalize/flow/source-class-instanceof.d.ts +13 -0
  562. package/dist/semantics/normalize/flow/source-class-instanceof.js +37 -0
  563. package/dist/semantics/normalize/flow/source-class-static-data.d.ts +16 -0
  564. package/dist/semantics/normalize/flow/source-class-static-data.js +47 -0
  565. package/dist/semantics/normalize/flow/source-construction-frames.d.ts +12 -0
  566. package/dist/semantics/normalize/flow/source-construction-frames.js +118 -0
  567. package/dist/semantics/normalize/flow/source-invocation-frame-layout.d.ts +34 -0
  568. package/dist/semantics/normalize/flow/source-invocation-frame-layout.js +78 -0
  569. package/dist/semantics/normalize/flow/source-invocation-receiver.d.ts +37 -0
  570. package/dist/semantics/normalize/flow/source-invocation-receiver.js +95 -0
  571. package/dist/semantics/normalize/flow/source-prototype-method-identity.d.ts +23 -0
  572. package/dist/semantics/normalize/flow/source-prototype-method-identity.js +81 -0
  573. package/dist/semantics/normalize/flow/source-record-data.d.ts +29 -0
  574. package/dist/semantics/normalize/flow/source-record-data.js +626 -0
  575. package/dist/semantics/normalize/flow/source-value-session.d.ts +77 -0
  576. package/dist/semantics/normalize/flow/source-value-session.js +3089 -0
  577. package/dist/semantics/normalize/flow/targets.d.ts +118 -0
  578. package/dist/semantics/normalize/flow/targets.js +405 -0
  579. package/dist/semantics/normalize/flow/value-flow.d.ts +36 -0
  580. package/dist/semantics/normalize/flow/value-flow.js +823 -0
  581. package/dist/semantics/normalize/flow/value-provenance.d.ts +31 -0
  582. package/dist/semantics/normalize/flow/value-provenance.js +112 -0
  583. package/dist/semantics/normalize/gating.d.ts +51 -0
  584. package/dist/semantics/normalize/gating.js +560 -0
  585. package/dist/semantics/normalize/generic-function-choice.d.ts +31 -0
  586. package/dist/semantics/normalize/generic-function-choice.js +115 -0
  587. package/dist/semantics/normalize/global-host-mutations.d.ts +51 -0
  588. package/dist/semantics/normalize/global-host-mutations.js +5989 -0
  589. package/dist/semantics/normalize/host-effect-contracts.d.ts +77 -0
  590. package/dist/semantics/normalize/host-effect-contracts.js +143 -0
  591. package/dist/semantics/normalize/host-mutation-computed-keys.d.ts +38 -0
  592. package/dist/semantics/normalize/host-mutation-computed-keys.js +26 -0
  593. package/dist/semantics/normalize/host-mutation-key-reader.d.ts +66 -0
  594. package/dist/semantics/normalize/host-mutation-key-reader.js +192 -0
  595. package/dist/semantics/normalize/host-mutation-keys.d.ts +114 -0
  596. package/dist/semantics/normalize/host-mutation-keys.js +183 -0
  597. package/dist/semantics/normalize/identities.d.ts +172 -0
  598. package/dist/semantics/normalize/identities.js +426 -0
  599. package/dist/semantics/normalize/implicit-arguments-tuple.d.ts +97 -0
  600. package/dist/semantics/normalize/implicit-arguments-tuple.js +197 -0
  601. package/dist/semantics/normalize/implicit-arguments.d.ts +11 -0
  602. package/dist/semantics/normalize/implicit-arguments.js +39 -0
  603. package/dist/semantics/normalize/instantiation.d.ts +73 -0
  604. package/dist/semantics/normalize/instantiation.js +399 -0
  605. package/dist/semantics/normalize/intrinsic-property-call.d.ts +18 -0
  606. package/dist/semantics/normalize/intrinsic-property-call.js +69 -0
  607. package/dist/semantics/normalize/intrinsic-prototype.d.ts +41 -0
  608. package/dist/semantics/normalize/intrinsic-prototype.js +87 -0
  609. package/dist/semantics/normalize/intrinsic-static-member.d.ts +14 -0
  610. package/dist/semantics/normalize/intrinsic-static-member.js +23 -0
  611. package/dist/semantics/normalize/jsdoc-type-names.d.ts +32 -0
  612. package/dist/semantics/normalize/jsdoc-type-names.js +512 -0
  613. package/dist/semantics/normalize/keyof.d.ts +32 -0
  614. package/dist/semantics/normalize/keyof.js +110 -0
  615. package/dist/semantics/normalize/local-bindings.d.ts +176 -0
  616. package/dist/semantics/normalize/local-bindings.js +1826 -0
  617. package/dist/semantics/normalize/logical-result-type.d.ts +16 -0
  618. package/dist/semantics/normalize/logical-result-type.js +102 -0
  619. package/dist/semantics/normalize/namespace-paths.d.ts +57 -0
  620. package/dist/semantics/normalize/namespace-paths.js +108 -0
  621. package/dist/semantics/normalize/normalize.d.ts +57 -0
  622. package/dist/semantics/normalize/normalize.js +68 -0
  623. package/dist/semantics/normalize/object-bag-bindings.d.ts +305 -0
  624. package/dist/semantics/normalize/object-bag-bindings.js +1290 -0
  625. package/dist/semantics/normalize/omitted-stated-parameter.d.ts +53 -0
  626. package/dist/semantics/normalize/omitted-stated-parameter.js +59 -0
  627. package/dist/semantics/normalize/open-type-form.d.ts +10 -0
  628. package/dist/semantics/normalize/open-type-form.js +32 -0
  629. package/dist/semantics/normalize/parameter-bindings.d.ts +361 -0
  630. package/dist/semantics/normalize/parameter-bindings.js +3339 -0
  631. package/dist/semantics/normalize/parameter-slot.d.ts +264 -0
  632. package/dist/semantics/normalize/parameter-slot.js +491 -0
  633. package/dist/semantics/normalize/physical-overload-result.d.ts +77 -0
  634. package/dist/semantics/normalize/physical-overload-result.js +99 -0
  635. package/dist/semantics/normalize/primitive-property-absence.d.ts +12 -0
  636. package/dist/semantics/normalize/primitive-property-absence.js +60 -0
  637. package/dist/semantics/normalize/producer-context.d.ts +376 -0
  638. package/dist/semantics/normalize/producer-context.js +1 -0
  639. package/dist/semantics/normalize/producers/allocations.d.ts +3 -0
  640. package/dist/semantics/normalize/producers/allocations.js +863 -0
  641. package/dist/semantics/normalize/producers/binding-kind.d.ts +37 -0
  642. package/dist/semantics/normalize/producers/binding-kind.js +36 -0
  643. package/dist/semantics/normalize/producers/bindings.d.ts +85 -0
  644. package/dist/semantics/normalize/producers/bindings.js +710 -0
  645. package/dist/semantics/normalize/producers/boundary.d.ts +34 -0
  646. package/dist/semantics/normalize/producers/boundary.js +123 -0
  647. package/dist/semantics/normalize/producers/class-lifecycle.d.ts +3 -0
  648. package/dist/semantics/normalize/producers/class-lifecycle.js +902 -0
  649. package/dist/semantics/normalize/producers/computations.d.ts +3 -0
  650. package/dist/semantics/normalize/producers/computations.js +613 -0
  651. package/dist/semantics/normalize/producers/control-loops.d.ts +30 -0
  652. package/dist/semantics/normalize/producers/control-loops.js +91 -0
  653. package/dist/semantics/normalize/producers/control.d.ts +30 -0
  654. package/dist/semantics/normalize/producers/control.js +923 -0
  655. package/dist/semantics/normalize/producers/declaration-lifecycle.d.ts +3 -0
  656. package/dist/semantics/normalize/producers/declaration-lifecycle.js +390 -0
  657. package/dist/semantics/normalize/producers/destructuring.d.ts +45 -0
  658. package/dist/semantics/normalize/producers/destructuring.js +1180 -0
  659. package/dist/semantics/normalize/producers/dynamic-language.d.ts +3 -0
  660. package/dist/semantics/normalize/producers/dynamic-language.js +70 -0
  661. package/dist/semantics/normalize/producers/erasure.d.ts +51 -0
  662. package/dist/semantics/normalize/producers/erasure.js +90 -0
  663. package/dist/semantics/normalize/producers/installed.d.ts +3 -0
  664. package/dist/semantics/normalize/producers/installed.js +55 -0
  665. package/dist/semantics/normalize/producers/invocations.d.ts +35 -0
  666. package/dist/semantics/normalize/producers/invocations.js +1796 -0
  667. package/dist/semantics/normalize/producers/iteration-yield.d.ts +59 -0
  668. package/dist/semantics/normalize/producers/iteration-yield.js +235 -0
  669. package/dist/semantics/normalize/producers/jsx.d.ts +3 -0
  670. package/dist/semantics/normalize/producers/jsx.js +360 -0
  671. package/dist/semantics/normalize/producers/mint.d.ts +39 -0
  672. package/dist/semantics/normalize/producers/mint.js +44 -0
  673. package/dist/semantics/normalize/producers/nullish.d.ts +16 -0
  674. package/dist/semantics/normalize/producers/nullish.js +27 -0
  675. package/dist/semantics/normalize/producers/object-assignment.d.ts +8 -0
  676. package/dist/semantics/normalize/producers/object-assignment.js +204 -0
  677. package/dist/semantics/normalize/producers/object-tag.d.ts +9 -0
  678. package/dist/semantics/normalize/producers/object-tag.js +119 -0
  679. package/dist/semantics/normalize/producers/optional-chain.d.ts +44 -0
  680. package/dist/semantics/normalize/producers/optional-chain.js +75 -0
  681. package/dist/semantics/normalize/producers/properties.d.ts +21 -0
  682. package/dist/semantics/normalize/producers/properties.js +1053 -0
  683. package/dist/semantics/normalize/producers/protocol.d.ts +67 -0
  684. package/dist/semantics/normalize/producers/protocol.js +695 -0
  685. package/dist/semantics/normalize/producers/references.d.ts +53 -0
  686. package/dist/semantics/normalize/producers/references.js +1027 -0
  687. package/dist/semantics/normalize/producers/shared.d.ts +561 -0
  688. package/dist/semantics/normalize/producers/shared.js +1683 -0
  689. package/dist/semantics/normalize/producers/spread-arguments.d.ts +72 -0
  690. package/dist/semantics/normalize/producers/spread-arguments.js +375 -0
  691. package/dist/semantics/normalize/producers/tagged-template.d.ts +5 -0
  692. package/dist/semantics/normalize/producers/tagged-template.js +307 -0
  693. package/dist/semantics/normalize/producers/tuple-spread.d.ts +189 -0
  694. package/dist/semantics/normalize/producers/tuple-spread.js +279 -0
  695. package/dist/semantics/normalize/property-key-domain.d.ts +36 -0
  696. package/dist/semantics/normalize/property-key-domain.js +150 -0
  697. package/dist/semantics/normalize/reachability.d.ts +189 -0
  698. package/dist/semantics/normalize/reachability.js +1057 -0
  699. package/dist/semantics/normalize/reassigned-bindings.d.ts +13 -0
  700. package/dist/semantics/normalize/reassigned-bindings.js +41 -0
  701. package/dist/semantics/normalize/record-storage-families.d.ts +11 -0
  702. package/dist/semantics/normalize/record-storage-families.js +109 -0
  703. package/dist/semantics/normalize/return-bindings.d.ts +260 -0
  704. package/dist/semantics/normalize/return-bindings.js +1311 -0
  705. package/dist/semantics/normalize/return-paths.d.ts +2 -0
  706. package/dist/semantics/normalize/return-paths.js +28 -0
  707. package/dist/semantics/normalize/script-global-redefinition.d.ts +44 -0
  708. package/dist/semantics/normalize/script-global-redefinition.js +75 -0
  709. package/dist/semantics/normalize/specialization.d.ts +201 -0
  710. package/dist/semantics/normalize/specialization.js +1824 -0
  711. package/dist/semantics/normalize/structural-array-element.d.ts +176 -0
  712. package/dist/semantics/normalize/structural-array-element.js +700 -0
  713. package/dist/semantics/normalize/structural-array-read.d.ts +13 -0
  714. package/dist/semantics/normalize/structural-array-read.js +124 -0
  715. package/dist/semantics/normalize/structural-callable.d.ts +12 -0
  716. package/dist/semantics/normalize/structural-callable.js +82 -0
  717. package/dist/semantics/normalize/structural-creation-order.d.ts +32 -0
  718. package/dist/semantics/normalize/structural-creation-order.js +111 -0
  719. package/dist/semantics/normalize/structural-declarations.d.ts +395 -0
  720. package/dist/semantics/normalize/structural-declarations.js +968 -0
  721. package/dist/semantics/normalize/structural-declared-body.d.ts +25 -0
  722. package/dist/semantics/normalize/structural-declared-body.js +147 -0
  723. package/dist/semantics/normalize/structural-generics.d.ts +56 -0
  724. package/dist/semantics/normalize/structural-generics.js +120 -0
  725. package/dist/semantics/normalize/structural-indexed-access.d.ts +11 -0
  726. package/dist/semantics/normalize/structural-indexed-access.js +126 -0
  727. package/dist/semantics/normalize/structural-instantiated-member.d.ts +64 -0
  728. package/dist/semantics/normalize/structural-instantiated-member.js +407 -0
  729. package/dist/semantics/normalize/structural-joins.d.ts +44 -0
  730. package/dist/semantics/normalize/structural-joins.js +143 -0
  731. package/dist/semantics/normalize/structural-layout-relevance.d.ts +29 -0
  732. package/dist/semantics/normalize/structural-layout-relevance.js +391 -0
  733. package/dist/semantics/normalize/structural-layout-type.d.ts +11 -0
  734. package/dist/semantics/normalize/structural-layout-type.js +1468 -0
  735. package/dist/semantics/normalize/structural-leaves.d.ts +49 -0
  736. package/dist/semantics/normalize/structural-leaves.js +125 -0
  737. package/dist/semantics/normalize/structural-local-union.d.ts +13 -0
  738. package/dist/semantics/normalize/structural-local-union.js +133 -0
  739. package/dist/semantics/normalize/structural-members.d.ts +26 -0
  740. package/dist/semantics/normalize/structural-members.js +84 -0
  741. package/dist/semantics/normalize/structural-mutable-method.d.ts +15 -0
  742. package/dist/semantics/normalize/structural-mutable-method.js +109 -0
  743. package/dist/semantics/normalize/structural-parts.d.ts +131 -0
  744. package/dist/semantics/normalize/structural-parts.js +737 -0
  745. package/dist/semantics/normalize/structural-receiver.d.ts +66 -0
  746. package/dist/semantics/normalize/structural-receiver.js +551 -0
  747. package/dist/semantics/normalize/structural-rules.d.ts +112 -0
  748. package/dist/semantics/normalize/structural-rules.js +93 -0
  749. package/dist/semantics/normalize/structural-self-reference.d.ts +150 -0
  750. package/dist/semantics/normalize/structural-self-reference.js +494 -0
  751. package/dist/semantics/normalize/structural.d.ts +202 -0
  752. package/dist/semantics/normalize/structural.js +4218 -0
  753. package/dist/semantics/normalize/unreduced-type-form.d.ts +41 -0
  754. package/dist/semantics/normalize/unreduced-type-form.js +53 -0
  755. package/dist/semantics/normalize/unresolvable-names.d.ts +56 -0
  756. package/dist/semantics/normalize/unresolvable-names.js +140 -0
  757. package/dist/semantics/package-sources.d.ts +16 -0
  758. package/dist/semantics/package-sources.js +365 -0
  759. package/dist/semantics/program.d.ts +151 -0
  760. package/dist/semantics/program.js +667 -0
  761. package/dist/semantics/prototype-install-source-transform.d.ts +4 -0
  762. package/dist/semantics/prototype-install-source-transform.js +341 -0
  763. package/dist/semantics/prototype-object-class-source-transform.d.ts +4 -0
  764. package/dist/semantics/prototype-object-class-source-transform.js +525 -0
  765. package/dist/semantics/prototype-reparenting.d.ts +50 -0
  766. package/dist/semantics/prototype-reparenting.js +317 -0
  767. package/dist/semantics/stable-checker.d.ts +10 -0
  768. package/dist/semantics/stable-checker.js +148 -0
  769. package/dist/semantics/subclass-member-overlay-transform.d.ts +35 -0
  770. package/dist/semantics/subclass-member-overlay-transform.js +1418 -0
  771. package/dist/semantics/symbol-keyed-expando-source-transform.d.ts +4 -0
  772. package/dist/semantics/symbol-keyed-expando-source-transform.js +66 -0
  773. package/dist/semantics/this-constructor-source-transform.d.ts +4 -0
  774. package/dist/semantics/this-constructor-source-transform.js +122 -0
  775. package/dist/semantics/uninstantiable-classes.d.ts +22 -0
  776. package/dist/semantics/uninstantiable-classes.js +75 -0
  777. package/dist/targets/cpp/balanced-units.d.ts +3 -0
  778. package/dist/targets/cpp/balanced-units.js +58 -0
  779. package/dist/targets/cpp/borrowed-call-entry.d.ts +30 -0
  780. package/dist/targets/cpp/borrowed-call-entry.js +68 -0
  781. package/dist/targets/cpp/captures.d.ts +68 -0
  782. package/dist/targets/cpp/captures.js +269 -0
  783. package/dist/targets/cpp/class-layout.d.ts +313 -0
  784. package/dist/targets/cpp/class-layout.js +483 -0
  785. package/dist/targets/cpp/class-properties/computed-method-value.d.ts +25 -0
  786. package/dist/targets/cpp/class-properties/computed-method-value.js +22 -0
  787. package/dist/targets/cpp/class-properties/emit-class-properties.d.ts +216 -0
  788. package/dist/targets/cpp/class-properties/emit-class-properties.js +917 -0
  789. package/dist/targets/cpp/class-properties/native-prototype.d.ts +11 -0
  790. package/dist/targets/cpp/class-properties/native-prototype.js +101 -0
  791. package/dist/targets/cpp/class-ref-transport.d.ts +12 -0
  792. package/dist/targets/cpp/class-ref-transport.js +32 -0
  793. package/dist/targets/cpp/conversions.d.ts +3 -0
  794. package/dist/targets/cpp/conversions.js +2027 -0
  795. package/dist/targets/cpp/deferral-safety.d.ts +82 -0
  796. package/dist/targets/cpp/deferral-safety.js +86 -0
  797. package/dist/targets/cpp/direct-call-receivers.d.ts +37 -0
  798. package/dist/targets/cpp/direct-call-receivers.js +79 -0
  799. package/dist/targets/cpp/document.d.ts +74 -0
  800. package/dist/targets/cpp/document.js +106 -0
  801. package/dist/targets/cpp/emit-allocation.d.ts +60 -0
  802. package/dist/targets/cpp/emit-allocation.js +573 -0
  803. package/dist/targets/cpp/emit-arrays.d.ts +119 -0
  804. package/dist/targets/cpp/emit-arrays.js +1047 -0
  805. package/dist/targets/cpp/emit-binding-reference.d.ts +17 -0
  806. package/dist/targets/cpp/emit-binding-reference.js +120 -0
  807. package/dist/targets/cpp/emit-bindings.d.ts +158 -0
  808. package/dist/targets/cpp/emit-bindings.js +769 -0
  809. package/dist/targets/cpp/emit-buffers.d.ts +156 -0
  810. package/dist/targets/cpp/emit-buffers.js +573 -0
  811. package/dist/targets/cpp/emit-callable.d.ts +230 -0
  812. package/dist/targets/cpp/emit-callable.js +2154 -0
  813. package/dist/targets/cpp/emit-carrier-members.d.ts +406 -0
  814. package/dist/targets/cpp/emit-carrier-members.js +1224 -0
  815. package/dist/targets/cpp/emit-coercion.d.ts +26 -0
  816. package/dist/targets/cpp/emit-coercion.js +39 -0
  817. package/dist/targets/cpp/emit-context.d.ts +1882 -0
  818. package/dist/targets/cpp/emit-context.js +904 -0
  819. package/dist/targets/cpp/emit-dynamic-properties.d.ts +174 -0
  820. package/dist/targets/cpp/emit-dynamic-properties.js +1249 -0
  821. package/dist/targets/cpp/emit-equality.d.ts +39 -0
  822. package/dist/targets/cpp/emit-equality.js +472 -0
  823. package/dist/targets/cpp/emit-exceptions.d.ts +104 -0
  824. package/dist/targets/cpp/emit-exceptions.js +513 -0
  825. package/dist/targets/cpp/emit-field-owner.d.ts +4 -0
  826. package/dist/targets/cpp/emit-field-owner.js +27 -0
  827. package/dist/targets/cpp/emit-in.d.ts +31 -0
  828. package/dist/targets/cpp/emit-in.js +426 -0
  829. package/dist/targets/cpp/emit-instanceof.d.ts +19 -0
  830. package/dist/targets/cpp/emit-instanceof.js +601 -0
  831. package/dist/targets/cpp/emit-integers.d.ts +68 -0
  832. package/dist/targets/cpp/emit-integers.js +184 -0
  833. package/dist/targets/cpp/emit-iterator.d.ts +100 -0
  834. package/dist/targets/cpp/emit-iterator.js +1137 -0
  835. package/dist/targets/cpp/emit-json.d.ts +73 -0
  836. package/dist/targets/cpp/emit-json.js +823 -0
  837. package/dist/targets/cpp/emit-jsx.d.ts +74 -0
  838. package/dist/targets/cpp/emit-jsx.js +806 -0
  839. package/dist/targets/cpp/emit-mixed-binary.d.ts +51 -0
  840. package/dist/targets/cpp/emit-mixed-binary.js +60 -0
  841. package/dist/targets/cpp/emit-namespaces.d.ts +101 -0
  842. package/dist/targets/cpp/emit-namespaces.js +133 -0
  843. package/dist/targets/cpp/emit-narrowing.d.ts +738 -0
  844. package/dist/targets/cpp/emit-narrowing.js +3967 -0
  845. package/dist/targets/cpp/emit-native-equality.d.ts +3 -0
  846. package/dist/targets/cpp/emit-native-equality.js +14 -0
  847. package/dist/targets/cpp/emit-native-selection.d.ts +5 -0
  848. package/dist/targets/cpp/emit-native-selection.js +37 -0
  849. package/dist/targets/cpp/emit-object-tag.d.ts +4 -0
  850. package/dist/targets/cpp/emit-object-tag.js +108 -0
  851. package/dist/targets/cpp/emit-owned-record.d.ts +2 -0
  852. package/dist/targets/cpp/emit-owned-record.js +15 -0
  853. package/dist/targets/cpp/emit-presence.d.ts +78 -0
  854. package/dist/targets/cpp/emit-presence.js +376 -0
  855. package/dist/targets/cpp/emit-properties.d.ts +105 -0
  856. package/dist/targets/cpp/emit-properties.js +1640 -0
  857. package/dist/targets/cpp/emit-record-view.d.ts +20 -0
  858. package/dist/targets/cpp/emit-record-view.js +354 -0
  859. package/dist/targets/cpp/emit-return.d.ts +5 -0
  860. package/dist/targets/cpp/emit-return.js +237 -0
  861. package/dist/targets/cpp/emit-sum-widening.d.ts +10 -0
  862. package/dist/targets/cpp/emit-sum-widening.js +69 -0
  863. package/dist/targets/cpp/emit-tonumber.d.ts +38 -0
  864. package/dist/targets/cpp/emit-tonumber.js +177 -0
  865. package/dist/targets/cpp/emit-tostring.d.ts +92 -0
  866. package/dist/targets/cpp/emit-tostring.js +556 -0
  867. package/dist/targets/cpp/emit-typeof.d.ts +49 -0
  868. package/dist/targets/cpp/emit-typeof.js +317 -0
  869. package/dist/targets/cpp/emit-union-properties.d.ts +181 -0
  870. package/dist/targets/cpp/emit-union-properties.js +1281 -0
  871. package/dist/targets/cpp/emit.d.ts +45 -0
  872. package/dist/targets/cpp/emit.js +2225 -0
  873. package/dist/targets/cpp/error-types.d.ts +4 -0
  874. package/dist/targets/cpp/error-types.js +11 -0
  875. package/dist/targets/cpp/function-source-reads.d.ts +72 -0
  876. package/dist/targets/cpp/function-source-reads.js +148 -0
  877. package/dist/targets/cpp/host/atomics.d.ts +25 -0
  878. package/dist/targets/cpp/host/atomics.js +63 -0
  879. package/dist/targets/cpp/host/core-globals.d.ts +108 -0
  880. package/dist/targets/cpp/host/core-globals.js +158 -0
  881. package/dist/targets/cpp/host/dynamic-argument-members.d.ts +42 -0
  882. package/dist/targets/cpp/host/dynamic-argument-members.js +61 -0
  883. package/dist/targets/cpp/host/emit-host-arity.d.ts +139 -0
  884. package/dist/targets/cpp/host/emit-host-arity.js +232 -0
  885. package/dist/targets/cpp/host/emit-host-invoke.d.ts +91 -0
  886. package/dist/targets/cpp/host/emit-host-invoke.js +1105 -0
  887. package/dist/targets/cpp/host/emit-host-object.d.ts +55 -0
  888. package/dist/targets/cpp/host/emit-host-object.js +2206 -0
  889. package/dist/targets/cpp/host/emit-host-properties.d.ts +69 -0
  890. package/dist/targets/cpp/host/emit-host-properties.js +533 -0
  891. package/dist/targets/cpp/host/emit-host-reflect.d.ts +4 -0
  892. package/dist/targets/cpp/host/emit-host-reflect.js +180 -0
  893. package/dist/targets/cpp/host/emit-host-value.d.ts +120 -0
  894. package/dist/targets/cpp/host/emit-host-value.js +392 -0
  895. package/dist/targets/cpp/host/host-members.d.ts +505 -0
  896. package/dist/targets/cpp/host/host-members.js +819 -0
  897. package/dist/targets/cpp/host/host-method-aliases.d.ts +30 -0
  898. package/dist/targets/cpp/host/host-method-aliases.js +76 -0
  899. package/dist/targets/cpp/host/native-protocols.d.ts +47 -0
  900. package/dist/targets/cpp/host/native-protocols.js +183 -0
  901. package/dist/targets/cpp/host/object-protocol.d.ts +351 -0
  902. package/dist/targets/cpp/host/object-protocol.js +671 -0
  903. package/dist/targets/cpp/host-namespace-reads.d.ts +83 -0
  904. package/dist/targets/cpp/host-namespace-reads.js +113 -0
  905. package/dist/targets/cpp/manifest/capabilities.d.ts +39 -0
  906. package/dist/targets/cpp/manifest/capabilities.js +1484 -0
  907. package/dist/targets/cpp/manifest.d.ts +23 -0
  908. package/dist/targets/cpp/manifest.js +113 -0
  909. package/dist/targets/cpp/native-error-base.d.ts +38 -0
  910. package/dist/targets/cpp/native-error-base.js +74 -0
  911. package/dist/targets/cpp/native-narrowing-transport.d.ts +12 -0
  912. package/dist/targets/cpp/native-narrowing-transport.js +151 -0
  913. package/dist/targets/cpp/native-selection-helpers.d.ts +11 -0
  914. package/dist/targets/cpp/native-selection-helpers.js +46 -0
  915. package/dist/targets/cpp/native-symbol-keys.d.ts +8 -0
  916. package/dist/targets/cpp/native-symbol-keys.js +34 -0
  917. package/dist/targets/cpp/ownership.d.ts +43 -0
  918. package/dist/targets/cpp/ownership.js +38 -0
  919. package/dist/targets/cpp/owning-conversion-input.d.ts +14 -0
  920. package/dist/targets/cpp/owning-conversion-input.js +12 -0
  921. package/dist/targets/cpp/property-read-claims.d.ts +62 -0
  922. package/dist/targets/cpp/property-read-claims.js +23 -0
  923. package/dist/targets/cpp/property-store-claims.d.ts +62 -0
  924. package/dist/targets/cpp/property-store-claims.js +26 -0
  925. package/dist/targets/cpp/prototype/emit-prototype-array.d.ts +111 -0
  926. package/dist/targets/cpp/prototype/emit-prototype-array.js +602 -0
  927. package/dist/targets/cpp/prototype/emit-prototype-date.d.ts +133 -0
  928. package/dist/targets/cpp/prototype/emit-prototype-date.js +515 -0
  929. package/dist/targets/cpp/prototype/emit-prototype-error.d.ts +13 -0
  930. package/dist/targets/cpp/prototype/emit-prototype-error.js +54 -0
  931. package/dist/targets/cpp/prototype/emit-prototype-invoke.d.ts +34 -0
  932. package/dist/targets/cpp/prototype/emit-prototype-invoke.js +1003 -0
  933. package/dist/targets/cpp/prototype/emit-prototype-iterator.d.ts +47 -0
  934. package/dist/targets/cpp/prototype/emit-prototype-iterator.js +250 -0
  935. package/dist/targets/cpp/prototype/emit-prototype-promise.d.ts +46 -0
  936. package/dist/targets/cpp/prototype/emit-prototype-promise.js +143 -0
  937. package/dist/targets/cpp/prototype/emit-prototype-regexp.d.ts +335 -0
  938. package/dist/targets/cpp/prototype/emit-prototype-regexp.js +853 -0
  939. package/dist/targets/cpp/prototype/emit-prototype-string.d.ts +42 -0
  940. package/dist/targets/cpp/prototype/emit-prototype-string.js +252 -0
  941. package/dist/targets/cpp/prototype/prototype-method-reads.d.ts +25 -0
  942. package/dist/targets/cpp/prototype/prototype-method-reads.js +182 -0
  943. package/dist/targets/cpp/reactive-dependencies.d.ts +140 -0
  944. package/dist/targets/cpp/reactive-dependencies.js +432 -0
  945. package/dist/targets/cpp/reactive-origins.d.ts +44 -0
  946. package/dist/targets/cpp/reactive-origins.js +82 -0
  947. package/dist/targets/cpp/records.d.ts +277 -0
  948. package/dist/targets/cpp/records.js +2427 -0
  949. package/dist/targets/cpp/recursive-containers.d.ts +43 -0
  950. package/dist/targets/cpp/recursive-containers.js +144 -0
  951. package/dist/targets/cpp/regexp-types.d.ts +56 -0
  952. package/dist/targets/cpp/regexp-types.js +59 -0
  953. package/dist/targets/cpp/substrate.d.ts +125 -0
  954. package/dist/targets/cpp/substrate.js +12 -0
  955. package/dist/targets/cpp/translation-unit.d.ts +219 -0
  956. package/dist/targets/cpp/translation-unit.js +2063 -0
  957. package/dist/targets/cpp/types.d.ts +280 -0
  958. package/dist/targets/cpp/types.js +1135 -0
  959. package/dist/targets/cpp/virtual-methods.d.ts +95 -0
  960. package/dist/targets/cpp/virtual-methods.js +264 -0
  961. package/package.json +95 -0
  962. package/src/targets/cpp/runtime/gea_dynamic_proxy.h +824 -0
  963. package/src/targets/cpp/runtime/gea_eval.h +1376 -0
  964. package/src/targets/cpp/runtime/gea_native_class_prototype.h +44 -0
  965. package/src/targets/cpp/runtime/gea_runtime.h +29222 -0
  966. package/src/targets/cpp/runtime/gea_runtime_builtins.cpp +55 -0
@@ -0,0 +1,2225 @@
1
+ import { objectTagExpression, objectTagCapability } from './emit-object-tag.js';
2
+ import { stableBorrowActualsOf } from '../../ir/borrowed-call-arguments.js';
3
+ import { owningConversionInputText } from './owning-conversion-input.js';
4
+ import { boxedValueText } from './emit-dynamic-properties.js';
5
+ import { ownedDyingValuesOf, ownedFormalInputsOf, transfersFormalConversion } from '../../ir/transfer.js';
6
+ import { constructedBaseOf } from '../../projection/classes.js';
7
+ import { allOperationsOf } from '../../ir/model.js';
8
+ import { resultOfIrOperation } from '../../ir/queries.js';
9
+ import { representationKey } from '../../representation/model.js';
10
+ import { cppFormalName, cppReceiverName, createCppEmitBlockedError, createEmitContext, defineValue, defineValueAlias, directCalleesOf, emptyCaptureIndex, isIntegerStorageValue, isCppEmitBlockedError, operandText, storageTypeOf, cppThunkName, sealFactFieldsForRender } from './emit-context.js';
11
+ import { hostMemberReadsOf } from './host/emit-host-properties.js';
12
+ import { hostNamespaceReadsOf } from './host-namespace-reads.js';
13
+ import { functionSourceReadsOf } from './function-source-reads.js';
14
+ import { prototypeMethodReadsOf } from './prototype/prototype-method-reads.js';
15
+ import { directCallReceiversOf, virtualCalleesOf } from './direct-call-receivers.js';
16
+ import { unionMemberTypeofReadsOf, unionMethodReadsOf } from './emit-union-properties.js';
17
+ import { reactiveOriginsOf } from './reactive-origins.js';
18
+ import { renderTryRegion } from './emit-exceptions.js';
19
+ import { emitReturn } from './emit-return.js';
20
+ import { collectDirectBindingSinks, classObjectReadsOf, hostClassReadsOf, collectFormalCells, earlyCapturedCellPrologue, emitBindingRead, emitBindingWrite } from './emit-bindings.js';
21
+ import { alignedValueText, emitMergeLiveArmRebuild, namedConversionText, widenedStoreText } from './emit-narrowing.js';
22
+ import { admitDenseWindows, collectCapacityHints, emitAllocateArrayObject, emitDenseSetup, emitFillLoop } from './emit-arrays.js';
23
+ import { noInstantiationFacts } from '../../ir/instantiation.js';
24
+ import { observesEveryCallableIdentity } from '../../ir/callable-identity-demand.js';
25
+ import { stringConstantsOf } from '../../ir/dead-values.js';
26
+ import { bodyValueOriginsOf, irBodyCensusOf } from '../../ir/facts.js';
27
+ import { emitGetIterator, emitIteratorClose, emitIteratorDone, emitIteratorNext, renderIteratorCloseRegion } from './emit-iterator.js';
28
+ import { absenceComparisonText, booleanTestText, definedTestText, presenceTestText } from './emit-presence.js';
29
+ import { callableIdentityEqualityText, constantStringComparisonText, strictEqualityText } from './emit-equality.js';
30
+ import { nativeEqualityText } from './emit-native-equality.js';
31
+ import { denseRemainderCompanion, integerBitwiseOperators, integerBoundedComparison, remainderText } from './emit-integers.js';
32
+ import { instanceofText } from './emit-instanceof.js';
33
+ import { typeofTagLiteral, typeofTagText, typeofText, typeofTextFor, unionMemberTypeofTagText, unionMemberTypeofText } from './emit-typeof.js';
34
+ import { emitHasProperty } from './emit-in.js';
35
+ import { mergeWritesOf } from './emit-namespaces.js';
36
+ import { templateText, toStringRefusal } from './emit-tostring.js';
37
+ import { mixedDynamicPlusText } from './emit-mixed-binary.js';
38
+ import { emitFieldStore, emitGet, isPlainMemberRead } from './emit-properties.js';
39
+ import { directClassMethodBody } from './class-properties/emit-class-properties.js';
40
+ import { classMemberOf, lazyCalleeReadsOf, structNameOfReceiver } from './class-layout.js';
41
+ import { emitAllocateRecord, emitAllocateRegExp, emitAllocateTemplateObject, emitToNumericCoercion, emitSpreadCopy } from './emit-allocation.js';
42
+ import { alignedText, receiverBoundCallableText, emitAllocateCallable, emitAllocateConstructor, emitBindCallable, emitCall, emitConstruct, emitSuperInitialize } from './emit-callable.js';
43
+ import { cppClassName, cppCommonJsModuleName, cppCommonJsRecordName, cppConstantLiteral, cppStringLiteral, cppTypeOf, cppUndefinedValue } from './types.js';
44
+ import { awaitedText } from './prototype/emit-prototype-promise.js';
45
+ import { classTableRootsOf, emitElement, emitElementChild, emitElementProp } from './emit-jsx.js';
46
+ import { emitDeleteOperation, emitUnaryDelete } from './emit-dynamic-properties.js';
47
+ /**
48
+ * The execution region this section belongs to.
49
+ *
50
+ * `IrBody` carries it directly (`sourceOwner`), which is the only honest route:
51
+ * the `PhysicalBodyId` folds an owner and a variant key into one string, and
52
+ * taking that apart here would make this file a second authority over a
53
+ * structure `identity/ids.ts` alone defines -- the same objection that forbids
54
+ * recovering a decision by parsing rendered C++.
55
+ */
56
+ const sectionOwnerOf = (body) => body.sourceOwner;
57
+ const emitConstant = (ctx, lines, operation) => {
58
+ // Already spelled at every use by `spellConstants`; nothing is left to render.
59
+ if (ctx.deferredTexts.has(operation.result.id))
60
+ return;
61
+ const name = defineValue(ctx, operation.result);
62
+ ctx.constantTexts.set(operation.result.id, operation.text);
63
+ lines.push(`${name} = ${cppConstantLiteral(operation.text, operation.literal, operation.result.representation)};`);
64
+ };
65
+ /**
66
+ * Every literal of a body, spelled inline at each of its uses instead of once
67
+ * into a temporary.
68
+ *
69
+ * A literal reads no state and has no operands, so the two conditions the
70
+ * deferral census imposes on everything else -- one use, in the same block --
71
+ * protect nothing here: the text `("cities")` means the same thing wherever
72
+ * it lands, and there is no definition a `goto` could skip. What a temporary
73
+ * cost was real: a string literal used three times was one construction and
74
+ * two copies (three allocations) where three inline spellings are three
75
+ * constructions (three allocations, no worse), and a literal whose uses are
76
+ * all member keys -- spelled `->cities` by the access, never as text -- was
77
+ * a temporary nothing read at all. `examples/apps/weather` carried 142 of
78
+ * those. Recorded before any block renders so a use in an earlier block of
79
+ * `blockOrder` than its definition still finds the text.
80
+ */
81
+ const spellConstants = (ctx, body) => {
82
+ for (const block of body.blocks.values()) {
83
+ for (const operation of block.operations) {
84
+ if (operation.kind !== 'constant')
85
+ continue;
86
+ ctx.constantTexts.set(operation.result.id, operation.text);
87
+ ctx.deferredTexts.set(operation.result.id, `(${cppConstantLiteral(operation.text, operation.literal, operation.result.representation)})`);
88
+ }
89
+ }
90
+ };
91
+ /**
92
+ * The C++ spelling of one language operator on one carrier.
93
+ *
94
+ * Keyed by the carrier as well as the operator, because the same token is a
95
+ * different machine operation on different carriers -- and on several carriers
96
+ * it is not a machine operation at all. `null` means no spelling exists here,
97
+ * which is refused rather than approximated.
98
+ *
99
+ * `%` and `**` have no infix spelling on `double` in C++, so they are library
100
+ * calls (`gea::remainder`/`std::pow`, below) -- and so are `&`/`|`/`^`/`<<`/`>>`/
101
+ * `>>>`, for a different reason: ECMAScript defines every one of them through
102
+ * `ToInt32`/`ToUint32` (ECMA-262 7.1.6/7.1.7) of the operand, never through the
103
+ * IEEE-754 double the plan actually carries. `a & b` truncates and wraps each
104
+ * operand into a 32-bit two's-complement integer first (ECMA-262 6.1.6.1.16-19
105
+ * `NumberBitwiseOp`/`Number::bitwiseAND`/`bitwiseXOR`/`bitwiseOR`; 6.1.6.1.2
106
+ * `bitwiseNOT` for `~`), and the three shifts additionally reduce the shift
107
+ * count with `ToUint32(rhs) modulo 32` (6.1.6.1.9-11 `leftShift`/
108
+ * `signedRightShift`/`unsignedRightShift`) before shifting. A bare C++ `&`/
109
+ * `<<` on `double` would not even compile, and doing the ToInt32/ToUint32
110
+ * conversion inline at each of these six call sites would be six copies of
111
+ * the identical wraparound to keep in step, so `gea::toInt32`/`gea::toUint32`
112
+ * and the `gea::bitwise*`/`*Shift` wrappers built from them live once in
113
+ * `runtime/gea_runtime.h` -- reusing the identical modulo-2**32 wraparound the
114
+ * TypedArray element store already performs there
115
+ * (`detail::typedArrayIntegerModulo`) -- and are called here as
116
+ * `CppOperatorSpelling`s of kind `'call'`, exactly like `gea::remainder`/`std::pow`.
117
+ *
118
+ * Only the `number`/`float64` domain gets a bitwise spelling. `bigint` looks
119
+ * like it belongs in the same table -- ECMAScript spells the identical six
120
+ * tokens over it -- but it is a genuinely different operation: arbitrary-
121
+ * precision two's complement, no `ToInt32` anywhere in the algorithm
122
+ * (ECMA-262 6.1.6.2.2/.9/.18-19 `BigInt::bitwiseNOT`/`leftShift`/`bitwiseAND`/
123
+ * `bitwiseOR`), and `ApplyStringOrNumericBinaryOperator` (13.15.3) step 5
124
+ * throws a `TypeError` rather than ever converting a `BigInt` through the
125
+ * `Number` path. So it stays refused here by the same `null` this table
126
+ * already returns for every other unimplemented `bigint` operator, not routed
127
+ * through `ToInt32` as an approximation -- which would silently truncate any
128
+ * BigInt outside the 32-bit range. `int32`/`uint32` are listed in
129
+ * `ScalarDomain` but `representation/derive.ts` never actually selects either
130
+ * for an ordinary value -- every plain `number` reaches this table as domain
131
+ * `'number'` -- so there is, today, no carrier for which the round trip could
132
+ * be skipped; see `.scratch/port/bitwise/citations.md` section 5.
133
+ *
134
+ * `===` maps to `==` and `!==` to `!=`: on a single, non-dynamic carrier the
135
+ * strict comparison has no type check left to perform, because both sides were
136
+ * already proven to hold the same carrier before this is reached.
137
+ *
138
+ * `==` and `!=` map to the same spellings, and for the same reason -- not as a
139
+ * shortcut, but because that identical-carrier proof is precisely the premise
140
+ * ECMA-262 7.2.15 (IsLooselyEqual) tests first: "If Type(x) is Type(y), return
141
+ * IsStrictlyEqual(x, y)". Loose equality only diverges from strict when it has
142
+ * a type difference to coerce across, and `emitBinary` refuses a mixed-carrier
143
+ * operator by name immediately above this lookup, so no such pair can reach a
144
+ * table. The one other divergence -- `x == null` matching both `null` and
145
+ * `undefined` -- never reaches here either: `absenceComparisonText` settles a
146
+ * comparison against an absent value earlier, and distinguishes the loose form
147
+ * from the strict one itself (`emit-presence.ts`). What is left is the case the
148
+ * spec collapses, so collapsing it here is the language's own answer rather
149
+ * than this emitter's approximation of it.
150
+ */
151
+ const numericBinaryOperators = new Map([
152
+ ['+', { kind: 'infix', text: '+' }],
153
+ ['-', { kind: 'infix', text: '-' }],
154
+ ['*', { kind: 'infix', text: '*' }],
155
+ ['/', { kind: 'infix', text: '/' }],
156
+ ['%', { kind: 'call', text: 'gea::remainder' }],
157
+ ['**', { kind: 'call', text: 'std::pow' }],
158
+ ['<', { kind: 'infix', text: '<' }],
159
+ ['>', { kind: 'infix', text: '>' }],
160
+ ['<=', { kind: 'infix', text: '<=' }],
161
+ ['>=', { kind: 'infix', text: '>=' }],
162
+ ['===', { kind: 'infix', text: '==' }],
163
+ ['!==', { kind: 'infix', text: '!=' }],
164
+ ['==', { kind: 'infix', text: '==' }],
165
+ ['!=', { kind: 'infix', text: '!=' }],
166
+ // ECMA-262 6.1.6.1.16-19: both operands go through ToInt32 (7.1.6), the 32-bit
167
+ // two's-complement bits combine, and the result widens back to Number as signed.
168
+ ['&', { kind: 'call', text: 'gea::bitwiseAnd' }],
169
+ ['|', { kind: 'call', text: 'gea::bitwiseOr' }],
170
+ ['^', { kind: 'call', text: 'gea::bitwiseXor' }],
171
+ // ECMA-262 6.1.6.1.9-11: the shift count is ToUint32(rhs) (7.1.7) modulo 32;
172
+ // `<<`/`>>` keep the left signed (ToInt32), `>>>` makes it unsigned (ToUint32)
173
+ // -- the one place these diverge from AND/OR/XOR, so each gets its own wrapper.
174
+ ['<<', { kind: 'call', text: 'gea::leftShift' }],
175
+ ['>>', { kind: 'call', text: 'gea::signedRightShift' }],
176
+ ['>>>', { kind: 'call', text: 'gea::unsignedRightShift' }]
177
+ ]);
178
+ /** The relational operators `mixedRelationalText` answers -- IsLessThan's own four spellings, never `===`/`==` (a different rule, `emit-equality.ts`). */
179
+ const relationalOperators = new Set(['<', '>', '<=', '>=']);
180
+ const stringBinaryOperators = new Map([
181
+ ['+', { kind: 'infix', text: '+' }],
182
+ ['<', { kind: 'infix', text: '<' }],
183
+ ['>', { kind: 'infix', text: '>' }],
184
+ ['<=', { kind: 'infix', text: '<=' }],
185
+ ['>=', { kind: 'infix', text: '>=' }],
186
+ ['===', { kind: 'infix', text: '==' }],
187
+ ['!==', { kind: 'infix', text: '!=' }],
188
+ ['==', { kind: 'infix', text: '==' }],
189
+ ['!=', { kind: 'infix', text: '!=' }]
190
+ ]);
191
+ /**
192
+ * Symbols compare and do nothing else.
193
+ *
194
+ * `<`/`>`/`+` on a symbol are TypeErrors in the language, so they have no
195
+ * spelling here rather than a wrong one. `==` is listed beside `===` because
196
+ * this table is only ever reached with BOTH sides already carrying `symbol`
197
+ * (`emitCompute` refuses a mixed-carrier operator above it), and for two
198
+ * symbols the loose and strict comparisons are the same operation.
199
+ */
200
+ const symbolBinaryOperators = new Map([
201
+ ['===', { kind: 'infix', text: '==' }],
202
+ ['!==', { kind: 'infix', text: '!=' }],
203
+ ['==', { kind: 'infix', text: '==' }],
204
+ ['!=', { kind: 'infix', text: '!=' }]
205
+ ]);
206
+ /**
207
+ * `||` is here and `logical` is not the form that reaches it.
208
+ *
209
+ * A source `a || b` is a `logical` computation -- ECMA-262 13.13.1 evaluates
210
+ * the right operand only when the left is falsy -- and `ir/lower.ts` lowers
211
+ * that one through a merge of two arms, never through this table. What arrives
212
+ * here as a `binary` `||` is a disjunction whose operands are both already
213
+ * evaluated values, which is what `producers/control.ts` mints to give a group
214
+ * of `case` clauses one guard. Rendering it `a || b` is exact: C++ would
215
+ * short-circuit a computation that has already happened.
216
+ */
217
+ const booleanBinaryOperators = new Map([
218
+ ['===', { kind: 'infix', text: '==' }],
219
+ ['!==', { kind: 'infix', text: '!=' }],
220
+ ['==', { kind: 'infix', text: '==' }],
221
+ ['!=', { kind: 'infix', text: '!=' }],
222
+ ['||', { kind: 'infix', text: '||' }]
223
+ ]);
224
+ /**
225
+ * ECMAScript OBJECT IDENTITY, for the two carriers that are exactly a pointer.
226
+ *
227
+ * `IsStrictlyEqual` on two objects (ECMA-262 7.2.16, via SameValueNonNumber
228
+ * 7.2.12) is "the same object reference", and both of these carriers are a
229
+ * `std::shared_ptr` to an object nothing copies behind the program's back --
230
+ * so `==` on the pointers answers precisely that question, with no conversion
231
+ * invented. `view.buffer === buffer` is the idiom this exists for: it is how a
232
+ * program asks whether two views alias the same block, and the only way to ask
233
+ * it that does not involve writing through one view and reading another.
234
+ *
235
+ * It is deliberately NOT generalized to every reference-shaped carrier.
236
+ * `borrowed-ref` and `native-record-ref` are views this compiler mints rather
237
+ * than objects the program created, and a `record` may be carried by value --
238
+ * pointer identity on any of those would answer a different question than the
239
+ * language asks, so they keep refusing by name.
240
+ */
241
+ const referenceIdentityOperators = new Map([
242
+ ['===', { kind: 'infix', text: '==' }],
243
+ ['!==', { kind: 'infix', text: '!=' }],
244
+ ['==', { kind: 'infix', text: '==' }],
245
+ ['!=', { kind: 'infix', text: '!=' }]
246
+ ]);
247
+ const binaryOperatorFor = (operator, carrier) => {
248
+ if (carrier.kind === 'string')
249
+ return stringBinaryOperators.get(operator) ?? null;
250
+ // `CallableObject` stores the ECMAScript function allocation's stable
251
+ // identity, and its `operator==` compares exactly that identity. Copies and
252
+ // ABI adapters preserve it, while separately evaluated capture-free arrows
253
+ // receive distinct identities. The carrier therefore owns the same strict
254
+ // and loose same-type equality rule as Symbol and the pointer-backed object
255
+ // carriers below.
256
+ if (carrier.kind === 'function-value-dispatch')
257
+ return referenceIdentityOperators.get(operator) ?? null;
258
+ // The identity carrier IS that stable identity, reached through the same
259
+ // handle -- so equality on it is the very comparison the paragraph above
260
+ // describes, with the convention stripped away.
261
+ if (carrier.kind === 'callable-identity')
262
+ return referenceIdentityOperators.get(operator) ?? null;
263
+ // Two references to one generic source function are one function object,
264
+ // and the set's tag IS which function: equal tags, same function.
265
+ if (carrier.kind === 'generic-function-set')
266
+ return referenceIdentityOperators.get(operator) ?? null;
267
+ // A native handle with no host-stated carrier is `gea::NativeHandle<Tag>`,
268
+ // whose whole content is the `int id_` indexing the native store -- so two
269
+ // handles name the same host object exactly when their ids agree, and `==`
270
+ // over that id is the entirety of SameValueNonNumeric for the carrier. This
271
+ // is what answers `const m = Math; m === Math` for a namespace-shaped
272
+ // protocol, where the handle has exactly one inhabitant.
273
+ //
274
+ // A protocol whose plugin DID state a carrier is spelled as that host type
275
+ // instead (`cppTypeOf`'s `representation.native ?? ...`), and this emitter
276
+ // has been told nothing about its equality -- so it keeps refusing rather
277
+ // than emitting a comparison whose meaning belongs to the host.
278
+ if (carrier.kind === 'native-handle')
279
+ return carrier.native === null ? (referenceIdentityOperators.get(operator) ?? null) : null;
280
+ if (carrier.kind === 'array-buffer' ||
281
+ carrier.kind === 'shared-array-buffer' ||
282
+ carrier.kind === 'data-view' ||
283
+ (carrier.kind === 'typed-array' && carrier.ownership === 'shared-refcount'))
284
+ return referenceIdentityOperators.get(operator) ?? null;
285
+ if (carrier.kind === 'symbol')
286
+ return symbolBinaryOperators.get(operator) ?? null;
287
+ if (carrier.kind !== 'scalar')
288
+ return null;
289
+ if (carrier.domain === 'boolean')
290
+ return booleanBinaryOperators.get(operator) ?? null;
291
+ if (carrier.domain === 'bigint') {
292
+ if (operator === '**')
293
+ return { kind: 'call', text: 'gea::BigInt::pow' };
294
+ if (operator === '>>>')
295
+ return null;
296
+ const spelling = numericBinaryOperators.get(operator);
297
+ return spelling ? { kind: 'infix', text: ['%', '&', '|', '^', '<<', '>>'].includes(operator) ? operator : spelling.text } : null;
298
+ }
299
+ if (carrier.domain === 'number' || carrier.domain === 'float64')
300
+ return numericBinaryOperators.get(operator) ?? null;
301
+ // int32/uint32/bigint have exact range semantics that a bare C++ operator does
302
+ // not reproduce (wrapping, promotion, arbitrary precision); no spelling here.
303
+ return null;
304
+ };
305
+ const updateStepOperators = new Map([
306
+ ['++', '+'],
307
+ ['--', '-']
308
+ ]);
309
+ const numericUnaryOperators = new Map([
310
+ ['-', { kind: 'infix', text: '-' }],
311
+ ['+', { kind: 'infix', text: '+' }],
312
+ // ECMA-262 6.1.6.1.2 Number::bitwiseNOT: ToInt32(x) (7.1.6), bitwise
313
+ // complement, widened back to Number as signed -- the same round trip
314
+ // `gea::bitwiseAnd`/... perform, so it goes through the identical helper.
315
+ ['~', { kind: 'call', text: 'gea::bitwiseNot' }]
316
+ ]);
317
+ const unaryOperatorFor = (operator, carrier) => {
318
+ if (carrier.kind === 'scalar' && carrier.domain === 'bigint')
319
+ return operator === '-' || operator === '~' ? { kind: 'infix', text: operator } : null;
320
+ if (carrier.kind === 'scalar' && carrier.domain === 'boolean')
321
+ return operator === '!' ? { kind: 'infix', text: '!' } : null;
322
+ if (carrier.kind === 'scalar' && (carrier.domain === 'number' || carrier.domain === 'float64')) {
323
+ return numericUnaryOperators.get(operator) ?? null;
324
+ }
325
+ return null;
326
+ };
327
+ const emitCompute = (ctx, lines, operation) => {
328
+ // `ctx.computeOrigins` already names this operation for this result --
329
+ // settled in `EmitBodyFacts` before any spelling is chosen, so
330
+ // `emit-bindings.ts` can recognize a cell's own compound update regardless
331
+ // of which of the returns below spells this same operation.
332
+ const queryComparison = ctx.typeQueryComparisons.get(operation);
333
+ if (queryComparison) {
334
+ const left = queryComparison.left.kind === 'tag' ? operandText(ctx, queryComparison.left.operand) : typeofTagLiteral(queryComparison.left.text);
335
+ const right = queryComparison.right.kind === 'tag' ? operandText(ctx, queryComparison.right.operand) : typeofTagLiteral(queryComparison.right.text);
336
+ const answer = left === null || right === null ? String(queryComparison.unequal) : `${left} ${queryComparison.unequal ? '!=' : '=='} ${right}`;
337
+ lines.push(`${defineValue(ctx, operation.result)} = ${answer};`);
338
+ return;
339
+ }
340
+ const operands = operation.operands;
341
+ if (operation.nativeEquality) {
342
+ const left = operands[0];
343
+ const right = operands[1];
344
+ if (!left || !right)
345
+ throw createCppEmitBlockedError('runtime-helper:computation:binary:arity', 'a native equality recipe requires two operands');
346
+ const answer = nativeEqualityText(operation.nativeEquality, [operandText(ctx, left), operandText(ctx, right)]);
347
+ lines.push(`${defineValue(ctx, operation.result)} = ${answer};`);
348
+ return;
349
+ }
350
+ // `void x` evaluates its operand and yields `undefined` (ECMA-262 13.5.2).
351
+ // Nothing about that answer depends on what the operand carried, so it is
352
+ // settled before any carrier lookup -- like `!` below, and unlike `-`/`+`,
353
+ // which run ToNumber and so must consult one. The operand's own evaluation
354
+ // is already its own operation in this graph, so discarding its value here
355
+ // is the whole of the semantics -- which is also why this is the one form
356
+ // that legitimately arrives with NO operand at all: `void f()` for an `f`
357
+ // that returns nothing has no SSA name to cite, and the lowering cites none
358
+ // rather than inventing one (`ir/lower.ts`).
359
+ if (operation.form === 'unary' && operation.operator === 'void') {
360
+ const produced = operation.result.representation;
361
+ if (produced.kind !== 'undefined') {
362
+ throw createCppEmitBlockedError(`physical-cpp-type:${representationKey(produced)}`, `unary "void" published a "${produced.kind}" carrier, but the language gives the expression undefined`);
363
+ }
364
+ lines.push(`${defineValue(ctx, operation.result)} = ${cppUndefinedValue};`);
365
+ return;
366
+ }
367
+ const first = operands[0];
368
+ if (!first)
369
+ throw createCppEmitBlockedError('runtime-helper:computation:no-operands', 'a computation with no operands has no C++ spelling');
370
+ if (operation.form === 'require-object-coercible') {
371
+ const text = operandText(ctx, first);
372
+ lines.push(`if (!(${presenceTestText(text, first.representation)})) gea::host::throwGetPropertyOfNullish<void>();`);
373
+ defineValueAlias(ctx, operation.result, text);
374
+ return;
375
+ }
376
+ // The presence half of an array pattern's own possibly-absent source
377
+ // (`ir/lower-destructuring.ts`'s `lowerArrayPatternSource`): the identical
378
+ // `gea::detail::requireIterablePresent` the general `for`-`of` protocol's
379
+ // own absent sources already call in front of their cursor constructor
380
+ // (`emit-iterator.ts`), reused here in front of the array-pattern fast
381
+ // path's positional reads instead.
382
+ if (operation.form === 'require-iterable-present') {
383
+ const text = operandText(ctx, first);
384
+ const name = defineValue(ctx, operation.result);
385
+ lines.push(`${name} = gea::detail::requireIterablePresent(${text}, ${cppStringLiteral('a nested array-destructuring position')});`);
386
+ return;
387
+ }
388
+ // The arm half of the same source, once unwrapped: `soleArrayPatternCapableArm`
389
+ // (`representation/model.ts`) proved exactly one arm of this tagged union
390
+ // supports the pattern's positional reads at compile time, but which VALUE
391
+ // this program actually holds at runtime is still an open question -- the
392
+ // other arm is a real value ECMA-262 7.4.2's `GetIterator` would throw a
393
+ // `TypeError` over, and this is that throw. The arm index was carried
394
+ // through the `operator` field as a decimal string (see `ir/model.ts`'s
395
+ // own doc for why) rather than a real language operator, since `.is<N>()`/
396
+ // `.get<N>()` need it as a compile-time template argument.
397
+ if (operation.form === 'require-tagged-union-arm') {
398
+ const text = operandText(ctx, first);
399
+ const index = operation.operator;
400
+ const name = defineValue(ctx, operation.result);
401
+ lines.push(`if (!(${text}).is<${index}>()) gea::detail::refuseTaggedUnionArmMismatch(${cppStringLiteral('a nested array-destructuring position')});`);
402
+ lines.push(`${name} = (${text}).get<${index}>();`);
403
+ return;
404
+ }
405
+ if (operation.form === 'unary') {
406
+ if (operation.operator === 'ObjectTag') {
407
+ const answer = objectTagExpression(first.representation, operandText(ctx, first), ctx);
408
+ if (answer === null)
409
+ throw createCppEmitBlockedError(`runtime-helper:${objectTagCapability(first.representation)}`, 'Object.prototype.toString has no native tag algorithm for this carrier');
410
+ lines.push(`${defineValue(ctx, operation.result)} = ${answer};`);
411
+ return;
412
+ }
413
+ // `!x` is `ToBoolean(x)` negated, over whatever carrier `x` arrived in --
414
+ // the same abstract operation a conditional's guard runs, so it is spelled
415
+ // by the same authority rather than by a second rule that could disagree
416
+ // with it. Only `!` is a coercion this way: `-x`/`+x` run ToNumber, which
417
+ // is a different table and stays on the operator map below.
418
+ if (operation.operator === '!') {
419
+ const name = defineValue(ctx, operation.result);
420
+ lines.push(`${name} = !${booleanTestText(operandText(ctx, first), first.representation, isIntegerStorageValue(ctx, first.value))};`);
421
+ return;
422
+ }
423
+ // `delete o.p`'s value is the boolean its own `[[Delete]]` published.
424
+ if (operation.operator === 'delete') {
425
+ emitUnaryDelete(ctx, lines, defineValue(ctx, operation.result), first);
426
+ return;
427
+ }
428
+ if (operation.operator === 'ToNumeric')
429
+ return emitToNumericCoercion(ctx, lines, first, operation.result);
430
+ const spelling = unaryOperatorFor(operation.operator, first.representation);
431
+ if (!spelling) {
432
+ throw createCppEmitBlockedError(`runtime-helper:computation:unary:${operation.operator}:${first.representation.kind}`, `unary "${operation.operator}" on a "${first.representation.kind}" carrier has no C++ spelling in this emitter`);
433
+ }
434
+ const name = defineValue(ctx, operation.result);
435
+ const operandRendered = operandText(ctx, first);
436
+ const narrowedNot = operation.operator === '~' && ctx.integerValues.has(first.value);
437
+ const call = narrowedNot ? `gea::integerBitwiseNot(${operandRendered})` : `${spelling.text}(${operandRendered})`;
438
+ // C++ integer zero has no negative representation: `-(0)` is still the
439
+ // integer `0`, and converting it to double afterward loses JavaScript's
440
+ // observable -0 (`Object.is`, reciprocal sign, BSON number width). Give a
441
+ // constant zero a floating spelling before negation; every nonzero unary
442
+ // operation keeps the ordinary carrier-directed spelling.
443
+ const constantText = ctx.constantTexts.get(first.value);
444
+ const negativeZero = operation.operator === '-' &&
445
+ first.representation.kind === 'scalar' &&
446
+ (first.representation.domain === 'number' || first.representation.domain === 'float64') &&
447
+ constantText !== undefined &&
448
+ Number(constantText) === 0;
449
+ const expression = negativeZero ? '-0.0' : spelling.kind === 'infix' ? `${spelling.text}${operandRendered}` : call;
450
+ lines.push(`${name} = ${expression};`);
451
+ return;
452
+ }
453
+ // `typeof` is a question about the carrier, and for every carrier but a sum
454
+ // the answer is settled before the program runs. `emit-typeof.ts` owns both
455
+ // the mapping and the refusal.
456
+ if (operation.form === 'typeof') {
457
+ // A member read off a union whose arms disagree about the member: the
458
+ // answer is per-arm and the read itself rendered nothing, so the
459
+ // discriminant answers here. See `EmitContext.unionMemberTypeofReads`.
460
+ const memberRead = ctx.unionMemberTypeofReads.get(first.value);
461
+ if (memberRead !== undefined) {
462
+ const receiver = operandText(ctx, memberRead.receiver);
463
+ const answer = ctx.typeQueryValues.has(operation.result.id)
464
+ ? unionMemberTypeofTagText(memberRead.answers, receiver, memberRead.member)
465
+ : unionMemberTypeofText(memberRead.answers, receiver, memberRead.member);
466
+ lines.push(`${defineValue(ctx, operation.result)} = ${answer};`);
467
+ return;
468
+ }
469
+ const namespacePath = ctx.hostNamespaceReads.get(first.value) ?? ctx.hostNamespaceValues.get(first.value);
470
+ const namespaceTypeof = namespacePath === undefined ? undefined : ctx.hosts.namespaces.typeofs.get(namespacePath);
471
+ if (ctx.typeQueryValues.has(operation.result.id)) {
472
+ const tag = namespaceTypeof === undefined
473
+ ? typeofTagText(first.representation, () => operandText(ctx, first))
474
+ : typeofTagLiteral(namespaceTypeof);
475
+ if (tag === null)
476
+ throw createCppEmitBlockedError(`runtime-helper:computation:typeof:${representationKey(first.representation)}`, `host typeof published an unknown result ${namespaceTypeof}`);
477
+ lines.push(`${defineValue(ctx, operation.result)} = ${tag};`);
478
+ return;
479
+ }
480
+ if (namespaceTypeof !== undefined) {
481
+ ctx.constantTexts.set(operation.result.id, namespaceTypeof);
482
+ lines.push(`${defineValue(ctx, operation.result)} = ${cppConstantLiteral(namespaceTypeof, 'string', operation.result.representation)};`);
483
+ return;
484
+ }
485
+ // A settled answer is a string CONSTANT, and saying so is what lets every
486
+ // later rule that reasons about constants see it -- the comparison fold
487
+ // above included. Without this the two halves of `typeof x !== 'undefined'`
488
+ // were a folded literal and a recorded constant, so the fold did not fire
489
+ // and the pair reached C++ as `("object") != ("undefined")`: two literal
490
+ // ADDRESSES. Only recorded when the answer really is static; a sum answers
491
+ // at runtime and is no constant.
492
+ const settled = typeofTextFor(first.representation);
493
+ if (settled !== null)
494
+ ctx.constantTexts.set(operation.result.id, settled);
495
+ lines.push(`${defineValue(ctx, operation.result)} = ${typeofText(first.representation, () => operandText(ctx, first))};`);
496
+ return;
497
+ }
498
+ // `instanceof` is `[[HasInstance]]`, which this backend answers only for the
499
+ // error constructors -- see `emit-instanceof.ts` for why the general case is
500
+ // refused rather than approximated.
501
+ if (operation.form === 'instanceof') {
502
+ const constructor = operands[1];
503
+ if (!constructor || operands.length !== 2) {
504
+ throw createCppEmitBlockedError('runtime-helper:computation:instanceof:arity', `an "instanceof" with ${operands.length} operand(s) has no C++ spelling`);
505
+ }
506
+ lines.push(`${defineValue(ctx, operation.result)} = ${instanceofText(ctx, first, constructor, operation.classInstanceTest)};`);
507
+ return;
508
+ }
509
+ // A template is a concatenation of its pieces, each through ToString.
510
+ if (operation.form === 'template') {
511
+ const rendered = templateText(ctx, operation);
512
+ if ('refused' in rendered)
513
+ throw createCppEmitBlockedError('runtime-helper:computation:template', toStringRefusal(rendered.refused, ctx.classes, ctx.deriver));
514
+ lines.push(`${defineValue(ctx, operation.result)} = ${rendered.text};`);
515
+ return;
516
+ }
517
+ // `x++` is `x + 1` over the value ToNumeric already produced, and `x--` is
518
+ // `x - 1`. The store is a separate operation; this instruction only computes
519
+ // the number that gets stored, so it never appears as a C++ `++`.
520
+ if (operation.form === 'update') {
521
+ const step = updateStepOperators.get(operation.operator);
522
+ if (!step || !binaryOperatorFor(step, first.representation)) {
523
+ throw createCppEmitBlockedError(`runtime-helper:computation:update:${operation.operator}:${first.representation.kind}`, `update "${operation.operator}" on a "${first.representation.kind}" carrier has no C++ spelling in this emitter`);
524
+ }
525
+ const name = defineValue(ctx, operation.result), raw = `${operandText(ctx, first)} ${step} 1`;
526
+ lines.push(`${name} = ${widenedStoreText(operation.result.representation, first.representation, raw) ?? raw};`);
527
+ return;
528
+ }
529
+ const second = operands[1];
530
+ if (!second || operands.length !== 2) {
531
+ throw createCppEmitBlockedError('runtime-helper:computation:binary:arity', `a binary computation with ${operands.length} operand(s) has no C++ spelling`);
532
+ }
533
+ // Equality against `null`/`undefined` is settled by the carriers, not by a
534
+ // conversion between them, so it is answered before the mixed-carrier refusal
535
+ // below -- which would otherwise reject the language's most common absence
536
+ // check as a coercion with no recipe.
537
+ // Native host singleton/class handles are compile-time identity tags. Do
538
+ // not ask them for a runtime value before answering identity: authenticated
539
+ // `process === globalThis.process` has two routes to the same Process
540
+ // protocol and neither route needs to box or materialize that singleton.
541
+ const firstHostIdentity = ctx.hostClassReads.get(first.value);
542
+ const secondHostIdentity = ctx.hostClassReads.get(second.value);
543
+ if (firstHostIdentity && secondHostIdentity && referenceIdentityOperators.has(operation.operator)) {
544
+ const equal = firstHostIdentity.declaration === secondHostIdentity.declaration;
545
+ const negated = operation.operator === '!==' || operation.operator === '!=';
546
+ const answer = equal !== negated ? 'true' : 'false';
547
+ lines.push(`${defineValue(ctx, operation.result)} = ${answer};`);
548
+ return;
549
+ }
550
+ const sides = [first, second].map((operand) => ({ text: operandText(ctx, operand), representation: operand.representation }));
551
+ const absent = sides[0] && sides[1] ? absenceComparisonText(operation.operator, sides[0], sides[1]) : null;
552
+ if (absent !== null) {
553
+ lines.push(`${defineValue(ctx, operation.result)} = ${absent};`);
554
+ return;
555
+ }
556
+ // Function equality is allocation identity even when the two statically
557
+ // visible call signatures differ. The rule itself is
558
+ // `callableIdentityEqualityText`, asked here and from inside
559
+ // `strictEqualityText`'s own recursion so that a callable wrapped in an
560
+ // OPTIONAL gets the identical answer -- it used to live inline here, where
561
+ // that recursion could not reach it. `Alias === Routed` in
562
+ // `dynamic-callable-abi-recovery.runtime.js` is the bare pair;
563
+ // `stateStack[stackIndex] !== State.done` in `generic-state-function-array.ts`
564
+ // is the wrapped one.
565
+ const callableIdentity = sides[0] && sides[1] ? callableIdentityEqualityText(operation.operator, sides[0], sides[1]) : null;
566
+ if (callableIdentity !== null) {
567
+ lines.push(`${defineValue(ctx, operation.result)} = ${callableIdentity};`);
568
+ return;
569
+ }
570
+ // A sum on either side is a discriminant test plus one arm's comparison,
571
+ // which the generic path below cannot reach: two different carriers hit its
572
+ // mixed-carrier refusal, and two identical sums hit `binaryOperatorFor`,
573
+ // which has no `==` for a byte buffer. Answered here, before both.
574
+ const equality = sides[0] && sides[1] ? strictEqualityText(operation.operator, sides[0], sides[1]) : null;
575
+ if (equality !== null) {
576
+ lines.push(`${defineValue(ctx, operation.result)} = ${equality};`);
577
+ return;
578
+ }
579
+ // Two string constants compared: answered in the source language rather than
580
+ // by a C++ operator, which would compare the two literals' ADDRESSES. See
581
+ // `constantStringComparisonText`. Before the `+` fold below because `+` on
582
+ // two strings is concatenation, which that fold already owns.
583
+ if (first.representation.kind === 'string' && second.representation.kind === 'string') {
584
+ const leftConstant = ctx.constantTexts.get(first.value);
585
+ const rightConstant = ctx.constantTexts.get(second.value);
586
+ if (leftConstant !== undefined && rightConstant !== undefined) {
587
+ const folded = constantStringComparisonText(operation.operator, leftConstant, rightConstant);
588
+ if (folded !== null) {
589
+ lines.push(`${defineValue(ctx, operation.result)} = ${folded};`);
590
+ return;
591
+ }
592
+ }
593
+ }
594
+ // `+` is string concatenation whenever either operand is a string, and the
595
+ // plan has already settled which `+` this is: the result carrier. Both sides
596
+ // then go through ToString, folded by the same authority a template
597
+ // expression uses -- `'n: ' + count` and `` `n: ${count}` `` are the same
598
+ // value, and spelling them by two rules that could disagree is how one of
599
+ // them ends up wrong. A carrier with no ToString refuses by name here exactly
600
+ // as it does in a template, rather than being boxed.
601
+ if (operation.operator === '+' && operation.result.representation.kind === 'string') {
602
+ const rendered = templateText(ctx, operation);
603
+ if ('refused' in rendered)
604
+ throw createCppEmitBlockedError('runtime-helper:computation:template', toStringRefusal(rendered.refused, ctx.classes, ctx.deriver));
605
+ lines.push(`${defineValue(ctx, operation.result)} = ${rendered.text};`);
606
+ return;
607
+ }
608
+ // Exactly one side already `dynamic` and the other an ordinary typed
609
+ // carrier -- `parsed + 1`, `1 + parsed` where `parsed` came from
610
+ // `JSON.parse` or a declared `any` never narrowed -- is answered without
611
+ // boxing the typed side (`mixedDynamicPlusText`'s own comment says why),
612
+ // and UNCONDITIONALLY: a `dynamic` carrier this ordinary is not the opt-in
613
+ // `ctx.deriver.dynamicFallback` feature (that flag gates a different,
614
+ // riskier fallback below), and gating this recipe behind it left the most
615
+ // common dynamic-boundary program -- `JSON.parse(...) + 1` -- refusing by
616
+ // name with exactly this file's own "mixes a dynamic and a scalar carrier"
617
+ // message whenever the flag was off, which is the ordinary case.
618
+ if (operation.operator === '+') {
619
+ const firstDynamic = first.representation.kind === 'dynamic';
620
+ const secondDynamic = second.representation.kind === 'dynamic';
621
+ if (firstDynamic !== secondDynamic) {
622
+ const dynamicOperand = firstDynamic ? sides[0] : sides[1];
623
+ const typedOperand = firstDynamic ? sides[1] : sides[0];
624
+ const native = dynamicOperand && typedOperand ? mixedDynamicPlusText(dynamicOperand, typedOperand, firstDynamic, ctx.classes, ctx.deriver) : null;
625
+ if (native !== null) {
626
+ const dynamicResult = { kind: 'dynamic', reason: 'opt-in-fallback' };
627
+ const text = alignedValueText(ctx, 'emit.ts:711', dynamicResult, operation.result.representation, native);
628
+ if (text === null)
629
+ throw createCppEmitBlockedError(`conversion:dynamic->${representationKey(operation.result.representation)}`, 'dynamic addition result has no checked conversion');
630
+ lines.push(`${defineValue(ctx, operation.result)} = ${text};`);
631
+ return;
632
+ }
633
+ }
634
+ }
635
+ // Two dynamic sides, or a `tagged-union` on either side, still need
636
+ // `gea::dynamicAdd`'s full ToPrimitive dispatch -- a tagged union's live
637
+ // arm is exactly as unknown at compile time as a dynamic operand's tag, and
638
+ // two genuinely dynamic operands may each be a real JS object whose own
639
+ // `valueOf`/`toString` only `gea::dynamicAdd` runs. This IS the boxing this
640
+ // file's header describes as correct to keep, and stays behind the opt-in
641
+ // flag: it is the one case left that boxes an operand this backend could
642
+ // otherwise have kept native (the `firstDynamic !== secondDynamic` branch
643
+ // just above, when it applies).
644
+ if (ctx.deriver.dynamicFallback &&
645
+ operation.operator === '+' &&
646
+ (first.representation.kind === 'dynamic' ||
647
+ second.representation.kind === 'dynamic' ||
648
+ first.representation.kind === 'tagged-union' ||
649
+ second.representation.kind === 'tagged-union')) {
650
+ const left = boxedValueText(ctx, first, 'dynamic addition');
651
+ const right = boxedValueText(ctx, second, 'dynamic addition');
652
+ const dynamic = { kind: 'dynamic', reason: 'opt-in-fallback' };
653
+ const text = alignedValueText(ctx, 'emit.ts:738', dynamic, operation.result.representation, `gea::dynamicAdd(${left}, ${right})`);
654
+ if (text === null)
655
+ throw createCppEmitBlockedError(`conversion:dynamic->${representationKey(operation.result.representation)}`, 'dynamic addition result has no checked conversion');
656
+ lines.push(`${defineValue(ctx, operation.result)} = ${text};`);
657
+ return;
658
+ }
659
+ // A function compared against a function IDENTITY. Not a coercion this file
660
+ // invents: the identity IS what `CallableObject::operator==` compares, so
661
+ // converting the callable side to its own identity handle (the very field
662
+ // that comparison reads) and comparing the two handles is the same answer
663
+ // written one step earlier. Restricted to the four same-type equality
664
+ // operators, which is all `referenceIdentityOperators` spells.
665
+ const identitySpelling = referenceIdentityOperators.get(operation.operator);
666
+ const identitySide = first.representation.kind === 'callable-identity' ? 0 : second.representation.kind === 'callable-identity' ? 1 : null;
667
+ if (identitySpelling && identitySide !== null) {
668
+ const callable = identitySide === 0 ? second : first;
669
+ const identityCarrier = { kind: 'callable-identity' };
670
+ const converted = alignedValueText(ctx, 'emit.ts:764', callable.representation, identityCarrier, operandText(ctx, callable));
671
+ if (converted !== null) {
672
+ const held = operandText(ctx, identitySide === 0 ? first : second);
673
+ const [left, right] = identitySide === 0 ? [held, converted] : [converted, held];
674
+ lines.push(`${defineValue(ctx, operation.result)} = ${left} ${identitySpelling.text} ${right};`);
675
+ return;
676
+ }
677
+ }
678
+ // Two carriers reaching an operator is not a decision this printer makes
679
+ // any more: ECMA-262's ToNumeric/ToPrimitive before a binary operator is a
680
+ // conversion, and the slot census states it (`projection/slots.ts`'s
681
+ // `binarySlot`) -- lowering coerces both operands into one carrier, or the
682
+ // coercion node is `never` and the operands arrive as they were. What is
683
+ // left here is exactly that `never`: BigInt mixed with Number, a Date's
684
+ // `valueOf`-first ToPrimitive, an object whose own `toString` would have
685
+ // to be called. Refused by name, never spelled by a second table.
686
+ if (representationKey(first.representation) !== representationKey(second.representation)) {
687
+ throw createCppEmitBlockedError(`conversion:${representationKey(first.representation)}->${representationKey(second.representation)}`, `binary "${operation.operator}" mixes a "${first.representation.kind}" and a "${second.representation.kind}" carrier, ` +
688
+ 'and the census names no coercion that brings them together');
689
+ }
690
+ const spelling = binaryOperatorFor(operation.operator, first.representation);
691
+ if (!spelling) {
692
+ throw createCppEmitBlockedError(`runtime-helper:computation:binary:${operation.operator}:${first.representation.kind}`, `binary "${operation.operator}" on a "${first.representation.kind}" carrier has no C++ spelling in this emitter`);
693
+ }
694
+ const name = defineValue(ctx, operation.result);
695
+ const integral = ctx.integerValues.has(first.value) && ctx.integerValues.has(second.value);
696
+ // `/` is the one arithmetic operator whose C++ meaning CHANGES when both
697
+ // operands are integers: `7 / 2` would become 3 rather than 3.5, so two
698
+ // narrowed operands are widened back for it. `%` goes the other way -- C++
699
+ // truncates toward zero just as ECMA-262 6.1.6.1.6 does, so an integer
700
+ // remainder is the same answer without the fmod round trip, under its own
701
+ // name rather than an overload (a mixed call would make a pair ambiguous).
702
+ const widenForDivision = integral && operation.operator === '/';
703
+ const left = widenForDivision ? `static_cast<double>(${operandText(ctx, first)})` : operandText(ctx, first);
704
+ const right = widenForDivision ? `static_cast<double>(${operandText(ctx, second)})` : operandText(ctx, second);
705
+ const bounded = integerBoundedComparison(ctx.integerValues, ctx.loopInvariantValues, operation, first, second, left, right);
706
+ if (bounded !== null) {
707
+ lines.push(`${name} = ${bounded};`);
708
+ return;
709
+ }
710
+ // The cheaper spellings of `%`, chosen by the integer census (`ir/integers.ts`)
711
+ // and written out by `emit-integers.ts`; `null` keeps `gea::remainder`.
712
+ const form = integral && ctx.integerValues.has(operation.result.id) ? 'narrowed' : ctx.remainderForms.get(operation.result.id);
713
+ const hoisted = operation.operator === '%' ? ctx.denseLengths.get(second.value) : undefined;
714
+ const remainder = operation.operator !== '%' ? null : remainderText(form, left, right, ctx.declarations, hoisted);
715
+ if (remainder !== null) {
716
+ // A wrapped window's subscript is computed in the INTEGERS (`denseRemainderCompanion`).
717
+ const window = hoisted === undefined || !ctx.integerValues.has(first.value) ? undefined : hoisted;
718
+ const dense = window === undefined ? null : denseRemainderCompanion(window, left, ctx.declarations, lines);
719
+ if (dense !== null)
720
+ ctx.denseIndices.set(operation.result.id, dense.index);
721
+ lines.push(`${name} = ${dense === null ? remainder : dense.value};`);
722
+ return;
723
+ }
724
+ const integerBitwise = integral ? integerBitwiseOperators.get(operation.operator) : undefined;
725
+ if (integerBitwise !== undefined) {
726
+ lines.push(`${name} = ${integerBitwise}(${left}, ${right});`);
727
+ return;
728
+ }
729
+ const expression = spelling.kind === 'infix' ? `${left} ${spelling.text} ${right}` : `${spelling.text}(${left}, ${right})`;
730
+ // Coerced operands compute the operator's own result -- a Number, a String
731
+ // for `+` over strings, a Boolean for a relational -- but the CELL is what
732
+ // the checker published for the expression, which is `dynamic` whenever it
733
+ // could not type the mixed operands (`number + null` is a strictNullChecks
734
+ // error recovered as `any`). The census converts the operator's result
735
+ // into that cell like any other store; a scalar or string cell is the
736
+ // operator's own carrier already (an integer-narrowed cell included).
737
+ const result = operation.result.representation;
738
+ const natural = relationalOperators.has(operation.operator)
739
+ ? { kind: 'scalar', domain: 'boolean' }
740
+ : first.representation.kind === 'string'
741
+ ? { kind: 'string' }
742
+ : { kind: 'scalar', domain: 'number' };
743
+ const stored = result.kind === 'scalar' || result.kind === 'string' || representationKey(natural) === representationKey(result)
744
+ ? expression
745
+ : alignedValueText(ctx, 'emit.ts:compute-result', natural, result, expression);
746
+ if (stored === null) {
747
+ throw createCppEmitBlockedError(`conversion:${representationKey(natural)}->${representationKey(result)}`, `binary "${operation.operator}" produces a ${representationKey(natural)} that no installed conversion stores into ${representationKey(result)}`);
748
+ }
749
+ lines.push(`${name} = ${stored};`);
750
+ };
751
+ const emitParameter = (ctx, _lines, operation) => {
752
+ const declared = ctx.abi?.parameters[operation.ordinal];
753
+ if (!declared) {
754
+ throw createCppEmitBlockedError('call-abi:parameter', `reads ABI position ${operation.ordinal}, which this body's calling convention does not declare`);
755
+ }
756
+ // A formal the whole-program census settled is declared `long long` by this
757
+ // body's own signature (`formalsOf`, translation-unit.ts). The ABI is
758
+ // untouched -- it is what every caller, thunk and `CallableObject` agrees on
759
+ // -- and the thunk converts across; here the formal simply already has the
760
+ // carrier the body works in.
761
+ if (ctx.narrowedFormals.has(operation.ordinal)) {
762
+ // The formal already IS the narrowed carrier, so this is the alias below,
763
+ // not a conversion: the signature carried the census's answer.
764
+ defineValueAlias(ctx, operation.result, cppFormalName(operation.ordinal));
765
+ return;
766
+ }
767
+ // Otherwise the formal itself, for the reason `emitReceiver` states: it is a
768
+ // local of this frame that nothing ever writes, so naming it is naming the
769
+ // value the caller passed, and the copy that stood here was a retain and a
770
+ // release (or a string's heap copy) for a name the frame already had.
771
+ defineValueAlias(ctx, operation.result, cppFormalName(operation.ordinal));
772
+ };
773
+ /**
774
+ * One JSX element, constructed through the host's element protocol.
775
+ *
776
+ * The emitter states only what the language states -- create with this tag,
777
+ * then these props in order, then these children in order -- and hands each
778
+ * step to an overloaded host entry point. What a prop *means* is genuinely not
779
+ * decidable here: a style object, a string attribute, and an event handler are
780
+ * three different operations on the host's node, and the thing that can tell
781
+ * them apart is the C++ type of the value, which the host's own overload set
782
+ * already dispatches on. Encoding that decision here instead would put the
783
+ * framework's prop taxonomy inside the compiler, where it would immediately be
784
+ * a second authority against the runtime's.
785
+ *
786
+ * The result must be a `native-handle`: a host element is opaque, and rendering
787
+ * construction into a record carrier would produce a struct that compiles and
788
+ * renders nothing.
789
+ */
790
+ /**
791
+ * `ToBoolean` of one value, per carrier.
792
+ *
793
+ * The table is the language's, not a convenience: `0` and `NaN` are false and
794
+ * every other number true, an empty string is false and a one-space string
795
+ * true, `null` and `undefined` are false, an absent optional is false, and
796
+ * *every* object is true no matter what it holds. Writing any of these as a
797
+ * C++ implicit conversion would get several of them wrong -- `NaN` converts to
798
+ * `true`, and a `std::string` does not convert at all -- so each carrier gets
799
+ * the expression that is exactly its rule, and a carrier with no stated rule
800
+ * is refused rather than left to whatever `if (x)` happens to mean in C++.
801
+ */
802
+ const emitTest = (ctx, lines, operation) => {
803
+ const name = defineValue(ctx, operation.result);
804
+ const hostNamespace = ctx.hostNamespaceReads.get(operation.value.value) ?? ctx.hostNamespaceValues.get(operation.value.value);
805
+ const hostSingleton = ctx.hostClassReads.get(operation.value.value);
806
+ const hostMethod = ctx.hostMemberReads.get(operation.value.value);
807
+ if (hostNamespace !== undefined || hostSingleton !== undefined || hostMethod !== undefined) {
808
+ // A plugin-declared namespace segment is a real, present object in the
809
+ // source language even though the target fuses its member path and never
810
+ // materializes that intermediate object. Host singletons and exact host
811
+ // methods are the same kind of authenticated, always-present identity:
812
+ // testing either for an optional-chain guard must not materialize a class
813
+ // or method value. All three tests agree for every one: present, defined
814
+ // and true.
815
+ lines.push(`${name} = true;`);
816
+ return;
817
+ }
818
+ const text = operandText(ctx, operation.value);
819
+ const carrier = operation.value.representation;
820
+ // Which question was asked travels on the operation, from the census that
821
+ // recorded it, and is never re-derived from the carrier here: `if (x)` and
822
+ // `x ?? y` over one `x` ask different questions and a carrier cannot tell
823
+ // them apart.
824
+ const answer = operation.predicate === 'is-present'
825
+ ? presenceTestText(text, carrier)
826
+ : operation.predicate === 'is-defined'
827
+ ? definedTestText(text, carrier)
828
+ : booleanTestText(text, carrier, isIntegerStorageValue(ctx, operation.value.value));
829
+ lines.push(`${name} = ${answer};`);
830
+ };
831
+ /**
832
+ * A conversion the graph made explicit, rendered by the one authority on what
833
+ * a narrowing loads.
834
+ *
835
+ * `emit-narrowing.ts` already answers "given a value carried as X and wanted as
836
+ * Y, what is the load" -- it is what a narrowed binding read renders -- and
837
+ * asking it here rather than writing a second dereference is what keeps the two
838
+ * from disagreeing. A pair it has no load for is refused by name: preflight
839
+ * censused the conversion, so reaching this with no answer means the census and
840
+ * the renderer disagree, which is worth saying out loud rather than papering
841
+ * over with an implicit C++ conversion.
842
+ */
843
+ const emitConvert = (ctx, lines, operation) => {
844
+ // A deferred host method has no standalone C++ value. Optional chaining can
845
+ // narrow/widen the callee between its property read, presence test and call;
846
+ // carry the authenticated deferred invocation through those SSA views
847
+ // without asking `operandText` to materialize a function the host never
848
+ // supplied. Any non-call consumer still reaches `operandText` later and
849
+ // fails closed as a host-method-value.
850
+ if (ctx.hostMemberReads.has(operation.source.value))
851
+ return;
852
+ // A host singleton is a compile-time identity, including after the
853
+ // statically-present arm of `globalThis?.singleton` is narrowed for a
854
+ // following optional call. No object is converted or boxed here, so the
855
+ // conversion renders nothing; the identity's travel onto the new SSA view is
856
+ // stated by `emit-bindings.ts`'s `hostClassReadsOf`.
857
+ if (ctx.hostClassReads.has(operation.source.value) && operation.result.representation.kind === 'native-handle')
858
+ return;
859
+ // A host NAMESPACE is a path, not a value (`emit-namespaces.ts`), and a path
860
+ // does not change by being viewed under another carrier. `export const
861
+ // Accelerometer = typeof __gea_Accelerometer !== 'undefined' ?
862
+ // __gea_Accelerometer : (undefined as unknown as typeof __gea_Accelerometer)`
863
+ // merges the namespace with the host-absent arm into one path, then converts
864
+ // that merge into the cell's own carrier before the binding write; the write
865
+ // recognises the path and renders nothing (`emitBindingWrite`), so the
866
+ // convert in between has to carry it rather than ask `operandText` for a
867
+ // value the namespace never had.
868
+ // The propagation itself is settled before this body rendered a line, by
869
+ // `host-namespace-reads.ts`'s `hostNamespaceReadsOf`, which folds `convert`
870
+ // into the same fixed point that finds the path in the first place. All this
871
+ // has to ask is whether THIS conversion's result is one of the paths it
872
+ // found -- a conversion of a namespace still renders nothing.
873
+ if (ctx.hostNamespaceReads.has(operation.result.id))
874
+ return;
875
+ // Converting an expression to `void` evaluates the source and discards its
876
+ // value. Evaluation has already happened in the source operation, so this
877
+ // conversion only needs to publish the C++ void expression for any later
878
+ // SSA use; it must not try to allocate storage for a carrier that has none.
879
+ if (operation.result.representation.kind === 'void') {
880
+ defineValueAlias(ctx, operation.result, '(void)0');
881
+ return;
882
+ }
883
+ const input = owningConversionInputText(ctx, operation.source, operation.result.representation, operandText(ctx, operation.source));
884
+ // A load no program fact proves present (`ir/presence-proof.ts`) tests the
885
+ // cell first: `presentOrThrow` hands back the same cell or raises.
886
+ const sourceText = operation.presence === 'checked' ? `gea::host::presentOrThrow(${input})` : input;
887
+ // The node lowering named on this instruction, rendered by its recipe
888
+ // (`alignedValueText` asks the census for the same pair and renders the
889
+ // same node; a pair the census refused is its drift row, and the chain's).
890
+ const named = ctx.conversions.nodeById(operation.conversionUse);
891
+ const text = (named?.capability.kind === 'coercion'
892
+ ? namedConversionText(ctx, 'emit.ts:1026', named, sourceText)
893
+ : alignedValueText(ctx, 'emit.ts:1026', operation.source.representation, operation.result.representation, sourceText)) ??
894
+ // A method value escaping into a receiver-less slot: the receiver is
895
+ // recovered from the read itself (`emit-callable.ts`'s
896
+ // `receiverBoundCallableText`), a fact of this context, not of the pair.
897
+ receiverBoundCallableText(ctx, operation.source, operation.result.representation, sourceText);
898
+ // A storage-free source converting into a real carrier is a branch flow
899
+ // analysis proved dead, not a missing load: `undefined` is also `never`'s
900
+ // carrier (`representation/primitives.ts`), and a pair the loads refuse can
901
+ // only be reached when the source holds nothing. `var [d = 7] = []` is the
902
+ // standing case -- the extraction past an empty tuple is `undefined`
903
+ // outright, the default's present arm converts it to the bound `number`,
904
+ // and the `is-defined` test guarding that arm is the constant `false`.
905
+ // Rendered as the throw the call-site argument path already renders
906
+ // (`emit-callable.ts`) so the dead arm does not block the live one.
907
+ if (text === null && (operation.source.representation.kind === 'undefined' || operation.source.representation.kind === 'void')) {
908
+ defineValueAlias(ctx, operation.result, `gea::host::unreachableValue<${cppTypeOf(operation.result.representation)}>()`);
909
+ return;
910
+ }
911
+ if (text === null) {
912
+ throw createCppEmitBlockedError(`conversion:${representationKey(operation.source.representation)}->${representationKey(operation.result.representation)}`, `converts ${representationKey(operation.source.representation)} to ${representationKey(operation.result.representation)}, ` +
913
+ `which no installed load performs (conversion use ${operation.conversionUse})`);
914
+ }
915
+ const consumed = transfersFormalConversion(ctx.consumingFormalConversions, operation.result.id) === 'move' ? `std::move(${text})` : text;
916
+ lines.push(`${defineValue(ctx, operation.result)} = ${consumed};`);
917
+ };
918
+ /**
919
+ * `await p`.
920
+ *
921
+ * `gea::Promise<V>` is a settled-value box with no job queue
922
+ * (`runtime/gea_runtime.h`'s `Promise` doc comment): the only promise this
923
+ * runtime can ever construct is one whose result is already known. `await`
924
+ * therefore renders as reading that value right now -- `.awaited()`, the
925
+ * same synchronous-immediate answer `.then()` already commits to for the
926
+ * identical reason (see that method's own doc comment) -- rather than a real
927
+ * suspension, which this substrate has no coroutine primitive to express.
928
+ *
929
+ * The operand is not always a `promise` carrier: `await` accepts any
930
+ * expression (`Awaited<T>` is `T` unchanged for a non-thenable `T`), and a
931
+ * non-promise operand is already its own resolution, so it passes through
932
+ * unchanged rather than calling a method that carrier does not have.
933
+ *
934
+ * And it is not always one of those two, either. A union of both --
935
+ * `string | Promise<string>`, what every conditionally-async helper returns --
936
+ * is a discriminant test away from either, and asking only `kind === 'promise'`
937
+ * passed it through untouched, handing a `TaggedUnion<...>` to a consumer told
938
+ * it would get the payload. `awaitedText` (prototype/emit-prototype-promise.ts)
939
+ * is ECMA-262 27.2.4.7.1 `PromiseResolve` stated once, for all three shapes,
940
+ * and shared with `Promise.all`, which resolves each element by the same rule.
941
+ */
942
+ const emitAwait = (ctx, lines, operation) => {
943
+ const text = operandText(ctx, operation.operand);
944
+ const expression = awaitedText(ctx, 'emit.ts:emitAwait', operation.operand.representation, text, operation.result?.representation ?? null) ?? text;
945
+ if (!operation.result) {
946
+ lines.push(`${expression};`);
947
+ return;
948
+ }
949
+ lines.push(`${defineValue(ctx, operation.result)} = ${expression};`);
950
+ };
951
+ /**
952
+ * `yield x` -- a real suspension, unlike `await` above.
953
+ *
954
+ * The enclosing body's ABI result is `gea::Iterator<T>`, whose nested
955
+ * `promise_type` (`runtime/gea_runtime.h`) is what makes this function a C++20
956
+ * coroutine; `co_yield` stores the value in the frame and suspends, and the
957
+ * `next()` that resumes it reads it back. That is v1's own mechanism
958
+ * (`value_09_generator.h`'s `yield_value`/`yield_awaiter`), re-typed over the
959
+ * concrete `E` the checker proved instead of v1's `gea_cpp_value`.
960
+ *
961
+ * The value is aligned to the cursor's element carrier on the way in, by the
962
+ * same rule an argument written into a parameter slot is: a `Generator<number>`
963
+ * yielding an `int`-carried expression must store the `double` the cursor
964
+ * holds.
965
+ *
966
+ * `yield` with no operand is `yield undefined`, and this backend has no
967
+ * `undefined` to yield into a typed cursor, so it is refused rather than
968
+ * yielding a default-constructed element the program never wrote.
969
+ */
970
+ const emitYield = (ctx, lines, operation) => {
971
+ const cursor = ctx.abi?.result;
972
+ if (cursor?.kind !== 'iterator') {
973
+ throw createCppEmitBlockedError('abrupt-edge:suspend', `appears in a body whose calling convention returns "${cursor ? representationKey(cursor) : 'nothing'}"; ` +
974
+ 'only a body returning an "iterator" cursor is emitted as a coroutine');
975
+ }
976
+ // A bare `yield` yields `undefined`; it is spelled only when the cursor's
977
+ // element carrier has an `undefined` to hold (`Iterator<Undefined>` for a
978
+ // generator that yields nothing else, an optional or a sum carrying the
979
+ // absence otherwise), never as a default-constructed element the program
980
+ // did not write.
981
+ const bareUndefined = operation.operand
982
+ ? null
983
+ : alignedValueText(ctx, 'emit.ts:1128', { kind: 'undefined' }, cursor.element, cppUndefinedValue);
984
+ if (!operation.operand && bareUndefined === null) {
985
+ throw createCppEmitBlockedError('abrupt-edge:suspend', `yields no value; a bare \`yield\` yields \`undefined\`, which this cursor's "${representationKey(cursor.element)}" element carrier cannot hold`);
986
+ }
987
+ const yieldText = `(co_yield ${operation.operand ? alignedText(ctx, cursor.element, operation.operand, 'yield') : bareUndefined})`;
988
+ // Statement form: nobody reads what `next(v)` sent back, so the resumed
989
+ // value -- whatever it turns out to be -- is evaluated and discarded, the
990
+ // same as any other unread expression statement.
991
+ if (operation.result === null) {
992
+ lines.push(`${yieldText};`);
993
+ return;
994
+ }
995
+ // A yield whose own value IS read needs a real resume channel to read it
996
+ // from: `TNext` collapsed to `undefined` (`representation/derive.ts`) means
997
+ // there is no storage behind `yieldText`'s own value to convert, so this
998
+ // refuses by name rather than converting a `void`/`undefined` expression
999
+ // into whatever type the read expects.
1000
+ if (cursor.resume.kind === 'void' || cursor.resume.kind === 'undefined') {
1001
+ throw createCppEmitBlockedError('abrupt-edge:suspend', "a yield whose own value is read needs the generator's resume channel (what `next(v)`/an abrupt `.return`/`.throw` sends back), " +
1002
+ 'and this generator\'s own resume channel is "undefined" -- either TNext never resolved to a native carrier, or this ' +
1003
+ 'generator is not annotated as one');
1004
+ }
1005
+ const text = alignedValueText(ctx, 'emit.ts:1156', cursor.resume, operation.result.representation, yieldText);
1006
+ if (text === null) {
1007
+ throw createCppEmitBlockedError(`conversion:${representationKey(cursor.resume)}->${representationKey(operation.result.representation)}`, `resumes with "${representationKey(cursor.resume)}" where this read expects "${representationKey(operation.result.representation)}", ` +
1008
+ 'and no installed conversion reconciles them');
1009
+ }
1010
+ lines.push(`${defineValue(ctx, operation.result)} = ${text};`);
1011
+ };
1012
+ const emitReceiver = (ctx, _lines, operation) => {
1013
+ const declared = ctx.abi?.receiver;
1014
+ if (!declared) {
1015
+ throw createCppEmitBlockedError('call-abi:receiver', "reads the frame's receiver, which this body's calling convention does not declare");
1016
+ }
1017
+ // The formal IS the receiver, so the read names it rather than copying it --
1018
+ // the same argument `emit-bindings.ts` makes for a cell written once, and
1019
+ // stronger here: a formal is written zero times, by anyone, so no later value
1020
+ // exists for the alias to drift onto.
1021
+ //
1022
+ // The copy it removes is real work on every carrier a receiver can have. A
1023
+ // `gea::Ref` receiver pays a retain and a release per call for a name the
1024
+ // frame already had; measured on `bench/comparison/fixtures/method_calls.ts`,
1025
+ // whose loop is one method call, that pair alone was a third of the program
1026
+ // (57.4ms to 38.4ms).
1027
+ defineValueAlias(ctx, operation.result, cppReceiverName);
1028
+ };
1029
+ const emitGlobalThis = (ctx, lines, operation) => {
1030
+ const name = defineValue(ctx, operation.result);
1031
+ lines.push(`${name} = gea::runtime::globalThis();`);
1032
+ };
1033
+ /**
1034
+ * A name with no declaration anywhere -- reading it is a ReferenceError, not
1035
+ * a value this backend approximates or boxes (`ir/lower.ts`'s
1036
+ * `unresolvableThrows`). `throwReferenceError<T>()` is `[[noreturn]]`,
1037
+ * templated on this result's declared type, so it type-checks without
1038
+ * producing one -- the `[[noreturn]] void` idiom generalized to a value spot.
1039
+ */
1040
+ const emitUnresolvableReference = (ctx, lines, operation) => {
1041
+ const name = defineValue(ctx, operation.result);
1042
+ const type = storageTypeOf(ctx, operation.result.id, operation.result.representation);
1043
+ lines.push(`${name} = gea::host::detail::throwReferenceError<${type}>();`);
1044
+ };
1045
+ /** Every non-terminator kind this file lowers. Anything else falls to the `default` and refuses, including kinds added after this file was written. */
1046
+ const emitOperationStatements = (ctx, lines, operation) => {
1047
+ switch (operation.kind) {
1048
+ case 'constant':
1049
+ emitConstant(ctx, lines, operation);
1050
+ return;
1051
+ case 'binding-read':
1052
+ emitBindingRead(ctx, lines, operation);
1053
+ return;
1054
+ case 'binding-write':
1055
+ emitBindingWrite(ctx, lines, operation);
1056
+ return;
1057
+ case 'parameter':
1058
+ emitParameter(ctx, lines, operation);
1059
+ return;
1060
+ case 'receiver':
1061
+ emitReceiver(ctx, lines, operation);
1062
+ return;
1063
+ case 'global-this':
1064
+ emitGlobalThis(ctx, lines, operation);
1065
+ return;
1066
+ case 'unresolvable-reference':
1067
+ emitUnresolvableReference(ctx, lines, operation);
1068
+ return;
1069
+ case 'await':
1070
+ emitAwait(ctx, lines, operation);
1071
+ return;
1072
+ case 'yield':
1073
+ emitYield(ctx, lines, operation);
1074
+ return;
1075
+ case 'compute':
1076
+ emitCompute(ctx, lines, operation);
1077
+ return;
1078
+ case 'call':
1079
+ emitCall(ctx, lines, operation);
1080
+ return;
1081
+ case 'commonjs-require':
1082
+ lines.push(`${defineValue(ctx, operation.result)} = ${cppCommonJsModuleName(operation.target)}();`);
1083
+ return;
1084
+ case 'commonjs-binding':
1085
+ // Publication forces every unproved wrapper read to `dynamic`; a
1086
+ // non-dynamic module result is therefore the consumed source proof, not
1087
+ // a second backend shape heuristic.
1088
+ if (operation.result.representation.kind !== 'dynamic') {
1089
+ if (operation.global !== 'module') {
1090
+ throw createCppEmitBlockedError('native-boundary:commonjs-binding', `native CommonJS record proof reached the "${operation.global}" wrapper; only the exact module record has a native carrier`);
1091
+ }
1092
+ lines.push(`${defineValue(ctx, operation.result)} = ${cppCommonJsRecordName(operation.owner)}();`);
1093
+ }
1094
+ else {
1095
+ lines.push(`${defineValue(ctx, operation.result)} = gea::commonjs::${operation.global}();`);
1096
+ }
1097
+ return;
1098
+ case 'commonjs-binding-set':
1099
+ lines.push(`gea::commonjs::setBinding("${operation.global}", ${operandText(ctx, operation.value)});`);
1100
+ return;
1101
+ case 'super-initialize':
1102
+ emitSuperInitialize(ctx, lines, operation);
1103
+ return;
1104
+ case 'reparent-constructor':
1105
+ lines.push(`gea::reparentNativeClass<${cppClassName(operation.derived)}, ${cppClassName(operation.base)}>(` +
1106
+ `${operandText(ctx, operation.classValue)}.environment, ${operandText(ctx, operation.heritage)}.environment);`);
1107
+ return;
1108
+ case 'allocate-callable':
1109
+ emitAllocateCallable(ctx, lines, operation);
1110
+ return;
1111
+ case 'bind-callable':
1112
+ emitBindCallable(ctx, lines, operation);
1113
+ return;
1114
+ case 'allocate-constructor':
1115
+ emitAllocateConstructor(ctx, lines, operation);
1116
+ return;
1117
+ case 'construct':
1118
+ emitConstruct(ctx, lines, operation);
1119
+ return;
1120
+ case 'get': {
1121
+ const priorLength = ctx.reusedStringLengths.get(operation.result.id);
1122
+ if (priorLength !== undefined) {
1123
+ lines.push(`${defineValue(ctx, operation.result)} = ${operandText(ctx, priorLength)};`);
1124
+ return;
1125
+ }
1126
+ emitGet(ctx, lines, operation);
1127
+ return;
1128
+ }
1129
+ case 'set':
1130
+ emitFieldStore(ctx, classTableLines(ctx, lines, operation.receiver.value), operation, 'set');
1131
+ return;
1132
+ case 'define-own-property':
1133
+ emitFieldStore(ctx, classTableLines(ctx, lines, operation.receiver.value), operation, 'define-own-property');
1134
+ return;
1135
+ case 'spread-copy':
1136
+ emitSpreadCopy(ctx, lines, operation);
1137
+ return;
1138
+ // Answered for the one receiver with a runtime property table, refused by
1139
+ // name for every other carrier; both rules live with the dynamic machinery.
1140
+ case 'delete':
1141
+ emitDeleteOperation(ctx, lines, operation);
1142
+ return;
1143
+ case 'has-property':
1144
+ emitHasProperty(ctx, lines, operation);
1145
+ return;
1146
+ case 'allocate-ordinary-object':
1147
+ lines.push(`${defineValue(ctx, operation.result)} = gea::Value::object();`);
1148
+ return;
1149
+ case 'allocate-record':
1150
+ emitAllocateRecord(ctx, classTableLines(ctx, lines, operation.result.id), operation);
1151
+ return;
1152
+ case 'allocate-regexp':
1153
+ emitAllocateRegExp(ctx, lines, operation);
1154
+ return;
1155
+ case 'allocate-template-object':
1156
+ emitAllocateTemplateObject(ctx, lines, operation);
1157
+ return;
1158
+ case 'allocate-array-object':
1159
+ emitAllocateArrayObject(ctx, lines, operation);
1160
+ return;
1161
+ case 'get-iterator':
1162
+ emitGetIterator(ctx, lines, operation);
1163
+ return;
1164
+ case 'iterator-next':
1165
+ emitIteratorNext(ctx, lines, operation);
1166
+ return;
1167
+ case 'iterator-done':
1168
+ emitIteratorDone(ctx, lines, operation);
1169
+ return;
1170
+ case 'iterator-close':
1171
+ emitIteratorClose(ctx, lines, operation);
1172
+ return;
1173
+ case 'element':
1174
+ emitElement(ctx, lines, operation);
1175
+ return;
1176
+ case 'element-prop':
1177
+ emitElementProp(ctx, lines, operation);
1178
+ return;
1179
+ case 'element-child':
1180
+ emitElementChild(ctx, lines, operation);
1181
+ return;
1182
+ case 'test':
1183
+ emitTest(ctx, lines, operation);
1184
+ return;
1185
+ case 'convert':
1186
+ emitConvert(ctx, lines, operation);
1187
+ return;
1188
+ case 'merge-live-arm-rebuild':
1189
+ emitMergeLiveArmRebuild(ctx, lines, operation);
1190
+ return;
1191
+ case 'phi':
1192
+ // The variable is declared with every other local and written by each
1193
+ // predecessor; there is nothing left to render where it is read.
1194
+ return;
1195
+ default:
1196
+ throw createCppEmitBlockedError(`runtime-helper:operation:${operation.kind}`, `no C++ rendering is implemented for the "${operation.kind}" operation yet`);
1197
+ }
1198
+ };
1199
+ /** A block's assigned `goto` label. Absence means a jump names a block outside this body's own `blockOrder`, an IR-verification bug, not a rendering gap. */
1200
+ const requireBlockLabel = (labels, block) => {
1201
+ const label = labels.get(block);
1202
+ if (label === undefined)
1203
+ throw new Error(`ir block ${block} has no assigned label; every block in this body must be labeled before emission`);
1204
+ return label;
1205
+ };
1206
+ /**
1207
+ * `text` with one outermost parenthesis layer removed, when that layer wraps
1208
+ * the whole of it.
1209
+ *
1210
+ * `operandText` renders a binary expression fully parenthesized, because it
1211
+ * does not know what it will be spliced into and precedence is not something a
1212
+ * renderer may guess at. A branch condition is the one place that layer is
1213
+ * always redundant: `if (...)` is itself a grouping, so `if (((b0) == (3)))`
1214
+ * says exactly what `if ((b0) == (3))` says -- and clang reads the first as a
1215
+ * person who meant `=` and wrote `==`, raising -Wparentheses-equality on every
1216
+ * one. Measured across the emitted units in this tree: roughly 350 of them,
1217
+ * 61 in `button-tetris` alone. Not a large number, but a warning that is always
1218
+ * present is a warning nobody reads.
1219
+ *
1220
+ * Only the OUTER layer, and only when it really is one: the scan below returns
1221
+ * the text unchanged for `(a) == (b)`, whose first parenthesis closes at index
1222
+ * 2, and for a leading cast like `(bool)(x)`. Quoted runs are skipped whole,
1223
+ * because an emitted string literal may contain either parenthesis --
1224
+ * `gea_class_decl_f3_545` and every other name literal proves nothing about
1225
+ * nesting.
1226
+ */
1227
+ const unwrapConditionParentheses = (text) => {
1228
+ if (text.length < 2 || text[0] !== '(' || text[text.length - 1] !== ')')
1229
+ return text;
1230
+ let depth = 0;
1231
+ let quote = '';
1232
+ for (let index = 0; index < text.length; index += 1) {
1233
+ const character = text[index];
1234
+ if (quote !== '') {
1235
+ if (character === '\\')
1236
+ index += 1;
1237
+ else if (character === quote)
1238
+ quote = '';
1239
+ continue;
1240
+ }
1241
+ if (character === '"' || character === "'") {
1242
+ quote = character;
1243
+ continue;
1244
+ }
1245
+ if (character === '(')
1246
+ depth += 1;
1247
+ else if (character === ')') {
1248
+ depth -= 1;
1249
+ // Closed before the end, so the opening parenthesis wrapped a part and
1250
+ // not the whole -- there is nothing redundant to take off.
1251
+ if (depth === 0 && index !== text.length - 1)
1252
+ return text;
1253
+ }
1254
+ }
1255
+ // An unbalanced count means the text is not what this reads it as (an
1256
+ // unterminated literal, say). Leave it exactly as rendered.
1257
+ return depth === 0 ? text.slice(1, -1) : text;
1258
+ };
1259
+ /**
1260
+ * The `goto`s a `jump` or `branch` renders, given the label of the block
1261
+ * rendered immediately after it (`null` when nothing follows or the caller
1262
+ * does not know).
1263
+ *
1264
+ * Two `goto`s rather than an `if`/`else` pair: the blocks this names are
1265
+ * siblings in one flat sequence, and wrapping either in a C++ block would put
1266
+ * every declaration inside it out of the other blocks' reach. Within that
1267
+ * shape, three things spell less than the IR says:
1268
+ *
1269
+ * - a jump to the very next block is the fall-through it already is and
1270
+ * spells nothing (`goto block1; block1:` was every loop's entry);
1271
+ * - a branch on a literal -- `while (true)`, `for (;;)` -- and a branch whose
1272
+ * two arms thread to one block are each a jump, and render as one: `if
1273
+ * (true) goto block3;` leaves the untaken arm behind as a block nothing
1274
+ * reaches, which `threadedFlowOf` has already left out;
1275
+ * - a branch one of whose arms is the next block spells only the other arm,
1276
+ * negating the condition when the TAKEN arm is the one that falls through.
1277
+ */
1278
+ const spelledExitsOf = (ctx, labels, terminator, nextLabel) => {
1279
+ if (terminator.kind === 'jump') {
1280
+ const label = requireBlockLabel(labels, terminator.target);
1281
+ return label === nextLabel ? [] : [{ label, condition: 'always' }];
1282
+ }
1283
+ if (terminator.kind !== 'branch')
1284
+ return [];
1285
+ const whenTrue = requireBlockLabel(labels, terminator.whenTrue);
1286
+ const whenFalse = requireBlockLabel(labels, terminator.whenFalse);
1287
+ const known = ctx.booleanConstants.get(terminator.condition.value);
1288
+ if (known !== undefined || whenTrue === whenFalse) {
1289
+ const only = known === false ? whenFalse : whenTrue;
1290
+ return only === nextLabel ? [] : [{ label: only, condition: 'always' }];
1291
+ }
1292
+ if (whenFalse === nextLabel)
1293
+ return [{ label: whenTrue, condition: 'when-true' }];
1294
+ if (whenTrue === nextLabel)
1295
+ return [{ label: whenFalse, condition: 'when-false' }];
1296
+ return [
1297
+ { label: whenTrue, condition: 'when-true' },
1298
+ { label: whenFalse, condition: 'always' }
1299
+ ];
1300
+ };
1301
+ const emitTerminator = (ctx, lines, labels, isSingleBlock, terminator, nextLabel = null) => {
1302
+ switch (terminator.kind) {
1303
+ case 'jump':
1304
+ case 'branch': {
1305
+ // A single-block body has no other block to name: falling off the end
1306
+ // of this text is exactly what the jump means, so it renders as nothing
1307
+ // rather than a `goto` to a label this file never assigns.
1308
+ if (isSingleBlock)
1309
+ return;
1310
+ const condition = terminator.kind === 'branch' ? terminator.condition : null;
1311
+ for (const exit of spelledExitsOf(ctx, labels, terminator, nextLabel)) {
1312
+ if (exit.condition === 'always' || condition === null) {
1313
+ lines.push(`goto ${exit.label};`);
1314
+ continue;
1315
+ }
1316
+ const text = unwrapConditionParentheses(operandText(ctx, condition));
1317
+ lines.push(exit.condition === 'when-true' ? `if (${text}) goto ${exit.label};` : `if (!(${text})) goto ${exit.label};`);
1318
+ }
1319
+ return;
1320
+ }
1321
+ case 'return':
1322
+ emitReturn(ctx, lines, terminator);
1323
+ return;
1324
+ case 'throw':
1325
+ // A C++ `throw` of the value's own carrier, not of a boxed wrapper: what
1326
+ // the program throws is whatever it constructed, and re-typing it on the
1327
+ // way out would make the thing a handler catches different from the thing
1328
+ // the `throw` statement named.
1329
+ //
1330
+ // No handler is claimed alongside this. That is not an oversight: an
1331
+ // uncaught `throw` terminating the process is exactly what an uncaught
1332
+ // ECMAScript exception does, so this is complete on its own, while `try`
1333
+ // needs a catch-side carrier decision this does not make and does not
1334
+ // pre-empt.
1335
+ lines.push(`throw ${operandText(ctx, terminator.value)};`);
1336
+ // A generator whose body throws before it ever yields or returns
1337
+ // (`function* () { throw new Test262Error() }`) has no other keyword to
1338
+ // make it a coroutine, and C++ would compile it as a plain function
1339
+ // that throws AT THE CALL rather than on the first `next()`. The
1340
+ // unreachable `co_return` after the throw is what keeps the frame a
1341
+ // coroutine, so the throw surfaces where the language says it does.
1342
+ if (ctx.generatorBody)
1343
+ lines.push('co_return;');
1344
+ return;
1345
+ case 'switch':
1346
+ throw createCppEmitBlockedError(`runtime-helper:control:${terminator.kind}`, `no C++ rendering is implemented for the "${terminator.kind}" terminator yet`);
1347
+ }
1348
+ };
1349
+ /**
1350
+ * One operation's statements, withheld where the census proved they may
1351
+ * render at the use instead.
1352
+ *
1353
+ * The withholding is recognized from what the emitter did, not predicted: a
1354
+ * kind that renders exactly one assignment to the name it just minted is the
1355
+ * only shape that can move, and any emitter that rendered anything else --
1356
+ * several statements, a name some other construct declares, nothing at all --
1357
+ * falls through unchanged. That is what keeps this a rendering choice rather
1358
+ * than a second authority over what an operation means: it can only ever
1359
+ * decline.
1360
+ */
1361
+ /**
1362
+ * Where a candidate class table's own lines go: into that table's buffer, so
1363
+ * the `class` prop can drop them if it spells the table away. See
1364
+ * `EmitContext.classTableRoots`.
1365
+ */
1366
+ const classTableLines = (ctx, lines, value) => {
1367
+ const root = ctx.classTableRoots.get(value);
1368
+ if (root === undefined)
1369
+ return lines;
1370
+ const pending = ctx.pendingClassTableLines.get(root);
1371
+ if (pending !== undefined)
1372
+ return pending;
1373
+ const opened = [];
1374
+ ctx.pendingClassTableLines.set(root, opened);
1375
+ return opened;
1376
+ };
1377
+ const emitOperation = (ctx, lines, operation) => {
1378
+ try {
1379
+ const result = resultOfIrOperation(operation);
1380
+ if (result !== null && ctx.deadValues.has(result.id)) {
1381
+ settleDeadCalleeSideEffects(ctx, operation);
1382
+ return;
1383
+ }
1384
+ if (result === null || !ctx.deferrable.has(result.id)) {
1385
+ emitOperationStatements(ctx, lines, operation);
1386
+ return;
1387
+ }
1388
+ const lineMark = lines.length;
1389
+ const declarationMark = ctx.declarations.length;
1390
+ emitOperationStatements(ctx, lines, operation);
1391
+ // An array literal withheld whole records its own elements instead
1392
+ // (`emit-arrays.ts`) and has neither a name nor a statement to reclaim.
1393
+ if (ctx.pendingPacks.has(result.id))
1394
+ return;
1395
+ const name = ctx.valueNames.get(result.id);
1396
+ if (name === undefined)
1397
+ return;
1398
+ if (lines.length !== lineMark + 1 || ctx.declarations.length !== declarationMark + 1)
1399
+ return;
1400
+ if (ctx.declarations[declarationMark]?.name !== name)
1401
+ return;
1402
+ const statement = lines[lineMark] ?? '';
1403
+ const prefix = `${name} = `;
1404
+ if (!statement.startsWith(prefix) || !statement.endsWith(';'))
1405
+ return;
1406
+ ctx.declarations.pop();
1407
+ lines.pop();
1408
+ ctx.deferredTexts.set(result.id, `(${statement.slice(prefix.length, statement.length - 1)})`);
1409
+ }
1410
+ catch (error) {
1411
+ if (isCppEmitBlockedError(error)) {
1412
+ const result = resultOfIrOperation(operation);
1413
+ error.message += ` while emitting ${operation.kind}${result === null ? '' : ` -> ${result.id}`}${operation.lineage === null ? '' : ` from ${operation.lineage}`}`;
1414
+ }
1415
+ if (error instanceof Error && error.message.startsWith('ir value ')) {
1416
+ const result = resultOfIrOperation(operation);
1417
+ error.message += ` while emitting ${operation.kind}${result === null ? '' : ` -> ${result.id}`}${operation.lineage === null ? '' : ` from ${operation.lineage}`}`;
1418
+ }
1419
+ throw error;
1420
+ }
1421
+ };
1422
+ /**
1423
+ * What a dead callee producer still has to do, now that `ctx.directCallees`
1424
+ * itself is populated up front from `CallOperation.target` (`emitBody`'s own
1425
+ * walk, above) rather than by each producer's live emitter as a side effect
1426
+ * of rendering: nothing about NAMING the callee is left for this function,
1427
+ * only the two side effects that are tied to the producer's OWN skipped
1428
+ * render rather than to the eventual call.
1429
+ *
1430
+ * `ir/dead-values.ts` counts a directly-called callee as unread precisely
1431
+ * because `emit-callable.ts` spells such a call as `body(args)`, and it
1432
+ * decides that with its own `directCallee` predicate -- a copy of the same
1433
+ * three tests (allocate-callable/binding-read/get) this file used to restate
1434
+ * here as writes. That predicate is unrelated to `CallOperation.target` (it
1435
+ * answers for a PRODUCER value, not a call) and stays as its own render-time
1436
+ * decision; only the direct-callee NAME it used to also mint moved to the
1437
+ * `emitBody`-level pass.
1438
+ */
1439
+ const settleDeadCalleeSideEffects = (ctx, operation) => {
1440
+ if (operation.kind === 'allocate-callable') {
1441
+ if (ctx.captures.of(operation.functionId).kind === 'none') {
1442
+ // What is left here once `thunkValues` is a sealed fact
1443
+ // (`ir/facts.ts`'s `bodyValueOriginsOf`): the thunk's TEXT. A captureless
1444
+ // thunk is exactly the one the dead-value rule elides -- its only call
1445
+ // is by name -- so its producer never renders, and the one use that
1446
+ // does need a value has to be able to spell it. It is spelled as the
1447
+ // prvalue it is, a body pointer and a null environment.
1448
+ //
1449
+ // The registration this used to also do is why the field moved: the
1450
+ // reader is `emit-jsx.ts`'s `reactiveThunkPlan`, which re-runs the thunk
1451
+ // behind a slot's call on every change of a cell that body reads, and a
1452
+ // registration performed as a side effect of rendering was missing for
1453
+ // exactly the producer whose render is skipped. Every such slot fell to
1454
+ // the once-only path -- the piece in button-tetris drew at its spawn
1455
+ // position and never moved, while the plain-text FPS slot beside it kept
1456
+ // updating.
1457
+ const carrier = operation.result.representation;
1458
+ if (carrier.kind === 'function-value-dispatch' && carrier.abi.parameters.length === 0 && carrier.abi.receiver === null) {
1459
+ ctx.deferredTexts.set(operation.result.id, `${cppTypeOf(carrier)}{&${cppThunkName(operation.functionId)}, nullptr}`);
1460
+ }
1461
+ }
1462
+ return;
1463
+ }
1464
+ };
1465
+ const threadedFlowOf = (ctx, body, labels, hoists, mergeWrites) => {
1466
+ if (body.tryRegions.length > 0 || (body.iteratorCloseRegions?.length ?? 0) > 0 || body.blockOrder.length === 1) {
1467
+ return { labels, skipped: new Set(), labeled: new Set(labels.values()), nextLabel: new Map() };
1468
+ }
1469
+ // A literal is spelled at its uses (`spellConstants`) and a merge is written
1470
+ // by its predecessors (`mergeWritesOf`): neither renders where it sits. A
1471
+ // read hoisted INTO a block renders there -- unless it is one of those, as
1472
+ // the `true` of a `while (true)` hoisted to the loop's preheader is.
1473
+ const rendersNothingAtOrigin = (operation) => {
1474
+ if (operation.kind === 'constant' || operation.kind === 'phi')
1475
+ return true;
1476
+ const result = resultOfIrOperation(operation);
1477
+ return result !== null && (ctx.deadValues.has(result.id) || hoists.relocated.has(result.id));
1478
+ };
1479
+ const rendersNothingWhenHoisted = (operation) => {
1480
+ if (operation.kind === 'constant' || operation.kind === 'phi')
1481
+ return true;
1482
+ const result = resultOfIrOperation(operation);
1483
+ return result !== null && ctx.deadValues.has(result.id);
1484
+ };
1485
+ const rendersNothing = (block) => block.operations.every(rendersNothingAtOrigin) &&
1486
+ (mergeWrites.get(block.id) ?? []).length === 0 &&
1487
+ // A relocated operation renders here, in its destination block. Counting
1488
+ // it as absent a second time lets the flow thread this block away and
1489
+ // leaves later users with no dominating C++ definition.
1490
+ (hoists.into.get(block.id) ?? []).every(rendersNothingWhenHoisted) &&
1491
+ !ctx.fillLoops.has(block.id) &&
1492
+ ![...ctx.denseGroups.values()].some((group) => group.preheader === block.id);
1493
+ const forwarding = new Map();
1494
+ for (const block of body.blocks.values()) {
1495
+ if (block.id !== body.entry && block.terminator.kind === 'jump' && rendersNothing(block))
1496
+ forwarding.set(block.id, block.terminator.target);
1497
+ }
1498
+ const resolve = (id) => {
1499
+ const seen = new Set();
1500
+ let at = id;
1501
+ while (forwarding.has(at) && !seen.has(at)) {
1502
+ seen.add(at);
1503
+ at = forwarding.get(at) ?? at;
1504
+ }
1505
+ return at;
1506
+ };
1507
+ for (let settled = false; !settled;) {
1508
+ settled = true;
1509
+ for (const id of [...forwarding.keys()]) {
1510
+ if (!forwarding.has(resolve(id)))
1511
+ continue;
1512
+ forwarding.delete(id);
1513
+ settled = false;
1514
+ }
1515
+ }
1516
+ const aliased = new Map(labels);
1517
+ for (const id of forwarding.keys())
1518
+ aliased.set(id, requireBlockLabel(labels, resolve(id)));
1519
+ const successorsOf = (block) => {
1520
+ const fill = ctx.fillLoops.get(block.id);
1521
+ if (fill)
1522
+ return [fill.exit];
1523
+ const terminator = block.terminator;
1524
+ switch (terminator.kind) {
1525
+ case 'jump':
1526
+ return [terminator.target];
1527
+ case 'branch': {
1528
+ const known = ctx.booleanConstants.get(terminator.condition.value);
1529
+ return known === undefined ? [terminator.whenTrue, terminator.whenFalse] : [known ? terminator.whenTrue : terminator.whenFalse];
1530
+ }
1531
+ case 'switch':
1532
+ return [...terminator.cases.map((entry) => entry.target), terminator.defaultTarget];
1533
+ default:
1534
+ return [];
1535
+ }
1536
+ };
1537
+ const reachable = new Set();
1538
+ const pending = [body.entry];
1539
+ while (pending.length > 0) {
1540
+ const id = pending.pop();
1541
+ if (id === undefined || reachable.has(id))
1542
+ continue;
1543
+ reachable.add(id);
1544
+ const block = body.blocks.get(id);
1545
+ if (!block)
1546
+ continue;
1547
+ for (const next of successorsOf(block)) {
1548
+ const target = resolve(next);
1549
+ if (!reachable.has(target))
1550
+ pending.push(target);
1551
+ }
1552
+ }
1553
+ const rendered = body.blockOrder.filter((id) => reachable.has(id));
1554
+ const nextLabel = new Map();
1555
+ rendered.forEach((id, index) => {
1556
+ const next = rendered[index + 1];
1557
+ if (next !== undefined)
1558
+ nextLabel.set(id, requireBlockLabel(aliased, next));
1559
+ });
1560
+ const labeled = new Set();
1561
+ for (const id of rendered) {
1562
+ const block = body.blocks.get(id);
1563
+ if (!block)
1564
+ continue;
1565
+ // A counted fill loop's header always spells the `goto` to its exit (`emitFillLoop`).
1566
+ const fill = ctx.fillLoops.get(id);
1567
+ if (fill) {
1568
+ labeled.add(requireBlockLabel(aliased, fill.exit));
1569
+ continue;
1570
+ }
1571
+ for (const exit of spelledExitsOf(ctx, aliased, block.terminator, nextLabel.get(id) ?? null))
1572
+ labeled.add(exit.label);
1573
+ }
1574
+ return { labels: aliased, skipped: new Set(body.blockOrder.filter((id) => !reachable.has(id))), labeled, nextLabel };
1575
+ };
1576
+ /** One `blockN` label per block, in `blockOrder`, so a forward jump (a loop back-edge included) always resolves before any block renders. */
1577
+ const blockLabelsOf = (order) => {
1578
+ const labels = new Map();
1579
+ order.forEach((block, index) => labels.set(block, `block${index}`));
1580
+ return labels;
1581
+ };
1582
+ /**
1583
+ * The C++ statements one lowered body renders to, as artifacts for the
1584
+ * emission boundary.
1585
+ *
1586
+ * `hostMembers` is every host spelling this compilation installed -- the
1587
+ * backend's own plus every plugin's. It is a parameter rather than an import
1588
+ * because which host is in front of the compiler is a property of the
1589
+ * compilation, not of this file.
1590
+ *
1591
+ * `deriver` is what `targets/cpp/emit-properties.ts` asks for a receiver's
1592
+ * own declared field representation, to widen a concrete value into a
1593
+ * `dynamic` field the same way this function's own `return` handling widens
1594
+ * into a `dynamic` ABI result -- see citations.md finding 1.
1595
+ *
1596
+ * `captures` defaults to `emptyCaptureIndex` (every owner closes over
1597
+ * nothing) so every existing caller keeps compiling and behaving exactly as
1598
+ * before; `translation-unit.ts` is the one caller that has an index to pass,
1599
+ * built once for the whole program by `targets/cpp/captures.ts`.
1600
+ */
1601
+ /**
1602
+ * The namespace every incoming value of a merge stands for, or `null`.
1603
+ *
1604
+ * `null` unless at least one arm is a namespace and every other arm is either
1605
+ * the same namespace or an absent constant -- see the call site for why an
1606
+ * absent arm is the one thing that may accompany it.
1607
+ */
1608
+ export const emitBody = (body, placements, classes, hosts, deriver, wellKnownSymbols = new Map(), captures = emptyCaptureIndex,
1609
+ // No default: `symbolKeys`/`templateObjects` are ONE table for the whole
1610
+ // program (`translation-unit.ts`'s own comment on its `templateObjects`
1611
+ // says why -- a tagged-template site's object must be the same one across
1612
+ // every body that reaches it). A default `new Map()` here would be a
1613
+ // second creation site for state that has exactly one legitimate owner;
1614
+ // `translation-unit.ts` is this function's only caller and always passes
1615
+ // its own program-wide map, so the default was dead and only invited a
1616
+ // future caller to silently get an empty, per-call table instead of the
1617
+ // shared one (scripts/architecture.mjs's EmitContext Map/Set check).
1618
+ symbolKeys, templateObjects, directCallableBindings = new Map(),
1619
+ // `virtualDispatch` is every `class key` with a dispatch member (`virtual-methods.ts`);
1620
+ // `narrowedStorage`/`narrowedFormals` are what the integer census settled here.
1621
+ virtualDispatch = new Map(), narrowedStorage = { reads: new Map(), integral: new Set(), magnitudes: new Map() }, narrowedFormals = new Set(), repeatedConstructors = new Map(), dyingArguments = new Set(), instantiation = noInstantiationFacts, abiOfCallable = () => null, hostMethodAliases = new Map(), callableMemberCandidates = new Map(), borrowableMemberBodies = new Set(), stableBorrowEntries = new Map(), printerDrift = [], conversions = null, nativeSelections = undefined, callableIdentityDemand = observesEveryCallableIdentity, nativeIntegrityRestricted = true, fixedFieldStateConstant = false) => {
1622
+ // Every fact this body settles before a single line renders, computed here
1623
+ // -- from `body` and the plain, already-available inputs above -- and
1624
+ // handed to `createEmitContext` as one argument instead of mutated onto the
1625
+ // context afterward. See `EmitBodyFacts`'s own doc
1626
+ // (the no-write-during-render
1627
+ // rule") for why this stopped being twelve `ctx.field.add(...)` calls.
1628
+ const stableBorrowActuals = stableBorrowActualsOf(body, (declaration) => {
1629
+ const placement = placements.get(declaration);
1630
+ return placement?.storage.kind === 'local' && placement.storage.owner === body.sourceOwner && !captures.isBoxed(declaration)
1631
+ ? placement.representation
1632
+ : null;
1633
+ });
1634
+ // A read has to know what the REST of the body does to the cell it reads.
1635
+ // `emit-bindings.ts` lets a host object's read name its cell rather than
1636
+ // copy out of it, and that identity only holds while the cell keeps
1637
+ // pointing at the one object -- which a body that rebinds it cannot
1638
+ // promise, and which the linear emit would otherwise discover only after
1639
+ // the read had already rendered.
1640
+ const receiverValues = new Set();
1641
+ const bindingWriteCounts = new Map();
1642
+ let callsSuper = false;
1643
+ for (const block of body.blocks.values()) {
1644
+ for (const operation of allOperationsOf(block)) {
1645
+ // Censused in the same pass, for `EmitBodyFacts.receiverValues`: a
1646
+ // member access has to know whether its receiver came from `super`, and
1647
+ // the operation that defines it is the only place that says so.
1648
+ if (operation.kind === 'receiver')
1649
+ receiverValues.add(operation.result.id);
1650
+ if (operation.kind === 'super-initialize')
1651
+ callsSuper = true;
1652
+ if (operation.kind !== 'binding-write')
1653
+ continue;
1654
+ bindingWriteCounts.set(operation.declaration, (bindingWriteCounts.get(operation.declaration) ?? 0) + 1);
1655
+ }
1656
+ }
1657
+ const owningClass = [...classes.values()].find((layout) => layout.constructor === body.sourceOwner) ?? null;
1658
+ const constructorOf = owningClass
1659
+ ? { layout: owningClass, derived: constructedBaseOf(owningClass) !== null || owningClass.nativeBase !== null, callsSuper }
1660
+ : null;
1661
+ const formalInputs = ownedFormalInputsOf(body);
1662
+ const ownedDyingValues = new Set([...ownedDyingValuesOf(body), ...formalInputs.arguments]);
1663
+ const origins = bodyValueOriginsOf(body);
1664
+ const hostClassReads = hostClassReadsOf(body, placements);
1665
+ const classObjectReads = classObjectReadsOf(body, placements);
1666
+ const hostNamespaces = hostNamespaceReadsOf(body, placements, hosts, origins.staticKeyTexts);
1667
+ // Settled here rather than as a post-construction merge (invariant 5, 2.3):
1668
+ // both are pure walks over `body` plus a plain, already-available input --
1669
+ // `staticKeyTexts` (== `origins.staticKeyTexts`) and `abiOfCallable` -- with
1670
+ // no dependency on `ctx` at all, unlike the seventeen `EmitBodyPrepassFacts`
1671
+ // fields below, whose collectors genuinely do need one.
1672
+ const functionSources = functionSourceReadsOf(origins.staticKeyTexts, body);
1673
+ const directCalleeFacts = directCalleesOf(body, abiOfCallable);
1674
+ const bodyFacts = {
1675
+ generatorBody: body.generator === true,
1676
+ receiverValues,
1677
+ bindingWriteCounts,
1678
+ constructorOf,
1679
+ ownedDyingValues,
1680
+ consumingFormalConversions: formalInputs.conversions,
1681
+ classTableRoots: classTableRootsOf(body),
1682
+ stableBorrowActuals,
1683
+ computeOrigins: origins.computeOrigins,
1684
+ propertyReadOrigins: origins.propertyReadOrigins,
1685
+ bindingReadDeclarations: origins.bindingReadDeclarations,
1686
+ conversionSources: origins.conversionSources,
1687
+ callCallees: origins.callCallees,
1688
+ calleeOnlyValues: origins.calleeOnlyValues,
1689
+ recordFieldSources: origins.recordFieldSources,
1690
+ thunkValues: origins.thunkValues,
1691
+ hostClassReads,
1692
+ classObjectReads,
1693
+ // Every deferred host member read, decided from the IR, the unioned host
1694
+ // tables and `hostClassReads` -- all settled -- before this body renders a
1695
+ // line. The census was measured against the render-time map it replaces on
1696
+ // both emitted sets (154 + 281 programs): no read the printer recorded was
1697
+ // missing from it and none differed, and every extra was the unconditional
1698
+ // `<value>:present` twin nothing reads unless a narrowing mints one.
1699
+ hostMemberReads: hostMemberReadsOf(body, hosts, origins.staticKeyTexts, hostClassReads, hostMethodAliases),
1700
+ valueCellReads: origins.valueCellReads,
1701
+ staticKeyTexts: origins.staticKeyTexts,
1702
+ hostNamespaceReads: hostNamespaces.reads,
1703
+ hostNamespaceValues: hostNamespaces.values,
1704
+ hostFunctionReads: hostNamespaces.functionReads,
1705
+ functionSourceReads: functionSources.reads,
1706
+ functionSourceSnapshotNames: functionSources.names,
1707
+ directCallees: directCalleeFacts.directCallees,
1708
+ directCalleeAbis: directCalleeFacts.directCalleeAbis
1709
+ };
1710
+ const { ctx, prepass } = createEmitContext(body.abi, body.sourceOwner, placements, classes, hosts, deriver, bodyFacts, wellKnownSymbols, captures, symbolKeys, templateObjects, directCallableBindings, virtualDispatch, narrowedFormals, repeatedConstructors, dyingArguments, instantiation, abiOfCallable, hostMethodAliases, callableMemberCandidates, borrowableMemberBodies, stableBorrowEntries, printerDrift, conversions, nativeSelections, callableIdentityDemand, nativeIntegrityRestricted, fixedFieldStateConstant);
1711
+ // `ownedValues` stays a genuine render-time OUTPUT buffer (`EmitContext`'s
1712
+ // own doc: `defineValue` grows it as each operation's result is named) --
1713
+ // unlike `ownedDyingValues` above, a formal argument's membership in it is
1714
+ // not independent of the naming machinery, so it is set on `ctx` itself
1715
+ // rather than folded into `EmitBodyFacts`.
1716
+ for (const value of formalInputs.arguments)
1717
+ ctx.ownedValues.add(value);
1718
+ // Every deferred prototype-method read, composed from the carrier resolvers'
1719
+ // own claims before this body renders a line. It is filled onto `ctx` rather
1720
+ // than folded into `EmitBodyFacts` because two of the claims need the
1721
+ // context itself -- `objectViewFrom` is the authority for a known shape's
1722
+ // fields, and it reads the layouts `createEmitContext` assembles.
1723
+ for (const [value, read] of prototypeMethodReadsOf(ctx, body))
1724
+ prepass.prototypeMethodReads.set(value, read);
1725
+ // `class-layout.ts`'s `lazyCalleeReadsOf` needs `ctx.abiOfCallable` and
1726
+ // `ctx.classes`, the identical reason `prototypeMethodReadsOf` above is
1727
+ // filled here rather than folded into `EmitBodyFacts`.
1728
+ for (const value of lazyCalleeReadsOf(ctx, body))
1729
+ prepass.lazyCalleeReads.add(value);
1730
+ // The receiver every method-value read keeps for the call that consumes it,
1731
+ // asked of the class layout rather than recorded by whichever resolver
1732
+ // happened to spell the value.
1733
+ for (const [value, receiver] of directCallReceiversOf(ctx, body))
1734
+ prepass.directCallReceivers.set(value, receiver);
1735
+ for (const [value, callee] of virtualCalleesOf(ctx, body))
1736
+ prepass.virtualCallees.set(value, callee);
1737
+ for (const [value, read] of unionMethodReadsOf(ctx, body))
1738
+ prepass.unionMethodReads.set(value, read);
1739
+ // A member read nothing but `typeof` consumes, off arms that disagree about
1740
+ // the member; the read renders nothing and the `typeof` renders the dispatch.
1741
+ for (const [value, read] of unionMemberTypeofReadsOf(ctx, body))
1742
+ prepass.unionMemberTypeofReads.set(value, read);
1743
+ const reactive = reactiveOriginsOf(ctx, body);
1744
+ for (const [value, origin] of reactive.origins)
1745
+ prepass.reactiveOrigins.set(value, origin);
1746
+ for (const [declaration, origin] of reactive.bindingOrigins)
1747
+ prepass.reactiveBindingOrigins.set(declaration, origin);
1748
+ for (const [value, read] of reactive.fieldReads)
1749
+ prepass.reactiveFieldReads.set(value, read);
1750
+ // `functionSourceReads`/`functionSourceSnapshotNames` (both writes of no
1751
+ // C++ at all, from `functionSourceReadsOf`) and `directCallees`/
1752
+ // `directCalleeAbis` (the projection of `CallOperation.target` --
1753
+ // `ir/call-dispatch.ts`, filled once for the whole program in
1754
+ // `compiler.ts` after the shake -- replacing the four call sites in
1755
+ // `emit-bindings.ts`, `emit-callable.ts`, this file's own dead-value
1756
+ // handling below, and `class-properties/emit-class-properties.ts` that used
1757
+ // to re-derive the identical "does the callee capture nothing" test at
1758
+ // render time) are now settled in `bodyFacts` above, before `ctx` exists at
1759
+ // all: both are pure walks over `body` with no dependence on anything a
1760
+ // printer emits.
1761
+ const keyTexts = stringConstantsOf(body);
1762
+ const capturedQueryCells = new Set();
1763
+ for (const block of body.blocks.values())
1764
+ for (const operation of block.operations)
1765
+ if (operation.kind === 'allocate-callable') {
1766
+ const capture = ctx.captures.of(operation.functionId);
1767
+ if (capture.kind === 'ok')
1768
+ for (const slot of capture.layout.slots)
1769
+ capturedQueryCells.add(slot.declaration);
1770
+ }
1771
+ let entryPrologue = [];
1772
+ // Every per-body census, in the one order they depend on each other in --
1773
+ // `ir/facts.ts` owns that order now, and this backend supplies only the
1774
+ // questions about its own carriers plus the two storage steps that have to
1775
+ // run inside it.
1776
+ const census = irBodyCensusOf(body, {
1777
+ integerStorage: narrowedStorage,
1778
+ // A read of a plain field defers like an Array's `length` does -- see
1779
+ // `deferrableValuesOf`. Not a read of a reactive CELL: `gea_this->count`
1780
+ // spells the `Signal<double>` itself, and only the temporary it used to be
1781
+ // copied into converted it to a `double`. Inline, `(gea_this->a) ==
1782
+ // (gea_this->b)` is an ambiguous overload (`examples/apps/weather`).
1783
+ //
1784
+ // A CLASS field's reactivity is `operation.reactive`, filled at lowering
1785
+ // from the plugin's own table (`GetOperation.reactive`) -- precise per
1786
+ // read, including an INHERITED field, because lowering walked the same
1787
+ // inheritance chain `classMemberOf` always does to find which class truly
1788
+ // declares it. This used to be asked by bare key name across every
1789
+ // celled struct in the program (`[...celled.values()].flatMap(...)`),
1790
+ // which refused deferral for a plain field merely SHARING a name with
1791
+ // some unrelated class's reactive field anywhere in the program -- an
1792
+ // over-approximation now replaced by a per-operation fact.
1793
+ //
1794
+ // A RECORD element's reactivity has no plugin declaration to mark at
1795
+ // lowering (`reactiveBoundRecordFields` derives it from what JSX binds,
1796
+ // after lowering has already run), so that half asks the target's own
1797
+ // per-struct table -- exact already, since a record has no base class to
1798
+ // walk.
1799
+ //
1800
+ // But `reactive` alone is the WRONG question here, and answering it that
1801
+ // way materialized a read that had always deferred correctly. Being
1802
+ // declared reactive is not the same as HAVING a cell: a reactive field
1803
+ // whose carrier cannot be one -- an array, `records.ts`'s
1804
+ // `representationCanCell` -- gets a companion revision cell beside it and
1805
+ // is absent from `celled`, and its own read is then an ordinary field
1806
+ // load that must go on deferring. So the marker's job is to say WHICH
1807
+ // struct declares the field (the inheritance walk `celled`'s
1808
+ // declarer-keying needs and a receiver's own name cannot give), and
1809
+ // `celled` still decides whether that field is a cell.
1810
+ deferrableMemberRead: (operation) => {
1811
+ const key = keyTexts.get(operation.key.value) ?? null;
1812
+ if (!isPlainMemberRead(ctx, operation, key))
1813
+ return false;
1814
+ if (key === null)
1815
+ return true;
1816
+ const receiver = operation.receiver.representation;
1817
+ const declaring = operation.reactive === true && receiver.kind === 'class-ref'
1818
+ ? (classMemberOf(classes, receiver.declaration, key)?.owner ?? null)
1819
+ : null;
1820
+ const struct = declaring !== null ? cppClassName(declaring) : structNameOfReceiver(receiver);
1821
+ return struct === null || ctx.hosts.reactive.celled.get(struct)?.has(key) !== true;
1822
+ },
1823
+ forwarding: {
1824
+ // Only the renderers that pass every argument through `argumentText`
1825
+ // once: a call by program body or through a `CallableObject`, and a
1826
+ // construct of a program class. A host or prototype fusion spells its
1827
+ // arguments however the host's recipe does, a tagged-union callee
1828
+ // spells them once PER ARM inside one statement, a generic set once per
1829
+ // member, and an `imul` twice.
1830
+ //
1831
+ // And only into a slot the callee's convention HAS. 10.2.1.1 binds the
1832
+ // declared formals; an argument past them is evaluated and then dropped
1833
+ // from the frame (`extra-call-arguments`), and a dropped argument's text
1834
+ // is spelled nowhere -- so a producer forwarded into that position was
1835
+ // never evaluated at all, and `mark('c')` left no mark. A rest position
1836
+ // is packed into an Array by the caller, one more spelling this audit
1837
+ // has not read, and is refused with the extras.
1838
+ forwardsCallInto: (consumer, value) => {
1839
+ const intoDeclaredFormal = (abi) => {
1840
+ if (abi === null)
1841
+ return false;
1842
+ const index = consumer.kind === 'call' || consumer.kind === 'construct'
1843
+ ? consumer.arguments.findIndex((argument) => argument.value === value.value)
1844
+ : -1;
1845
+ return index !== -1 && index < (abi.restFrom ?? abi.parameters.length);
1846
+ };
1847
+ switch (consumer.kind) {
1848
+ case 'call': {
1849
+ const callee = consumer.callee;
1850
+ const representation = callee.representation;
1851
+ const carrier = representation.kind;
1852
+ const abi = carrier === 'function' || carrier === 'function-value-dispatch'
1853
+ ? representation.abi
1854
+ : carrier === 'function-and-constructor'
1855
+ ? representation.call
1856
+ : null;
1857
+ return (intoDeclaredFormal(abi) &&
1858
+ consumer.argumentsAreSpread !== true &&
1859
+ consumer.numericRestHostCall === undefined &&
1860
+ consumer.family === undefined &&
1861
+ !ctx.numericCalls.has(consumer) &&
1862
+ !ctx.hostMemberReads.has(callee.value) &&
1863
+ !ctx.hostFunctionReads.has(callee.value) &&
1864
+ !ctx.hostClassReads.has(callee.value) &&
1865
+ !ctx.prototypeMethodReads.has(callee.value) &&
1866
+ !ctx.unionMethodReads.has(callee.value) &&
1867
+ !ctx.functionSourceReads.has(callee.value));
1868
+ }
1869
+ case 'construct': {
1870
+ const representation = consumer.callee.representation;
1871
+ const callee = representation.kind;
1872
+ const abi = callee === 'constructor-family' || callee === 'constructor-value-dispatch'
1873
+ ? representation.abi
1874
+ : callee === 'function-and-constructor'
1875
+ ? representation.construct
1876
+ : null;
1877
+ return (intoDeclaredFormal(abi) &&
1878
+ callee !== 'native-handle' &&
1879
+ callee !== 'dynamic' &&
1880
+ callee !== 'tagged-union' &&
1881
+ !ctx.hostClassReads.has(consumer.callee.value));
1882
+ }
1883
+ // The census admits only an Array element store of the element's
1884
+ // own carrier, which `emit-properties.ts` spells once per arm.
1885
+ case 'set':
1886
+ return true;
1887
+ // A cell holding exactly the value's carrier is a plain assignment;
1888
+ // anything else goes through a conversion whose spelling is its own.
1889
+ case 'binding-write': {
1890
+ const placement = ctx.placements.get(consumer.declaration);
1891
+ const held = placement?.representation;
1892
+ if (!placement || !held || (placement.storage.kind !== 'local' && placement.storage.kind !== 'region'))
1893
+ return false;
1894
+ if (ctx.hostMethodAliases.has(consumer.declaration))
1895
+ return false;
1896
+ return representationKey(held) === representationKey(value.representation);
1897
+ }
1898
+ // `emit-return.ts` reconciles the value against the ABI result (or
1899
+ // the promise payload an async body settles); equal carriers make
1900
+ // that reconciliation the identity.
1901
+ case 'return': {
1902
+ if (ctx.abi === null || ctx.generatorBody)
1903
+ return false;
1904
+ const result = ctx.abi.result;
1905
+ const target = result.kind === 'promise' && value.representation.kind !== 'promise' ? result.value : result;
1906
+ return representationKey(target) === representationKey(value.representation);
1907
+ }
1908
+ }
1909
+ },
1910
+ // A cell of this frame that no closure shares, holding exactly what is
1911
+ // written and read, and whose value renders as C++ of its own (a host
1912
+ // member, class or namespace read has no text until its use).
1913
+ forwardsBinding: (write, read) => {
1914
+ const declaration = write.declaration;
1915
+ const placement = ctx.placements.get(declaration);
1916
+ if (!placement || placement.storage.kind !== 'local' || placement.storage.owner !== ctx.owner)
1917
+ return false;
1918
+ const held = placement.representation;
1919
+ if (!held || held.kind === 'unresolved' || held.kind === 'void')
1920
+ return false;
1921
+ const key = representationKey(held);
1922
+ if (key !== representationKey(write.value.representation) || key !== representationKey(read.result.representation))
1923
+ return false;
1924
+ // A captured cell is read by the closure that copies it at allocation,
1925
+ // which no `binding-read` of this body records.
1926
+ if (ctx.captures.isBoxed(declaration) || ctx.captures.isCaptured(declaration))
1927
+ return false;
1928
+ if (ctx.hostMethodAliases.has(declaration) || ctx.reactiveBindingOrigins.has(declaration))
1929
+ return false;
1930
+ const value = write.value.value;
1931
+ return (!ctx.hostMemberReads.has(value) &&
1932
+ !ctx.hostClassReads.has(value) &&
1933
+ !ctx.hostFunctionReads.has(value) &&
1934
+ !ctx.hostNamespaceReads.has(value) &&
1935
+ !ctx.prototypeMethodReads.has(value));
1936
+ }
1937
+ },
1938
+ deadValues: {
1939
+ pureGet: (operation, key) => isPlainMemberRead(ctx, operation, key),
1940
+ // The exact producers `emit-callable.ts` (`admission.kind === 'none'`) and
1941
+ // `emit-bindings.ts` (`directCallableBindings`) register as direct callees.
1942
+ directCallee: (producer) => producer.kind === 'allocate-callable'
1943
+ ? ctx.captures.of(producer.functionId).kind === 'none'
1944
+ : producer.kind === 'binding-read'
1945
+ ? ctx.directCallableBindings.has(producer.declaration)
1946
+ : producer.kind === 'get' && directClassMethodBody(ctx, producer, keyTexts.get(producer.key.value) ?? null) !== null,
1947
+ // A named construct entry still reads the constructor's per-evaluation
1948
+ // prototype owner. Devirtualizing the code pointer cannot discard that
1949
+ // carrier, even for a class whose methods capture nothing.
1950
+ directConstructor: () => false,
1951
+ // A construction is deletable when the class it builds is one nothing can
1952
+ // observe being built. Keyed off the RESULT, which is the only operand of a
1953
+ // `construct` that names the class: the callee is the constructor object,
1954
+ // whose carrier is the constructor's convention rather than the instance's.
1955
+ pureConstruct: (operation) => {
1956
+ const result = operation.result.representation;
1957
+ return result.kind === 'class-ref' && ctx.instantiation.unobservableConstructions.has(result.declaration);
1958
+ },
1959
+ // Only for a callee reached BY NAME. An indirect call names no body, so
1960
+ // there is no body to ask -- and a thunk's frame declares the receiver
1961
+ // whatever the target does with it.
1962
+ ignoresReceiver: (callee) => callee !== undefined &&
1963
+ callee.kind === 'allocate-callable' &&
1964
+ ctx.captures.of(callee.functionId).kind === 'none' &&
1965
+ ctx.instantiation.receiverIgnoringFunctions.has(callee.functionId)
1966
+ },
1967
+ stringQueryCell: (declaration) => {
1968
+ const placement = ctx.placements.get(declaration);
1969
+ return (placement?.storage.kind === 'local' &&
1970
+ placement.storage.owner === body.sourceOwner &&
1971
+ placement.representation?.kind === 'string' &&
1972
+ !ctx.captures.isBoxed(declaration) &&
1973
+ !capturedQueryCells.has(declaration));
1974
+ },
1975
+ spellConstants: () => spellConstants(ctx, body),
1976
+ formalStorage: (settled) => {
1977
+ // The collectors below read these off the context, so they are published
1978
+ // first -- and the deferral set they see is deliberately the one the
1979
+ // hoists have not yet claimed from.
1980
+ //
1981
+ // Sixteen of these seventeen write through `prepass`, not `ctx`, because
1982
+ // `ctx`'s own view of the same field is `ReadonlyMap`/`ReadonlySet` --
1983
+ // see `EmitBodyPrepassFacts`'s doc. `ctx.deferrable` is the one
1984
+ // exception still written here directly: it has a genuine render-time
1985
+ // write of its own (`emit-arrays.ts`'s `materializeDenseReference`), so
1986
+ // it stays a plain mutable `Set` rather than joining its siblings.
1987
+ for (const value of settled.localIterators)
1988
+ prepass.localIterators.add(value);
1989
+ for (const value of settled.dead)
1990
+ prepass.deadValues.add(value);
1991
+ for (const value of settled.unread)
1992
+ prepass.unreadValues.add(value);
1993
+ for (const [value, known] of settled.booleanConstants)
1994
+ prepass.booleanConstants.set(value, known);
1995
+ for (const value of settled.deferrable)
1996
+ prepass.deferrable.add(value);
1997
+ for (const value of settled.callArgumentOnly)
1998
+ prepass.callArgumentOnly.add(value);
1999
+ for (const value of settled.typeQueryValues)
2000
+ prepass.typeQueryValues.add(value);
2001
+ for (const binding of settled.typeQueryBindings)
2002
+ prepass.typeQueryBindings.add(binding);
2003
+ for (const [operation, comparison] of settled.typeQueryComparisons)
2004
+ prepass.typeQueryComparisons.set(operation, comparison);
2005
+ for (const value of settled.integerValues)
2006
+ prepass.integerValues.add(value);
2007
+ for (const declaration of settled.integerBindings)
2008
+ prepass.integerBindings.add(declaration);
2009
+ for (const [value, form] of settled.remainderForms)
2010
+ prepass.remainderForms.set(value, form);
2011
+ for (const [call, intrinsic] of settled.numericCalls)
2012
+ prepass.numericCalls.set(call, intrinsic);
2013
+ for (const value of settled.numericCallOnly)
2014
+ prepass.numericCallOnly.add(value);
2015
+ collectFormalCells(ctx, prepass, body);
2016
+ // A captured cell initialized on separate branches has no single first
2017
+ // write that dominates the closure allocation. Allocate its handle at entry
2018
+ // so each branch only assigns the pointee. Kept separate from declarations:
2019
+ // declarations must remain uninitialized so gotos may cross their scope.
2020
+ entryPrologue = earlyCapturedCellPrologue(ctx, body);
2021
+ collectCapacityHints(ctx, prepass, body);
2022
+ return new Set(ctx.formalCells.keys());
2023
+ }
2024
+ });
2025
+ for (const value of census.loopInvariantValues)
2026
+ prepass.loopInvariantValues.add(value);
2027
+ for (const [value, layout] of census.sharedStringLayouts)
2028
+ prepass.sharedStringLayouts.set(value, layout);
2029
+ for (const value of census.hoistedResults)
2030
+ prepass.hoistedResults.add(value);
2031
+ for (const [declaration, forwarded] of census.forwardedBindings)
2032
+ prepass.forwardedBindings.set(declaration, forwarded);
2033
+ for (const [value, prior] of census.reusedStringLengths)
2034
+ prepass.reusedStringLengths.set(value, prior);
2035
+ // The hoists and the length reuse each claim a value out of the deferral set
2036
+ // after the storage step above took its copy, so drop what they claimed.
2037
+ for (const value of prepass.deferrable)
2038
+ if (!census.deferrable.has(value))
2039
+ prepass.deferrable.delete(value);
2040
+ const hoists = census.hoists;
2041
+ collectDirectBindingSinks(prepass, body, hoists.relocated);
2042
+ // After the hoists, because a window's own bound is often the loop-invariant
2043
+ // read they relocate, and a relocated value is one this may name.
2044
+ admitDenseWindows(ctx, prepass, body);
2045
+ const isSingleBlock = body.blockOrder.length === 1;
2046
+ const orderLabels = isSingleBlock ? new Map() : blockLabelsOf(body.blockOrder);
2047
+ const owner = sectionOwnerOf(body);
2048
+ // A merge is one variable written on each incoming path, so its name has to
2049
+ // exist before any predecessor renders -- including a predecessor that comes
2050
+ // earlier in the block order than the merge itself. Minting every merge's
2051
+ // name up front is what makes that hold without depending on block order.
2052
+ const mergeWrites = mergeWritesOf(ctx, body, (result) => defineValue(ctx, result));
2053
+ // After the merges, because a block that writes one is not empty.
2054
+ const flow = threadedFlowOf(ctx, body, orderLabels, hoists, mergeWrites);
2055
+ const labels = flow.labels;
2056
+ // A try region's blocks are rendered together, as one `try { } catch (...)
2057
+ // { }` chunk, by `renderTryRegion` -- never one at a time by the loop below.
2058
+ // `consumedByRegion` is filled in as each region is rendered, so the loop
2059
+ // can skip every block a region already accounted for.
2060
+ const regionByTryEntry = new Map(body.tryRegions.map((region) => [region.tryEntry, region]));
2061
+ const iteratorCloseRegionByEntry = new Map((body.iteratorCloseRegions ?? []).map((region) => [region.entry, region]));
2062
+ const consumedByRegion = new Set();
2063
+ const lineageOf = (blockIds) => {
2064
+ for (const id of blockIds) {
2065
+ const block = body.blocks.get(id);
2066
+ if (!block)
2067
+ continue;
2068
+ const found = allOperationsOf(block).find((operation) => operation.lineage !== null);
2069
+ if (found)
2070
+ return found.lineage;
2071
+ }
2072
+ return null;
2073
+ };
2074
+ const blocks = [];
2075
+ // Invariant 5's seal (`emit-context.ts`'s `sealFactFieldsForRender`): from
2076
+ // here to the end of the loop every operation renders against a context
2077
+ // whose facts are settled. Inert unless `GEA_SEAL_EMIT_CONTEXT` is set.
2078
+ const unseal = sealFactFieldsForRender(ctx);
2079
+ try {
2080
+ for (const blockId of body.blockOrder) {
2081
+ if (consumedByRegion.has(blockId))
2082
+ continue;
2083
+ const block = body.blocks.get(blockId);
2084
+ if (!block)
2085
+ throw new Error(`ir body ${body.owner} lists block ${blockId} in blockOrder but has no matching block`);
2086
+ // Shared by both region renderers below, and by each other's nested
2087
+ // calls: `renderTryRegion`'s `preparePart` recognizes an iterator-close
2088
+ // region nested inside a try part through `iteratorCloseRegionByEntry`/
2089
+ // `renderIteratorCloseRegion`, the reverse of the more common nesting
2090
+ // `renderIteratorCloseRegion` itself already handled through `regionByTryEntry`.
2091
+ const regionRendering = {
2092
+ emitOperation,
2093
+ emitTerminator,
2094
+ labelOf: requireBlockLabel,
2095
+ labels,
2096
+ isSingleBlock,
2097
+ mergeWrites,
2098
+ regionByTryEntry,
2099
+ iteratorCloseRegionByEntry,
2100
+ renderIteratorCloseRegion,
2101
+ // The hoist plan and the block tail, so a region's blocks render the
2102
+ // way every other block does -- see `RegionRendering` for what was
2103
+ // being dropped, and why one of the three was a defect rather than a
2104
+ // missed optimization.
2105
+ relocated: hoists.relocated,
2106
+ emitHoistedInto: (partCtx, partLines, partBlock) => {
2107
+ for (const operation of hoists.into.get(partBlock) ?? [])
2108
+ emitOperation(partCtx, partLines, operation);
2109
+ },
2110
+ emitBlockTail: (partCtx, partLines, partBlock) => {
2111
+ emitDenseSetup(partCtx, partLines, partBlock);
2112
+ const partFill = partCtx.fillLoops.get(partBlock);
2113
+ if (!partFill)
2114
+ return false;
2115
+ emitFillLoop(partCtx, partLines, partFill, requireBlockLabel(labels, partFill.exit));
2116
+ return true;
2117
+ }
2118
+ };
2119
+ const iteratorCloseRegion = iteratorCloseRegionByEntry.get(blockId);
2120
+ if (iteratorCloseRegion) {
2121
+ const lines = [];
2122
+ const consumed = renderIteratorCloseRegion(ctx, lines, body, iteratorCloseRegion, regionRendering);
2123
+ for (const id of consumed)
2124
+ consumedByRegion.add(id);
2125
+ blocks.push({
2126
+ text: lines.join('\n'),
2127
+ facts: { kind: 'materialized', representation: { kind: 'void' }, owner, lineage: iteratorCloseRegion.lineage }
2128
+ });
2129
+ continue;
2130
+ }
2131
+ const region = regionByTryEntry.get(blockId);
2132
+ if (region) {
2133
+ const lines = [];
2134
+ const consumed = renderTryRegion(ctx, lines, body, region, regionRendering);
2135
+ for (const id of consumed)
2136
+ consumedByRegion.add(id);
2137
+ blocks.push({
2138
+ text: lines.join('\n'),
2139
+ facts: { kind: 'materialized', representation: { kind: 'void' }, owner, lineage: lineageOf(consumed) }
2140
+ });
2141
+ continue;
2142
+ }
2143
+ if (flow.skipped.has(blockId))
2144
+ continue;
2145
+ const lines = [];
2146
+ if (!isSingleBlock && flow.labeled.has(requireBlockLabel(labels, blockId)))
2147
+ lines.push(`${requireBlockLabel(labels, blockId)}:`);
2148
+ for (const operation of block.operations) {
2149
+ const result = 'result' in operation ? operation.result : null;
2150
+ if (result && hoists.relocated.has(result.id))
2151
+ continue;
2152
+ emitOperation(ctx, lines, operation);
2153
+ }
2154
+ // AFTER the block's own statements: a preheader assigns the cells a hoisted read names.
2155
+ for (const operation of hoists.into.get(blockId) ?? [])
2156
+ emitOperation(ctx, lines, operation);
2157
+ // The writes belong after everything this block computed and before it
2158
+ // transfers control: that is exactly where the incoming value is live.
2159
+ for (const write of mergeWrites.get(blockId) ?? []) {
2160
+ const raw = operandText(ctx, write.value);
2161
+ const converted = alignedValueText(ctx, 'emit.ts:2111', write.value.representation, write.target, raw);
2162
+ if (converted === null) {
2163
+ throw createCppEmitBlockedError(`conversion:${representationKey(write.value.representation)}->${representationKey(write.target)}`, `cannot convert merge input from "${representationKey(write.value.representation)}" to "${representationKey(write.target)}"`);
2164
+ }
2165
+ lines.push(`${write.name} = ${converted};`);
2166
+ }
2167
+ // Last of all, so every value a window's condition names -- a hoisted read,
2168
+ // a merge -- is already assigned in this block.
2169
+ emitDenseSetup(ctx, lines, blockId);
2170
+ // A counted `push` loop's header does not branch: it appends (`emit-arrays.ts`).
2171
+ const fill = ctx.fillLoops.get(blockId);
2172
+ if (fill)
2173
+ emitFillLoop(ctx, lines, fill, requireBlockLabel(labels, fill.exit));
2174
+ else
2175
+ emitTerminator(ctx, lines, labels, isSingleBlock, block.terminator, flow.nextLabel.get(blockId) ?? null);
2176
+ blocks.push({
2177
+ text: lines.join('\n'),
2178
+ facts: {
2179
+ kind: 'materialized',
2180
+ // A block is a sequence of statements, not a value: `void` is the one
2181
+ // carrier that says exactly that instead of borrowing some operand's
2182
+ // representation to stand in for a whole statement sequence.
2183
+ representation: { kind: 'void' },
2184
+ owner,
2185
+ // The block's authority is the first operation in it that has any: a
2186
+ // terminator is frequently synthesized and carries none, and a section
2187
+ // attributed to nothing when it does contain real work would lose the
2188
+ // trace back to the source that produced it.
2189
+ lineage: allOperationsOf(block).find((operation) => operation.lineage !== null)?.lineage ?? null
2190
+ }
2191
+ });
2192
+ }
2193
+ }
2194
+ finally {
2195
+ unseal();
2196
+ }
2197
+ // Every dispatched method reference has to have been CALLED. One that was
2198
+ // stored, passed or returned instead is carried as a `CallableObject` over a
2199
+ // single statically named body, which for an overridden method is the base's
2200
+ // -- the exact silent miscompile the dispatch exists to remove. Asked here,
2201
+ // once the whole body has rendered, because only then is it known that no
2202
+ // call consumed it.
2203
+ const carried = [...ctx.virtualCallees.keys()].filter((value) => !ctx.virtualCalleesUsed.has(value));
2204
+ if (carried.length > 0) {
2205
+ throw createCppEmitBlockedError('call-abi:virtual-dispatch', `takes a function object of an overridden method rather than calling it (${carried.map((value) => ctx.virtualCallees.get(value)?.member ?? value).join(', ')}); a carrier names one body, which for an overridden method is the base's`);
2206
+ }
2207
+ const carriedUnionMethods = [...ctx.unionMethodReads.keys()].filter((value) => !ctx.unionMethodReadsUsed.has(value));
2208
+ if (carriedUnionMethods.length > 0) {
2209
+ throw createCppEmitBlockedError('call-abi:tagged-union-method', `takes ${carriedUnionMethods.length} tagged-union method value(s) without calling them; each union arm has its own receiver convention, so no single callable carrier can preserve them`);
2210
+ }
2211
+ // Declarations come last because they are only complete once every block has
2212
+ // rendered, and first in the output because a `goto` may not jump into the
2213
+ // scope of a variable whose declaration initializes it.
2214
+ const declarationFacts = { kind: 'materialized', representation: { kind: 'void' }, owner, lineage: null };
2215
+ const declarations = {
2216
+ text: ctx.declarations.map((entry) => `${entry.type} ${entry.name};`).join('\n'),
2217
+ facts: declarationFacts
2218
+ };
2219
+ const prologue = entryPrologue.length === 0 ? [] : [{ text: entryPrologue.join('\n'), facts: declarationFacts }];
2220
+ return [declarations, ...prologue, ...blocks];
2221
+ };
2222
+ // Re-exported so a consumer that emits bodies has one import for the naming
2223
+ // rules those bodies are rendered under; the definitions live with the context
2224
+ // they name.
2225
+ export { cppConstructedThunkName, cppConstructThunkName, cppFormalName, cppReceiverName, cppThunkName, isCppEmitBlockedError } from './emit-context.js';