@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,2027 @@
1
+ import { coercionText } from './emit-coercion.js';
2
+ import { classRefTransportKind, constructorUpcastMember } from './class-ref-transport.js';
3
+ import { chainFieldProtocolUnused, nativeSumNarrowingTransports } from './native-narrowing-transport.js';
4
+ import { classRefDomainsOverlap, classifierDomainsOverlap } from '../../conversion/algebra.js';
5
+ import { recordCastableToArray } from './emit-arrays.js';
6
+ import { emptyConversionRegistry, narrowingReachesTarget, narrowsToDescendantClassUnion } from '../../conversion/build.js';
7
+ import { defaultRecordLayoutPolicy } from '../../representation/policies.js';
8
+ import { abiKey, arrayExtensionKey, representationKey, carriesUndefined } from '../../representation/model.js';
9
+ import { isSpellable, callableObjectAbi, resultAdapterTransportOf, boxDiscriminantsOfArm, conversionRecipeOf, boxedAssertionText, dropsAllParametersIntoResultArm, dropsUnboundParameters, dynamicTagFor, promisePayloadConvertible, rebasesRestOverLeadingParameters, dictionaryCastableToDictionary, recordCastableToDictionary, recordRecastCrossesDynamic, recordsRecastable, sameArrayUpToExtension, sumIntoPayloadText, widensResultIntoArm } from './emit-narrowing.js';
10
+ import { cppTypeOf } from './types.js';
11
+ import { nativeSumWidenable } from '../../conversion/native-sum.js';
12
+ import { nativeSelectionRecipeOf, nativeTotalSelectionRecipeOf } from '../../conversion/native-selection.js';
13
+ import { nativeClassReferenceIdentityOf } from '../../conversion/native-class-reference.js';
14
+ import { ownedRecordMaterializationPlan, recordViewUsesOnlyDirectFields } from '../../conversion/record-view.js';
15
+ import { cppStringObjectNativeType } from './regexp-types.js';
16
+ import { viewPlanFor } from './emit-record-view.js';
17
+ /** Called only after the native converting-constructor predicate has selected this pair. */
18
+ const nativeClassPresence = (value) => {
19
+ if (value.kind === 'class-ref' || value.kind === 'null' || value.kind === 'undefined')
20
+ return true;
21
+ if (value.kind === 'optional')
22
+ return nativeClassPresence(value.payload);
23
+ return value.kind === 'tagged-union' && value.arms.every((arm) => nativeClassPresence(arm.value));
24
+ };
25
+ const nativeCallableTransport = (source, target) => {
26
+ const from = callableObjectAbi(source);
27
+ const to = callableObjectAbi(target);
28
+ return from === null || to === null
29
+ ? {}
30
+ : { nativeFieldProtocol: 'unused', callableAdapter: { from, to }, callableIdentityTransport: 'preserved' };
31
+ };
32
+ const nativeSumConversion = (source, target) => {
33
+ if (!nativeSumWidenable(source, target))
34
+ return null;
35
+ const domain = `sum-widen:${representationKey(source)}->${representationKey(target)}`;
36
+ return {
37
+ classifier: { id: 'gea::native-sum::live-alternative', domain },
38
+ materializer: {
39
+ id: 'gea::native-sum::inject-alternative',
40
+ domain,
41
+ allocates: false,
42
+ nativeFieldProtocol: 'unused',
43
+ nativePayloadTransport: 'preserved',
44
+ ...nativeClassReferenceIdentityOf(source, target)
45
+ }
46
+ };
47
+ };
48
+ const nativeSelectionConversion = (source, target, nativeSelection) => {
49
+ const domain = `native-selection:${representationKey(source)}->${representationKey(target)}`;
50
+ return {
51
+ classifier: { id: 'gea::native-sum::selected-alternative', domain },
52
+ materializer: {
53
+ id: 'gea::native-sum::select',
54
+ domain,
55
+ allocates: false,
56
+ nativeFieldProtocol: 'unused',
57
+ nativePayloadTransport: 'preserved',
58
+ nativeSelection,
59
+ ...nativeClassReferenceIdentityOf(source, target)
60
+ }
61
+ };
62
+ };
63
+ /**
64
+ * What this backend can actually convert, stated as a registry the conversion
65
+ * graph asks rather than assumes.
66
+ *
67
+ * Most entries are `null`, and that is the honest answer rather than a
68
+ * placeholder. Conversion *from* the dynamic carrier -- classifying a boxed
69
+ * value and materializing a concrete one out of it -- needs the box to be able
70
+ * to say what it holds and to hand the payload back, and an entry is installed
71
+ * here only where a primitive that really does both is already built.
72
+ *
73
+ * This paragraph used to say `gea::Value` could do neither, and that it was
74
+ * storage and a tag and deliberately nothing more. The second half is right
75
+ * about the part that matters -- a box has no dynamic OPERATIONS, no call, no
76
+ * arithmetic, no coercion, which is what keeps a program that reads an
77
+ * `unknown` refused while one that merely carries an unread one compiles. The
78
+ * first half was wrong, and wrong in a way that hid four working primitives
79
+ * behind a blanket claim: `Value::box` records
80
+ * `payloadTypeTagFor<std::decay_t<T>>()` for every payload it stores, so a box
81
+ * can name its payload's exact C++ type, and `gea::detail::unboxAs` hands that
82
+ * payload back after checking both the tag and that type. Reporting a payload
83
+ * is not the same capability as operating on one, and only the second is
84
+ * deliberately absent.
85
+ *
86
+ * So the discipline this file keeps is not "install almost nothing". It is:
87
+ * install exactly where a real classifier and a real materializer exist and
88
+ * their domains are disjoint, and refuse everywhere else WITH THE REASON, so
89
+ * that a later reader can tell an unimplemented entry from an impossible one.
90
+ * A blanket claim cannot make that distinction, which is how the class-ref
91
+ * entry below came to be missing for as long as it was while both directions
92
+ * of its round trip sat built and unused.
93
+ *
94
+ * The one entry that is installed is the narrowing unwrap, and it is installed
95
+ * because it is genuinely built. `gea::Optional<T>` (gea_runtime.h) is a
96
+ * presence flag plus an always-constructed payload, with `has_value()` as the
97
+ * pure membership test and `operator*` as the load. Both are real operations on
98
+ * a real type, and `emitBindingRead` renders exactly them.
99
+ *
100
+ * What licenses the unwrap is the checker's own narrowing, not a proof this
101
+ * backend re-derives: inside `if (tag)` TypeScript has already established that
102
+ * the cell holds a value, and re-testing it here would be a second authority
103
+ * answering a settled question -- and would need somewhere to go when it
104
+ * disagreed, which a load has not got. The payload is always constructed, so a
105
+ * narrowing that was somehow wrong reads a default-constructed value rather
106
+ * than stepping off the end of anything; deterministic, and still wrong, which
107
+ * is the right place for the consequence of an unsound narrowing to land.
108
+ */
109
+ /**
110
+ * The exact-tag read out of a box, for the three carriers whose payload C++
111
+ * type the carrier itself names.
112
+ *
113
+ * `gea::detail::unboxValue` (gea_runtime.h) checks the box's tag AND the C++
114
+ * type of its payload and aborts by name when either disagrees, so this is an
115
+ * exact tag test and never a coercion -- which is the discipline
116
+ * `ConversionRuntimeRegistry` puts on these three entries specifically. What
117
+ * licenses it is the same thing that licenses the narrowing unwrap below: the
118
+ * program stated the type (`a as unknown as string`) and the checker erased
119
+ * the statement, so the only thing left to do at runtime is read the payload
120
+ * and refuse loudly if it is not there.
121
+ *
122
+ * `emit-narrowing.ts`'s `unboxedLoadText` renders this same
123
+ * `unboxValue<T>` load, and it renders it for every tag that has a payload to
124
+ * read rather than only for these three -- which is why `classRefMaterializer`
125
+ * below can be installed without touching the emitter at all.
126
+ */
127
+ /**
128
+ * Whether a carrier can be boxed into `gea::Value`.
129
+ *
130
+ * `dynamicTagFor` answers for a carrier that HAS one JavaScript type. A sum
131
+ * does not -- which type it is depends on which arm is live, or on whether an
132
+ * optional is present at all -- so the question recurses through both sum
133
+ * carriers, exactly as `emit-narrowing.ts`'s `widenedStoreText` recurses when
134
+ * it RENDERS the store. Asked as one predicate rather than restated per
135
+ * branch, because the branch that restated it read only one level and refused
136
+ * `tagged-union(record | optional(callable))`: hono's `compose` builds that
137
+ * carrier for its `handler`, and the render was ready for it.
138
+ */
139
+ const boxable = (representation) => {
140
+ // Already a box. `dynamicTagFor` answers `null` for it -- a box holds
141
+ // whichever tag its value carries, not one fixed tag -- and reading that as
142
+ // "cannot be boxed" refused hono's `compose` handler,
143
+ // `tagged-union(dynamic | optional(callable))`, whose first arm is one.
144
+ if (representation.kind === 'dynamic')
145
+ return true;
146
+ if (representation.kind === 'optional')
147
+ return boxable(representation.payload);
148
+ if (representation.kind === 'tagged-union')
149
+ return representation.arms.every((arm) => boxable(arm.value));
150
+ return dynamicTagFor(representation) !== null;
151
+ };
152
+ const exactTagRead = (tag) => ({
153
+ classifier: { id: 'gea::Value::tag', domain: `tag:${tag}` },
154
+ materializer: { id: 'gea::detail::unboxValue', domain: `tag:${tag}`, allocates: false }
155
+ });
156
+ /**
157
+ * A derived class-ref stored into a base class-ref cell.
158
+ *
159
+ * `gea::Ref<T>` declares a converting constructor from `gea::Ref<Other>` gated
160
+ * on `std::is_convertible_v<Other*, T*>` (`gea_runtime.h`), and `records.ts`
161
+ * emits `struct D : B` for a class that states a base -- so the C++ base
162
+ * subobject the conversion needs is exactly the one the struct already has.
163
+ * Nothing is rendered for it: the emitter's ordinary store text is the
164
+ * conversion, the same way the `CallableObject` converting constructors above
165
+ * are performed by naming the target type.
166
+ *
167
+ * Only in the ancestor direction, and only between two classes with the same
168
+ * ownership. A base written into a derived cell is a downcast the language
169
+ * does not perform implicitly either, and two carriers of the same class under
170
+ * different ownership are different physical things (`gea::Ref<T>` and a `T`
171
+ * by value), not a heritage question at all.
172
+ */
173
+ const upcastsToBase = (source, target) => classRefTransportKind(source, target) === 'upcast';
174
+ /**
175
+ * The exact mirror: a BASE class-ref read at one of its descendants, which is
176
+ * what `instanceof` narrows and what `upcastsToBase` above cannot express.
177
+ *
178
+ * `Object3D.traverse( part => { if ( part instanceof Mesh ) part.castShadow =
179
+ * true } )` is the shape, and it is the one `instanceof` exists for -- the
180
+ * handle is declared at the base and the guard proves the object is a
181
+ * descendant. Nothing had ever PROPOSED the pair (`conversion/build.ts`'s
182
+ * class-ref loop asked only `widening`), so the reads past the guard carried
183
+ * two unmet obligations and the program could not certify.
184
+ *
185
+ * `gea::host::downcastClassRef` (gea_runtime.h) is the load: `staticCast` plus
186
+ * a `static_assert` that the heritage this function checks really holds in the
187
+ * emitted structs. The physical layout classifier reads the handle's allocated
188
+ * type. JavaScript `instanceof` additionally observes prototype ancestry;
189
+ * layout selection must not discard a prototype object merely because it is
190
+ * not an instance of its own constructor.
191
+ */
192
+ const downcastsToDerived = (source, target) => classRefTransportKind(source, target) === 'downcast';
193
+ /** Exactly one class arm inside `target` accepts `source` by inheritance. */
194
+ const hasSingleClassUpcastHome = (source, target) => {
195
+ if (upcastsToBase(source, target))
196
+ return true;
197
+ if (target.kind === 'optional')
198
+ return hasSingleClassUpcastHome(source, target.payload);
199
+ if (target.kind !== 'tagged-union')
200
+ return false;
201
+ return target.arms.filter((arm) => hasSingleClassUpcastHome(source, arm.value)).length === 1;
202
+ };
203
+ /** The checked dynamic-call adapter shape currently installed by the runtime registry. */
204
+ /**
205
+ * A choice among generic functions into a superset of the same choice: the
206
+ * tag is remapped (`emit-narrowing.ts`'s `genericFunctionSetWideningText`).
207
+ * One pair for every direction a store, a merge or a recast asks it in --
208
+ * the index space is the target's, whichever way the plan phrased the step.
209
+ */
210
+ const genericFunctionSetPair = (source, target) => {
211
+ if (target.kind !== 'generic-function-set')
212
+ return null;
213
+ if (source.kind === 'generic-function-set') {
214
+ if (!source.members.every((member) => target.members.includes(member)))
215
+ return null;
216
+ }
217
+ else if (
218
+ // A member's own name, read as the callable its cell holds, into the
219
+ // one-member set it denotes: index 0, whatever the callable is.
220
+ !((source.kind === 'function' ||
221
+ source.kind === 'function-family' ||
222
+ source.kind === 'function-value-family' ||
223
+ source.kind === 'function-value-dispatch') &&
224
+ target.members.length === 1)) {
225
+ return null;
226
+ }
227
+ const domain = `generic-function-set:${representationKey(source)}->${representationKey(target)}`;
228
+ return {
229
+ classifier: { id: 'generic-function-set::index', domain },
230
+ materializer: { id: 'generic-function-set::remap', domain, allocates: false }
231
+ };
232
+ };
233
+ /**
234
+ * A declaration/family callable and an evaluated callable dispatch differ in
235
+ * authentication, not in their stored frame. This is intentionally narrower
236
+ * than an adapter: each formal, its passing ownership, receiver, rest slot,
237
+ * and result must share the representation model's exact ABI identity.
238
+ */
239
+ /**
240
+ * Any callable stored where a function IDENTITY is declared -- the carrier of
241
+ * `(...args: never[]) => R`.
242
+ *
243
+ * `gea::CallableObject` already holds a `Ref<FunctionObjectIdentity>` beside
244
+ * its thunk, so this reads a field rather than building anything; the accessor
245
+ * mints the identity on first read for a callable that has not been asked
246
+ * before, which is why it is declared as allocating. `gea::ConstructorObject`
247
+ * carries no such field, so the constructor-only carriers are not offered and
248
+ * keep their refusal. Kept in step with `emit-narrowing.ts`'s
249
+ * `callableIdentityText`, which renders exactly this pair.
250
+ */
251
+ const callableIdentityPair = (source, target) => {
252
+ if (target.kind !== 'callable-identity')
253
+ return null;
254
+ const spellsCallableObject = source.kind === 'function' ||
255
+ source.kind === 'function-family' ||
256
+ source.kind === 'function-value-family' ||
257
+ source.kind === 'function-value-dispatch' ||
258
+ source.kind === 'function-and-constructor';
259
+ if (!spellsCallableObject)
260
+ return null;
261
+ const domain = `callable-identity:${representationKey(source)}`;
262
+ return {
263
+ classifier: { id: 'gea::CallableObject::functionObjectIdentity', domain },
264
+ materializer: { id: 'gea::CallableObject::functionObjectIdentity', domain, allocates: true }
265
+ };
266
+ };
267
+ /**
268
+ * A call-only function object entering a slot that also names its
269
+ * `[[Construct]]` -- `Factory as typeof Factory & (new (v: number) => T)`.
270
+ *
271
+ * The call halves must be the SAME frame, not merely compatible ones: an
272
+ * adapted frame is a different function object, and what this pair claims is
273
+ * that the value survives unchanged -- same environment, same
274
+ * `FunctionObjectIdentity`, one own-property table. The only thing added is
275
+ * the construct entry, and `emit-narrowing.ts`'s `callableConstructEntryText`
276
+ * renders it as a lookup by the value's own invoke pointer, against the table
277
+ * `translation-unit.ts` publishes beside each construct thunk. So the pair is
278
+ * admissible on the frames alone: whether THIS function object has such an
279
+ * entry is a fact only the value carries, and a value that does not refuses by
280
+ * name at run time rather than constructing through another body.
281
+ */
282
+ const callableConstructEntryPair = (source, target) => {
283
+ if (target.kind !== 'function-and-constructor')
284
+ return null;
285
+ const call = source.kind === 'function' ||
286
+ source.kind === 'function-family' ||
287
+ source.kind === 'function-value-family' ||
288
+ source.kind === 'function-value-dispatch'
289
+ ? source.abi
290
+ : null;
291
+ if (call === null || abiKey(call) !== abiKey(target.call))
292
+ return null;
293
+ const domain = `callable-construct-entry:${representationKey(source)}->${representationKey(target)}`;
294
+ return {
295
+ classifier: { id: 'gea::CallableObject::identity', domain },
296
+ materializer: { id: 'gea::withConstructEntry', domain, allocates: false }
297
+ };
298
+ };
299
+ const exactFunctionDispatchPair = (source, target) => {
300
+ if (target.kind !== 'function-value-dispatch')
301
+ return null;
302
+ if (source.kind !== 'function' &&
303
+ source.kind !== 'function-family' &&
304
+ source.kind !== 'function-value-family' &&
305
+ source.kind !== 'function-value-dispatch') {
306
+ return null;
307
+ }
308
+ if (abiKey(source.abi) !== abiKey(target.abi))
309
+ return null;
310
+ const domain = `callable-exact-dispatch:${representationKey(source)}->${representationKey(target)}`;
311
+ return {
312
+ classifier: { id: 'gea::CallableObject::identity', domain },
313
+ materializer: { id: 'gea::CallableObject::identity', domain, allocates: false }
314
+ };
315
+ };
316
+ /** The executable classifier used by both dynamic sums and callable-carrier admission. */
317
+ const cppTaggedUnionArmClassifier = (arm) => {
318
+ let discriminants;
319
+ try {
320
+ discriminants = boxDiscriminantsOfArm(arm);
321
+ }
322
+ catch {
323
+ return null;
324
+ }
325
+ if (discriminants === null || discriminants.length === 0)
326
+ return null;
327
+ if (arm.runtimeDiscriminator.kind === 'callable-tag') {
328
+ return {
329
+ id: 'gea::Value::tag',
330
+ domain: 'tag:Function',
331
+ callableDomain: { kind: 'tag' }
332
+ };
333
+ }
334
+ // An arm that is itself a union -- `T | undefined | null` whose present
335
+ // arm holds `string | number` -- is classified by the disjunction of its
336
+ // members' tests: the box holds this arm when any member's test accepts
337
+ // it, and it is disjoint from another arm when no member's domain meets
338
+ // that arm's (`algebra.ts`'s `classifierDomainsOverlap` reads the
339
+ // composite). Callable memberships are not a flat partition, so an arm
340
+ // mixing them in stays unclassified, as it always was.
341
+ if (discriminants.length > 1) {
342
+ if (discriminants.some((entry) => entry.callableMembers !== null))
343
+ return null;
344
+ const domains = [...new Set(discriminants.map(boxDiscriminantDomainOf))].sort();
345
+ return { id: 'gea::Value::tagAnyOf', domain: `any-of:${domains.join('|')}` };
346
+ }
347
+ const discriminant = discriminants[0];
348
+ if (discriminant.callableMembers !== null) {
349
+ return {
350
+ id: 'gea::Value::callableDeclarationIdentity',
351
+ domain: `callable-membership:${[...discriminant.callableMembers].sort().join('+')}`,
352
+ callableDomain: { kind: 'membership', members: [...discriminant.callableMembers].sort() }
353
+ };
354
+ }
355
+ if (discriminant.nominal !== null) {
356
+ return { id: 'gea::detail::classIdentityExtends', domain: boxDiscriminantDomainOf(discriminant) };
357
+ }
358
+ if (discriminant.payload !== null) {
359
+ return { id: 'gea::Value::tag+payloadType', domain: boxDiscriminantDomainOf(discriminant) };
360
+ }
361
+ return { id: 'gea::Value::tag', domain: boxDiscriminantDomainOf(discriminant) };
362
+ };
363
+ /** The runtime domain one box discriminant accepts, spelled the way `classifierDomainsOverlap` compares it. */
364
+ const boxDiscriminantDomainOf = (discriminant) => discriminant.nominal !== null
365
+ ? `class-family:${discriminant.nominal}`
366
+ : discriminant.payload !== null
367
+ ? `tag-payload:${discriminant.tag}:${discriminant.payload}`
368
+ : `tag:${discriminant.tag}`;
369
+ /** The exact Representation-side mirror of callable-runtime carrier support. */
370
+ const dynamicCarrierSupported = (representation, seen = new Set()) => {
371
+ if (seen.has(representation))
372
+ return true;
373
+ const nested = new Set(seen).add(representation);
374
+ switch (representation.kind) {
375
+ case 'dynamic':
376
+ case 'string':
377
+ case 'symbol':
378
+ case 'null':
379
+ case 'undefined':
380
+ return true;
381
+ case 'scalar':
382
+ return representation.domain === 'number' || representation.domain === 'boolean';
383
+ case 'optional':
384
+ // Callable Optional<T> has one deliberately narrow runtime ABI:
385
+ // absence is Undefined. The Representation retains which source tag
386
+ // absence means, so nullable forms fail preflight while the exact
387
+ // undefined form can use that ABI without accepting Null by accident.
388
+ return representation.absence === 'undefined' && dynamicCarrierSupported(representation.payload, nested);
389
+ case 'tagged-union': {
390
+ if (!representation.arms.every((arm) => dynamicCarrierSupported(arm.value, nested)))
391
+ return false;
392
+ for (let left = 0; left < representation.arms.length; left++) {
393
+ const leftValue = representation.arms[left].value;
394
+ if (leftValue.kind !== 'class-ref')
395
+ continue;
396
+ for (let right = left + 1; right < representation.arms.length; right++) {
397
+ const rightValue = representation.arms[right].value;
398
+ if (rightValue.kind === 'class-ref' && classRefDomainsOverlap(leftValue, rightValue))
399
+ return false;
400
+ }
401
+ }
402
+ const classifiers = representation.arms.map(cppTaggedUnionArmClassifier);
403
+ if (classifiers.some((classifier) => classifier === null))
404
+ return false;
405
+ const installed = classifiers;
406
+ return !installed.some((classifier, index) => installed.slice(index + 1).some((other) => classifierDomainsOverlap(classifier, other)));
407
+ }
408
+ case 'array-object':
409
+ case 'class-ref':
410
+ case 'record':
411
+ case 'record-with-index':
412
+ case 'native-record-ref':
413
+ return representation.ownership === 'shared-refcount';
414
+ case 'promise':
415
+ return dynamicCarrierSupported(representation.value, nested);
416
+ case 'function':
417
+ case 'function-family':
418
+ case 'function-value-family':
419
+ case 'function-value-dispatch':
420
+ return dynamicCallableAbiSupported(representation.abi, nested);
421
+ case 'void':
422
+ return true;
423
+ default:
424
+ return false;
425
+ }
426
+ };
427
+ const dynamicCallableAbiSupported = (abi, seen = new Set()) => {
428
+ if (abi.receiver !== null && !dynamicCarrierSupported(abi.receiver, seen))
429
+ return false;
430
+ if (abi.result.kind !== 'void' && !dynamicCarrierSupported(abi.result, seen))
431
+ return false;
432
+ if (!abi.parameters.every((parameter) => dynamicCarrierSupported(parameter.value, seen)))
433
+ return false;
434
+ if (abi.restFrom === null)
435
+ return true;
436
+ const rest = abi.parameters[abi.restFrom]?.value;
437
+ return (abi.restFrom === abi.parameters.length - 1 &&
438
+ rest?.kind === 'array-object' &&
439
+ rest.ownership === 'shared-refcount' &&
440
+ dynamicCarrierSupported(rest.element, seen));
441
+ };
442
+ const dynamicCallablePair = (target) => {
443
+ const domain = `dynamic-callable:${representationKey(target)}`;
444
+ return {
445
+ classifier: { id: 'gea::Value::tag', domain },
446
+ materializer: { id: 'gea::detail::DynamicCarrier::in', domain, allocates: true }
447
+ };
448
+ };
449
+ export const createCppConversionRegistry = (layouts = defaultRecordLayoutPolicy) => {
450
+ // A sum narrowing's contract is composed from the contracts this same
451
+ // registry states for its leaf pairs (`native-narrowing-transport.ts`), so
452
+ // the tables are handed a view of the finished registry.
453
+ const registry = cppConversionTables(layouts, (source, target) => nativeSumNarrowingTransports(registry, source, target) ? { nativeFieldProtocol: 'unused', nativePayloadTransport: 'preserved' } : {}, (source, payload) => (chainFieldProtocolUnused(registry, source, payload) ? { nativeFieldProtocol: 'unused' } : {}));
454
+ return registry;
455
+ };
456
+ const cppConversionTables = (layouts, nativeNarrowing, nativeWrappedPayload) => ({
457
+ ...emptyConversionRegistry,
458
+ stringMaterializer: () => exactTagRead('String'),
459
+ /**
460
+ * `gea::Symbol` out of a box is the same exact-tag read as a string: the
461
+ * printer's `unboxedLoadText` spells it `unboxValue<gea::Symbol>(v,
462
+ * Tag::Symbol, ...)` off `dynamicTagFor`'s own `symbol -> 'Symbol'` row.
463
+ * The registry left this `null` while the printer rendered it, so a
464
+ * `typeof x === 'symbol'` narrowing certified nothing (no installed exact
465
+ * symbol-tag materializer) on a program the printer had always emitted --
466
+ * the census/printer disagreement Phase 2.3's emission gate exists to
467
+ * surface, found on `symbol-description.runtime.js`.
468
+ */
469
+ symbolMaterializer: () => exactTagRead('Symbol'),
470
+ scalarMaterializer: (domain) => domain === 'number'
471
+ ? exactTagRead('Number')
472
+ : domain === 'boolean'
473
+ ? exactTagRead('Boolean')
474
+ : domain === 'bigint'
475
+ ? exactTagRead('BigInt')
476
+ : null,
477
+ /**
478
+ * `undefined` out of a box: `exactTagRead` above cannot serve this either,
479
+ * for the identical reason `gea::detail::unboxUndefinedValue`
480
+ * (gea_runtime.h) exists instead of reusing `unboxValue<T>` -- there is no
481
+ * payload, so no `T` to have recorded a `payloadTypeTagFor` for. The tag
482
+ * alone is the whole check; a mismatch aborts by name, exactly the same
483
+ * refusal discipline as every other exact-tag read in this registry.
484
+ */
485
+ undefinedMaterializer: () => ({
486
+ classifier: { id: 'gea::Value::tag', domain: 'tag:Undefined' },
487
+ materializer: { id: 'gea::detail::unboxUndefinedValue', domain: 'tag:Undefined', allocates: false }
488
+ }),
489
+ /**
490
+ * A bare `Function` is intentionally dynamic: it promises `[[Call]]`, but
491
+ * no static parameter or result types. The runtime's
492
+ * `DynamicCarrier<CallableObject<R(A...)>>::in` is the checked bridge from
493
+ * that boundary. It verifies `Tag::Function`, preserves an exact-ABI value
494
+ * directly when possible, and otherwise returns a callable adapter that
495
+ * boxes the target ABI's arguments, invokes the source box, and checks the
496
+ * returned value as `R`.
497
+ *
498
+ * Install only the ABI presently proved end to end: a receiver-less,
499
+ * fixed-arity numeric comparator whose arguments are themselves dynamic
500
+ * values. This is Three's public `Function | null` sort hook. Broadening the
501
+ * predicate requires matching `DynamicCarrier<T>::supported` for every new
502
+ * parameter/result carrier; guessing there would move an honest preflight
503
+ * refusal into a C++ template failure.
504
+ */
505
+ functionValueDispatchMaterializer: (abi) => {
506
+ const target = { kind: 'function-value-dispatch', abi };
507
+ return dynamicCallableAbiSupported(abi) ? dynamicCallablePair(target) : null;
508
+ },
509
+ functionMaterializer: (functionId, abi) => {
510
+ if (!dynamicCallableAbiSupported(abi))
511
+ return null;
512
+ const domain = `dynamic-callable-identity:${functionId}:${representationKey({ kind: 'function', functionId, abi })}`;
513
+ return {
514
+ classifier: { id: 'gea::Value::callableDeclarationIdentity', domain },
515
+ materializer: { id: 'gea::detail::DynamicCarrier::in', domain, allocates: true }
516
+ };
517
+ },
518
+ /**
519
+ * `null` out of a box: the exact sibling of `undefinedMaterializer` above,
520
+ * and absent for as long as it was on a premise that was simply false.
521
+ *
522
+ * `conversion/derive.ts` asks this hook and, with nothing installed,
523
+ * answers `never('the runtime does not distinguish null with an exact
524
+ * tag')`. The runtime distinguishes it precisely: `Value::Tag::Null` is its
525
+ * own enumerator, `dynamicTagFor` already WRITES it on the boxing side, and
526
+ * `DynamicCarrier<std::nullptr_t>::accepts` already tests it. What was
527
+ * missing was only the read.
528
+ *
529
+ * `null` has no PAYLOAD, which is not the same as having no VALUE -- its
530
+ * carrier is `std::nullptr_t`, whose one inhabitant is `nullptr` -- so this
531
+ * is the identical verify-then-produce `undefined` gets, never a payload
532
+ * load. `gea::detail::unboxNullValue`.
533
+ *
534
+ * The cost of its absence was not one conversion: `deriveTaggedUnion`
535
+ * derives one arm at a time and a single `never` arm makes the whole sum
536
+ * `never`, so EVERY nullable tagged-union read out of a box was refused --
537
+ * 15 of the three.js app's 74 unmet obligations, all on this one arm.
538
+ */
539
+ nullMaterializer: () => ({
540
+ classifier: { id: 'gea::Value::tag', domain: 'tag:Null' },
541
+ materializer: { id: 'gea::detail::unboxNullValue', domain: 'tag:Null', allocates: false }
542
+ }),
543
+ /**
544
+ * `gea::Optional<T>` records only presence/absence, with no memory of which
545
+ * JavaScript absent value a caller meant -- so the runtime TAG that marks a
546
+ * dynamic value's own absence is the only place that fact still lives, and
547
+ * this backend already writes `Tag::Null`/`Tag::Undefined` for exactly those
548
+ * two on the boxing side (`dynamicTagFor`). Reading the two spellings apart
549
+ * is just naming that same pair back for the unboxing side.
550
+ */
551
+ optionalAbsenceTag: (absence) => (absence === 'null' ? 'gea::Value::Tag::Null' : 'gea::Value::Tag::Undefined'),
552
+ /**
553
+ * Reading a class instance back out of a box, discriminated by the payload's
554
+ * own recorded C++ type rather than by its tag.
555
+ *
556
+ * The tag cannot do this job, and the header above overstates the case by
557
+ * concluding from that that the box cannot do it at all. Both the limit and
558
+ * the overstatement are specific: `Tag::Object` is shared by a record, a
559
+ * class instance, an array and a host handle (`dynamicTagFor`), so a
560
+ * `tag:Object` domain would not be disjoint across those four and `as<T>()`
561
+ * over it would be a `static_pointer_cast` to whichever type the reader
562
+ * happened to name. What actually discriminates is `payloadType()`:
563
+ * `Value::box` records `payloadTypeTagFor<std::decay_t<T>>()` for EVERY
564
+ * payload it stores -- one program-wide address per C++ type, `typeid`
565
+ * without RTTI -- and `gea::detail::unboxAs` compares the tag AND that
566
+ * address, refusing by name when either disagrees. That is a real classifier
567
+ * over a really-stored fact, which is why the domain below is keyed on the
568
+ * class identity and not on the tag.
569
+ *
570
+ * Both halves of the round trip were already built and only this entry was
571
+ * missing: `dynamicTagFor` boxes `class-ref`, and `unboxedLoadText` renders
572
+ * `unboxValue<T>` for every tag except the three with no payload to read.
573
+ * `dynamicTagFor`'s own comment writes this same argument out for
574
+ * `typed-array`, which reached the identical conclusion by the identical
575
+ * route.
576
+ *
577
+ * Only `shared-refcount` is installed. The other two are refused with a
578
+ * reason rather than left for later, because for each of them the refusal is
579
+ * the correct permanent answer as the runtime currently stands:
580
+ *
581
+ * - `borrowed` spells `Foo&` (`cppOwnershipWrap`), and `box` decays the
582
+ * reference away before recording the type, so `payloadTypeTagFor<Foo&>`
583
+ * cannot equal what any box holds. Installing it would emit a load that
584
+ * aborts on every execution rather than one that sometimes works.
585
+ * `narrowing` above refuses borrowed targets for a separate lifetime
586
+ * reason, and both reasons apply here.
587
+ * - `owned` spells a bare `Foo`, which `unboxValue` reaches by
588
+ * copy-constructing from the `const Foo&` `unboxAs` hands back, while
589
+ * boxing the same value needs only a MOVE (`makeRef<std::decay_t<T>>`
590
+ * forwards). So the question is whether any emitted struct is
591
+ * copy-constructible, and that is decidable rather than speculative:
592
+ * `records.ts` writes no copy constructor and no assignment operator at
593
+ * all, so copyability is never a property of the class this compiler
594
+ * emits -- it is implicitly derived from the FIELD carriers. Surveying
595
+ * every emitted struct across the corpus gives a closed carrier
596
+ * vocabulary, and `is_copy_constructible_v` holds for all of the ones this
597
+ * header owns (`double`, `bool`, `long long`, `std::string`,
598
+ * `gea::Optional<T>`, `gea::TaggedUnion<...>`, `gea::Ref<T>`,
599
+ * `gea::Value`) and for a struct built from them.
600
+ *
601
+ * What is still unproven is the HOST-owned carriers a struct can also hold
602
+ * -- `gea::apple::UIKit::*`, `embedded::ui::Signal<T>`, `NodeHandle`,
603
+ * `CanvasRenderingContext2D` -- which live in headers this survey did not
604
+ * reach. One move-only type among them is all it takes, and it would fail
605
+ * as a clang error inside a generated struct rather than at the entry that
606
+ * licensed it. So this stays refused until that half is checked too: a
607
+ * narrower reason than the one first written here, and the honest one.
608
+ */
609
+ classRefMaterializer: (declaration, ownership) => {
610
+ if (ownership !== 'shared-refcount')
611
+ return null;
612
+ // A class projection is authenticated by the allocation's emitted class
613
+ // family, not by the static `Ref<T>` spelling the writer happened to box:
614
+ // a Ref<Base> may carry a Derived allocation. `unboxClassRef` checks the
615
+ // same family table and retains the original allocation, so this domain is
616
+ // intentionally nominal rather than a payload-type claim.
617
+ const domain = `class-family:${declaration}:${ownership}`;
618
+ return {
619
+ classifier: { id: 'gea::Value::classIdentity', domain },
620
+ materializer: { id: 'gea::detail::unboxClassRef', domain, allocates: false }
621
+ };
622
+ },
623
+ // The compiler's own opaque host carrier is `NativeHandle<protocol>`: its
624
+ // generated tag is an authenticated, copyable host identity, and an exact
625
+ // payload read preserves that handle (and therefore host sidecars) without
626
+ // reconstructing a native object. A plugin-provided C++ spelling may be a
627
+ // value struct, an alias, or a handle; `nativeTypes` communicates only that
628
+ // spelling, not that it is a dynamic identity carrier, so it stays refused
629
+ // until the plugin publishes that stronger fact explicitly.
630
+ nativeHandleMaterializer: (protocol, version, native) => {
631
+ if (native !== null)
632
+ return null;
633
+ const domain = `opaque-native-handle:${protocol}@${version}`;
634
+ return {
635
+ classifier: { id: 'gea::Value::payloadType', domain },
636
+ materializer: { id: 'gea::detail::unboxValue', domain, allocates: false }
637
+ };
638
+ },
639
+ // Compiler-owned records have a closed field census, so a dynamic object can
640
+ // materialize one only by checking object-ness, every required key, and every
641
+ // declared field. `emit-narrowing.ts` renders that recipe. A boxed record of
642
+ // the exact target type is merely its identity-preserving fast path; it does
643
+ // not replace this product capability with an identity-only conversion.
644
+ recordMaterializer: (shapeId, ownership) => {
645
+ if (ownership === 'borrowed')
646
+ return null;
647
+ const domain = `record-product:${shapeId}:${ownership}`;
648
+ return {
649
+ id: 'gea::detail::unboxDynamicRecord',
650
+ domain,
651
+ allocates: ownership === 'shared-refcount'
652
+ };
653
+ },
654
+ /**
655
+ * Reading a record -- compiler-owned layout or host-stated native type
656
+ * alike -- back out of a box BY IDENTITY, the exact mirror of
657
+ * `classRefMaterializer` immediately above and installed on the identical
658
+ * evidence.
659
+ *
660
+ * `Value::box` records `payloadTypeTagFor<std::decay_t<T>>()` for whatever
661
+ * C++ type it stores, so a `gea::Ref<gea_record_type_N>` or a
662
+ * `gea::Ref<gea::runtime::Date>` this program boxed records that exact
663
+ * address, and `gea::detail::unboxValue<T>` -- the same primitive
664
+ * `classRefMaterializer` uses, which `emit-narrowing.ts`'s `unboxedLoadText`
665
+ * already renders through its generic `dynamicTagFor(target)` fallback --
666
+ * checks both the tag and that address before handing the payload back. No
667
+ * emitter change: both halves of the round trip were already built.
668
+ *
669
+ * Handing back the SAME object rather than a rebuild is the point. The
670
+ * Compiler-owned records use `recordMaterializer`'s checked product path;
671
+ * native records do not publish fields this compiler can walk, so this exact
672
+ * identity recovery is their only admissible dynamic conversion.
673
+ *
674
+ * `shared-refcount` only, for the two reasons `classRefMaterializer`'s own
675
+ * doc states in full: `borrowed` spells `Foo&`, which `box` decays away
676
+ * before recording the type, so no box can ever match it; and `owned`
677
+ * spells a bare `Foo`, whose copy-constructibility across every HOST carrier
678
+ * a struct can hold is unchecked. Both stay refused rather than emitting a
679
+ * load that aborts.
680
+ */
681
+ /**
682
+ * A carrier read back out of the box BY IDENTITY -- the same round trip
683
+ * `recordRefMaterializer` performs for a named record shape, for the
684
+ * carriers that have no shape id to key on.
685
+ *
686
+ * Gated on `dynamicTagFor` answering, which is the one authority for which
687
+ * carriers this backend boxes at all, so a value can never be admitted here
688
+ * under a tag the boxing direction does not write. Gated on
689
+ * `shared-refcount` for the reasons `classRefMaterializer` states in full:
690
+ * `borrowed` spells `Foo&`, which `box` decays away before recording the
691
+ * type, and `owned` spells a bare `Foo` whose copy-constructibility is
692
+ * unchecked.
693
+ *
694
+ * `record`/`native-record-ref`/`class-ref`/`array-object` are deliberately
695
+ * NOT routed here even though they would qualify -- each already has its own
696
+ * entry with its own reasoning, and a second answer to the same question is
697
+ * how two authorities drift apart.
698
+ */
699
+ boxedIdentityMaterializer: (target) => {
700
+ const eligible = (target.kind === 'dictionary' || target.kind === 'record-with-index' || target.kind === 'typed-array') &&
701
+ target.ownership === 'shared-refcount';
702
+ if (!eligible && target.kind !== 'array-buffer' && target.kind !== 'shared-array-buffer')
703
+ return null;
704
+ if (dynamicTagFor(target) === null)
705
+ return null;
706
+ const domain = `boxed-identity:${representationKey(target)}`;
707
+ return {
708
+ classifier: { id: 'gea::Value::payloadType', domain },
709
+ materializer: { id: 'gea::detail::unboxValue', domain, allocates: false }
710
+ };
711
+ },
712
+ recordRefMaterializer: (shapeId, ownership) => {
713
+ if (ownership !== 'shared-refcount')
714
+ return null;
715
+ const domain = `record-payload:${shapeId}:${ownership}`;
716
+ return {
717
+ classifier: { id: 'gea::Value::payloadType', domain },
718
+ materializer: { id: 'gea::detail::unboxValue', domain, allocates: false }
719
+ };
720
+ },
721
+ /**
722
+ * Reading a materializable ordinary Array back out of a box -- the
723
+ * MATERIALIZING direction (a genuinely dynamic value becoming a native
724
+ * shape at a point the program requires one), never the boxing shortcut:
725
+ * see `classRefMaterializer`'s own doc comment immediately above for the
726
+ * exact discipline this mirrors.
727
+ *
728
+ * `Value::box`'s payload-type recording is generic over EVERY C++ type it
729
+ * stores (`payloadTypeTagFor<std::decay_t<T>>()`, see `classRefMaterializer`'s
730
+ * comment), so `gea::ArrayObject<Element>` is not a special case for it --
731
+ * an array literal boxed into `dynamic` elsewhere in the SAME program (the
732
+ * mirror widening this same registry's `widening` entry below already
733
+ * installs for any `array-object` source, via `dynamicTagFor`'s existing
734
+ * `'array-object' -> 'Object'` case) records that exact address, and
735
+ * `gea::detail::unboxValue<T>` -- the SAME primitive `classRefMaterializer`
736
+ * uses, and the one `emit-narrowing.ts`'s `unboxedLoadText` ALREADY renders
737
+ * for every non-tagged-union target via its generic `dynamicTagFor(target)`
738
+ * + `unboxValue<cppTypeOf(target)>` fallback -- checks both the tag and
739
+ * that address before handing the payload back. So this entry needs no
740
+ * emitter change at all: both halves of the round trip were already built,
741
+ * the exact shape `classRefMaterializer`'s own doc names as the reason it
742
+ * was missing for as long as it was.
743
+ *
744
+ * `unboxValue<Ref<ArrayObject<Element>>>` hands back a REFERENCE-COUNTED
745
+ * pointer to the SAME underlying `ArrayObject` the box recorded -- not a
746
+ * reconstruction -- so both properties `deriveArrayObject` requires hold
747
+ * honestly: identity is the original object, not a copy, and every hole
748
+ * `ArrayObject`'s own presence-bit storage tracked survives untouched,
749
+ * because nothing about it was rebuilt.
750
+ *
751
+ * Restricted to `shared-refcount` for the identical reason
752
+ * `classRefMaterializer` restricts to it: a `borrowed` target has no
753
+ * lifetime a materialized value can honestly hold (`narrowing` above
754
+ * refuses borrowed targets for the same reason), and `owned`'s
755
+ * copy-constructibility across every carrier this backend can select as an
756
+ * array element is unproven the same way it is for a class instance's own
757
+ * fields -- narrower than a blanket refusal, and the honest boundary of
758
+ * what has actually been checked.
759
+ */
760
+ arrayObjectDomain: (ownership) => {
761
+ if (ownership !== 'shared-refcount')
762
+ return null;
763
+ return {
764
+ classifier: { id: 'gea::Value::payloadType', domain: `array-payload:${ownership}` },
765
+ excluded: [],
766
+ preservesHoles: true,
767
+ preservesIdentity: true
768
+ };
769
+ },
770
+ // The sum classifier is the emitter's actual condition: one exact tag and
771
+ // payload type, or an authenticated program-class family. A nested arm has
772
+ // several possible conditions and this algebra has no disjunctive classifier
773
+ // contract, so it remains explicitly refused rather than smuggling a
774
+ // checker-only semantic type into a fake runtime domain.
775
+ taggedUnionArmClassifier: cppTaggedUnionArmClassifier,
776
+ narrowing: (source, target) => {
777
+ // Presence loads and native class casts below inspect tags/allocation
778
+ // identity, never a property's reflection protocol. State that on the
779
+ // installed materializer, where the implementation is known; the IR
780
+ // census must not reconstruct it from a helper name or a carrier kind.
781
+ // General union selections remain unannotated because their renderer can
782
+ // adapt a compatible arm through another conversion.
783
+ // A target the backend cannot spell has no load: there is no C++ type for
784
+ // it to produce. Asking the one authoritative type mapping keeps this from
785
+ // becoming a second opinion about what is spellable.
786
+ if (!isSpellable(target))
787
+ return null;
788
+ // A borrowed target is refused, and not for lack of syntax. `gea::Optional`
789
+ // and `gea::TaggedUnion` both own their contents, so the reference a load
790
+ // would hand back points into the cell -- which outlives nothing the caller
791
+ // can see, and whose lifetime the program never stated.
792
+ if ('ownership' in target && target.ownership === 'borrowed')
793
+ return null;
794
+ const setPair = genericFunctionSetPair(source, target);
795
+ if (setPair)
796
+ return setPair;
797
+ // The payload read as the array-extending interface it also is
798
+ // (`sameArrayUpToExtension`): the presence proof is the same and the load
799
+ // is the same, since both carriers are one C++ type.
800
+ if (source.kind === 'optional' &&
801
+ (representationKey(source.payload) === representationKey(target) || sameArrayUpToExtension(source.payload, target))) {
802
+ return {
803
+ classifier: { id: 'gea::Optional::has_value', domain: 'present-optional' },
804
+ materializer: {
805
+ id: 'gea::Optional::operator*',
806
+ domain: 'present-optional',
807
+ allocates: false,
808
+ nativeFieldProtocol: 'unused',
809
+ nativePayloadTransport: 'preserved',
810
+ ...nativeClassReferenceIdentityOf(source, target)
811
+ }
812
+ };
813
+ }
814
+ // The mirror of the presence narrowing directly above: the guard proved the
815
+ // cell ABSENT, and the read carries the absent value's own carrier. There is
816
+ // nothing in the cell to load -- `null`'s carrier is `std::nullptr_t` and
817
+ // `undefined`'s is `gea::Undefined`, and each has exactly one inhabitant --
818
+ // so the materializer produces that constant. Gated on the two absences
819
+ // AGREEING: an `optional(T,undefined)` narrowed by `x === null` is not this
820
+ // pair, and the checker would not have produced it.
821
+ if (source.kind === 'optional' && target.kind === source.absence) {
822
+ return {
823
+ classifier: { id: 'gea::Optional::has_value', domain: `absent-optional:${source.absence}` },
824
+ materializer: {
825
+ id: 'gea::constant',
826
+ domain: `absent-optional:${source.absence}`,
827
+ allocates: false,
828
+ nativeFieldProtocol: 'unused',
829
+ ...nativeClassReferenceIdentityOf(source, target)
830
+ }
831
+ };
832
+ }
833
+ // A structural value read as an instance of a class nothing can
834
+ // instantiate. No such instance exists, so a guard that narrowed to it --
835
+ // `incoming instanceof Http2ServerRequest` -- never passes, and the
836
+ // instance-test census renders that guard only when it proved the view
837
+ // cannot hold one (`projection/instance-test.ts`). The load is the branch's
838
+ // own unreachability, never a value.
839
+ if (target.kind === 'class-ref' &&
840
+ layouts.classUninstantiable?.(target.declaration) === true &&
841
+ (source.kind === 'record' ||
842
+ source.kind === 'record-with-index' ||
843
+ source.kind === 'dictionary' ||
844
+ (source.kind === 'native-record-ref' && source.native === null))) {
845
+ const domain = `uninstantiable-class:${representationKey(target)}`;
846
+ return {
847
+ classifier: { id: 'gea::host::neverInstance', domain },
848
+ materializer: { id: 'gea::host::unreachableValue', domain, allocates: false, nativeFieldProtocol: 'unused' }
849
+ };
850
+ }
851
+ // A shared structural view read as a class, under the `instanceof` that
852
+ // proved it was built from one: the view remembers its origin
853
+ // (`gea::record::viewOrigin`) and the origin is narrowed like any boxed
854
+ // class instance, checked. An optional view is the same read of its
855
+ // payload, which the test proved present.
856
+ const sharedView = (value) => (value.kind === 'record' || value.kind === 'record-with-index' || (value.kind === 'native-record-ref' && value.native === null)) &&
857
+ value.ownership === 'shared-refcount';
858
+ if (target.kind === 'class-ref' &&
859
+ target.ownership === 'shared-refcount' &&
860
+ (sharedView(source) || (source.kind === 'optional' && sharedView(source.payload)))) {
861
+ const domain = `view-origin:${representationKey(target)}`;
862
+ return {
863
+ classifier: { id: 'gea::record::viewOriginIs', domain },
864
+ materializer: { id: 'gea::record::viewOrigin', domain, allocates: false, nativeFieldProtocol: 'unused' }
865
+ };
866
+ }
867
+ // A base class-ref read at a descendant -- see `downcastsToDerived` above.
868
+ // `downcastClassRef` (gea_runtime.h) is `Ref::staticCast`, which adopts
869
+ // `static_cast<Derived*>` of the SAME pointee: the payload travels as the
870
+ // object it already was, so payload transport is preserved as well.
871
+ if (downcastsToDerived(source, target)) {
872
+ return {
873
+ classifier: { id: 'gea::host::hasNativeClassLayoutRef', domain: `class-descendant:${representationKey(target)}` },
874
+ materializer: {
875
+ id: 'gea::host::downcastClassRef',
876
+ domain: `class-descendant:${representationKey(target)}`,
877
+ allocates: false,
878
+ nativeFieldProtocol: 'unused',
879
+ nativePayloadTransport: 'preserved',
880
+ ...nativeClassReferenceIdentityOf(source, target)
881
+ }
882
+ };
883
+ }
884
+ // The same handle read at a UNION of descendants -- `object instanceof Mesh
885
+ // || object instanceof Line || object instanceof Points`. The physical
886
+ // carrier stays one `Ref<Base>`; allocation identity is the discriminant,
887
+ // so the classifier is the same family test and the materializer the same
888
+ // checked downcast, applied per arm by `emit-narrowing.ts`'s
889
+ // `classFamilyLoadText`. `conversion/build.ts` owns the predicate and this
890
+ // imports it, so the pair this admits is exactly the pair that proposed it.
891
+ if (narrowsToDescendantClassUnion(source, target)) {
892
+ return {
893
+ classifier: { id: 'gea::host::hasNativeClassLayoutRef', domain: `class-descendant-union:${representationKey(target)}` },
894
+ materializer: {
895
+ id: 'gea::host::downcastClassRef',
896
+ domain: `class-descendant-union:${representationKey(target)}`,
897
+ allocates: false,
898
+ nativeFieldProtocol: 'unused',
899
+ // Each arm is `ofArm<I>(downcastClassRef<D>(held))`: one pointee,
900
+ // injected into the target union (and its optional, if any).
901
+ nativePayloadTransport: 'preserved',
902
+ ...nativeClassReferenceIdentityOf(source, target)
903
+ }
904
+ };
905
+ }
906
+ // The census asks this table before widening. A total native transfer
907
+ // must therefore win here too; otherwise the broad subset fallback below
908
+ // can shadow its selected recipe and lose its payload identity contract.
909
+ const nativeSelection = nativeTotalSelectionRecipeOf(source, target) ??
910
+ ((source.kind === 'optional' || source.kind === 'tagged-union') && narrowingReachesTarget(source, target)
911
+ ? nativeSelectionRecipeOf(source, target)
912
+ : null);
913
+ if (nativeSelection)
914
+ return nativeSelectionConversion(source, target, nativeSelection);
915
+ if ((source.kind === 'optional' || source.kind === 'tagged-union') &&
916
+ target.kind === 'class-ref' &&
917
+ narrowingReachesTarget(source, target)) {
918
+ return {
919
+ classifier: { id: 'gea::host::hasNativeClassLayoutRef', domain: `class-descendant-sum:${representationKey(target)}` },
920
+ materializer: {
921
+ id: 'gea::host::downcastClassRef',
922
+ domain: `class-descendant-sum:${representationKey(target)}`,
923
+ allocates: false,
924
+ // Presence and sum selection over native class handles never reads
925
+ // field values. Mixed sums retain their general converting protocol.
926
+ ...(nativeClassPresence(source)
927
+ ? { nativeFieldProtocol: 'unused', ...nativeClassReferenceIdentityOf(source, target) }
928
+ : {})
929
+ }
930
+ };
931
+ }
932
+ // Selecting one arm of a union, either directly or through an optional the
933
+ // same narrowing also proved present. `gea::TaggedUnion::is<Index>` is the
934
+ // discriminant test and `get<Index>` is the load, and both are indexed by
935
+ // the arm's position in `representation.arms` -- the checker's own order,
936
+ // which is what the emitter already uses to build one.
937
+ //
938
+ // More than one arm may carry the target's C++ type: `A | B | C` where all
939
+ // three lower to `std::string` is one narrowing target with three possible
940
+ // live arms. That is a fact about the load -- it dispatches on which arm is
941
+ // live -- not about whether the capability exists, so it does not change
942
+ // the answer here.
943
+ //
944
+ // The target may itself still be an optional: narrowing `A | B | undefined`
945
+ // to `A | undefined` rules out an arm and proves nothing about presence, so
946
+ // both sides unwrap before the arms are compared and the load rebuilds the
947
+ // optional around whichever arm it read.
948
+ const union = source.kind === 'optional' ? source.payload : source;
949
+ const selected = source.kind === 'optional' && target.kind === 'optional' ? target.payload : target;
950
+ if (union.kind !== 'tagged-union')
951
+ return null;
952
+ const targetKey = representationKey(selected);
953
+ // A SUB-union target: `selected` is still a tagged union, just missing one
954
+ // or more of `union`'s arms -- `h instanceof Headers`'s `else` branch
955
+ // leaving a `Headers | Record<string,string> | [string,string][]` cell
956
+ // narrowed to the latter two. Installed exactly when every one of
957
+ // `selected`'s own arms has a same-shaped home among `union`'s -- the
958
+ // identical admission `emit-narrowing.ts`'s `narrowedUnionSubsetText`
959
+ // checks before it renders the `ofArm<Index>` rebuild, asked here rather
960
+ // than restated so the two cannot disagree about which pairs install.
961
+ if (selected.kind === 'tagged-union') {
962
+ const installed = selected.arms.every((arm) => union.arms.some((candidate) => representationKey(candidate.value) === representationKey(arm.value) ||
963
+ narrowingReachesTarget(candidate.value, arm.value) ||
964
+ downcastsToDerived(candidate.value, arm.value)));
965
+ if (!installed)
966
+ return null;
967
+ return {
968
+ classifier: { id: 'gea::TaggedUnion::is', domain: `live-arm-subset:${targetKey}` },
969
+ materializer: {
970
+ id: 'gea::TaggedUnion::ofArm',
971
+ domain: `live-arm-subset:${targetKey}`,
972
+ allocates: false,
973
+ // The discriminant selects; each candidate leaf's own contract says
974
+ // whether the selected payload travels natively.
975
+ ...nativeNarrowing(source, target)
976
+ }
977
+ };
978
+ }
979
+ // A target OPTIONAL whose payload is one of the union's arms, where the
980
+ // union carries no bare absent arm at all -- absence living inside another
981
+ // arm's own optional. `emit-narrowing.ts`'s `narrowedLoadText` renders the
982
+ // arm test as the presence test; this installs the capability it needs.
983
+ if (target.kind === 'optional' && union.arms.some((arm) => representationKey(arm.value) === representationKey(target.payload))) {
984
+ return {
985
+ classifier: { id: 'gea::TaggedUnion::is', domain: `live-arm-optional:${targetKey}` },
986
+ materializer: {
987
+ id: 'gea::TaggedUnion::get',
988
+ domain: `live-arm-optional:${targetKey}`,
989
+ allocates: false,
990
+ ...nativeNarrowing(source, target)
991
+ }
992
+ };
993
+ }
994
+ if (!union.arms.some((arm) => representationKey(arm.value) === targetKey)) {
995
+ // An arm the target lives INSIDE, not one that equals it. A narrowing
996
+ // does not stop at the top level: three's `?(string|number|boolean)`
997
+ // field is `undefined | null | (string|number|boolean)`, and a guard past
998
+ // the two absences lands on one of the inner arms -- two steps, and this
999
+ // test saw only one. `narrowingReachesTarget` (`conversion/build.ts`) is
1000
+ // the same enumeration that PROPOSED this pair, asked here rather than
1001
+ // restated so the admission cannot admit fewer levels than the graph
1002
+ // offers, and `emit-narrowing.ts`'s `taggedUnionArmText` recurses through
1003
+ // `narrowedLoadText` to render exactly the step this admits.
1004
+ if (!narrowingReachesTarget(source, target))
1005
+ return null;
1006
+ return {
1007
+ classifier: { id: 'gea::TaggedUnion::is', domain: `live-arm-nested:${targetKey}` },
1008
+ materializer: {
1009
+ id: 'gea::TaggedUnion::get',
1010
+ domain: `live-arm-nested:${targetKey}`,
1011
+ allocates: false,
1012
+ ...nativeNarrowing(source, target)
1013
+ }
1014
+ };
1015
+ }
1016
+ return {
1017
+ classifier: { id: 'gea::TaggedUnion::is', domain: `live-arm:${targetKey}` },
1018
+ materializer: { id: 'gea::TaggedUnion::get', domain: `live-arm:${targetKey}`, allocates: false, ...nativeNarrowing(source, target) }
1019
+ };
1020
+ },
1021
+ // The mirror of `narrowing`: a plain value taking the place of the tagged
1022
+ // union (or the union payload of an optional) that declares it as one arm --
1023
+ // or, when the target is an optional and the source is exactly its bare
1024
+ // payload, no union at all, because `gea::Optional<T>` declares its own
1025
+ // converting constructor from `T`. `gea::TaggedUnion::ofArm<Index>` is a
1026
+ // real constructor -- built, not assumed -- so the union case is installed
1027
+ // exactly when the source's carrier is one of the target union's arms,
1028
+ // indexed the same way the emitter already reads one back
1029
+ // (`representation.arms`'s own order).
1030
+ widening: (source, target) => {
1031
+ if (!isSpellable(target))
1032
+ return null;
1033
+ const nativeSum = nativeSumConversion(source, target);
1034
+ if (nativeSum)
1035
+ return nativeSum;
1036
+ const totalSelection = nativeTotalSelectionRecipeOf(source, target);
1037
+ if (totalSelection)
1038
+ return nativeSelectionConversion(source, target, totalSelection);
1039
+ const setPair = genericFunctionSetPair(source, target);
1040
+ if (setPair)
1041
+ return setPair;
1042
+ const exactDispatch = exactFunctionDispatchPair(source, target);
1043
+ if (exactDispatch)
1044
+ return exactDispatch;
1045
+ const identity = callableIdentityPair(source, target);
1046
+ if (identity)
1047
+ return identity;
1048
+ const constructEntry = callableConstructEntryPair(source, target);
1049
+ if (constructEntry)
1050
+ return constructEntry;
1051
+ // `Function` promises only callability, so crossing into an evaluated
1052
+ // callable slot needs the same checked ABI adapter as the generic dynamic
1053
+ // materializer above. This pair is proposed explicitly by
1054
+ // `wideningSourcesOf`: dynamic provenance is part of a representation's
1055
+ // key, and the generic node is intentionally keyed to declared `any`.
1056
+ if (source.kind === 'dynamic' &&
1057
+ source.reason === 'untyped-callable' &&
1058
+ target.kind === 'function-value-dispatch' &&
1059
+ dynamicCallableAbiSupported(target.abi)) {
1060
+ return dynamicCallablePair(target);
1061
+ }
1062
+ // A callable declaring a type-matching PREFIX of the target's own
1063
+ // parameters widening into it -- `gea::CallableObject`'s own converting
1064
+ // constructor (`gea_runtime.h`) performs this, so the pairing this
1065
+ // capability approves is exactly the one `dropsUnboundParameters` (the
1066
+ // same authority `emit-narrowing.ts`'s renderer asks) proves sound. Asked
1067
+ // before the `dynamic`/absence/optional cases below because a callable
1068
+ // pair can never satisfy any of those (`callableObjectAbi` inside
1069
+ // `dropsUnboundParameters` answers `null` for anything that is not a
1070
+ // `function`/`function-family`/`function-value-family`/
1071
+ // `function-value-dispatch`), so ordering only ever skips work, never
1072
+ // changes an answer.
1073
+ if (constructorUpcastMember(source, target) !== null) {
1074
+ const domain = `constructor-upcast:${representationKey(source)}->${representationKey(target)}`;
1075
+ return {
1076
+ classifier: { id: 'gea::upcastConstructor', domain },
1077
+ materializer: { id: 'gea::upcastConstructor', domain, allocates: false }
1078
+ };
1079
+ }
1080
+ if (upcastsToBase(source, target)) {
1081
+ const sourceKey = representationKey(source);
1082
+ const targetKey = representationKey(target);
1083
+ return {
1084
+ classifier: { id: 'gea::Ref::converting-ctor', domain: `class-upcast:${sourceKey}->${targetKey}` },
1085
+ materializer: {
1086
+ id: 'gea::Ref::converting-ctor',
1087
+ domain: `class-upcast:${sourceKey}->${targetKey}`,
1088
+ allocates: false,
1089
+ nativeFieldProtocol: 'unused',
1090
+ // `Ref<Base>(derived)` retains the same pointee.
1091
+ nativePayloadTransport: 'preserved',
1092
+ ...nativeClassReferenceIdentityOf(source, target)
1093
+ }
1094
+ };
1095
+ }
1096
+ if (dropsUnboundParameters(source, target)) {
1097
+ const sourceKey = representationKey(source);
1098
+ const targetKey = representationKey(target);
1099
+ return {
1100
+ classifier: { id: 'gea::CallableObject::converting-ctor', domain: `callable-prefix:${sourceKey}->${targetKey}` },
1101
+ materializer: {
1102
+ id: 'gea::CallableObject::converting-ctor',
1103
+ domain: `callable-prefix:${sourceKey}->${targetKey}`,
1104
+ allocates: true,
1105
+ ...nativeCallableTransport(source, target)
1106
+ }
1107
+ };
1108
+ }
1109
+ // The composed sibling of the pairing just above: a zero-parameter
1110
+ // callable widening into a slot that ALSO widens its result into one arm
1111
+ // of a tagged union -- `gea_runtime.h`'s `ResultWidensIntoArm` performs
1112
+ // both steps as one converting constructor, asked here through
1113
+ // `dropsAllParametersIntoResultArm` for the identical reason
1114
+ // `dropsUnboundParameters` is asked above it, so the two authorities
1115
+ // cannot disagree about which pairs the runtime actually accepts.
1116
+ if (dropsAllParametersIntoResultArm(source, target)) {
1117
+ const sourceKey = representationKey(source);
1118
+ const targetKey = representationKey(target);
1119
+ return {
1120
+ classifier: { id: 'gea::CallableObject::result-arm-ctor', domain: `callable-result-arm:${sourceKey}->${targetKey}` },
1121
+ materializer: {
1122
+ id: 'gea::CallableObject::result-arm-ctor',
1123
+ domain: `callable-result-arm:${sourceKey}->${targetKey}`,
1124
+ allocates: true,
1125
+ ...nativeCallableTransport(source, target)
1126
+ }
1127
+ };
1128
+ }
1129
+ // The same widening at a nonzero arity the source already declares in
1130
+ // full -- `gea_runtime.h`'s `widenResultIntoArm` constructor, gated by the
1131
+ // very same `ResultWidensIntoArm` trait as the composed case above.
1132
+ // Installed here for the identical reason its two siblings are: the
1133
+ // conversion graph decides admissibility, and a pairing the emitter
1134
+ // renders but the graph never heard of is refused at certification for a
1135
+ // conversion this backend can already perform.
1136
+ if (widensResultIntoArm(source, target)) {
1137
+ const sourceKey = representationKey(source);
1138
+ const targetKey = representationKey(target);
1139
+ return {
1140
+ classifier: {
1141
+ id: 'gea::CallableObject::same-arity-result-arm-ctor',
1142
+ domain: `callable-result-arm-fixed:${sourceKey}->${targetKey}`
1143
+ },
1144
+ materializer: {
1145
+ id: 'gea::CallableObject::same-arity-result-arm-ctor',
1146
+ domain: `callable-result-arm-fixed:${sourceKey}->${targetKey}`,
1147
+ allocates: true,
1148
+ ...nativeCallableTransport(source, target)
1149
+ }
1150
+ };
1151
+ }
1152
+ // The rest slot rebased to position 0 -- `gea_runtime.h`'s
1153
+ // `spreadRestOverLeading` constructor, gated by the very same
1154
+ // `RestRebaseAdmits` trait. Installed here for the identical reason its
1155
+ // siblings are: a pairing the emitter renders but the graph never heard
1156
+ // of is refused at certification for a conversion this backend performs.
1157
+ if (rebasesRestOverLeadingParameters(source, target)) {
1158
+ const sourceKey = representationKey(source);
1159
+ const targetKey = representationKey(target);
1160
+ return {
1161
+ classifier: { id: 'gea::CallableObject::rest-rebase-ctor', domain: `callable-rest-rebase:${sourceKey}->${targetKey}` },
1162
+ materializer: {
1163
+ id: 'gea::CallableObject::rest-rebase-ctor',
1164
+ domain: `callable-rest-rebase:${sourceKey}->${targetKey}`,
1165
+ allocates: true
1166
+ }
1167
+ };
1168
+ }
1169
+ // A fifth pair, and the one that is not a constructor at all: same frame,
1170
+ // a result no `CallableObject` constructor can convert because converting
1171
+ // it means BOXING, and the tag table lives in the emitter. Rendered as a
1172
+ // captureless-lambda adapter at the conversion site
1173
+ // (`emit-narrowing.ts`'s `resultAdapterOf`); named here so the graph
1174
+ // states the capability rather than leaving the pair to be licensed by
1175
+ // accident and refused at emission -- which is exactly what happened
1176
+ // before this entry existed, the inverse of the usual gap.
1177
+ //
1178
+ // Asked AFTER the four above and never before: every pair one of them
1179
+ // accepts is an implicit conversion with no allocation of its own, and
1180
+ // an adapter for such a pair would make an identity store allocate.
1181
+ const resultAdapter = resultAdapterTransportOf(source, target);
1182
+ if (resultAdapter !== null) {
1183
+ const sourceKey = representationKey(source);
1184
+ const targetKey = representationKey(target);
1185
+ const domain = `callable-result-adapter:${sourceKey}->${targetKey}`;
1186
+ const callableAdapter = resultAdapter.nativeConventions;
1187
+ return {
1188
+ classifier: { id: 'gea::CallableObject::result-adapter', domain },
1189
+ materializer: {
1190
+ id: 'gea::CallableObject::result-adapter',
1191
+ domain,
1192
+ allocates: true,
1193
+ ...(callableAdapter === null
1194
+ ? {}
1195
+ : { nativeFieldProtocol: 'unused', callableAdapter, callableIdentityTransport: 'preserved' })
1196
+ }
1197
+ };
1198
+ }
1199
+ // Boxing into `dynamic`: the one widening direction whose *target*
1200
+ // carries no structural information about which sources are valid at
1201
+ // all (a tagged union's arms are a fixed list; `gea::Value` accepts
1202
+ // anything `dynamicTagFor` recognizes). `emit-narrowing.ts`'s
1203
+ // `widenedStoreText` already renders exactly this store; asking the
1204
+ // identical function here is what lets the conversion graph -- built
1205
+ // structurally from `target`'s own shape everywhere else -- offer this
1206
+ // one capability too, rather than leaving every merge whose carrier is
1207
+ // `dynamic` refused for a conversion emission can already perform.
1208
+ if (target.kind === 'dynamic') {
1209
+ // An optional value has no single tag of its own -- see this
1210
+ // function's sibling render, `emit-narrowing.ts`'s `widenedStoreText`,
1211
+ // whose `held.kind === 'dynamic'` branch already renders exactly this
1212
+ // recursively: absence boxes to `Null`/`Undefined`, presence boxes
1213
+ // whatever the payload itself boxes as (which may in turn be a tagged
1214
+ // union, the case just below). This installs the capability that
1215
+ // render already implements; without it, every optional value merging
1216
+ // or returning into a declared-`any`/`unknown` carrier refused for a
1217
+ // conversion `emitConvert` could already perform.
1218
+ if (source.kind === 'optional') {
1219
+ const payload = source.payload;
1220
+ if (!boxable(payload))
1221
+ return null;
1222
+ return {
1223
+ classifier: { id: 'gea::Value::box', domain: `box:optional:${representationKey(payload)}` },
1224
+ materializer: { id: 'gea::Value::box', domain: `box:optional:${representationKey(payload)}`, allocates: true }
1225
+ };
1226
+ }
1227
+ // A tagged union is the other sum carrier, and it boxes on exactly the
1228
+ // condition the optional case above already states for its payload:
1229
+ // every arm boxes. `dynamicTagFor` cannot answer for the union itself --
1230
+ // a sum has no single tag, which is the whole point of it -- but each
1231
+ // arm has one, and `widenedStoreText` already renders the per-arm store
1232
+ // recursively. Without this the identical value refused one level out
1233
+ // from where it was admitted: `optional(tagged-union(A|B))` boxed and a
1234
+ // bare `tagged-union(A|B)` did not.
1235
+ if (source.kind === 'tagged-union') {
1236
+ if (!boxable(source))
1237
+ return null;
1238
+ return {
1239
+ classifier: { id: 'gea::Value::box', domain: `box:sum:${representationKey(source)}` },
1240
+ materializer: { id: 'gea::Value::box', domain: `box:sum:${representationKey(source)}`, allocates: true }
1241
+ };
1242
+ }
1243
+ const tag = dynamicTagFor(source);
1244
+ if (tag === null)
1245
+ return null;
1246
+ // Absence constructs only the dynamic tag; there is no native payload
1247
+ // to allocate, inspect or publish. In particular, an omitted any formal
1248
+ // must not turn an otherwise known constructor into an external entry.
1249
+ const absent = source.kind === 'undefined' || source.kind === 'null';
1250
+ return {
1251
+ classifier: { id: 'gea::Value::box', domain: `box:${tag}` },
1252
+ materializer: {
1253
+ id: 'gea::Value::box',
1254
+ domain: `box:${tag}`,
1255
+ allocates: !absent,
1256
+ ...(absent ? { nativeFieldProtocol: 'unused' } : {})
1257
+ }
1258
+ };
1259
+ }
1260
+ // The bare absence marker -- `null`/`undefined` as its OWN static type,
1261
+ // not a literal appearing where a wider carrier is held -- widening into
1262
+ // an optional whose absence tag it matches: no payload conversion at
1263
+ // all, just the optional's own empty state. `emit-narrowing.ts`'s
1264
+ // `emptyOptionalText` already renders exactly this (`written.kind ===
1265
+ // held.absence` -> default-construct); this installs the capability
1266
+ // that render already implements. Gated to a matching tag on purpose --
1267
+ // `null` reaching an `undefined`-absent optional is a real semantic
1268
+ // mismatch `emptyOptionalText` itself refuses, not a spelling gap.
1269
+ if ((source.kind === 'null' || source.kind === 'undefined') && target.kind === 'optional' && source.kind === target.absence) {
1270
+ return {
1271
+ classifier: { id: 'gea::Optional::empty', domain: `absence:${target.absence}` },
1272
+ materializer: {
1273
+ id: 'gea::Optional::empty',
1274
+ domain: `absence:${target.absence}`,
1275
+ allocates: false,
1276
+ nativeFieldProtocol: 'unused',
1277
+ ...nativeClassReferenceIdentityOf(source, target)
1278
+ }
1279
+ };
1280
+ }
1281
+ // widenedStoreText already renders null as the empty state of a native
1282
+ // handle or refcounted class. Neither admits undefined without a flag.
1283
+ // The render is the default-constructed handle (`Ref<T>()`): no payload is
1284
+ // read or built, which is the payload-transport statement below.
1285
+ if (source.kind === 'null' &&
1286
+ (target.kind === 'native-handle' || (target.kind === 'class-ref' && target.ownership === 'shared-refcount'))) {
1287
+ return {
1288
+ classifier: { id: 'empty-reference', domain: 'absence:null' },
1289
+ materializer: {
1290
+ id: 'empty-reference',
1291
+ domain: 'absence:null',
1292
+ allocates: false,
1293
+ nativeFieldProtocol: 'unused',
1294
+ nativePayloadTransport: 'preserved',
1295
+ ...nativeClassReferenceIdentityOf(source, target)
1296
+ }
1297
+ };
1298
+ }
1299
+ // A source still wearing its own optional widens by reading its own
1300
+ // presence flag rather than assuming one -- `emit-narrowing.ts`'s
1301
+ // `widenedStoreText` is what actually renders that read, guarded by a
1302
+ // `has_value()` check when the target keeps an absence of its own and
1303
+ // unconditional (the checker having already proven presence) when it does
1304
+ // not. This only states the pairing is real: the payload widens exactly
1305
+ // as a bare source would, one optional layer down, so the domain is named
1306
+ // separately from the bare-payload case below to keep the two capability
1307
+ // pairs from being mistaken for one another.
1308
+ if (source.kind === 'optional') {
1309
+ const payloadKey = representationKey(source.payload);
1310
+ if (target.kind === 'optional' && representationKey(target.payload) === payloadKey) {
1311
+ return {
1312
+ classifier: { id: 'gea::Optional::converting-ctor', domain: `optional-payload:${payloadKey}` },
1313
+ materializer: {
1314
+ id: 'gea::Optional::converting-ctor',
1315
+ domain: `optional-payload:${payloadKey}`,
1316
+ allocates: false,
1317
+ nativeFieldProtocol: 'unused',
1318
+ ...nativeClassReferenceIdentityOf(source, target)
1319
+ }
1320
+ };
1321
+ }
1322
+ const wrappedUnion = target.kind === 'optional' ? target.payload : target;
1323
+ if (wrappedUnion.kind !== 'tagged-union')
1324
+ return null;
1325
+ if (!wrappedUnion.arms.some((arm) => representationKey(arm.value) === payloadKey))
1326
+ return null;
1327
+ return {
1328
+ classifier: { id: 'gea::TaggedUnion::ofArm', domain: `optional-arm:${payloadKey}` },
1329
+ materializer: {
1330
+ id: 'gea::TaggedUnion::ofArm',
1331
+ domain: `optional-arm:${payloadKey}`,
1332
+ allocates: false,
1333
+ nativeFieldProtocol: 'unused',
1334
+ ...nativeClassReferenceIdentityOf(source, target)
1335
+ }
1336
+ };
1337
+ }
1338
+ const sourceKey = representationKey(source);
1339
+ // The bare payload widening straight into its own optional --
1340
+ // `gea::Optional<T>` declares a converting constructor from `T`, so this
1341
+ // needs no tagged union and no arm index at all.
1342
+ if (target.kind === 'optional' && representationKey(target.payload) === sourceKey) {
1343
+ return {
1344
+ classifier: { id: 'gea::Optional::converting-ctor', domain: `payload:${sourceKey}` },
1345
+ materializer: {
1346
+ id: 'gea::Optional::converting-ctor',
1347
+ domain: `payload:${sourceKey}`,
1348
+ allocates: false,
1349
+ nativeFieldProtocol: 'unused',
1350
+ ...nativeClassReferenceIdentityOf(source, target)
1351
+ }
1352
+ };
1353
+ }
1354
+ // A source that is not the payload but reaches it by one of the four
1355
+ // `gea::CallableObject` converting constructors above. Every one of those
1356
+ // was installed only for a BARE callable target, so
1357
+ // `((gl, v) => void)` returned where `((gl, v, textures) => void) |
1358
+ // undefined` is expected -- three's `getSingularSetter`, 30 returns of
1359
+ // exactly that shape -- refused for a pair whose two halves this backend
1360
+ // performs individually. The same four authorities are asked here, one
1361
+ // optional layer down, so the graph and the emitter cannot disagree about
1362
+ // which pairs the runtime accepts.
1363
+ //
1364
+ // `allocates` is true, unlike the bare-payload case: the emitter names
1365
+ // the payload type EXPLICITLY (`convertedValueText`'s optional branch)
1366
+ // because C++ allows one user-defined conversion per implicit sequence
1367
+ // and this pair needs two, so a `CallableObject` really is constructed
1368
+ // here rather than merely wrapped.
1369
+ if (target.kind === 'optional') {
1370
+ const payload = target.payload;
1371
+ const nativeConstructor = dropsUnboundParameters(source, payload) || dropsAllParametersIntoResultArm(source, payload) || widensResultIntoArm(source, payload);
1372
+ const restRebase = !nativeConstructor && rebasesRestOverLeadingParameters(source, payload);
1373
+ const adapter = nativeConstructor || restRebase ? null : resultAdapterTransportOf(source, payload);
1374
+ if (nativeConstructor || restRebase || adapter !== null) {
1375
+ const domain = `payload-callable:${sourceKey}->${representationKey(payload)}`;
1376
+ const native = nativeConstructor
1377
+ ? nativeCallableTransport(source, payload)
1378
+ : adapter?.nativeConventions
1379
+ ? {
1380
+ nativeFieldProtocol: 'unused',
1381
+ callableAdapter: adapter.nativeConventions,
1382
+ callableIdentityTransport: 'preserved'
1383
+ }
1384
+ : {};
1385
+ return {
1386
+ classifier: { id: 'gea::Optional::converting-ctor', domain },
1387
+ materializer: { id: 'gea::Optional::converting-ctor', domain, allocates: true, ...native }
1388
+ };
1389
+ }
1390
+ }
1391
+ if ((target.kind === 'optional' || target.kind === 'tagged-union') && hasSingleClassUpcastHome(source, target)) {
1392
+ const domain = `class-upcast-arm:${sourceKey}->${representationKey(target)}`;
1393
+ return {
1394
+ classifier: { id: 'gea::TaggedUnion::ofArm', domain },
1395
+ materializer: {
1396
+ id: 'gea::TaggedUnion::ofArm',
1397
+ domain,
1398
+ allocates: false,
1399
+ nativeFieldProtocol: 'unused',
1400
+ ...nativeClassReferenceIdentityOf(source, target)
1401
+ }
1402
+ };
1403
+ }
1404
+ const union = target.kind === 'optional' ? target.payload : target;
1405
+ if (union.kind !== 'tagged-union')
1406
+ return null;
1407
+ if (union.arms.some((arm) => representationKey(arm.value) === sourceKey)) {
1408
+ return {
1409
+ classifier: { id: 'gea::TaggedUnion::ofArm', domain: `arm:${sourceKey}` },
1410
+ materializer: {
1411
+ id: 'gea::TaggedUnion::ofArm',
1412
+ domain: `arm:${sourceKey}`,
1413
+ allocates: false,
1414
+ nativeFieldProtocol: 'unused',
1415
+ ...nativeClassReferenceIdentityOf(source, target)
1416
+ }
1417
+ };
1418
+ }
1419
+ return null;
1420
+ },
1421
+ // Two tagged unions built from the same member set at different tag orders
1422
+ // -- one declared `boolean | number`, the other `number | boolean` -- need a
1423
+ // recast: every value the source can hold must have a same-typed home among
1424
+ // the target's arms, so the live one can always be rebuilt at the target's
1425
+ // own tag. A source arm with no match in the target is a real hole, not a
1426
+ // missing recipe, and is refused rather than dropped.
1427
+ recasting: (source, target) => {
1428
+ if (!isSpellable(target))
1429
+ return null;
1430
+ const setPair = genericFunctionSetPair(source, target);
1431
+ if (setPair)
1432
+ return setPair;
1433
+ if (source.kind === 'native-record-ref' && source.native === cppStringObjectNativeType && target.kind === 'string') {
1434
+ const domain = `string-object-value:${representationKey(source)}`;
1435
+ return {
1436
+ classifier: { id: 'gea::runtime::StringObject::value', domain },
1437
+ materializer: { id: 'gea::runtime::StringObject::value', domain, allocates: false }
1438
+ };
1439
+ }
1440
+ // The two void-payload guards that used to sit here now live inside
1441
+ // `promisePayloadConvertible`, which is the printer's own authority: a
1442
+ // `Promise<never>` source is admissible and a `Promise<void>` one is not,
1443
+ // and stating that twice is how the census and the printer drift apart.
1444
+ if (source.kind === 'promise' && target.kind === 'promise' && promisePayloadConvertible(source.value, target.value)) {
1445
+ const domain = `promise-state-adoption:${representationKey(source)}->${representationKey(target)}`;
1446
+ return {
1447
+ classifier: { id: 'gea::Promise::state', domain },
1448
+ materializer: { id: 'gea::Promise::adopt-converted', domain, allocates: true }
1449
+ };
1450
+ }
1451
+ if (source.kind === 'record' && target.kind === 'tagged-union' && ownedRecordMaterializationPlan(source, target, layouts) !== null) {
1452
+ const domain = `owned-record-arm:${representationKey(source)}->${representationKey(target)}`;
1453
+ return {
1454
+ classifier: { id: 'gea::record::ownedArm', domain },
1455
+ materializer: { id: 'gea::record::ownedArm', domain, allocates: true }
1456
+ };
1457
+ }
1458
+ // Built on demand, never up front: this function is asked about EVERY
1459
+ // ordered pair of recastable carriers (`conversion/build.ts`), hundreds
1460
+ // of millions on TypeScript's own compiler, and almost every pair leaves
1461
+ // through an early `null` without ever needing its key. Concatenating
1462
+ // it first was one string allocation per pair and a collector busy
1463
+ // reclaiming them -- the same cost `build.ts`'s own loop already paid once.
1464
+ let pairKeyMemo = null;
1465
+ const pairKey = () => {
1466
+ pairKeyMemo ??= `${representationKey(source)}->${representationKey(target)}`;
1467
+ return pairKeyMemo;
1468
+ };
1469
+ if (source.kind === 'native-record-ref' &&
1470
+ target.kind === 'native-record-ref' &&
1471
+ source.native !== null &&
1472
+ source.native === target.native &&
1473
+ source.ownership === target.ownership &&
1474
+ cppTypeOf(source) === cppTypeOf(target)) {
1475
+ return {
1476
+ classifier: { id: 'gea::native-record::identity', domain: `native-identity:${source.native}:${source.ownership}` },
1477
+ materializer: {
1478
+ id: 'gea::native-record::identity',
1479
+ domain: `native-identity:${source.native}:${source.ownership}`,
1480
+ allocates: false
1481
+ }
1482
+ };
1483
+ }
1484
+ const sum = nativeSumConversion(source, target);
1485
+ if (sum)
1486
+ return sum;
1487
+ // Two boxes are one box. `dynamic`'s `reason` records WHY a value is
1488
+ // carried dynamically -- it is diagnostic provenance, not a physical
1489
+ // difference -- and `cppTypeOf` spells every one of them `gea::Value`. So
1490
+ // a store from one to another is the identity, and refusing it would
1491
+ // refuse an assignment C++ performs with no conversion at all.
1492
+ //
1493
+ // The pair became reachable when `untyped-callable` joined the reason list
1494
+ // (`representation/model.ts`): a `Function`-typed value flowing into a
1495
+ // cell that holds a declared `any` is two reasons over one carrier, and
1496
+ // before this the conversion graph had no node for it even though there
1497
+ // was nothing to convert.
1498
+ if (source.kind === 'dynamic' && target.kind === 'dynamic') {
1499
+ return {
1500
+ classifier: { id: 'gea::Value::identity', domain: `dynamic-reason:${pairKey()}` },
1501
+ materializer: { id: 'gea::Value::identity', domain: `dynamic-reason:${pairKey()}`, allocates: false }
1502
+ };
1503
+ }
1504
+ // The plain array and the array an interface extended with typed fields
1505
+ // (`NodeArray<T> extends ReadonlyArray<T>`, `array-object.extension`) are
1506
+ // ONE `gea::ArrayObject<E>`: the fields live in the object's own
1507
+ // extension sidecar, so `elements.slice() as MutableNodeArray<T>` is the
1508
+ // same object gaining fields on their first write, and a `NodeArray<T>`
1509
+ // handed to a `readonly T[]` parameter is that object read as the array
1510
+ // it is. Same element, same ownership, and only the extension differs;
1511
+ // the identity spelling `convertedValueText` already renders for two
1512
+ // carriers with one C++ type is what performs it.
1513
+ if (source.kind === 'array-object' &&
1514
+ target.kind === 'array-object' &&
1515
+ source.ownership === target.ownership &&
1516
+ representationKey(source.element) === representationKey(target.element) &&
1517
+ arrayExtensionKey(source.extension) !== arrayExtensionKey(target.extension)) {
1518
+ return {
1519
+ classifier: { id: 'gea::ArrayObject::identity', domain: `array-extension:${pairKey()}` },
1520
+ materializer: { id: 'gea::ArrayObject::identity', domain: `array-extension:${pairKey()}`, allocates: false }
1521
+ };
1522
+ }
1523
+ // `never[]` into `E[]`: THE empty array of `E`, by identity. tsc's
1524
+ // `emptyArray: never[]` is a sentinel the program compares by identity
1525
+ // (`type.resolvedBaseTypes = emptyArray` marks a circular resolution in
1526
+ // progress; `=== emptyArray` detects it), so a fresh `[]` is a silently
1527
+ // wrong answer and a boxed one a refusal; `gea::emptyArraySentinel<E>()`
1528
+ // is one object per element type, so every `never[]` that reaches an
1529
+ // `E[]` slot is the same one and compares equal to itself. The carrier
1530
+ // cannot tell `never[]` from `undefined[]` (an element with no storage is
1531
+ // stored as the absence), so the recipe admits only the pairs TypeScript
1532
+ // admits for `never[]` alone: an element that does not carry `undefined`
1533
+ // (a genuine `undefined[]` is not assignable to it) and, for `any[]`, a
1534
+ // runtime test -- empty is the sentinel, anything else is boxed element
1535
+ // by element, which is what a real `undefined[]` into `any[]` means.
1536
+ if (source.kind === 'array-object' &&
1537
+ target.kind === 'array-object' &&
1538
+ source.element.kind === 'undefined' &&
1539
+ source.ownership === 'shared-refcount' &&
1540
+ target.ownership === 'shared-refcount' &&
1541
+ (target.element.kind === 'dynamic' || !carriesUndefined(target.element))) {
1542
+ return {
1543
+ classifier: { id: 'gea::emptyArraySentinel', domain: `empty-array:${pairKey()}` },
1544
+ materializer: { id: 'gea::emptyArraySentinel', domain: `empty-array:${pairKey()}`, allocates: false }
1545
+ };
1546
+ }
1547
+ // ⛔ NO CONVERSION IS INSTALLED between two `array-object` carriers whose
1548
+ // ELEMENTS disagree, and none may be. Such a conversion can only ALLOCATE
1549
+ // -- every element needs its own unbox -- and an `ArrayObject` a program
1550
+ // can still reach is a mutable reference, so a fresh array silently drops
1551
+ // every later write through the other name and loses identity outright.
1552
+ // `gea::ArrayObject::recastElements` did exactly that at a call argument
1553
+ // in three's `getProgramCacheKey`: the two helpers pushed ~60 values into
1554
+ // the COPY, so every material's cache key came out identical, one shader
1555
+ // program served the whole scene, and every HUD glyph rendered as a solid
1556
+ // rectangle. A compile refusal is the correct outcome here, and the fix
1557
+ // for a disagreement is to make the two authorities agree -- which is
1558
+ // where `structural-array-element.ts`'s `unstatedNeverArray` parameter
1559
+ // form and `structural.ts`'s `refusedArrayParameterTypeAt` now put it.
1560
+ // See `test/runtime/array-object-call-argument-aliasing.ts`.
1561
+ // Two records declaring the SAME fields under two shape ids -- one written
1562
+ // as `Named & { age: number }`, the other as the literal that satisfies it
1563
+ // -- are one shape this backend spells as two structs, so a value of one is
1564
+ // rebuilt member-wise as the other. `emit-narrowing.ts`'s
1565
+ // `recastedRecordText` is what performs it; asking it here rather than
1566
+ // restating the admission rule keeps the census and the renderer from
1567
+ // disagreeing about which pairs are installed.
1568
+ // A `native-record-ref` target is the SAME question asked of a layout the
1569
+ // carrier only names: it holds a shape id, never a field list, so the pair
1570
+ // was never even proposed (`conversion/build.ts`'s `recastable` filter had
1571
+ // no reason to include a carrier nothing could compare). Resolving the
1572
+ // layout through the one policy and asking `recordsRecastable` the
1573
+ // identical question keeps this admission and the record-to-record one from
1574
+ // ever disagreeing. `emit-callable.ts`'s `structuralRecordViewText` is what
1575
+ // performs it -- the one place in the emitter both layouts are in hand --
1576
+ // reached from an argument slot and, since this pair became admissible,
1577
+ // from a return as well.
1578
+ const asRecord = (candidate) => {
1579
+ if (candidate.kind !== 'native-record-ref' || candidate.native !== null)
1580
+ return candidate;
1581
+ const fields = layouts.forShape(candidate.shapeId);
1582
+ if (fields === null)
1583
+ return candidate;
1584
+ return { kind: 'record', shapeId: candidate.shapeId, ownership: candidate.ownership, fields, accessors: [] };
1585
+ };
1586
+ // A generated class written to a structural interface is materialized as
1587
+ // the native record view `emit-callable.ts` renders. Data fields are read
1588
+ // from the instance and methods become receiver-bound callable members.
1589
+ // Build the same effective source shape here so certification asks the
1590
+ // existing recursive record predicate about every field carrier before
1591
+ // the renderer sees the pair. The concrete source class supplies its own
1592
+ // method set, so interfaces with several implementors need no nominal or
1593
+ // sole-implementor shortcut.
1594
+ if (source.kind === 'class-ref' &&
1595
+ source.ownership === 'shared-refcount' &&
1596
+ (target.kind === 'native-record-ref' || target.kind === 'record') &&
1597
+ !(target.kind === 'native-record-ref' && target.native !== null)) {
1598
+ const sourceFields = layouts.forShape(source.shapeId);
1599
+ const targetFields = target.kind === 'record'
1600
+ ? target.accessors.length === 0
1601
+ ? target.fields
1602
+ : null
1603
+ : (layouts.plainFieldsForShape?.(target.shapeId) ?? null);
1604
+ if (sourceFields !== null && targetFields !== null) {
1605
+ const projected = [...sourceFields];
1606
+ for (const field of targetFields) {
1607
+ if (!layouts.classMethodFor?.(source.declaration, field.key))
1608
+ continue;
1609
+ const abi = 'abi' in field.value ? field.value.abi : null;
1610
+ if (abi === null || abi.receiver !== null || abi.restFrom !== null)
1611
+ continue;
1612
+ const structuralIndex = projected.findIndex((candidate) => candidate.key === field.key);
1613
+ if (structuralIndex >= 0)
1614
+ projected.splice(structuralIndex, 1);
1615
+ projected.push({ key: field.key, value: field.value, required: true });
1616
+ }
1617
+ const sourceView = {
1618
+ kind: 'record',
1619
+ shapeId: source.shapeId,
1620
+ ownership: source.ownership,
1621
+ fields: projected,
1622
+ accessors: []
1623
+ };
1624
+ const targetView = {
1625
+ kind: 'record',
1626
+ shapeId: target.shapeId,
1627
+ ownership: target.ownership,
1628
+ fields: targetFields,
1629
+ accessors: []
1630
+ };
1631
+ if (recordsRecastable(sourceView, targetView)) {
1632
+ return {
1633
+ classifier: { id: 'gea::record::classStructuralView', domain: `class-view:${pairKey()}` },
1634
+ materializer: {
1635
+ id: 'gea::record::classStructuralView',
1636
+ domain: `class-view:${pairKey()}`,
1637
+ allocates: target.ownership === 'shared-refcount'
1638
+ }
1639
+ };
1640
+ }
1641
+ }
1642
+ }
1643
+ // An EMPTY record -- what `[]` with no contextual array type derives, via
1644
+ // the empty tuple -- into a native array-like. Nothing is carried across
1645
+ // and nothing is lost: the source declares no field at all, and the target
1646
+ // is minted value-initialized, which is an array-like holding nothing.
1647
+ // `emit-narrowing.ts`'s `convertedValueText` renders it; installed here so
1648
+ // the merge that needs it is certified rather than emitted uncertified.
1649
+ if (source.kind === 'record' && source.fields.length === 0 && source.accessors.length === 0 && target.kind === 'native-record-ref') {
1650
+ return {
1651
+ classifier: { id: 'gea::record::emptyNative', domain: `empty:${pairKey()}` },
1652
+ materializer: { id: 'gea::record::emptyNative', domain: `empty:${pairKey()}`, allocates: target.ownership === 'shared-refcount' }
1653
+ };
1654
+ }
1655
+ if (source.kind === 'record-with-index' && target.kind === 'native-record-ref' && target.native === null) {
1656
+ const targetFields = layouts.forShape(target.shapeId);
1657
+ const targetIndexes = layouts.indexesForShape?.(target.shapeId) ?? [];
1658
+ const sourceFields = {
1659
+ kind: 'record',
1660
+ shapeId: source.shapeId,
1661
+ ownership: source.ownership,
1662
+ fields: source.fields,
1663
+ accessors: []
1664
+ };
1665
+ const targetFieldsView = targetFields === null
1666
+ ? null
1667
+ : { kind: 'record', shapeId: target.shapeId, ownership: target.ownership, fields: targetFields, accessors: [] };
1668
+ if (targetFieldsView !== null &&
1669
+ targetIndexes.length === source.indexes.length &&
1670
+ targetIndexes.every((targetIndex, index) => {
1671
+ const sourceIndex = source.indexes[index];
1672
+ return (sourceIndex !== undefined &&
1673
+ targetIndex.key === sourceIndex.key &&
1674
+ representationKey(targetIndex.value) === representationKey(sourceIndex.value));
1675
+ }) &&
1676
+ recordsRecastable(sourceFields, targetFieldsView)) {
1677
+ return {
1678
+ classifier: { id: 'gea::record::recastWithIndex', domain: `recast-index:${pairKey()}` },
1679
+ materializer: {
1680
+ id: 'gea::record::recastWithIndex',
1681
+ domain: `recast-index:${pairKey()}`,
1682
+ allocates: target.ownership === 'shared-refcount'
1683
+ }
1684
+ };
1685
+ }
1686
+ // A closed named interface may receive an open record at runtime even
1687
+ // though the interface itself declares no index signature. TypeScript's
1688
+ // structural assignment permits that value, and JavaScript keeps the
1689
+ // extra own properties: BSON's `Object.assign(o, this.fields)` returns a
1690
+ // `DBRefLike` whose user fields must still enumerate and serialize.
1691
+ //
1692
+ // The target does not need an inline index member. Every shared native
1693
+ // record already has the identity-keyed expando table implemented by
1694
+ // `nativeDynamicGet`/`Set` in the runtime. Admit only the sidecar carrier
1695
+ // that table stores exactly -- string keys and `gea::Value` payloads --
1696
+ // and only a data-only target layout. `emit-callable.ts` copies the
1697
+ // source sidecar into that expando table after rebuilding the named
1698
+ // fields, so no property is dropped and the typed target stays native.
1699
+ const plainTargetFields = layouts.plainFieldsForShape?.(target.shapeId) ?? null;
1700
+ const plainTargetView = plainTargetFields === null
1701
+ ? null
1702
+ : { kind: 'record', shapeId: target.shapeId, ownership: target.ownership, fields: plainTargetFields, accessors: [] };
1703
+ if (targetIndexes.length === 0 &&
1704
+ target.ownership === 'shared-refcount' &&
1705
+ source.indexes.length === 1 &&
1706
+ source.indexes[0]?.key === 'string' &&
1707
+ source.indexes[0]?.value.kind === 'dynamic' &&
1708
+ plainTargetView !== null &&
1709
+ recordsRecastable(sourceFields, plainTargetView)) {
1710
+ return {
1711
+ classifier: { id: 'gea::record::recastWithExpando', domain: `recast-expando:${pairKey()}` },
1712
+ materializer: { id: 'gea::record::recastWithExpando', domain: `recast-expando:${pairKey()}`, allocates: true }
1713
+ };
1714
+ }
1715
+ }
1716
+ if ((source.kind === 'record' || source.kind === 'native-record-ref') && target.kind === 'native-record-ref') {
1717
+ const viewed = asRecord(source);
1718
+ const viewedTarget = asRecord(target);
1719
+ if (viewedTarget.kind !== 'record' || viewed.kind !== 'record')
1720
+ return null;
1721
+ if (!recordsRecastable(viewed, viewedTarget))
1722
+ return null;
1723
+ return {
1724
+ classifier: { id: 'gea::record::recast', domain: `recast:${pairKey()}` },
1725
+ materializer: {
1726
+ id: 'gea::record::recast',
1727
+ domain: `recast:${pairKey()}`,
1728
+ allocates: target.ownership === 'shared-refcount',
1729
+ // Unused only while no field crosses the dynamic boundary; a boxed
1730
+ // field is read through the payload's protocol later
1731
+ // (`recordRecastCrossesDynamic`).
1732
+ ...(recordRecastCrossesDynamic(viewed, viewedTarget) ? {} : { nativeFieldProtocol: 'unused' })
1733
+ }
1734
+ };
1735
+ }
1736
+ // The arm the value belongs in, written as a DIFFERENT shape id than the
1737
+ // arm declares. A tuple literal returned into a union of tuple types is
1738
+ // the case -- hono's `PatternRouter.match` writes `[handlers]` against
1739
+ // `Result<T> = [[T, Params][]] | [[T, ParamIndexMap][], ParamStash]` --
1740
+ // and an exact-key search cannot see it, because the literal's own shape
1741
+ // id is minted at the literal and the arm's at the declaration. It is
1742
+ // still the same shape: `recordsRecastable` is the one authority on that,
1743
+ // asked here so this admission and `armInjectedText`'s render, which asks
1744
+ // it through `recastedRecordText`, can never disagree. When several arms
1745
+ // accept the value it carries no field that tells them apart (every
1746
+ // distinguishing field is optional and absent), so each is a correct
1747
+ // home; the first is the one `armInjectedText` renders into.
1748
+ if (source.kind === 'record' && target.kind === 'tagged-union') {
1749
+ const recastable = target.arms.map((arm) => arm.value).filter((arm) => arm.kind === 'record' && recordsRecastable(source, arm));
1750
+ const sole = recastable[0];
1751
+ if (!sole || sole.kind !== 'record')
1752
+ return null;
1753
+ return {
1754
+ classifier: { id: 'gea::TaggedUnion::ofArm', domain: `arm-recast:${pairKey()}` },
1755
+ materializer: {
1756
+ id: 'gea::TaggedUnion::ofArm',
1757
+ domain: `arm-recast:${pairKey()}`,
1758
+ allocates: sole.ownership === 'shared-refcount',
1759
+ nativeFieldProtocol: 'unused'
1760
+ }
1761
+ };
1762
+ }
1763
+ // The same admission for a dictionary whose values widen into ONE
1764
+ // dictionary arm of the union -- the string dictionary `@hono/node-server`
1765
+ // merges into `[string, string][] | OutgoingHttpHeaders`. Only a SOLE
1766
+ // castable arm, for the same reason as the record rule: two would make
1767
+ // the choice of arm a guess. `emit-narrowing.ts`'s `widenedStoreText`
1768
+ // renders it through `recastedDictionaryText` at the arm it finds first,
1769
+ // which under this admission is the only one.
1770
+ if (source.kind === 'dictionary' && target.kind === 'tagged-union') {
1771
+ const recastable = target.arms
1772
+ .map((arm) => arm.value)
1773
+ .filter((arm) => arm.kind === 'dictionary' && dictionaryCastableToDictionary(source, arm));
1774
+ if (recastable.length !== 1)
1775
+ return null;
1776
+ return {
1777
+ classifier: { id: 'gea::TaggedUnion::ofArm', domain: `arm-recast:${pairKey()}` },
1778
+ materializer: { id: 'gea::TaggedUnion::ofArm', domain: `arm-recast:${pairKey()}`, allocates: true, nativeFieldProtocol: 'unused' }
1779
+ };
1780
+ }
1781
+ if (source.kind === 'record' && target.kind === 'record') {
1782
+ if (!recordsRecastable(source, target))
1783
+ return null;
1784
+ return {
1785
+ classifier: { id: 'gea::record::recast', domain: `recast:${pairKey()}` },
1786
+ materializer: {
1787
+ id: 'gea::record::recast',
1788
+ domain: `recast:${pairKey()}`,
1789
+ allocates: target.ownership === 'shared-refcount',
1790
+ // This renderer only copies fields, injects native alternatives and
1791
+ // recursively rebuilds records. It never asks a dynamic field table
1792
+ // -- unless a field it copies is boxed into (or unboxed out of) a
1793
+ // `dynamic` destination: that payload is read through its own field
1794
+ // protocol by every later dynamic read, so the claim is withheld
1795
+ // (`recordRecastCrossesDynamic`) and the payload keeps its protocol.
1796
+ ...(recordRecastCrossesDynamic(source, target) ? {} : { nativeFieldProtocol: 'unused' })
1797
+ }
1798
+ };
1799
+ }
1800
+ // A closed record's fields poured into an open dictionary -- one level out
1801
+ // from the record-to-record recast just above, and sound for the same
1802
+ // reason: the dictionary can hold every field the record has, so nothing
1803
+ // is lost going from the closed shape to the open one. `derive.ts`'s
1804
+ // `dictionary` case is the mirror refusal (recovering a closed field list
1805
+ // from an open one is not derivable); this direction has no such gap.
1806
+ // `emit-narrowing.ts`'s `recordCastableToDictionary` is the one authority
1807
+ // for which pairs actually rebuild, asked here rather than restated.
1808
+ if (source.kind === 'record' && target.kind === 'dictionary') {
1809
+ if (!recordCastableToDictionary(source, target))
1810
+ return null;
1811
+ return {
1812
+ classifier: { id: 'gea::record::recastToDictionary', domain: `recast:${pairKey()}` },
1813
+ materializer: { id: 'gea::record::recastToDictionary', domain: `recast:${pairKey()}`, allocates: true }
1814
+ };
1815
+ }
1816
+ // One shape wider: an open dictionary's values widened into another open
1817
+ // dictionary's -- `Record<string, string>` reaching `OutgoingHttpHeaders`.
1818
+ // `emit-narrowing.ts`'s `dictionaryCastableToDictionary` is the one
1819
+ // authority for which pairs rebuild, asked here rather than restated.
1820
+ if (source.kind === 'dictionary' && target.kind === 'dictionary') {
1821
+ if (!dictionaryCastableToDictionary(source, target))
1822
+ return null;
1823
+ return {
1824
+ classifier: { id: 'gea::dictionary::recastValues', domain: `recast:${pairKey()}` },
1825
+ materializer: { id: 'gea::dictionary::recastValues', domain: `recast:${pairKey()}`, allocates: true }
1826
+ };
1827
+ }
1828
+ // A third recast at the same distance: a closed, contiguous-numeric-keyed
1829
+ // record -- an unannotated rest parameter's open-arity tuple view, from
1830
+ // `semantics/normalize/structural.ts`'s `restParameterArrayElementAt` --
1831
+ // poured into the array it physically is. `emit-narrowing.ts`'s
1832
+ // `recordCastableToArray` is the one authority for which pairs rebuild.
1833
+ if (source.kind === 'record' && target.kind === 'array-object') {
1834
+ if (!recordCastableToArray(source, target))
1835
+ return null;
1836
+ return {
1837
+ classifier: { id: 'gea::record::recastToArray', domain: `recast:${pairKey()}` },
1838
+ materializer: { id: 'gea::record::recastToArray', domain: `recast:${pairKey()}`, allocates: true }
1839
+ };
1840
+ }
1841
+ // Two optionals over the IDENTICAL payload that disagree only on which
1842
+ // falsy JS value spends the absence -- `string | null` widened into a
1843
+ // `string | undefined` slot (`request.ts`'s `this.raw.headers.get(name) ??
1844
+ // undefined`, where DOM `Headers.get` returns `string | null`). `gea::
1845
+ // Optional<T>` has no field for which value caused the empty state --
1846
+ // `cppTypeOf` never reads `.absence` -- so the two carriers are one C++
1847
+ // type under two identities, and `emit-narrowing.ts`'s `convertedValueText`
1848
+ // already renders this as the value unchanged (its `cppTypeOf(source) ===
1849
+ // cppTypeOf(target)` shortcut). This only asks whether the CAPABILITY
1850
+ // exists; a payload that itself still needs converting is refused here and
1851
+ // left to the ordinary narrowing/widening obligations to require.
1852
+ if (source.kind === 'optional' && target.kind === 'optional') {
1853
+ if (representationKey(source.payload) === representationKey(target.payload)) {
1854
+ // Payload already identical: the only difference is which falsy value
1855
+ // spends the absence, so this is `rebrandAbsence` alone (see above).
1856
+ if (source.absence === target.absence)
1857
+ return null;
1858
+ return {
1859
+ classifier: { id: 'gea::Optional::rebrandAbsence', domain: `recast:${pairKey()}` },
1860
+ materializer: { id: 'gea::Optional::rebrandAbsence', domain: `recast:${pairKey()}`, allocates: false }
1861
+ };
1862
+ }
1863
+ // The payload is a record recast one level in: `return toSearchResult(
1864
+ // undefined)` where the copy at `T = undefined` returns `{ value:
1865
+ // undefined } | undefined` into a slot declared `SearchResult<Resolved>`
1866
+ // (13 rows on tsc's moduleNameResolver.ts). The bare pair is already
1867
+ // admitted just below (`gea::record::recast`); the presence bit adds
1868
+ // nothing to convert, only a branch to render, so the admission is the
1869
+ // same question asked of the payloads. Same absence on both sides, as
1870
+ // for the union case: an absence-tag difference alongside a reshaping is
1871
+ // two conversions, not one.
1872
+ if (source.payload.kind === 'record' &&
1873
+ target.payload.kind === 'record' &&
1874
+ source.absence === target.absence &&
1875
+ recordsRecastable(source.payload, target.payload)) {
1876
+ return {
1877
+ classifier: { id: 'gea::Optional::has_value', domain: `recast:${pairKey()}` },
1878
+ materializer: {
1879
+ id: 'gea::Optional::recastPayload',
1880
+ domain: `recast:${pairKey()}`,
1881
+ allocates: target.payload.ownership === 'shared-refcount',
1882
+ nativeFieldProtocol: 'unused'
1883
+ }
1884
+ };
1885
+ }
1886
+ // The payload is a dictionary reaching the one wider dictionary arm of
1887
+ // the target's union, still wrapped in its presence bit: `cache[2] ||
1888
+ // (... ? undefined : { 'content-type': ... })` merged as `optional(
1889
+ // dictionary(string, string))` into `optional([string, string][] |
1890
+ // OutgoingHttpHeaders)`. The bare pair is the arm-recast admission just
1891
+ // above; the presence bit adds only the branch `emit-narrowing.ts`'s
1892
+ // `optional-payload-convert` already renders around any converted
1893
+ // payload. Same absence on both sides, as for every optional pair here.
1894
+ const sourceDictionary = source.payload.kind === 'dictionary' ? source.payload : null;
1895
+ if (sourceDictionary !== null &&
1896
+ target.payload.kind === 'tagged-union' &&
1897
+ source.absence === target.absence &&
1898
+ target.payload.arms.filter((arm) => arm.value.kind === 'dictionary' && dictionaryCastableToDictionary(sourceDictionary, arm.value))
1899
+ .length === 1) {
1900
+ return {
1901
+ classifier: { id: 'gea::Optional::has_value', domain: `recast:${pairKey()}` },
1902
+ materializer: {
1903
+ id: 'gea::Optional::recastPayloadArm',
1904
+ domain: `recast:${pairKey()}`,
1905
+ allocates: true,
1906
+ nativeFieldProtocol: 'unused'
1907
+ }
1908
+ };
1909
+ }
1910
+ // The payload itself is a union recast one level in -- `optional(string |
1911
+ // boolean, undefined)` merged against `optional(boolean | string,
1912
+ // undefined)`, the two branches of a control-flow merge each arriving
1913
+ // through an independently-declared union (the SAME shape
1914
+ // `recastedUnionText` handles for a bare union, just still wrapped in the
1915
+ // presence bit). Both payloads must be tagged unions built from the same
1916
+ // member set for this to be sound -- an absence-tag difference alongside
1917
+ // a genuine payload reshaping is two conversions, not one, and is left
1918
+ // unclaimed rather than composed here.
1919
+ if (source.payload.kind !== 'tagged-union' || target.payload.kind !== 'tagged-union')
1920
+ return null;
1921
+ if (source.absence !== target.absence)
1922
+ return null;
1923
+ const payloadTargetKeys = target.payload.arms.map((arm) => representationKey(arm.value));
1924
+ if (!source.payload.arms.every((arm) => payloadTargetKeys.includes(representationKey(arm.value))))
1925
+ return null;
1926
+ return {
1927
+ classifier: { id: 'gea::TaggedUnion::is', domain: `recast:${pairKey()}` },
1928
+ materializer: { id: 'gea::TaggedUnion::ofArm', domain: `recast:${pairKey()}`, allocates: false }
1929
+ };
1930
+ }
1931
+ // A sum every arm of which reaches ONE payload, wrapped in the presence
1932
+ // bit: `fn === undefined ? node : fn(node, ...)` returned as `T |
1933
+ // undefined` from tsc's `visitEachChild<T>` -- `tagged-union(
1934
+ // native-record-ref | dynamic)` into `optional(native-record-ref)`, 74
1935
+ // rows from one site on the self-compile, one per instantiation. The
1936
+ // typed arm is the payload and the dynamic arm is the checked unbox, and
1937
+ // `emit-narrowing.ts`'s `sumIntoPayloadText` is asked here so the pair is
1938
+ // admitted on exactly the render that will spell it.
1939
+ if (source.kind === 'tagged-union' &&
1940
+ target.kind === 'optional' &&
1941
+ target.absence === 'undefined' &&
1942
+ sumIntoPayloadText(source, target.payload, 'gea_sum', (arm) => arm) !== null) {
1943
+ return {
1944
+ classifier: { id: 'gea::TaggedUnion::is', domain: `sum-into-payload:${pairKey()}` },
1945
+ materializer: { id: 'gea::TaggedUnion::intoPayload', domain: `sum-into-payload:${pairKey()}`, allocates: false }
1946
+ };
1947
+ }
1948
+ if (source.kind !== 'tagged-union' || target.kind !== 'tagged-union')
1949
+ return null;
1950
+ const targetKeys = target.arms.map((arm) => representationKey(arm.value));
1951
+ if (!source.arms.every((arm) => targetKeys.includes(representationKey(arm.value))))
1952
+ return null;
1953
+ return {
1954
+ classifier: { id: 'gea::TaggedUnion::is', domain: `recast:${pairKey()}` },
1955
+ materializer: { id: 'gea::TaggedUnion::ofArm', domain: `recast:${pairKey()}`, allocates: false }
1956
+ };
1957
+ },
1958
+ /**
1959
+ * Asked of the printer's own chain (`emit-narrowing.ts`'s
1960
+ * `conversionChain`), so the census answers exactly what the printer
1961
+ * renders. The chain's step ids are the recipe ids; a step that claims the
1962
+ * pair but cannot render it is reported as no recipe, which is the same
1963
+ * refusal the printer would raise at emission. `allocates` is stated per
1964
+ * step: the recipes that mint a fresh value are the ones that construct
1965
+ * a target from parts.
1966
+ */
1967
+ // Installed exactly when the printer's own renderer has a text for it
1968
+ // (`emit-coercion.ts` says why the same function answers both).
1969
+ coercion: (source, operation) => coercionText(operation, 'x', source, layouts) === null
1970
+ ? null
1971
+ : { id: `coercion:${operation}`, domain: `coercion:${operation}:${representationKey(source)}`, allocates: operation === 'ToString' },
1972
+ staticRecipe: (source, target) => {
1973
+ if (!isSpellable(source) || !isSpellable(target))
1974
+ return null;
1975
+ const recipe = conversionRecipeOf(source, target);
1976
+ if (recipe !== null && recipe.renders) {
1977
+ // `unreachable-value` spells either `unreachableValue<T>()` (a throw that
1978
+ // reads nothing) or a discard into `undefined`: no field is read and no
1979
+ // payload is built. A `narrowed-load` out of a sum is the structural
1980
+ // load whose contract its leaf pairs compose (see `nativeNarrowing`).
1981
+ // `optional-wrap-converted` spells `Optional<P>{P{inner}}` around the
1982
+ // chain's own text for (source, payload), so it reads a field table
1983
+ // exactly when that inner conversion does (`nativeWrappedPayload`).
1984
+ const native = recipe.id === 'unreachable-value'
1985
+ ? { nativeFieldProtocol: 'unused', nativePayloadTransport: 'preserved' }
1986
+ : recipe.id === 'narrowed-load' && (source.kind === 'optional' || source.kind === 'tagged-union')
1987
+ ? nativeNarrowing(source, target)
1988
+ : recipe.id === 'optional-wrap-converted' && target.kind === 'optional'
1989
+ ? nativeWrappedPayload(source, target.payload)
1990
+ : {};
1991
+ return { id: `chain:${recipe.id}`, domain: `static:${recipe.id}`, allocates: allocatingRecipes.has(recipe.id), ...native };
1992
+ }
1993
+ // After the chain, as the printer asks (`emit.ts`'s `emitConvert`): a
1994
+ // record rebuilt as another shape it satisfies, decided by the plan the
1995
+ // printer renders from (`conversion/record-view.ts`). `viewPlanFor`
1996
+ // caches this build so the printer's later render of the same node
1997
+ // (`emit-record-view.ts`'s `structuralRecordViewText`) reads the plan
1998
+ // this existence check already built rather than rebuilding it.
1999
+ const view = viewPlanFor(layouts, source, target);
2000
+ if (view !== null)
2001
+ return {
2002
+ id: 'view:structural-record',
2003
+ domain: 'static:structural-record-view',
2004
+ allocates: true,
2005
+ ...(recordViewUsesOnlyDirectFields(view) ? { nativeFieldProtocol: 'unused' } : {})
2006
+ };
2007
+ // The printer's own last resort behind the view (`structuralRecordViewText`).
2008
+ if (boxedAssertionText(source, target, 'gea_conversion_probe') !== null)
2009
+ return { id: 'view:boxed-assertion', domain: 'static:boxed-assertion', allocates: true };
2010
+ return null;
2011
+ }
2012
+ });
2013
+ const allocatingRecipes = new Set([
2014
+ 'array-element-recast',
2015
+ 'array-copy-recast',
2016
+ 'empty-record-into-native',
2017
+ 'optional-payload-convert',
2018
+ 'optional-wrap-converted',
2019
+ 'union-into-optional-payload',
2020
+ 'union-subset-narrow',
2021
+ 'union-recast',
2022
+ 'record-recast',
2023
+ 'optional-record-recast',
2024
+ 'record-to-dictionary',
2025
+ 'record-to-array',
2026
+ 'promise-payload'
2027
+ ]);