@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.
- package/LICENSE +202 -0
- package/README.md +149 -0
- package/dist/cli-analyze.d.ts +1 -0
- package/dist/cli-analyze.js +61 -0
- package/dist/cli-coverage.d.ts +1 -0
- package/dist/cli-coverage.js +329 -0
- package/dist/cli-emit.d.ts +10 -0
- package/dist/cli-emit.js +398 -0
- package/dist/cli-module-graph.d.ts +18 -0
- package/dist/cli-module-graph.js +123 -0
- package/dist/cli-package-source.d.ts +5 -0
- package/dist/cli-package-source.js +116 -0
- package/dist/cli-project.d.ts +2 -0
- package/dist/cli-project.js +60 -0
- package/dist/cli.d.ts +2 -0
- package/dist/cli.js +199 -0
- package/dist/compiler.d.ts +228 -0
- package/dist/compiler.js +1029 -0
- package/dist/conversion/algebra.d.ts +218 -0
- package/dist/conversion/algebra.js +155 -0
- package/dist/conversion/build.d.ts +67 -0
- package/dist/conversion/build.js +1378 -0
- package/dist/conversion/derive.d.ts +37 -0
- package/dist/conversion/derive.js +260 -0
- package/dist/conversion/graph-validation.d.ts +8 -0
- package/dist/conversion/graph-validation.js +97 -0
- package/dist/conversion/native-callable-adapter.d.ts +13 -0
- package/dist/conversion/native-callable-adapter.js +53 -0
- package/dist/conversion/native-class-reference.d.ts +12 -0
- package/dist/conversion/native-class-reference.js +39 -0
- package/dist/conversion/native-payload-transport.d.ts +25 -0
- package/dist/conversion/native-payload-transport.js +33 -0
- package/dist/conversion/native-selection.d.ts +49 -0
- package/dist/conversion/native-selection.js +135 -0
- package/dist/conversion/native-sum.d.ts +42 -0
- package/dist/conversion/native-sum.js +115 -0
- package/dist/conversion/nodes.d.ts +55 -0
- package/dist/conversion/nodes.js +91 -0
- package/dist/conversion/operand-view.d.ts +14 -0
- package/dist/conversion/operand-view.js +20 -0
- package/dist/conversion/record-view.d.ts +157 -0
- package/dist/conversion/record-view.js +273 -0
- package/dist/conversion/registry.d.ts +217 -0
- package/dist/conversion/registry.js +1 -0
- package/dist/diagnostics/model.d.ts +76 -0
- package/dist/diagnostics/model.js +60 -0
- package/dist/diagnostics/sweep.d.ts +31 -0
- package/dist/diagnostics/sweep.js +112 -0
- package/dist/identity/ids.d.ts +179 -0
- package/dist/identity/ids.js +212 -0
- package/dist/ir/absent-class-arm.d.ts +48 -0
- package/dist/ir/absent-class-arm.js +157 -0
- package/dist/ir/borrow-effects.d.ts +23 -0
- package/dist/ir/borrow-effects.js +151 -0
- package/dist/ir/borrowed-call-arguments.d.ts +40 -0
- package/dist/ir/borrowed-call-arguments.js +117 -0
- package/dist/ir/build.d.ts +168 -0
- package/dist/ir/build.js +459 -0
- package/dist/ir/call-dispatch.d.ts +38 -0
- package/dist/ir/call-dispatch.js +502 -0
- package/dist/ir/call-entry.d.ts +142 -0
- package/dist/ir/call-entry.js +386 -0
- package/dist/ir/callable-class-flow.d.ts +27 -0
- package/dist/ir/callable-class-flow.js +1386 -0
- package/dist/ir/callable-field-slots.d.ts +22 -0
- package/dist/ir/callable-field-slots.js +166 -0
- package/dist/ir/callable-identity-demand.d.ts +52 -0
- package/dist/ir/callable-identity-demand.js +460 -0
- package/dist/ir/callable-member-candidates.d.ts +9 -0
- package/dist/ir/callable-member-candidates.js +39 -0
- package/dist/ir/callable-records.d.ts +21 -0
- package/dist/ir/callable-records.js +411 -0
- package/dist/ir/captures.d.ts +26 -0
- package/dist/ir/captures.js +335 -0
- package/dist/ir/certificate.d.ts +45 -0
- package/dist/ir/certificate.js +47 -0
- package/dist/ir/certify/carrier-keys.d.ts +73 -0
- package/dist/ir/certify/carrier-keys.js +221 -0
- package/dist/ir/certify/function-source.d.ts +4 -0
- package/dist/ir/certify/function-source.js +28 -0
- package/dist/ir/certify/has-property-key.d.ts +88 -0
- package/dist/ir/certify/has-property-key.js +116 -0
- package/dist/ir/certify/instanceof-key.d.ts +24 -0
- package/dist/ir/certify/instanceof-key.js +35 -0
- package/dist/ir/certify/property-access-keys.d.ts +172 -0
- package/dist/ir/certify/property-access-keys.js +291 -0
- package/dist/ir/certify/property-access.d.ts +3 -0
- package/dist/ir/certify/property-access.js +597 -0
- package/dist/ir/certify/runtime-helper.d.ts +3 -0
- package/dist/ir/certify/runtime-helper.js +326 -0
- package/dist/ir/certify/typeof-operand.d.ts +14 -0
- package/dist/ir/certify/typeof-operand.js +16 -0
- package/dist/ir/certify.d.ts +123 -0
- package/dist/ir/certify.js +481 -0
- package/dist/ir/class-evaluation.d.ts +26 -0
- package/dist/ir/class-evaluation.js +50 -0
- package/dist/ir/class-static-fields.d.ts +60 -0
- package/dist/ir/class-static-fields.js +108 -0
- package/dist/ir/construct-entry.d.ts +26 -0
- package/dist/ir/construct-entry.js +117 -0
- package/dist/ir/dead-values.d.ts +90 -0
- package/dist/ir/dead-values.js +184 -0
- package/dist/ir/deferral.d.ts +99 -0
- package/dist/ir/deferral.js +409 -0
- package/dist/ir/dense-loops.d.ts +230 -0
- package/dist/ir/dense-loops.js +697 -0
- package/dist/ir/dominance.d.ts +82 -0
- package/dist/ir/dominance.js +268 -0
- package/dist/ir/emission-representations.d.ts +71 -0
- package/dist/ir/emission-representations.js +350 -0
- package/dist/ir/facts.d.ts +218 -0
- package/dist/ir/facts.js +181 -0
- package/dist/ir/fixed-data-definition.d.ts +19 -0
- package/dist/ir/fixed-data-definition.js +49 -0
- package/dist/ir/generator-split.d.ts +38 -0
- package/dist/ir/generator-split.js +329 -0
- package/dist/ir/hoist.d.ts +55 -0
- package/dist/ir/hoist.js +375 -0
- package/dist/ir/instantiation.d.ts +61 -0
- package/dist/ir/instantiation.js +137 -0
- package/dist/ir/integer-storage.d.ts +170 -0
- package/dist/ir/integer-storage.js +822 -0
- package/dist/ir/integers.d.ts +161 -0
- package/dist/ir/integers.js +539 -0
- package/dist/ir/integrity-restrictions.d.ts +50 -0
- package/dist/ir/integrity-restrictions.js +118 -0
- package/dist/ir/local-iterators.d.ts +4 -0
- package/dist/ir/local-iterators.js +27 -0
- package/dist/ir/lower-allocation.d.ts +4 -0
- package/dist/ir/lower-allocation.js +325 -0
- package/dist/ir/lower-completion.d.ts +15 -0
- package/dist/ir/lower-completion.js +25 -0
- package/dist/ir/lower-destructuring.d.ts +5 -0
- package/dist/ir/lower-destructuring.js +693 -0
- package/dist/ir/lower-element.d.ts +29 -0
- package/dist/ir/lower-element.js +111 -0
- package/dist/ir/lower-exceptions.d.ts +47 -0
- package/dist/ir/lower-exceptions.js +92 -0
- package/dist/ir/lower-flow.d.ts +137 -0
- package/dist/ir/lower-flow.js +600 -0
- package/dist/ir/lower-graph.d.ts +218 -0
- package/dist/ir/lower-graph.js +687 -0
- package/dist/ir/lower-invocation.d.ts +4 -0
- package/dist/ir/lower-invocation.js +514 -0
- package/dist/ir/lower-narrow.d.ts +53 -0
- package/dist/ir/lower-narrow.js +320 -0
- package/dist/ir/lower-operands.d.ts +272 -0
- package/dist/ir/lower-operands.js +461 -0
- package/dist/ir/lower-property.d.ts +21 -0
- package/dist/ir/lower-property.js +132 -0
- package/dist/ir/lower-protocol.d.ts +11 -0
- package/dist/ir/lower-protocol.js +118 -0
- package/dist/ir/lower-short-circuit.d.ts +41 -0
- package/dist/ir/lower-short-circuit.js +63 -0
- package/dist/ir/lower.d.ts +82 -0
- package/dist/ir/lower.js +1346 -0
- package/dist/ir/model.d.ts +1474 -0
- package/dist/ir/model.js +6 -0
- package/dist/ir/native-absent-property.d.ts +3 -0
- package/dist/ir/native-absent-property.js +13 -0
- package/dist/ir/native-array-transport.d.ts +7 -0
- package/dist/ir/native-array-transport.js +46 -0
- package/dist/ir/native-callable-bind.d.ts +9 -0
- package/dist/ir/native-callable-bind.js +30 -0
- package/dist/ir/native-carrier-predicate.d.ts +34 -0
- package/dist/ir/native-carrier-predicate.js +49 -0
- package/dist/ir/native-class-accessor.d.ts +18 -0
- package/dist/ir/native-class-accessor.js +52 -0
- package/dist/ir/native-class-construction.d.ts +16 -0
- package/dist/ir/native-class-construction.js +71 -0
- package/dist/ir/native-class-initialization.d.ts +15 -0
- package/dist/ir/native-class-initialization.js +56 -0
- package/dist/ir/native-class-origins.d.ts +13 -0
- package/dist/ir/native-class-origins.js +237 -0
- package/dist/ir/native-dictionary-transport.d.ts +6 -0
- package/dist/ir/native-dictionary-transport.js +37 -0
- package/dist/ir/native-enumeration.d.ts +14 -0
- package/dist/ir/native-enumeration.js +26 -0
- package/dist/ir/native-equality.d.ts +10 -0
- package/dist/ir/native-equality.js +18 -0
- package/dist/ir/native-field-owner.d.ts +37 -0
- package/dist/ir/native-field-owner.js +183 -0
- package/dist/ir/native-fixed-layout.d.ts +41 -0
- package/dist/ir/native-fixed-layout.js +232 -0
- package/dist/ir/native-host-construction.d.ts +53 -0
- package/dist/ir/native-host-construction.js +62 -0
- package/dist/ir/native-key-query.d.ts +4 -0
- package/dist/ir/native-key-query.js +38 -0
- package/dist/ir/native-merge-transport.d.ts +25 -0
- package/dist/ir/native-merge-transport.js +71 -0
- package/dist/ir/native-record-index-transport.d.ts +11 -0
- package/dist/ir/native-record-index-transport.js +34 -0
- package/dist/ir/native-record-index.d.ts +12 -0
- package/dist/ir/native-record-index.js +27 -0
- package/dist/ir/native-reflect-field.d.ts +5 -0
- package/dist/ir/native-reflect-field.js +33 -0
- package/dist/ir/native-sequence-transport.d.ts +7 -0
- package/dist/ir/native-sequence-transport.js +53 -0
- package/dist/ir/numeric-intrinsics.d.ts +13 -0
- package/dist/ir/numeric-intrinsics.js +57 -0
- package/dist/ir/object-value-conversions.d.ts +20 -0
- package/dist/ir/object-value-conversions.js +50 -0
- package/dist/ir/physical-class-reflection.d.ts +9 -0
- package/dist/ir/physical-class-reflection.js +57 -0
- package/dist/ir/presence-proof.d.ts +42 -0
- package/dist/ir/presence-proof.js +490 -0
- package/dist/ir/program-facts.d.ts +106 -0
- package/dist/ir/program-facts.js +319 -0
- package/dist/ir/proven-branches.d.ts +16 -0
- package/dist/ir/proven-branches.js +219 -0
- package/dist/ir/queries.d.ts +41 -0
- package/dist/ir/queries.js +213 -0
- package/dist/ir/reflection-demand.d.ts +64 -0
- package/dist/ir/reflection-demand.js +1394 -0
- package/dist/ir/refusal.d.ts +43 -0
- package/dist/ir/refusal.js +28 -0
- package/dist/ir/shake.d.ts +37 -0
- package/dist/ir/shake.js +1078 -0
- package/dist/ir/static-callables.d.ts +11 -0
- package/dist/ir/static-callables.js +163 -0
- package/dist/ir/string-layout-reuse.d.ts +13 -0
- package/dist/ir/string-layout-reuse.js +39 -0
- package/dist/ir/string-length-reuse.d.ts +8 -0
- package/dist/ir/string-length-reuse.js +47 -0
- package/dist/ir/transfer.d.ts +78 -0
- package/dist/ir/transfer.js +270 -0
- package/dist/ir/type-query-results.d.ts +25 -0
- package/dist/ir/type-query-results.js +96 -0
- package/dist/ir/typed-property-access.d.ts +100 -0
- package/dist/ir/typed-property-access.js +161 -0
- package/dist/ir/verify.d.ts +19 -0
- package/dist/ir/verify.js +355 -0
- package/dist/plugins/apple/constructors.d.ts +112 -0
- package/dist/plugins/apple/constructors.js +217 -0
- package/dist/plugins/apple/host.d.ts +181 -0
- package/dist/plugins/apple/host.js +262 -0
- package/dist/plugins/apple/jsx.d.ts +2 -0
- package/dist/plugins/apple/jsx.js +293 -0
- package/dist/plugins/apple/members.d.ts +16 -0
- package/dist/plugins/apple/members.js +190 -0
- package/dist/plugins/apple/plugin.d.ts +2 -0
- package/dist/plugins/apple/plugin.js +156 -0
- package/dist/plugins/gea/component-classes.d.ts +25 -0
- package/dist/plugins/gea/component-classes.js +162 -0
- package/dist/plugins/gea/component-inline.d.ts +13 -0
- package/dist/plugins/gea/component-inline.js +532 -0
- package/dist/plugins/gea/constructors.d.ts +23 -0
- package/dist/plugins/gea/constructors.js +100 -0
- package/dist/plugins/gea/contract.d.ts +150 -0
- package/dist/plugins/gea/contract.js +195 -0
- package/dist/plugins/gea/element-ref.d.ts +31 -0
- package/dist/plugins/gea/element-ref.js +45 -0
- package/dist/plugins/gea/host.d.ts +520 -0
- package/dist/plugins/gea/host.js +762 -0
- package/dist/plugins/gea/lower.d.ts +6 -0
- package/dist/plugins/gea/lower.js +195 -0
- package/dist/plugins/gea/members.d.ts +22 -0
- package/dist/plugins/gea/members.js +221 -0
- package/dist/plugins/gea/plugin.d.ts +22 -0
- package/dist/plugins/gea/plugin.js +307 -0
- package/dist/plugins/gea/prelude.d.ts +78 -0
- package/dist/plugins/gea/prelude.js +153 -0
- package/dist/plugins/gea/producer.d.ts +5 -0
- package/dist/plugins/gea/producer.js +52 -0
- package/dist/plugins/gea/reactive-slots.d.ts +49 -0
- package/dist/plugins/gea/reactive-slots.js +578 -0
- package/dist/plugins/gea/render-bridge.d.ts +6 -0
- package/dist/plugins/gea/render-bridge.js +281 -0
- package/dist/plugins/gea/slots.d.ts +15 -0
- package/dist/plugins/gea/slots.js +36 -0
- package/dist/plugins/gea/template-analysis.d.ts +151 -0
- package/dist/plugins/gea/template-analysis.js +346 -0
- package/dist/plugins/gea/user-agent-styles.d.ts +9 -0
- package/dist/plugins/gea/user-agent-styles.js +94 -0
- package/dist/plugins/installed.d.ts +19 -0
- package/dist/plugins/installed.js +21 -0
- package/dist/plugins/load.d.ts +7 -0
- package/dist/plugins/load.js +207 -0
- package/dist/plugins/model.d.ts +735 -0
- package/dist/plugins/model.js +47 -0
- package/dist/plugins/webgl/host.d.ts +77 -0
- package/dist/plugins/webgl/host.js +162 -0
- package/dist/plugins/webgl/plugin.d.ts +40 -0
- package/dist/plugins/webgl/plugin.js +99 -0
- package/dist/preflight/obligations.d.ts +206 -0
- package/dist/preflight/obligations.js +36 -0
- package/dist/preflight/report.d.ts +20 -0
- package/dist/preflight/report.js +61 -0
- package/dist/preflight/run.d.ts +39 -0
- package/dist/preflight/run.js +403 -0
- package/dist/project-preparation.d.ts +33 -0
- package/dist/project-preparation.js +314 -0
- package/dist/projection/abi.d.ts +82 -0
- package/dist/projection/abi.js +349 -0
- package/dist/projection/apply-arguments.d.ts +12 -0
- package/dist/projection/apply-arguments.js +20 -0
- package/dist/projection/bindings.d.ts +250 -0
- package/dist/projection/bindings.js +340 -0
- package/dist/projection/callee.d.ts +196 -0
- package/dist/projection/callee.js +444 -0
- package/dist/projection/class-property-presence.d.ts +28 -0
- package/dist/projection/class-property-presence.js +58 -0
- package/dist/projection/class-prototype.d.ts +5 -0
- package/dist/projection/class-prototype.js +23 -0
- package/dist/projection/class-storage.d.ts +26 -0
- package/dist/projection/class-storage.js +236 -0
- package/dist/projection/classes.d.ts +283 -0
- package/dist/projection/classes.js +944 -0
- package/dist/projection/coercions.d.ts +20 -0
- package/dist/projection/coercions.js +33 -0
- package/dist/projection/dispatch.d.ts +167 -0
- package/dist/projection/dispatch.js +379 -0
- package/dist/projection/fields.d.ts +123 -0
- package/dist/projection/fields.js +383 -0
- package/dist/projection/instance-test.d.ts +78 -0
- package/dist/projection/instance-test.js +156 -0
- package/dist/projection/slots.d.ts +146 -0
- package/dist/projection/slots.js +663 -0
- package/dist/projection/synthesized-abi.d.ts +61 -0
- package/dist/projection/synthesized-abi.js +94 -0
- package/dist/representation/array-index.d.ts +14 -0
- package/dist/representation/array-index.js +17 -0
- package/dist/representation/callable-object.d.ts +3 -0
- package/dist/representation/callable-object.js +6 -0
- package/dist/representation/collections.d.ts +84 -0
- package/dist/representation/collections.js +139 -0
- package/dist/representation/derive.d.ts +159 -0
- package/dist/representation/derive.js +2546 -0
- package/dist/representation/difference.d.ts +30 -0
- package/dist/representation/difference.js +240 -0
- package/dist/representation/field-descriptor-policy.d.ts +19 -0
- package/dist/representation/field-descriptor-policy.js +39 -0
- package/dist/representation/function-constructor.d.ts +13 -0
- package/dist/representation/function-constructor.js +9 -0
- package/dist/representation/host-abi.d.ts +32 -0
- package/dist/representation/host-abi.js +97 -0
- package/dist/representation/host-templates.d.ts +67 -0
- package/dist/representation/host-templates.js +94 -0
- package/dist/representation/intersection.d.ts +84 -0
- package/dist/representation/intersection.js +149 -0
- package/dist/representation/literal-destination.d.ts +43 -0
- package/dist/representation/literal-destination.js +133 -0
- package/dist/representation/merge.d.ts +18 -0
- package/dist/representation/merge.js +83 -0
- package/dist/representation/model.d.ts +1160 -0
- package/dist/representation/model.js +1019 -0
- package/dist/representation/numeric-index.d.ts +13 -0
- package/dist/representation/numeric-index.js +29 -0
- package/dist/representation/object-shape.d.ts +109 -0
- package/dist/representation/object-shape.js +123 -0
- package/dist/representation/optional.d.ts +12 -0
- package/dist/representation/optional.js +87 -0
- package/dist/representation/plan.d.ts +60 -0
- package/dist/representation/plan.js +78 -0
- package/dist/representation/policies.d.ts +589 -0
- package/dist/representation/policies.js +107 -0
- package/dist/representation/primitive-domain.d.ts +1 -0
- package/dist/representation/primitive-domain.js +1 -0
- package/dist/representation/primitives.d.ts +44 -0
- package/dist/representation/primitives.js +78 -0
- package/dist/representation/publish.d.ts +49 -0
- package/dist/representation/publish.js +648 -0
- package/dist/representation/record-fields.d.ts +96 -0
- package/dist/representation/record-fields.js +116 -0
- package/dist/representation/template-object.d.ts +11 -0
- package/dist/representation/template-object.js +26 -0
- package/dist/representation/union.d.ts +30 -0
- package/dist/representation/union.js +324 -0
- package/dist/representation/value-records.d.ts +3 -0
- package/dist/representation/value-records.js +307 -0
- package/dist/representation/verify.d.ts +17 -0
- package/dist/representation/verify.js +221 -0
- package/dist/semantics/alias-this-field-declaration-transform.d.ts +4 -0
- package/dist/semantics/alias-this-field-declaration-transform.js +207 -0
- package/dist/semantics/ambient-type-realization-transform.d.ts +62 -0
- package/dist/semantics/ambient-type-realization-transform.js +168 -0
- package/dist/semantics/ambient.d.ts +24 -0
- package/dist/semantics/ambient.js +119 -0
- package/dist/semantics/borrowed-builtin-call-bind-source-transform.d.ts +4 -0
- package/dist/semantics/borrowed-builtin-call-bind-source-transform.js +341 -0
- package/dist/semantics/callable-origins.d.ts +46 -0
- package/dist/semantics/callable-origins.js +354 -0
- package/dist/semantics/class-alias.d.ts +7 -0
- package/dist/semantics/class-alias.js +37 -0
- package/dist/semantics/class-heritage.d.ts +34 -0
- package/dist/semantics/class-heritage.js +104 -0
- package/dist/semantics/commonjs-wrapper.d.ts +69 -0
- package/dist/semantics/commonjs-wrapper.js +231 -0
- package/dist/semantics/constructor-slot-subclasses.d.ts +28 -0
- package/dist/semantics/constructor-slot-subclasses.js +112 -0
- package/dist/semantics/declaration-overlay-transform.d.ts +35 -0
- package/dist/semantics/declaration-overlay-transform.js +2157 -0
- package/dist/semantics/define-property-source-transform.d.ts +4 -0
- package/dist/semantics/define-property-source-transform.js +437 -0
- package/dist/semantics/diagnostic-source-preparation.d.ts +24 -0
- package/dist/semantics/diagnostic-source-preparation.js +82 -0
- package/dist/semantics/documentation-ranges.d.ts +22 -0
- package/dist/semantics/documentation-ranges.js +36 -0
- package/dist/semantics/dynamic-fallback.d.ts +86 -0
- package/dist/semantics/dynamic-fallback.js +249 -0
- package/dist/semantics/frontend-timing.d.ts +6 -0
- package/dist/semantics/frontend-timing.js +35 -0
- package/dist/semantics/frontend.d.ts +504 -0
- package/dist/semantics/frontend.js +1157 -0
- package/dist/semantics/host-declaration-provenance.d.ts +11 -0
- package/dist/semantics/host-declaration-provenance.js +18 -0
- package/dist/semantics/host-methods.d.ts +24 -0
- package/dist/semantics/host-methods.js +74 -0
- package/dist/semantics/host-protocols.d.ts +429 -0
- package/dist/semantics/host-protocols.js +1501 -0
- package/dist/semantics/inherited-accessor.d.ts +7 -0
- package/dist/semantics/inherited-accessor.js +48 -0
- package/dist/semantics/interface-families.d.ts +70 -0
- package/dist/semantics/interface-families.js +180 -0
- package/dist/semantics/interface-implementors.d.ts +53 -0
- package/dist/semantics/interface-implementors.js +87 -0
- package/dist/semantics/jsdoc-namepath-transform.d.ts +4 -0
- package/dist/semantics/jsdoc-namepath-transform.js +85 -0
- package/dist/semantics/model/coverage.d.ts +68 -0
- package/dist/semantics/model/coverage.js +73 -0
- package/dist/semantics/model/edges.d.ts +103 -0
- package/dist/semantics/model/edges.js +20 -0
- package/dist/semantics/model/graph.d.ts +55 -0
- package/dist/semantics/model/graph.js +129 -0
- package/dist/semantics/model/operands.d.ts +159 -0
- package/dist/semantics/model/operands.js +26 -0
- package/dist/semantics/model/operations.d.ts +496 -0
- package/dist/semantics/model/operations.js +2 -0
- package/dist/semantics/model/primitive-domain.d.ts +26 -0
- package/dist/semantics/model/primitive-domain.js +38 -0
- package/dist/semantics/model/selected-signature.d.ts +261 -0
- package/dist/semantics/model/selected-signature.js +55 -0
- package/dist/semantics/model/structural-type-table.d.ts +93 -0
- package/dist/semantics/model/structural-type-table.js +237 -0
- package/dist/semantics/model/structural-types.d.ts +367 -0
- package/dist/semantics/model/structural-types.js +200 -0
- package/dist/semantics/module-resolution.d.ts +23 -0
- package/dist/semantics/module-resolution.js +227 -0
- package/dist/semantics/new-callee-class-tag-source-transform.d.ts +4 -0
- package/dist/semantics/new-callee-class-tag-source-transform.js +64 -0
- package/dist/semantics/node-project.d.ts +13 -0
- package/dist/semantics/node-project.js +107 -0
- package/dist/semantics/node-source-hooks.d.ts +1 -0
- package/dist/semantics/node-source-hooks.js +63 -0
- package/dist/semantics/normalize/absent-globals.d.ts +143 -0
- package/dist/semantics/normalize/absent-globals.js +191 -0
- package/dist/semantics/normalize/arguments-objects.d.ts +43 -0
- package/dist/semantics/normalize/arguments-objects.js +60 -0
- package/dist/semantics/normalize/asserted-arm-absence.d.ts +28 -0
- package/dist/semantics/normalize/asserted-arm-absence.js +61 -0
- package/dist/semantics/normalize/assignment-patterns.d.ts +70 -0
- package/dist/semantics/normalize/assignment-patterns.js +147 -0
- package/dist/semantics/normalize/bag-absence.d.ts +8 -0
- package/dist/semantics/normalize/bag-absence.js +42 -0
- package/dist/semantics/normalize/binding-fixpoint.d.ts +36 -0
- package/dist/semantics/normalize/binding-fixpoint.js +140 -0
- package/dist/semantics/normalize/callback-parameter-contracts.d.ts +16 -0
- package/dist/semantics/normalize/callback-parameter-contracts.js +91 -0
- package/dist/semantics/normalize/cells/agreement.d.ts +46 -0
- package/dist/semantics/normalize/cells/agreement.js +34 -0
- package/dist/semantics/normalize/cells/candidates.d.ts +17 -0
- package/dist/semantics/normalize/cells/candidates.js +35 -0
- package/dist/semantics/normalize/cells/facts.d.ts +19 -0
- package/dist/semantics/normalize/cells/facts.js +90 -0
- package/dist/semantics/normalize/cells/index.d.ts +10 -0
- package/dist/semantics/normalize/cells/index.js +6 -0
- package/dist/semantics/normalize/cells/model.d.ts +98 -0
- package/dist/semantics/normalize/cells/model.js +2 -0
- package/dist/semantics/normalize/cells/policies/bag.d.ts +44 -0
- package/dist/semantics/normalize/cells/policies/bag.js +114 -0
- package/dist/semantics/normalize/cells/policies/collection.d.ts +42 -0
- package/dist/semantics/normalize/cells/policies/collection.js +218 -0
- package/dist/semantics/normalize/cells/policies/field.d.ts +28 -0
- package/dist/semantics/normalize/cells/policies/field.js +40 -0
- package/dist/semantics/normalize/cells/policies/index.d.ts +49 -0
- package/dist/semantics/normalize/cells/policies/index.js +58 -0
- package/dist/semantics/normalize/cells/policies/local.d.ts +18 -0
- package/dist/semantics/normalize/cells/policies/local.js +37 -0
- package/dist/semantics/normalize/cells/policies/parameter.d.ts +28 -0
- package/dist/semantics/normalize/cells/policies/parameter.js +39 -0
- package/dist/semantics/normalize/cells/policies/return.d.ts +26 -0
- package/dist/semantics/normalize/cells/policies/return.js +45 -0
- package/dist/semantics/normalize/cells/policies/shared.d.ts +33 -0
- package/dist/semantics/normalize/cells/policies/shared.js +45 -0
- package/dist/semantics/normalize/cells/policy.d.ts +72 -0
- package/dist/semantics/normalize/cells/policy.js +18 -0
- package/dist/semantics/normalize/cells/registry.d.ts +14 -0
- package/dist/semantics/normalize/cells/registry.js +17 -0
- package/dist/semantics/normalize/census-refusal.d.ts +62 -0
- package/dist/semantics/normalize/census-refusal.js +27 -0
- package/dist/semantics/normalize/census.d.ts +109 -0
- package/dist/semantics/normalize/census.js +667 -0
- package/dist/semantics/normalize/collection-bindings.d.ts +278 -0
- package/dist/semantics/normalize/collection-bindings.js +677 -0
- package/dist/semantics/normalize/commonjs-module-record.d.ts +21 -0
- package/dist/semantics/normalize/commonjs-module-record.js +289 -0
- package/dist/semantics/normalize/commonjs-require.d.ts +13 -0
- package/dist/semantics/normalize/commonjs-require.js +1527 -0
- package/dist/semantics/normalize/contribution.d.ts +63 -0
- package/dist/semantics/normalize/contribution.js +172 -0
- package/dist/semantics/normalize/dead-typeof-guards.d.ts +64 -0
- package/dist/semantics/normalize/dead-typeof-guards.js +152 -0
- package/dist/semantics/normalize/deferred-intrinsic-protocols.d.ts +57 -0
- package/dist/semantics/normalize/deferred-intrinsic-protocols.js +109 -0
- package/dist/semantics/normalize/derived-expression-type.d.ts +1070 -0
- package/dist/semantics/normalize/derived-expression-type.js +3463 -0
- package/dist/semantics/normalize/evaluation-order.d.ts +16 -0
- package/dist/semantics/normalize/evaluation-order.js +37 -0
- package/dist/semantics/normalize/field-bindings.d.ts +167 -0
- package/dist/semantics/normalize/field-bindings.js +1125 -0
- package/dist/semantics/normalize/flow/array-element-continuation.d.ts +27 -0
- package/dist/semantics/normalize/flow/array-element-continuation.js +1452 -0
- package/dist/semantics/normalize/flow/callable-array-origins.d.ts +42 -0
- package/dist/semantics/normalize/flow/callable-array-origins.js +318 -0
- package/dist/semantics/normalize/flow/callable-completions.d.ts +45 -0
- package/dist/semantics/normalize/flow/callable-completions.js +82 -0
- package/dist/semantics/normalize/flow/callable-reach.d.ts +237 -0
- package/dist/semantics/normalize/flow/callable-reach.js +7174 -0
- package/dist/semantics/normalize/flow/class-family-member-read.d.ts +16 -0
- package/dist/semantics/normalize/flow/class-family-member-read.js +992 -0
- package/dist/semantics/normalize/flow/collection-value-continuation.d.ts +21 -0
- package/dist/semantics/normalize/flow/collection-value-continuation.js +192 -0
- package/dist/semantics/normalize/flow/component-solver.d.ts +199 -0
- package/dist/semantics/normalize/flow/component-solver.js +587 -0
- package/dist/semantics/normalize/flow/computed-key-set.d.ts +84 -0
- package/dist/semantics/normalize/flow/computed-key-set.js +660 -0
- package/dist/semantics/normalize/flow/export-importers.d.ts +24 -0
- package/dist/semantics/normalize/flow/export-importers.js +269 -0
- package/dist/semantics/normalize/flow/host-text-sink.d.ts +25 -0
- package/dist/semantics/normalize/flow/host-text-sink.js +87 -0
- package/dist/semantics/normalize/flow/intrinsic-array-callback-frames.d.ts +84 -0
- package/dist/semantics/normalize/flow/intrinsic-array-callback-frames.js +180 -0
- package/dist/semantics/normalize/flow/intrinsic-data-definition.d.ts +35 -0
- package/dist/semantics/normalize/flow/intrinsic-data-definition.js +140 -0
- package/dist/semantics/normalize/flow/invocation-facts.d.ts +98 -0
- package/dist/semantics/normalize/flow/invocation-facts.js +257 -0
- package/dist/semantics/normalize/flow/member-call-forwarding.d.ts +122 -0
- package/dist/semantics/normalize/flow/member-call-forwarding.js +835 -0
- package/dist/semantics/normalize/flow/model.d.ts +357 -0
- package/dist/semantics/normalize/flow/model.js +177 -0
- package/dist/semantics/normalize/flow/native-collection-protocol.d.ts +24 -0
- package/dist/semantics/normalize/flow/native-collection-protocol.js +252 -0
- package/dist/semantics/normalize/flow/node-path-token.d.ts +3 -0
- package/dist/semantics/normalize/flow/node-path-token.js +53 -0
- package/dist/semantics/normalize/flow/object-binding-continuation.d.ts +11 -0
- package/dist/semantics/normalize/flow/object-binding-continuation.js +42 -0
- package/dist/semantics/normalize/flow/origin-authority.d.ts +56 -0
- package/dist/semantics/normalize/flow/origin-authority.js +2 -0
- package/dist/semantics/normalize/flow/owned-class-receivers.d.ts +35 -0
- package/dist/semantics/normalize/flow/owned-class-receivers.js +191 -0
- package/dist/semantics/normalize/flow/parameter-values.d.ts +27 -0
- package/dist/semantics/normalize/flow/parameter-values.js +251 -0
- package/dist/semantics/normalize/flow/proof-hypotheses.d.ts +66 -0
- package/dist/semantics/normalize/flow/proof-hypotheses.js +162 -0
- package/dist/semantics/normalize/flow/record-alias-closure.d.ts +27 -0
- package/dist/semantics/normalize/flow/record-alias-closure.js +298 -0
- package/dist/semantics/normalize/flow/seeded-origins.d.ts +43 -0
- package/dist/semantics/normalize/flow/seeded-origins.js +54 -0
- package/dist/semantics/normalize/flow/source-class-data.d.ts +132 -0
- package/dist/semantics/normalize/flow/source-class-data.js +838 -0
- package/dist/semantics/normalize/flow/source-class-instanceof.d.ts +13 -0
- package/dist/semantics/normalize/flow/source-class-instanceof.js +37 -0
- package/dist/semantics/normalize/flow/source-class-static-data.d.ts +16 -0
- package/dist/semantics/normalize/flow/source-class-static-data.js +47 -0
- package/dist/semantics/normalize/flow/source-construction-frames.d.ts +12 -0
- package/dist/semantics/normalize/flow/source-construction-frames.js +118 -0
- package/dist/semantics/normalize/flow/source-invocation-frame-layout.d.ts +34 -0
- package/dist/semantics/normalize/flow/source-invocation-frame-layout.js +78 -0
- package/dist/semantics/normalize/flow/source-invocation-receiver.d.ts +37 -0
- package/dist/semantics/normalize/flow/source-invocation-receiver.js +95 -0
- package/dist/semantics/normalize/flow/source-prototype-method-identity.d.ts +23 -0
- package/dist/semantics/normalize/flow/source-prototype-method-identity.js +81 -0
- package/dist/semantics/normalize/flow/source-record-data.d.ts +29 -0
- package/dist/semantics/normalize/flow/source-record-data.js +626 -0
- package/dist/semantics/normalize/flow/source-value-session.d.ts +77 -0
- package/dist/semantics/normalize/flow/source-value-session.js +3089 -0
- package/dist/semantics/normalize/flow/targets.d.ts +118 -0
- package/dist/semantics/normalize/flow/targets.js +405 -0
- package/dist/semantics/normalize/flow/value-flow.d.ts +36 -0
- package/dist/semantics/normalize/flow/value-flow.js +823 -0
- package/dist/semantics/normalize/flow/value-provenance.d.ts +31 -0
- package/dist/semantics/normalize/flow/value-provenance.js +112 -0
- package/dist/semantics/normalize/gating.d.ts +51 -0
- package/dist/semantics/normalize/gating.js +560 -0
- package/dist/semantics/normalize/generic-function-choice.d.ts +31 -0
- package/dist/semantics/normalize/generic-function-choice.js +115 -0
- package/dist/semantics/normalize/global-host-mutations.d.ts +51 -0
- package/dist/semantics/normalize/global-host-mutations.js +5989 -0
- package/dist/semantics/normalize/host-effect-contracts.d.ts +77 -0
- package/dist/semantics/normalize/host-effect-contracts.js +143 -0
- package/dist/semantics/normalize/host-mutation-computed-keys.d.ts +38 -0
- package/dist/semantics/normalize/host-mutation-computed-keys.js +26 -0
- package/dist/semantics/normalize/host-mutation-key-reader.d.ts +66 -0
- package/dist/semantics/normalize/host-mutation-key-reader.js +192 -0
- package/dist/semantics/normalize/host-mutation-keys.d.ts +114 -0
- package/dist/semantics/normalize/host-mutation-keys.js +183 -0
- package/dist/semantics/normalize/identities.d.ts +172 -0
- package/dist/semantics/normalize/identities.js +426 -0
- package/dist/semantics/normalize/implicit-arguments-tuple.d.ts +97 -0
- package/dist/semantics/normalize/implicit-arguments-tuple.js +197 -0
- package/dist/semantics/normalize/implicit-arguments.d.ts +11 -0
- package/dist/semantics/normalize/implicit-arguments.js +39 -0
- package/dist/semantics/normalize/instantiation.d.ts +73 -0
- package/dist/semantics/normalize/instantiation.js +399 -0
- package/dist/semantics/normalize/intrinsic-property-call.d.ts +18 -0
- package/dist/semantics/normalize/intrinsic-property-call.js +69 -0
- package/dist/semantics/normalize/intrinsic-prototype.d.ts +41 -0
- package/dist/semantics/normalize/intrinsic-prototype.js +87 -0
- package/dist/semantics/normalize/intrinsic-static-member.d.ts +14 -0
- package/dist/semantics/normalize/intrinsic-static-member.js +23 -0
- package/dist/semantics/normalize/jsdoc-type-names.d.ts +32 -0
- package/dist/semantics/normalize/jsdoc-type-names.js +512 -0
- package/dist/semantics/normalize/keyof.d.ts +32 -0
- package/dist/semantics/normalize/keyof.js +110 -0
- package/dist/semantics/normalize/local-bindings.d.ts +176 -0
- package/dist/semantics/normalize/local-bindings.js +1826 -0
- package/dist/semantics/normalize/logical-result-type.d.ts +16 -0
- package/dist/semantics/normalize/logical-result-type.js +102 -0
- package/dist/semantics/normalize/namespace-paths.d.ts +57 -0
- package/dist/semantics/normalize/namespace-paths.js +108 -0
- package/dist/semantics/normalize/normalize.d.ts +57 -0
- package/dist/semantics/normalize/normalize.js +68 -0
- package/dist/semantics/normalize/object-bag-bindings.d.ts +305 -0
- package/dist/semantics/normalize/object-bag-bindings.js +1290 -0
- package/dist/semantics/normalize/omitted-stated-parameter.d.ts +53 -0
- package/dist/semantics/normalize/omitted-stated-parameter.js +59 -0
- package/dist/semantics/normalize/open-type-form.d.ts +10 -0
- package/dist/semantics/normalize/open-type-form.js +32 -0
- package/dist/semantics/normalize/parameter-bindings.d.ts +361 -0
- package/dist/semantics/normalize/parameter-bindings.js +3339 -0
- package/dist/semantics/normalize/parameter-slot.d.ts +264 -0
- package/dist/semantics/normalize/parameter-slot.js +491 -0
- package/dist/semantics/normalize/physical-overload-result.d.ts +77 -0
- package/dist/semantics/normalize/physical-overload-result.js +99 -0
- package/dist/semantics/normalize/primitive-property-absence.d.ts +12 -0
- package/dist/semantics/normalize/primitive-property-absence.js +60 -0
- package/dist/semantics/normalize/producer-context.d.ts +376 -0
- package/dist/semantics/normalize/producer-context.js +1 -0
- package/dist/semantics/normalize/producers/allocations.d.ts +3 -0
- package/dist/semantics/normalize/producers/allocations.js +863 -0
- package/dist/semantics/normalize/producers/binding-kind.d.ts +37 -0
- package/dist/semantics/normalize/producers/binding-kind.js +36 -0
- package/dist/semantics/normalize/producers/bindings.d.ts +85 -0
- package/dist/semantics/normalize/producers/bindings.js +710 -0
- package/dist/semantics/normalize/producers/boundary.d.ts +34 -0
- package/dist/semantics/normalize/producers/boundary.js +123 -0
- package/dist/semantics/normalize/producers/class-lifecycle.d.ts +3 -0
- package/dist/semantics/normalize/producers/class-lifecycle.js +902 -0
- package/dist/semantics/normalize/producers/computations.d.ts +3 -0
- package/dist/semantics/normalize/producers/computations.js +613 -0
- package/dist/semantics/normalize/producers/control-loops.d.ts +30 -0
- package/dist/semantics/normalize/producers/control-loops.js +91 -0
- package/dist/semantics/normalize/producers/control.d.ts +30 -0
- package/dist/semantics/normalize/producers/control.js +923 -0
- package/dist/semantics/normalize/producers/declaration-lifecycle.d.ts +3 -0
- package/dist/semantics/normalize/producers/declaration-lifecycle.js +390 -0
- package/dist/semantics/normalize/producers/destructuring.d.ts +45 -0
- package/dist/semantics/normalize/producers/destructuring.js +1180 -0
- package/dist/semantics/normalize/producers/dynamic-language.d.ts +3 -0
- package/dist/semantics/normalize/producers/dynamic-language.js +70 -0
- package/dist/semantics/normalize/producers/erasure.d.ts +51 -0
- package/dist/semantics/normalize/producers/erasure.js +90 -0
- package/dist/semantics/normalize/producers/installed.d.ts +3 -0
- package/dist/semantics/normalize/producers/installed.js +55 -0
- package/dist/semantics/normalize/producers/invocations.d.ts +35 -0
- package/dist/semantics/normalize/producers/invocations.js +1796 -0
- package/dist/semantics/normalize/producers/iteration-yield.d.ts +59 -0
- package/dist/semantics/normalize/producers/iteration-yield.js +235 -0
- package/dist/semantics/normalize/producers/jsx.d.ts +3 -0
- package/dist/semantics/normalize/producers/jsx.js +360 -0
- package/dist/semantics/normalize/producers/mint.d.ts +39 -0
- package/dist/semantics/normalize/producers/mint.js +44 -0
- package/dist/semantics/normalize/producers/nullish.d.ts +16 -0
- package/dist/semantics/normalize/producers/nullish.js +27 -0
- package/dist/semantics/normalize/producers/object-assignment.d.ts +8 -0
- package/dist/semantics/normalize/producers/object-assignment.js +204 -0
- package/dist/semantics/normalize/producers/object-tag.d.ts +9 -0
- package/dist/semantics/normalize/producers/object-tag.js +119 -0
- package/dist/semantics/normalize/producers/optional-chain.d.ts +44 -0
- package/dist/semantics/normalize/producers/optional-chain.js +75 -0
- package/dist/semantics/normalize/producers/properties.d.ts +21 -0
- package/dist/semantics/normalize/producers/properties.js +1053 -0
- package/dist/semantics/normalize/producers/protocol.d.ts +67 -0
- package/dist/semantics/normalize/producers/protocol.js +695 -0
- package/dist/semantics/normalize/producers/references.d.ts +53 -0
- package/dist/semantics/normalize/producers/references.js +1027 -0
- package/dist/semantics/normalize/producers/shared.d.ts +561 -0
- package/dist/semantics/normalize/producers/shared.js +1683 -0
- package/dist/semantics/normalize/producers/spread-arguments.d.ts +72 -0
- package/dist/semantics/normalize/producers/spread-arguments.js +375 -0
- package/dist/semantics/normalize/producers/tagged-template.d.ts +5 -0
- package/dist/semantics/normalize/producers/tagged-template.js +307 -0
- package/dist/semantics/normalize/producers/tuple-spread.d.ts +189 -0
- package/dist/semantics/normalize/producers/tuple-spread.js +279 -0
- package/dist/semantics/normalize/property-key-domain.d.ts +36 -0
- package/dist/semantics/normalize/property-key-domain.js +150 -0
- package/dist/semantics/normalize/reachability.d.ts +189 -0
- package/dist/semantics/normalize/reachability.js +1057 -0
- package/dist/semantics/normalize/reassigned-bindings.d.ts +13 -0
- package/dist/semantics/normalize/reassigned-bindings.js +41 -0
- package/dist/semantics/normalize/record-storage-families.d.ts +11 -0
- package/dist/semantics/normalize/record-storage-families.js +109 -0
- package/dist/semantics/normalize/return-bindings.d.ts +260 -0
- package/dist/semantics/normalize/return-bindings.js +1311 -0
- package/dist/semantics/normalize/return-paths.d.ts +2 -0
- package/dist/semantics/normalize/return-paths.js +28 -0
- package/dist/semantics/normalize/script-global-redefinition.d.ts +44 -0
- package/dist/semantics/normalize/script-global-redefinition.js +75 -0
- package/dist/semantics/normalize/specialization.d.ts +201 -0
- package/dist/semantics/normalize/specialization.js +1824 -0
- package/dist/semantics/normalize/structural-array-element.d.ts +176 -0
- package/dist/semantics/normalize/structural-array-element.js +700 -0
- package/dist/semantics/normalize/structural-array-read.d.ts +13 -0
- package/dist/semantics/normalize/structural-array-read.js +124 -0
- package/dist/semantics/normalize/structural-callable.d.ts +12 -0
- package/dist/semantics/normalize/structural-callable.js +82 -0
- package/dist/semantics/normalize/structural-creation-order.d.ts +32 -0
- package/dist/semantics/normalize/structural-creation-order.js +111 -0
- package/dist/semantics/normalize/structural-declarations.d.ts +395 -0
- package/dist/semantics/normalize/structural-declarations.js +968 -0
- package/dist/semantics/normalize/structural-declared-body.d.ts +25 -0
- package/dist/semantics/normalize/structural-declared-body.js +147 -0
- package/dist/semantics/normalize/structural-generics.d.ts +56 -0
- package/dist/semantics/normalize/structural-generics.js +120 -0
- package/dist/semantics/normalize/structural-indexed-access.d.ts +11 -0
- package/dist/semantics/normalize/structural-indexed-access.js +126 -0
- package/dist/semantics/normalize/structural-instantiated-member.d.ts +64 -0
- package/dist/semantics/normalize/structural-instantiated-member.js +407 -0
- package/dist/semantics/normalize/structural-joins.d.ts +44 -0
- package/dist/semantics/normalize/structural-joins.js +143 -0
- package/dist/semantics/normalize/structural-layout-relevance.d.ts +29 -0
- package/dist/semantics/normalize/structural-layout-relevance.js +391 -0
- package/dist/semantics/normalize/structural-layout-type.d.ts +11 -0
- package/dist/semantics/normalize/structural-layout-type.js +1468 -0
- package/dist/semantics/normalize/structural-leaves.d.ts +49 -0
- package/dist/semantics/normalize/structural-leaves.js +125 -0
- package/dist/semantics/normalize/structural-local-union.d.ts +13 -0
- package/dist/semantics/normalize/structural-local-union.js +133 -0
- package/dist/semantics/normalize/structural-members.d.ts +26 -0
- package/dist/semantics/normalize/structural-members.js +84 -0
- package/dist/semantics/normalize/structural-mutable-method.d.ts +15 -0
- package/dist/semantics/normalize/structural-mutable-method.js +109 -0
- package/dist/semantics/normalize/structural-parts.d.ts +131 -0
- package/dist/semantics/normalize/structural-parts.js +737 -0
- package/dist/semantics/normalize/structural-receiver.d.ts +66 -0
- package/dist/semantics/normalize/structural-receiver.js +551 -0
- package/dist/semantics/normalize/structural-rules.d.ts +112 -0
- package/dist/semantics/normalize/structural-rules.js +93 -0
- package/dist/semantics/normalize/structural-self-reference.d.ts +150 -0
- package/dist/semantics/normalize/structural-self-reference.js +494 -0
- package/dist/semantics/normalize/structural.d.ts +202 -0
- package/dist/semantics/normalize/structural.js +4218 -0
- package/dist/semantics/normalize/unreduced-type-form.d.ts +41 -0
- package/dist/semantics/normalize/unreduced-type-form.js +53 -0
- package/dist/semantics/normalize/unresolvable-names.d.ts +56 -0
- package/dist/semantics/normalize/unresolvable-names.js +140 -0
- package/dist/semantics/package-sources.d.ts +16 -0
- package/dist/semantics/package-sources.js +365 -0
- package/dist/semantics/program.d.ts +151 -0
- package/dist/semantics/program.js +667 -0
- package/dist/semantics/prototype-install-source-transform.d.ts +4 -0
- package/dist/semantics/prototype-install-source-transform.js +341 -0
- package/dist/semantics/prototype-object-class-source-transform.d.ts +4 -0
- package/dist/semantics/prototype-object-class-source-transform.js +525 -0
- package/dist/semantics/prototype-reparenting.d.ts +50 -0
- package/dist/semantics/prototype-reparenting.js +317 -0
- package/dist/semantics/stable-checker.d.ts +10 -0
- package/dist/semantics/stable-checker.js +148 -0
- package/dist/semantics/subclass-member-overlay-transform.d.ts +35 -0
- package/dist/semantics/subclass-member-overlay-transform.js +1418 -0
- package/dist/semantics/symbol-keyed-expando-source-transform.d.ts +4 -0
- package/dist/semantics/symbol-keyed-expando-source-transform.js +66 -0
- package/dist/semantics/this-constructor-source-transform.d.ts +4 -0
- package/dist/semantics/this-constructor-source-transform.js +122 -0
- package/dist/semantics/uninstantiable-classes.d.ts +22 -0
- package/dist/semantics/uninstantiable-classes.js +75 -0
- package/dist/targets/cpp/balanced-units.d.ts +3 -0
- package/dist/targets/cpp/balanced-units.js +58 -0
- package/dist/targets/cpp/borrowed-call-entry.d.ts +30 -0
- package/dist/targets/cpp/borrowed-call-entry.js +68 -0
- package/dist/targets/cpp/captures.d.ts +68 -0
- package/dist/targets/cpp/captures.js +269 -0
- package/dist/targets/cpp/class-layout.d.ts +313 -0
- package/dist/targets/cpp/class-layout.js +483 -0
- package/dist/targets/cpp/class-properties/computed-method-value.d.ts +25 -0
- package/dist/targets/cpp/class-properties/computed-method-value.js +22 -0
- package/dist/targets/cpp/class-properties/emit-class-properties.d.ts +216 -0
- package/dist/targets/cpp/class-properties/emit-class-properties.js +917 -0
- package/dist/targets/cpp/class-properties/native-prototype.d.ts +11 -0
- package/dist/targets/cpp/class-properties/native-prototype.js +101 -0
- package/dist/targets/cpp/class-ref-transport.d.ts +12 -0
- package/dist/targets/cpp/class-ref-transport.js +32 -0
- package/dist/targets/cpp/conversions.d.ts +3 -0
- package/dist/targets/cpp/conversions.js +2027 -0
- package/dist/targets/cpp/deferral-safety.d.ts +82 -0
- package/dist/targets/cpp/deferral-safety.js +86 -0
- package/dist/targets/cpp/direct-call-receivers.d.ts +37 -0
- package/dist/targets/cpp/direct-call-receivers.js +79 -0
- package/dist/targets/cpp/document.d.ts +74 -0
- package/dist/targets/cpp/document.js +106 -0
- package/dist/targets/cpp/emit-allocation.d.ts +60 -0
- package/dist/targets/cpp/emit-allocation.js +573 -0
- package/dist/targets/cpp/emit-arrays.d.ts +119 -0
- package/dist/targets/cpp/emit-arrays.js +1047 -0
- package/dist/targets/cpp/emit-binding-reference.d.ts +17 -0
- package/dist/targets/cpp/emit-binding-reference.js +120 -0
- package/dist/targets/cpp/emit-bindings.d.ts +158 -0
- package/dist/targets/cpp/emit-bindings.js +769 -0
- package/dist/targets/cpp/emit-buffers.d.ts +156 -0
- package/dist/targets/cpp/emit-buffers.js +573 -0
- package/dist/targets/cpp/emit-callable.d.ts +230 -0
- package/dist/targets/cpp/emit-callable.js +2154 -0
- package/dist/targets/cpp/emit-carrier-members.d.ts +406 -0
- package/dist/targets/cpp/emit-carrier-members.js +1224 -0
- package/dist/targets/cpp/emit-coercion.d.ts +26 -0
- package/dist/targets/cpp/emit-coercion.js +39 -0
- package/dist/targets/cpp/emit-context.d.ts +1882 -0
- package/dist/targets/cpp/emit-context.js +904 -0
- package/dist/targets/cpp/emit-dynamic-properties.d.ts +174 -0
- package/dist/targets/cpp/emit-dynamic-properties.js +1249 -0
- package/dist/targets/cpp/emit-equality.d.ts +39 -0
- package/dist/targets/cpp/emit-equality.js +472 -0
- package/dist/targets/cpp/emit-exceptions.d.ts +104 -0
- package/dist/targets/cpp/emit-exceptions.js +513 -0
- package/dist/targets/cpp/emit-field-owner.d.ts +4 -0
- package/dist/targets/cpp/emit-field-owner.js +27 -0
- package/dist/targets/cpp/emit-in.d.ts +31 -0
- package/dist/targets/cpp/emit-in.js +426 -0
- package/dist/targets/cpp/emit-instanceof.d.ts +19 -0
- package/dist/targets/cpp/emit-instanceof.js +601 -0
- package/dist/targets/cpp/emit-integers.d.ts +68 -0
- package/dist/targets/cpp/emit-integers.js +184 -0
- package/dist/targets/cpp/emit-iterator.d.ts +100 -0
- package/dist/targets/cpp/emit-iterator.js +1137 -0
- package/dist/targets/cpp/emit-json.d.ts +73 -0
- package/dist/targets/cpp/emit-json.js +823 -0
- package/dist/targets/cpp/emit-jsx.d.ts +74 -0
- package/dist/targets/cpp/emit-jsx.js +806 -0
- package/dist/targets/cpp/emit-mixed-binary.d.ts +51 -0
- package/dist/targets/cpp/emit-mixed-binary.js +60 -0
- package/dist/targets/cpp/emit-namespaces.d.ts +101 -0
- package/dist/targets/cpp/emit-namespaces.js +133 -0
- package/dist/targets/cpp/emit-narrowing.d.ts +738 -0
- package/dist/targets/cpp/emit-narrowing.js +3967 -0
- package/dist/targets/cpp/emit-native-equality.d.ts +3 -0
- package/dist/targets/cpp/emit-native-equality.js +14 -0
- package/dist/targets/cpp/emit-native-selection.d.ts +5 -0
- package/dist/targets/cpp/emit-native-selection.js +37 -0
- package/dist/targets/cpp/emit-object-tag.d.ts +4 -0
- package/dist/targets/cpp/emit-object-tag.js +108 -0
- package/dist/targets/cpp/emit-owned-record.d.ts +2 -0
- package/dist/targets/cpp/emit-owned-record.js +15 -0
- package/dist/targets/cpp/emit-presence.d.ts +78 -0
- package/dist/targets/cpp/emit-presence.js +376 -0
- package/dist/targets/cpp/emit-properties.d.ts +105 -0
- package/dist/targets/cpp/emit-properties.js +1640 -0
- package/dist/targets/cpp/emit-record-view.d.ts +20 -0
- package/dist/targets/cpp/emit-record-view.js +354 -0
- package/dist/targets/cpp/emit-return.d.ts +5 -0
- package/dist/targets/cpp/emit-return.js +237 -0
- package/dist/targets/cpp/emit-sum-widening.d.ts +10 -0
- package/dist/targets/cpp/emit-sum-widening.js +69 -0
- package/dist/targets/cpp/emit-tonumber.d.ts +38 -0
- package/dist/targets/cpp/emit-tonumber.js +177 -0
- package/dist/targets/cpp/emit-tostring.d.ts +92 -0
- package/dist/targets/cpp/emit-tostring.js +556 -0
- package/dist/targets/cpp/emit-typeof.d.ts +49 -0
- package/dist/targets/cpp/emit-typeof.js +317 -0
- package/dist/targets/cpp/emit-union-properties.d.ts +181 -0
- package/dist/targets/cpp/emit-union-properties.js +1281 -0
- package/dist/targets/cpp/emit.d.ts +45 -0
- package/dist/targets/cpp/emit.js +2225 -0
- package/dist/targets/cpp/error-types.d.ts +4 -0
- package/dist/targets/cpp/error-types.js +11 -0
- package/dist/targets/cpp/function-source-reads.d.ts +72 -0
- package/dist/targets/cpp/function-source-reads.js +148 -0
- package/dist/targets/cpp/host/atomics.d.ts +25 -0
- package/dist/targets/cpp/host/atomics.js +63 -0
- package/dist/targets/cpp/host/core-globals.d.ts +108 -0
- package/dist/targets/cpp/host/core-globals.js +158 -0
- package/dist/targets/cpp/host/dynamic-argument-members.d.ts +42 -0
- package/dist/targets/cpp/host/dynamic-argument-members.js +61 -0
- package/dist/targets/cpp/host/emit-host-arity.d.ts +139 -0
- package/dist/targets/cpp/host/emit-host-arity.js +232 -0
- package/dist/targets/cpp/host/emit-host-invoke.d.ts +91 -0
- package/dist/targets/cpp/host/emit-host-invoke.js +1105 -0
- package/dist/targets/cpp/host/emit-host-object.d.ts +55 -0
- package/dist/targets/cpp/host/emit-host-object.js +2206 -0
- package/dist/targets/cpp/host/emit-host-properties.d.ts +69 -0
- package/dist/targets/cpp/host/emit-host-properties.js +533 -0
- package/dist/targets/cpp/host/emit-host-reflect.d.ts +4 -0
- package/dist/targets/cpp/host/emit-host-reflect.js +180 -0
- package/dist/targets/cpp/host/emit-host-value.d.ts +120 -0
- package/dist/targets/cpp/host/emit-host-value.js +392 -0
- package/dist/targets/cpp/host/host-members.d.ts +505 -0
- package/dist/targets/cpp/host/host-members.js +819 -0
- package/dist/targets/cpp/host/host-method-aliases.d.ts +30 -0
- package/dist/targets/cpp/host/host-method-aliases.js +76 -0
- package/dist/targets/cpp/host/native-protocols.d.ts +47 -0
- package/dist/targets/cpp/host/native-protocols.js +183 -0
- package/dist/targets/cpp/host/object-protocol.d.ts +351 -0
- package/dist/targets/cpp/host/object-protocol.js +671 -0
- package/dist/targets/cpp/host-namespace-reads.d.ts +83 -0
- package/dist/targets/cpp/host-namespace-reads.js +113 -0
- package/dist/targets/cpp/manifest/capabilities.d.ts +39 -0
- package/dist/targets/cpp/manifest/capabilities.js +1484 -0
- package/dist/targets/cpp/manifest.d.ts +23 -0
- package/dist/targets/cpp/manifest.js +113 -0
- package/dist/targets/cpp/native-error-base.d.ts +38 -0
- package/dist/targets/cpp/native-error-base.js +74 -0
- package/dist/targets/cpp/native-narrowing-transport.d.ts +12 -0
- package/dist/targets/cpp/native-narrowing-transport.js +151 -0
- package/dist/targets/cpp/native-selection-helpers.d.ts +11 -0
- package/dist/targets/cpp/native-selection-helpers.js +46 -0
- package/dist/targets/cpp/native-symbol-keys.d.ts +8 -0
- package/dist/targets/cpp/native-symbol-keys.js +34 -0
- package/dist/targets/cpp/ownership.d.ts +43 -0
- package/dist/targets/cpp/ownership.js +38 -0
- package/dist/targets/cpp/owning-conversion-input.d.ts +14 -0
- package/dist/targets/cpp/owning-conversion-input.js +12 -0
- package/dist/targets/cpp/property-read-claims.d.ts +62 -0
- package/dist/targets/cpp/property-read-claims.js +23 -0
- package/dist/targets/cpp/property-store-claims.d.ts +62 -0
- package/dist/targets/cpp/property-store-claims.js +26 -0
- package/dist/targets/cpp/prototype/emit-prototype-array.d.ts +111 -0
- package/dist/targets/cpp/prototype/emit-prototype-array.js +602 -0
- package/dist/targets/cpp/prototype/emit-prototype-date.d.ts +133 -0
- package/dist/targets/cpp/prototype/emit-prototype-date.js +515 -0
- package/dist/targets/cpp/prototype/emit-prototype-error.d.ts +13 -0
- package/dist/targets/cpp/prototype/emit-prototype-error.js +54 -0
- package/dist/targets/cpp/prototype/emit-prototype-invoke.d.ts +34 -0
- package/dist/targets/cpp/prototype/emit-prototype-invoke.js +1003 -0
- package/dist/targets/cpp/prototype/emit-prototype-iterator.d.ts +47 -0
- package/dist/targets/cpp/prototype/emit-prototype-iterator.js +250 -0
- package/dist/targets/cpp/prototype/emit-prototype-promise.d.ts +46 -0
- package/dist/targets/cpp/prototype/emit-prototype-promise.js +143 -0
- package/dist/targets/cpp/prototype/emit-prototype-regexp.d.ts +335 -0
- package/dist/targets/cpp/prototype/emit-prototype-regexp.js +853 -0
- package/dist/targets/cpp/prototype/emit-prototype-string.d.ts +42 -0
- package/dist/targets/cpp/prototype/emit-prototype-string.js +252 -0
- package/dist/targets/cpp/prototype/prototype-method-reads.d.ts +25 -0
- package/dist/targets/cpp/prototype/prototype-method-reads.js +182 -0
- package/dist/targets/cpp/reactive-dependencies.d.ts +140 -0
- package/dist/targets/cpp/reactive-dependencies.js +432 -0
- package/dist/targets/cpp/reactive-origins.d.ts +44 -0
- package/dist/targets/cpp/reactive-origins.js +82 -0
- package/dist/targets/cpp/records.d.ts +277 -0
- package/dist/targets/cpp/records.js +2427 -0
- package/dist/targets/cpp/recursive-containers.d.ts +43 -0
- package/dist/targets/cpp/recursive-containers.js +144 -0
- package/dist/targets/cpp/regexp-types.d.ts +56 -0
- package/dist/targets/cpp/regexp-types.js +59 -0
- package/dist/targets/cpp/substrate.d.ts +125 -0
- package/dist/targets/cpp/substrate.js +12 -0
- package/dist/targets/cpp/translation-unit.d.ts +219 -0
- package/dist/targets/cpp/translation-unit.js +2063 -0
- package/dist/targets/cpp/types.d.ts +280 -0
- package/dist/targets/cpp/types.js +1135 -0
- package/dist/targets/cpp/virtual-methods.d.ts +95 -0
- package/dist/targets/cpp/virtual-methods.js +264 -0
- package/package.json +95 -0
- package/src/targets/cpp/runtime/gea_dynamic_proxy.h +824 -0
- package/src/targets/cpp/runtime/gea_eval.h +1376 -0
- package/src/targets/cpp/runtime/gea_native_class_prototype.h +44 -0
- package/src/targets/cpp/runtime/gea_runtime.h +29222 -0
- 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
|
+
]);
|