@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,1640 @@
|
|
|
1
|
+
import { dictionaryKeyDomainOf, ownershipOf, representationKey } from '../../representation/model.js';
|
|
2
|
+
import { carrierDifference, shortCarrierText } from '../../representation/difference.js';
|
|
3
|
+
import { nativeFieldOwnerReadText } from './emit-field-owner.js';
|
|
4
|
+
import { cppDenseFlagName, cppDensePointerName, createCppEmitBlockedError, defineValue, defineValueAlias, operandText, prototypeMethodReceiverText, unwrapPresentValue, isIntegerStorageValue, storedEnvironmentText } from './emit-context.js';
|
|
5
|
+
import { declaredHostMethodRead, emitNativeHostStore, nativeHostMemberText } from './host/emit-host-properties.js';
|
|
6
|
+
import { hostResultText } from './host/emit-host-arity.js';
|
|
7
|
+
import { classMemberOf, dispatchesStatically, fieldDeclaringStructOf, lazyArrowFieldGetPlanOf, lazyMaterializedFieldText, structNameOfReceiver } from './class-layout.js';
|
|
8
|
+
import { cppArrayExtensionStructName, cppBodyName, cppRecordAccessorEnvironmentName, cppRecordFieldAttributesName, cppRecordFieldName, cppRecordFieldPresenceName, cppTypeOf, cppScalarType, cppStringLiteral, cppUndefinedIn } from './types.js';
|
|
9
|
+
import { isNativeError } from './error-types.js';
|
|
10
|
+
import { cppVirtualMemberName, virtualDispatchKey } from './virtual-methods.js';
|
|
11
|
+
import { recordAccessorsOfShape, declaredFieldRepresentationOf, declaredRecordFieldOf, nativeBaseFieldOf } from './records.js';
|
|
12
|
+
import { nativeErrorMemberText } from './prototype/emit-prototype-error.js';
|
|
13
|
+
import { structuralRecordViewText } from './emit-record-view.js';
|
|
14
|
+
import { classMemberText, classConstructorStaticFieldStorage, classConstructorStaticMemberText } from './class-properties/emit-class-properties.js';
|
|
15
|
+
import { alignedValueText, classFamilyLoadText, movedValueText, narrowedLoadText } from './emit-narrowing.js';
|
|
16
|
+
import { namespaceMemberStore } from './emit-namespaces.js';
|
|
17
|
+
import { callableSidecarGetText, isNativeCallableCarrier, dynamicGetText, emitDynamicSet, emitNativeSidecarSet, nativeSidecarGetText } from './emit-dynamic-properties.js';
|
|
18
|
+
import { dynamicObjectPrototypeMemberRead, objectShapePrototypeMemberRead } from './host/object-protocol.js';
|
|
19
|
+
import { emitRegExpSet, emitStringObjectSet, regexpCaptureSlotStoreClaim, regexpMemberText, regexpStoreRefusal, stringObjectMemberText } from './prototype/emit-prototype-regexp.js';
|
|
20
|
+
import { emitTaggedUnionSet, taggedUnionGetText } from './emit-union-properties.js';
|
|
21
|
+
import { stringAppendStatement } from './emit-tostring.js';
|
|
22
|
+
/**
|
|
23
|
+
* The property spine: every `[[Get]]`, `[[Set]]`, and `[[DefineOwnProperty]]`
|
|
24
|
+
* this backend renders, over every receiver carrier it can render one for.
|
|
25
|
+
*
|
|
26
|
+
* One file, because the choice of spelling is one decision: a record field, a
|
|
27
|
+
* class field, a class method, and an Array element are four answers to the
|
|
28
|
+
* same question, and separating them is how two of them end up disagreeing
|
|
29
|
+
* about what a key means.
|
|
30
|
+
*/
|
|
31
|
+
/**
|
|
32
|
+
* The ownership a field store/load may dispatch on. Anything else has no
|
|
33
|
+
* member-access spelling this file knows how to pick.
|
|
34
|
+
*
|
|
35
|
+
* `record-with-index` reaches this only for its NAMED half -- a constant key
|
|
36
|
+
* that spells one of the carrier's own `fields`, exactly the same struct
|
|
37
|
+
* member a plain `record` has. Every branch that owns the carrier's OTHER
|
|
38
|
+
* half (a key that names no field, constant or computed) claims the operation
|
|
39
|
+
* first and returns before this generic fallback is ever asked --
|
|
40
|
+
* `recordWithIndexFieldText`/`recordIndexSidecarReadText` on the read side,
|
|
41
|
+
* `emitRecordIndexSidecarStore` on the store side -- so a `record-with-index`
|
|
42
|
+
* that DOES reach here is always its struct half, the one thing this function
|
|
43
|
+
* already knows how to spell.
|
|
44
|
+
*/
|
|
45
|
+
const recordOwnershipOf = (operand, contextDescription) => {
|
|
46
|
+
const representation = operand.representation;
|
|
47
|
+
if (representation.kind === 'record' ||
|
|
48
|
+
representation.kind === 'record-with-index' ||
|
|
49
|
+
representation.kind === 'native-record-ref' ||
|
|
50
|
+
representation.kind === 'class-ref') {
|
|
51
|
+
return representation.ownership;
|
|
52
|
+
}
|
|
53
|
+
throw createCppEmitBlockedError(`property-access:${representation.kind}:field`, `${contextDescription} has a receiver carrier of kind "${representation.kind}"; ` +
|
|
54
|
+
'this emitter only spells member access for "record", "record-with-index", "native-record-ref", and "class-ref"');
|
|
55
|
+
};
|
|
56
|
+
/** The static field name a `get`/`set`/`define-own-property` key resolves to. A key with no recorded constant text is a dynamic key. */
|
|
57
|
+
export const staticKeyTextOf = (ctx, key, contextDescription) => {
|
|
58
|
+
const text = ctx.staticKeyTexts.get(key.value);
|
|
59
|
+
if (text !== undefined)
|
|
60
|
+
return text;
|
|
61
|
+
throw createCppEmitBlockedError(`runtime-helper:computation:to-property-key:${contextDescription}`, `${contextDescription} has a key that was not produced by a "constant" operation in this body; this emitter has no dynamic-key path`);
|
|
62
|
+
};
|
|
63
|
+
import { dateMemberText } from './prototype/emit-prototype-date.js';
|
|
64
|
+
import { arrayAccessText, presentElementText, keyedCollectionMemberText, iteratorMemberText, canonicalIndexLiteral, dictionaryPrototypeMemberRead, memberAccessOperator, promiseMemberText, keyedTableKeyText, emitRecordIndexSidecarStore, recordIndexSidecarReadText, reactiveRevisionText, scalarMemberText, stringMemberText, symbolMemberText, typedArrayAccessText } from './emit-carrier-members.js';
|
|
65
|
+
import { arrayBufferAccessText, dataViewAccessText, sharedArrayBufferAccessText } from './emit-buffers.js';
|
|
66
|
+
import { functionSourceReadClaimOf } from './function-source-reads.js';
|
|
67
|
+
import { deferredCallableBuiltinReadClaimOf, recordWithIndexFieldClaimOf } from './property-read-claims.js';
|
|
68
|
+
/**
|
|
69
|
+
* The host-member reading of a property access, or `null` when the receiver is
|
|
70
|
+
* not a `native-handle`.
|
|
71
|
+
*
|
|
72
|
+
* A host singleton -- `Math`, `Date`, `String` -- carries no data of its own:
|
|
73
|
+
* every one of its interned handles names the same host object, and the value
|
|
74
|
+
* a `[[Get]]` produces depends only on the protocol and the key, never on
|
|
75
|
+
* which handle instance asked. So, unlike every other branch here, the
|
|
76
|
+
* materialized receiver operand is not read at all -- the qualified host
|
|
77
|
+
* symbol `gea::host::<protocol>::<key>` names the member directly, the same
|
|
78
|
+
* way `classMemberText` names a method without reading the instance. That
|
|
79
|
+
* symbol is read out of `hostMembers`, never built from the protocol and the
|
|
80
|
+
* key: the table states the spelling for every member that has one, so a
|
|
81
|
+
* member no table claims is refused by name below rather than handed an
|
|
82
|
+
* interpolated symbol no runtime header declares.
|
|
83
|
+
*
|
|
84
|
+
* A non-constant key is refused: a host object has no runtime member table
|
|
85
|
+
* for this backend to dispatch a dynamic key against, only the fixed set of
|
|
86
|
+
* qualified symbols `gea_runtime.h` declares.
|
|
87
|
+
*/
|
|
88
|
+
/**
|
|
89
|
+
* The dictionary table behind a receiver, in both spellings a use of it needs.
|
|
90
|
+
*
|
|
91
|
+
* A `dictionary` carrier is a `std::map`-backed container: `member` reaches
|
|
92
|
+
* its methods (`read`, `has`) through whichever accessor its ownership calls
|
|
93
|
+
* for, and `subscript` is the `operator[]` form a store writes through. Both
|
|
94
|
+
* are built here rather than at each use so the two cannot disagree about
|
|
95
|
+
* which object is being indexed.
|
|
96
|
+
*
|
|
97
|
+
* A `record-with-index` deliberately answers `null`. Its index signature does
|
|
98
|
+
* live in a dictionary sidecar beside the named fields, but a key that spells
|
|
99
|
+
* a declared field must reach the *struct member* and not the table, and
|
|
100
|
+
* deciding that needs the field list this function does not have. Answering
|
|
101
|
+
* here would route `style.width` into the sidecar and silently read nothing,
|
|
102
|
+
* so it stays refused by name in the caller until that decision is written.
|
|
103
|
+
*/
|
|
104
|
+
export const dictionaryTableOf = (ctx, receiver, key) => {
|
|
105
|
+
const representation = receiver.representation;
|
|
106
|
+
if (representation.kind !== 'dictionary')
|
|
107
|
+
return null;
|
|
108
|
+
const receiverText = operandText(ctx, receiver);
|
|
109
|
+
const indexed = representation.ownership === 'shared-refcount' ? `(*${receiverText})` : receiverText;
|
|
110
|
+
const keyText = keyedTableKeyText(ctx, key, dictionaryKeyDomainOf(representation.key, key.representation));
|
|
111
|
+
return {
|
|
112
|
+
member: `${receiverText}${memberAccessOperator(representation.ownership)}`,
|
|
113
|
+
subscript: `${indexed}[${keyText}]`,
|
|
114
|
+
key: keyText
|
|
115
|
+
};
|
|
116
|
+
};
|
|
117
|
+
/**
|
|
118
|
+
* Reading a dynamic-keyed property out of a dictionary.
|
|
119
|
+
*
|
|
120
|
+
* The language answers `undefined` for a key the table does not hold. Where
|
|
121
|
+
* the program was compiled to say so -- `noUncheckedIndexedAccess`, which
|
|
122
|
+
* types the read `V | undefined` and carries it as `optional<V>` -- this
|
|
123
|
+
* renders that exactly, testing `has` and constructing the present and absent
|
|
124
|
+
* cases separately. Where it was not, the checker itself asserted the value is
|
|
125
|
+
* a `V` and the plan carries a bare `V`; `read` answers that, and a missing
|
|
126
|
+
* key yields a value-initialized one. Rendering the optional form there would
|
|
127
|
+
* not be more truthful -- it would not compile, because the carrier the rest
|
|
128
|
+
* of the program agreed on has no way to hold an absence.
|
|
129
|
+
*/
|
|
130
|
+
const dictionaryReadText = (ctx, operation) => {
|
|
131
|
+
const table = dictionaryTableOf(ctx, operation.receiver, operation.key);
|
|
132
|
+
if (table === null)
|
|
133
|
+
return null;
|
|
134
|
+
if (operation.receiver.representation.kind !== 'dictionary')
|
|
135
|
+
return null;
|
|
136
|
+
const source = operation.receiver.representation.value;
|
|
137
|
+
const read = operation.result.representation;
|
|
138
|
+
const raw = `${table.member}read(${table.key})`;
|
|
139
|
+
if (representationKey(source) === representationKey(read))
|
|
140
|
+
return raw;
|
|
141
|
+
if (read.kind === 'optional' && representationKey(source) === representationKey(read.payload)) {
|
|
142
|
+
const carrier = cppTypeOf(read);
|
|
143
|
+
return `(${table.member}has(${table.key}) ? ${carrier}(${raw}) : ${carrier}())`;
|
|
144
|
+
}
|
|
145
|
+
const converted = alignedValueText(ctx, 'emit-properties.ts:213', source, read, raw);
|
|
146
|
+
if (converted !== null)
|
|
147
|
+
return converted;
|
|
148
|
+
throw createCppEmitBlockedError(`conversion:${representationKey(source)}->${representationKey(read)}`, `reads a dictionary value carried as "${representationKey(source)}" into "${representationKey(read)}", and no conversion is installed`);
|
|
149
|
+
};
|
|
150
|
+
/**
|
|
151
|
+
* The named-field half of a `record-with-index` receiver's own split layout
|
|
152
|
+
* (`representation/model.ts`'s own comment states the split; `records.ts`'s
|
|
153
|
+
* `renderStructDefinition` is where it becomes two struct members side by
|
|
154
|
+
* side). Only a constant key that spells one of the carrier's own `fields`
|
|
155
|
+
* resolves here -- exactly the same struct member the generic `record`/
|
|
156
|
+
* `native-record-ref` fallback below would spell for an ordinary record, so
|
|
157
|
+
* this reuses `memberAccessOperator` and `cppRecordFieldName` rather than a
|
|
158
|
+
* second opinion on either.
|
|
159
|
+
*
|
|
160
|
+
* A constant key that names no field is not answered here: it would have to
|
|
161
|
+
* route into the sidecar `gea_dynamic` member instead
|
|
162
|
+
* (`emit-carrier-members.ts`'s `recordIndexSidecarReadText` renders that, for
|
|
163
|
+
* the computed case `preflight/property-access.ts` actually admits; see
|
|
164
|
+
* `manifest.ts`'s own comment for why a *constant* key naming no field stays
|
|
165
|
+
* unclaimed rather than also routing there). `null` therefore covers two
|
|
166
|
+
* different receivers with one answer -- "not a `record-with-index`" and "a
|
|
167
|
+
* `record-with-index` this function does not resolve" -- which is safe only
|
|
168
|
+
* because `preflight/property-access.ts`'s `recordWithIndexKeyNamesAField`
|
|
169
|
+
* already refuses to certify the second case, so an uncertified program is
|
|
170
|
+
* the only way emission reaches here for one, and the fallback below still
|
|
171
|
+
* refuses it by name.
|
|
172
|
+
*/
|
|
173
|
+
/**
|
|
174
|
+
* `args.length` off a rest parameter.
|
|
175
|
+
*
|
|
176
|
+
* A rest parameter whose declared type is a tuple is carried as a POSITIONAL
|
|
177
|
+
* RECORD -- `model.ts`'s `isArrayPatternCapable` names the same shape, and
|
|
178
|
+
* there is deliberately no separate tuple carrier -- so its arity lives in the
|
|
179
|
+
* presence bits rather than in a `length` member. Without this the read fell
|
|
180
|
+
* through every native branch to the dynamic sidecar, which has no such key:
|
|
181
|
+
* the program certified and then aborted at runtime in `refusePayloadMismatch`.
|
|
182
|
+
* three's WebGL forwarding shims are the shape that needs it -- `texImage2D(
|
|
183
|
+
* ...args )` selects its 6-argument form with `args.length === 6`.
|
|
184
|
+
*
|
|
185
|
+
* Synthesizing `length` for a positional record cannot capture a plain object
|
|
186
|
+
* that merely has numeric keys: `({ 0: "a" }).length` is a type error, so the
|
|
187
|
+
* checker refuses that read long before emission, and this branch is only ever
|
|
188
|
+
* reached for a receiver whose static type declares a `length` -- a tuple.
|
|
189
|
+
*
|
|
190
|
+
* The count is the leading run of present slots, which is what arity means: a
|
|
191
|
+
* required prefix is present by construction, and each optional slot beyond it
|
|
192
|
+
* counts only when it is filled.
|
|
193
|
+
*/
|
|
194
|
+
const positionalRecordLengthText = (ctx, operation) => {
|
|
195
|
+
if (ctx.staticKeyTexts.get(operation.key.value) !== 'length')
|
|
196
|
+
return null;
|
|
197
|
+
const representation = operation.receiver.representation;
|
|
198
|
+
if (representation.kind !== 'record')
|
|
199
|
+
return null;
|
|
200
|
+
const fields = representation.fields;
|
|
201
|
+
if (fields.length === 0 || !fields.every((field, index) => field.key === String(index)))
|
|
202
|
+
return null;
|
|
203
|
+
// A tuple's optional elements are its trailing ones; a record whose required
|
|
204
|
+
// flags are not a prefix is not one, and its arity is not a count.
|
|
205
|
+
const required = fields.findIndex((field) => !field.required);
|
|
206
|
+
if (required === -1)
|
|
207
|
+
return `${fields.length}`;
|
|
208
|
+
if (fields.slice(required).some((field) => field.required))
|
|
209
|
+
return null;
|
|
210
|
+
const receiverText = operandText(ctx, operation.receiver);
|
|
211
|
+
const accessor = memberAccessOperator(representation.ownership);
|
|
212
|
+
let text = `${required}`;
|
|
213
|
+
for (let index = required; index < fields.length; index += 1) {
|
|
214
|
+
const field = fields[index];
|
|
215
|
+
if (field === undefined)
|
|
216
|
+
return null;
|
|
217
|
+
text = `(${receiverText}${accessor}${cppRecordFieldPresenceName(field.key)} ? ${index + 1} : ${text})`;
|
|
218
|
+
}
|
|
219
|
+
return text;
|
|
220
|
+
};
|
|
221
|
+
const recordWithIndexFieldText = (ctx, receiver, key) => {
|
|
222
|
+
const claim = recordWithIndexFieldClaimOf(ctx.staticKeyTexts, receiver, key);
|
|
223
|
+
if (claim === null)
|
|
224
|
+
return null;
|
|
225
|
+
// The claim already proved `receiver.representation.kind === 'record-with-index'`;
|
|
226
|
+
// this cast spells that same fact rather than re-deriving it from the kind tag.
|
|
227
|
+
const representation = receiver.representation;
|
|
228
|
+
const accessor = memberAccessOperator(representation.ownership);
|
|
229
|
+
return `${operandText(ctx, receiver)}${accessor}${cppRecordFieldName(claim.fieldKey)}`;
|
|
230
|
+
};
|
|
231
|
+
/**
|
|
232
|
+
* The accessor list behind a record-shaped receiver, read from wherever that
|
|
233
|
+
* receiver's carrier actually keeps it.
|
|
234
|
+
*
|
|
235
|
+
* A plain `record` carries its `accessors` inline (`derive.ts`'s
|
|
236
|
+
* `deriveObject`), because the whole shape was expanded right there. A
|
|
237
|
+
* `native-record-ref` carries none -- it is a *reference* by shape id,
|
|
238
|
+
* deliberately not expanded (`derive.ts`'s `declared`/`object-anchor` cases:
|
|
239
|
+
* expanding a name whose body can refer back to itself has no finite
|
|
240
|
+
* carrier). So a `native-record-ref` receiver's accessors are read back
|
|
241
|
+
* through `ctx.deriver` (`records.ts`'s `recordAccessorsOfShape`) -- the
|
|
242
|
+
* identical authority `declaredFieldRepresentation`, above, already reads
|
|
243
|
+
* that same reference's *fields* through -- never a second, re-derived
|
|
244
|
+
* opinion about what the shape's members are.
|
|
245
|
+
*/
|
|
246
|
+
const recordAccessorsFor = (ctx, representation) => {
|
|
247
|
+
if (representation.kind === 'record')
|
|
248
|
+
return representation.accessors;
|
|
249
|
+
if (representation.kind === 'native-record-ref')
|
|
250
|
+
return recordAccessorsOfShape(ctx.deriver, representation.shapeId);
|
|
251
|
+
return null;
|
|
252
|
+
};
|
|
253
|
+
/**
|
|
254
|
+
* The emitted body behind an accessor-backed *record* member, or `null` when
|
|
255
|
+
* the key is an ordinary field (or the receiver carries no record accessors
|
|
256
|
+
* at all).
|
|
257
|
+
*
|
|
258
|
+
* An object literal's `get width() { ... }` has no storage: the shape says so,
|
|
259
|
+
* and `records.ts` lays out no member for it. So the read is a call, spelled
|
|
260
|
+
* against the same free function every other body is emitted as, with the
|
|
261
|
+
* object passed as the receiver it was compiled to take.
|
|
262
|
+
*/
|
|
263
|
+
/**
|
|
264
|
+
* Whether a member read renders as a pure load -- an element, a `length`, a
|
|
265
|
+
* field, a method reference -- rather than as a call into the program.
|
|
266
|
+
*
|
|
267
|
+
* `ir/dead-values.ts` asks this before dropping a read nothing consumes, and
|
|
268
|
+
* `ir/deferral.ts` before moving one to its use. A read through a record
|
|
269
|
+
* accessor (`get width() { ... }`) runs a body; a read off a host handle may
|
|
270
|
+
* reach the host; a read through an `optional` receiver renders a presence
|
|
271
|
+
* check first. All three keep their statement. `key` is the IR's own text for
|
|
272
|
+
* a string-literal key, passed in rather than looked up: this is asked from the
|
|
273
|
+
* IR passes, before an `EmitContext` for the body exists at all, so neither
|
|
274
|
+
* `constantTexts` nor the settled `staticKeyTexts` is reachable from here.
|
|
275
|
+
*/
|
|
276
|
+
export const isPlainMemberRead = (ctx, operation, key) => {
|
|
277
|
+
const representation = operation.receiver.representation;
|
|
278
|
+
if (representation.kind === 'array-object' || representation.kind === 'string')
|
|
279
|
+
return true;
|
|
280
|
+
if (representation.kind !== 'class-ref' && representation.kind !== 'record' && representation.kind !== 'native-record-ref')
|
|
281
|
+
return false;
|
|
282
|
+
if (key === null)
|
|
283
|
+
return false;
|
|
284
|
+
if (representation.kind === 'class-ref') {
|
|
285
|
+
// The same inherited member lookup that renders the read decides whether
|
|
286
|
+
// it calls a getter. Dropping an unused extracted value must not drop that
|
|
287
|
+
// getter's observable effects.
|
|
288
|
+
const member = classMemberOf(ctx.classes, representation.declaration, key);
|
|
289
|
+
return member !== null && member.kind !== 'accessor';
|
|
290
|
+
}
|
|
291
|
+
const accessors = recordAccessorsFor(ctx, representation);
|
|
292
|
+
return accessors === null || !accessors.some((entry) => entry.key === key);
|
|
293
|
+
};
|
|
294
|
+
/**
|
|
295
|
+
* The environment actual a capturing accessor's body is called with, or no
|
|
296
|
+
* actual at all when the body captures nothing.
|
|
297
|
+
*
|
|
298
|
+
* `emit-iterator.ts` asks the identical question of the identical member for a
|
|
299
|
+
* `next`/`return` read it renders as one expression, so this is exported: one
|
|
300
|
+
* answer for "what does this accessor's body need beyond its receiver",
|
|
301
|
+
* reached from every site that calls one.
|
|
302
|
+
*/
|
|
303
|
+
export const accessorEnvironmentArguments = (ctx, receiver, key, body, half, receiverText) => {
|
|
304
|
+
if (body === null || ctx.captures.of(body).kind !== 'ok')
|
|
305
|
+
return [];
|
|
306
|
+
const member = `${receiverText}${ownershipOf(receiver) === 'owned' ? '.' : '->'}${cppRecordAccessorEnvironmentName(key, half)}`;
|
|
307
|
+
return [storedEnvironmentText(body, member)];
|
|
308
|
+
};
|
|
309
|
+
const recordAccessorBody = (ctx, receiver, key, half) => {
|
|
310
|
+
const accessors = recordAccessorsFor(ctx, receiver.representation);
|
|
311
|
+
if (!accessors)
|
|
312
|
+
return null;
|
|
313
|
+
const accessor = accessors.find((entry) => entry.key === key);
|
|
314
|
+
if (!accessor)
|
|
315
|
+
return null;
|
|
316
|
+
const body = half === 'getter' ? accessor.getter : accessor.setter;
|
|
317
|
+
if (!body) {
|
|
318
|
+
throw createCppEmitBlockedError(`property-access:record:${half === 'getter' ? 'get' : 'set'}:false`, `accessor "${key}" declares no ${half}, so ${half === 'getter' ? 'reading' : 'writing'} it has no body to call`);
|
|
319
|
+
}
|
|
320
|
+
return body;
|
|
321
|
+
};
|
|
322
|
+
/**
|
|
323
|
+
* A member reached through a host NAMESPACE.
|
|
324
|
+
*
|
|
325
|
+
* Asked first, because the receiver of one of these is not a value: nothing
|
|
326
|
+
* was materialized for `deviceInfo`, so every branch below it -- each of
|
|
327
|
+
* which reads the receiver operand -- would ask for a name that was never
|
|
328
|
+
* minted. What exists is a path, and this is where a path either grows a
|
|
329
|
+
* segment or resolves to a spelling.
|
|
330
|
+
*
|
|
331
|
+
* The three answers, from the host's own tables:
|
|
332
|
+
*
|
|
333
|
+
* - a METHOD renders nothing here and hands the call site the spelling, the
|
|
334
|
+
* same deferral `hostMemberReads` uses -- `deviceInfo.deviceId` names no C++
|
|
335
|
+
* on its own and only `gea::host::device_info::deviceId(...)` does;
|
|
336
|
+
* - a PROPERTY is already an expression -- `gea::host::Display.width` -- so it
|
|
337
|
+
* renders as the value;
|
|
338
|
+
* - a longer PATH -- `navigator.bluetooth` -- renders nothing and extends the
|
|
339
|
+
* path, because the host states members under it and not for it.
|
|
340
|
+
*
|
|
341
|
+
* A member none of the three claims is refused by name. That is the whole
|
|
342
|
+
* point of reading the host's tables rather than interpolating `path + '.' +
|
|
343
|
+
* member`: an interpolated symbol compiles as plausible text and fails at
|
|
344
|
+
* `ld`, which is exactly the failure this replaced.
|
|
345
|
+
*/
|
|
346
|
+
const namespaceMemberText = (ctx, operation) => {
|
|
347
|
+
const path = ctx.hostNamespaceReads.get(operation.receiver.value) ?? ctx.hostNamespaceValues.get(operation.receiver.value);
|
|
348
|
+
if (path === undefined)
|
|
349
|
+
return null;
|
|
350
|
+
// Which of the three answers this `get` is -- a method, a longer path, or a
|
|
351
|
+
// property -- was decided before this body rendered a line, by the SAME
|
|
352
|
+
// fixed point that settled `path` above: a longer path is exactly the value
|
|
353
|
+
// the next `get` in the chain has to find there, so the walk cannot resolve
|
|
354
|
+
// one without resolving the other. Asking it, rather than re-resolving
|
|
355
|
+
// `path.member` against the host tables a second time, is what keeps the one
|
|
356
|
+
// fact to one authority.
|
|
357
|
+
if (ctx.hostFunctionReads.has(operation.result.id))
|
|
358
|
+
return '';
|
|
359
|
+
if (ctx.hostNamespaceReads.has(operation.result.id))
|
|
360
|
+
return '';
|
|
361
|
+
const member = staticKeyTextOf(ctx, operation.key, `a member of the host namespace "${path}"`);
|
|
362
|
+
const key = `${path}.${member}`;
|
|
363
|
+
const property = ctx.hosts.namespaces.properties.get(key);
|
|
364
|
+
if (property !== undefined)
|
|
365
|
+
return property;
|
|
366
|
+
throw createCppEmitBlockedError(`host-invocation:${key}`, `"${key}" is not a member this host states a spelling for; the namespace is reachable and this member of it is not`);
|
|
367
|
+
};
|
|
368
|
+
/**
|
|
369
|
+
* One dense window's element, and the flag that says the pointer may be used.
|
|
370
|
+
*
|
|
371
|
+
* `null` unless `emitBody` admitted a window for this very access
|
|
372
|
+
* (`ir/dense-loops.ts`). The general form stays in the emitted text either way:
|
|
373
|
+
* the flag is loop-invariant, so the backend versions the loop on it rather
|
|
374
|
+
* than testing it per element, and the slow half is what runs for an array that
|
|
375
|
+
* holds a hole or an index the loop's own bound did not cover.
|
|
376
|
+
*/
|
|
377
|
+
const denseCellText = (ctx, operation) => {
|
|
378
|
+
const access = ctx.denseAccesses.get(operation);
|
|
379
|
+
if (access === undefined)
|
|
380
|
+
return null;
|
|
381
|
+
// The flag is stated as LIKELY at every site rather than left to the
|
|
382
|
+
// backend's own guess. It is loop-invariant and true for every array a
|
|
383
|
+
// program actually builds, but clang schedules the two halves as if either
|
|
384
|
+
// could run: measured on `bench/comparison/fixtures/object_create.ts`,
|
|
385
|
+
// 9.05ms without the hint and 8.49ms with it, for the same instructions in a
|
|
386
|
+
// better order.
|
|
387
|
+
return {
|
|
388
|
+
pointer: cppDensePointerName(access.array),
|
|
389
|
+
index: `static_cast<std::size_t>(${ctx.denseIndices.get(operation.key.value) ?? operandText(ctx, operation.key)})`,
|
|
390
|
+
flag: `GEA_LIKELY(${cppDenseFlagName(access.flag)})`,
|
|
391
|
+
text: `${cppDensePointerName(access.array)}[static_cast<std::size_t>(${ctx.denseIndices.get(operation.key.value) ?? operandText(ctx, operation.key)})]${operation.receiver.representation.kind === 'typed-array' ? '' : '.value'}`
|
|
392
|
+
};
|
|
393
|
+
};
|
|
394
|
+
/** The same, as a read: `flag ? base[i].value : <the general form>`. */
|
|
395
|
+
const denseElementText = (ctx, operation) => {
|
|
396
|
+
const dense = denseCellText(ctx, operation);
|
|
397
|
+
if (dense === null)
|
|
398
|
+
return null;
|
|
399
|
+
const general = operation.receiver.representation.kind === 'typed-array'
|
|
400
|
+
? typedArrayAccessText(ctx, operation.receiver, operation.key, operation.result)
|
|
401
|
+
: arrayAccessText(ctx, operation.receiver, operation.key, operation.result);
|
|
402
|
+
if (general === null || general === '')
|
|
403
|
+
return null;
|
|
404
|
+
// The window's flag is a proof of presence, so the fast half is written in
|
|
405
|
+
// the result's carrier the same way the general half's guarded arm is --
|
|
406
|
+
// see `presentElementText`. Without it the two arms are a bare element and
|
|
407
|
+
// an `Optional<T>`, and only the converting constructor makes that a type.
|
|
408
|
+
const element = operation.receiver.representation.kind === 'array-object'
|
|
409
|
+
? operation.receiver.representation.element
|
|
410
|
+
: operation.receiver.representation.kind === 'typed-array'
|
|
411
|
+
? { kind: 'scalar', domain: 'number' }
|
|
412
|
+
: null;
|
|
413
|
+
const value = operation.receiver.representation.kind === 'typed-array'
|
|
414
|
+
? `static_cast<double>(gea::TypedArray<${cppScalarType(operation.receiver.representation.element)}>::readInBounds(${dense.pointer}, ${dense.index}))`
|
|
415
|
+
: dense.text;
|
|
416
|
+
const fast = element === null ? null : presentElementText(ctx, element, operation.result, value);
|
|
417
|
+
return `(${dense.flag} ? ${fast ?? dense.text} : ${general})`;
|
|
418
|
+
};
|
|
419
|
+
export const emitGet = (ctx, lines, operation) => {
|
|
420
|
+
const ownerRead = nativeFieldOwnerReadText(ctx, operation);
|
|
421
|
+
if (ownerRead !== null) {
|
|
422
|
+
lines.push(`${defineValue(ctx, operation.result)} = ${ownerRead};`);
|
|
423
|
+
return;
|
|
424
|
+
}
|
|
425
|
+
// `ctx.propertyReadOrigins` already names this operation for this result --
|
|
426
|
+
// settled in `EmitBodyFacts` before any branch below runs.
|
|
427
|
+
// ECMA-262 6.2.5.5 GetV step 2: a read through `undefined` or `null` calls
|
|
428
|
+
// ToObject on the base, which throws a TypeError for both. Rendered before
|
|
429
|
+
// every other branch because none of them can apply -- a nullish receiver
|
|
430
|
+
// has no namespace, no accessor, no class member and no struct.
|
|
431
|
+
//
|
|
432
|
+
// The site that needed it is UNREACHABLE rather than a program that really
|
|
433
|
+
// reads through `undefined`: a generic narrowed by `instanceof` to a class
|
|
434
|
+
// its own monomorphized copy cannot be gives the narrowed binding an
|
|
435
|
+
// uninhabited intersection, and `derive.ts` answers that with `never`'s
|
|
436
|
+
// storage-free carrier (mongodb's `execute_operation.ts:198`, 28 copies).
|
|
437
|
+
// Refusing to lower it reported an emission blocker for code that cannot
|
|
438
|
+
// run; throwing is what the language says and costs the branch nothing.
|
|
439
|
+
const receiverKind = operation.receiver.representation.kind;
|
|
440
|
+
if (receiverKind === 'undefined' || receiverKind === 'null' || receiverKind === 'void') {
|
|
441
|
+
const nullishName = defineValue(ctx, operation.result);
|
|
442
|
+
lines.push(`${nullishName} = gea::host::throwGetPropertyOfNullish<${cppTypeOf(operation.result.representation)}>("${receiverKind === 'null' ? 'null' : 'undefined'}");`);
|
|
443
|
+
return;
|
|
444
|
+
}
|
|
445
|
+
const namespaceMember = namespaceMemberText(ctx, operation);
|
|
446
|
+
if (namespaceMember !== null) {
|
|
447
|
+
// An empty rendering is a deferred method read or a longer path; both are
|
|
448
|
+
// rendered whole by whatever consumes them.
|
|
449
|
+
if (namespaceMember === '')
|
|
450
|
+
return;
|
|
451
|
+
lines.push(`${defineValue(ctx, operation.result)} = ${namespaceMember};`);
|
|
452
|
+
return;
|
|
453
|
+
}
|
|
454
|
+
const present = unwrapPresentValue(ctx, lines, operation.receiver);
|
|
455
|
+
if (present !== operation.receiver) {
|
|
456
|
+
emitGet(ctx, lines, { ...operation, receiver: present });
|
|
457
|
+
return;
|
|
458
|
+
}
|
|
459
|
+
if (declaredHostMethodRead(ctx, operation))
|
|
460
|
+
return;
|
|
461
|
+
const accessorKey = ctx.staticKeyTexts.get(operation.key.value);
|
|
462
|
+
const getter = accessorKey === undefined ? null : recordAccessorBody(ctx, operation.receiver, accessorKey, 'getter');
|
|
463
|
+
if (getter !== null) {
|
|
464
|
+
const receiverText = operandText(ctx, operation.receiver);
|
|
465
|
+
const environment = accessorEnvironmentArguments(ctx, operation.receiver.representation, accessorKey ?? '', getter, 'getter', receiverText);
|
|
466
|
+
lines.push(`${defineValue(ctx, operation.result)} = ${cppBodyName(getter)}(${[...environment, receiverText].join(', ')});`);
|
|
467
|
+
return;
|
|
468
|
+
}
|
|
469
|
+
const classMember = classMemberText(ctx, operation);
|
|
470
|
+
if (classMember !== null) {
|
|
471
|
+
// A read that publishes no text at all is a dispatch with nothing to
|
|
472
|
+
// materialise -- an abstract method's declaration. The call site renders
|
|
473
|
+
// `receiver->member(args)` from `ctx.virtualCallees`, exactly as a
|
|
474
|
+
// deferred `Array.prototype` read leaves its own access empty.
|
|
475
|
+
if (classMember.text === '')
|
|
476
|
+
return;
|
|
477
|
+
const methodName = defineValue(ctx, operation.result, classMember.spelling ?? undefined);
|
|
478
|
+
lines.push(`${methodName} = ${classMember.text};`);
|
|
479
|
+
return;
|
|
480
|
+
}
|
|
481
|
+
const staticMember = classConstructorStaticMemberText(ctx, operation);
|
|
482
|
+
if (staticMember !== null) {
|
|
483
|
+
const methodName = defineValue(ctx, operation.result);
|
|
484
|
+
lines.push(`${methodName} = ${staticMember};`);
|
|
485
|
+
return;
|
|
486
|
+
}
|
|
487
|
+
const unionMember = taggedUnionGetText(ctx, lines, operation);
|
|
488
|
+
if (unionMember !== null) {
|
|
489
|
+
if (unionMember === '')
|
|
490
|
+
return;
|
|
491
|
+
const name = defineValue(ctx, operation.result);
|
|
492
|
+
lines.push(`${name} = ${unionMember};`);
|
|
493
|
+
return;
|
|
494
|
+
}
|
|
495
|
+
const arrayAccess = denseElementText(ctx, operation) ?? arrayAccessText(ctx, operation.receiver, operation.key, operation.result);
|
|
496
|
+
if (arrayAccess !== null) {
|
|
497
|
+
// An empty rendering is a deferred Array.prototype method read: the
|
|
498
|
+
// access itself produces no C++, and the call site renders the whole
|
|
499
|
+
// fused expression -- the same convention `nativeHandleMember` uses below.
|
|
500
|
+
if (arrayAccess === '')
|
|
501
|
+
return;
|
|
502
|
+
const arrayName = defineValue(ctx, operation.result);
|
|
503
|
+
lines.push(`${arrayName} = ${arrayAccess};`);
|
|
504
|
+
return;
|
|
505
|
+
}
|
|
506
|
+
const typedArrayAccess = typedArrayAccessText(ctx, operation.receiver, operation.key, operation.result);
|
|
507
|
+
if (typedArrayAccess !== null) {
|
|
508
|
+
// An empty rendering is a deferred %TypedArray%.prototype method read --
|
|
509
|
+
// see the identical comment on the array-access branch above.
|
|
510
|
+
if (typedArrayAccess === '')
|
|
511
|
+
return;
|
|
512
|
+
const typedArrayName = defineValue(ctx, operation.result);
|
|
513
|
+
lines.push(`${typedArrayName} = ${typedArrayAccess};`);
|
|
514
|
+
return;
|
|
515
|
+
}
|
|
516
|
+
// The two other members of the ECMA-262 binary family, rendered by
|
|
517
|
+
// `emit-buffers.ts` alongside the typed array's own block-shaped members.
|
|
518
|
+
const arrayBufferAccess = arrayBufferAccessText(ctx, operation.receiver, operation.key, operation.result.id);
|
|
519
|
+
if (arrayBufferAccess !== null) {
|
|
520
|
+
if (arrayBufferAccess === '')
|
|
521
|
+
return;
|
|
522
|
+
const bufferName = defineValue(ctx, operation.result);
|
|
523
|
+
lines.push(`${bufferName} = ${arrayBufferAccess};`);
|
|
524
|
+
return;
|
|
525
|
+
}
|
|
526
|
+
const sharedArrayBufferAccess = sharedArrayBufferAccessText(ctx, operation.receiver, operation.key);
|
|
527
|
+
if (sharedArrayBufferAccess !== null) {
|
|
528
|
+
const bufferName = defineValue(ctx, operation.result);
|
|
529
|
+
lines.push(`${bufferName} = ${sharedArrayBufferAccess};`);
|
|
530
|
+
return;
|
|
531
|
+
}
|
|
532
|
+
const dataViewAccess = dataViewAccessText(ctx, operation.receiver, operation.key, operation.result.id);
|
|
533
|
+
if (dataViewAccess !== null) {
|
|
534
|
+
if (dataViewAccess === '')
|
|
535
|
+
return;
|
|
536
|
+
const viewName = defineValue(ctx, operation.result);
|
|
537
|
+
lines.push(`${viewName} = ${dataViewAccess};`);
|
|
538
|
+
return;
|
|
539
|
+
}
|
|
540
|
+
const stringMember = stringMemberText(ctx, operation.receiver, operation.key, operation.result);
|
|
541
|
+
if (stringMember !== null) {
|
|
542
|
+
const shared = ctx.sharedStringLayouts.get(operation.result.id);
|
|
543
|
+
const sharedMetadata = shared === undefined ? null : `gea_shared_string_layout_${shared.ordinal}`;
|
|
544
|
+
if (shared?.initialize && sharedMetadata !== null) {
|
|
545
|
+
ctx.declarations.push({ type: 'gea::runtime::string::Utf16Metadata', name: sharedMetadata });
|
|
546
|
+
lines.push(`${sharedMetadata} = gea::runtime::string::utf16Metadata(${operandText(ctx, operation.receiver)});`);
|
|
547
|
+
}
|
|
548
|
+
// An empty rendering is a deferred String.prototype method read -- see
|
|
549
|
+
// the identical comment on the array-access branch above.
|
|
550
|
+
if (stringMember === '') {
|
|
551
|
+
const read = ctx.prototypeMethodReads.get(operation.result.id);
|
|
552
|
+
if (read?.member === 'charCodeAt' && ctx.hoistedResults.has(operation.result.id)) {
|
|
553
|
+
// The IR proves this receiver invariant. Keep its metadata in the
|
|
554
|
+
// same preheader, so each character avoids pointer-cache validation.
|
|
555
|
+
const metadata = `gea_string_metadata_${ctx.stringMetadataNames.size}`;
|
|
556
|
+
ctx.declarations.push({ type: 'gea::runtime::string::Utf16Metadata', name: metadata }, { type: 'std::size_t', name: `${metadata}_units` }, { type: 'bool', name: `${metadata}_basic_latin` });
|
|
557
|
+
// Layout is immutable, while the decoder cursor is updated by reads.
|
|
558
|
+
// Separate scalar locals keep cursor aliasing from hiding that invariant
|
|
559
|
+
// from native loop unswitching and range analysis.
|
|
560
|
+
// Each method site needs its own cursor. Sharing one between i and
|
|
561
|
+
// i+offset reads would turn two forward scans into repeated rewinds.
|
|
562
|
+
lines.push(`${metadata} = ${sharedMetadata ?? `gea::runtime::string::utf16Metadata(${prototypeMethodReceiverText(ctx, read.receiver)})`};`);
|
|
563
|
+
lines.push(`${metadata}_units = ${metadata}.units;`);
|
|
564
|
+
lines.push(`${metadata}_basic_latin = ${metadata}.basicLatin;`);
|
|
565
|
+
ctx.stringMetadataNames.set(operation.result.id, metadata);
|
|
566
|
+
}
|
|
567
|
+
return;
|
|
568
|
+
}
|
|
569
|
+
const name = defineValue(ctx, operation.result);
|
|
570
|
+
lines.push(`${name} = ${sharedMetadata === null ? stringMember : `static_cast<double>(${sharedMetadata}.units)`};`);
|
|
571
|
+
return;
|
|
572
|
+
}
|
|
573
|
+
const symbolMember = symbolMemberText(ctx, operation.receiver, operation.key, operation.result);
|
|
574
|
+
if (symbolMember !== null) {
|
|
575
|
+
const name = defineValue(ctx, operation.result);
|
|
576
|
+
lines.push(`${name} = ${symbolMember};`);
|
|
577
|
+
return;
|
|
578
|
+
}
|
|
579
|
+
const scalarMember = scalarMemberText(ctx, operation.receiver, operation.key, operation.result.id);
|
|
580
|
+
if (scalarMember !== null) {
|
|
581
|
+
// An empty rendering is a deferred Number.prototype method read -- see
|
|
582
|
+
// the identical comment on the array-access branch above.
|
|
583
|
+
if (scalarMember === '')
|
|
584
|
+
return;
|
|
585
|
+
const name = defineValue(ctx, operation.result);
|
|
586
|
+
lines.push(`${name} = ${scalarMember};`);
|
|
587
|
+
return;
|
|
588
|
+
}
|
|
589
|
+
// Asked ahead of every remaining branch that could claim a `native-record-ref`
|
|
590
|
+
// receiver -- the index-sidecar read below would otherwise take `m[0]` (a
|
|
591
|
+
// match result's layout really does carry a number index signature) and the
|
|
592
|
+
// struct-member fallthrough at the end would take `re.test` and emit
|
|
593
|
+
// `re->test`, which is a clang error naming a member instead of a refusal
|
|
594
|
+
// naming the method.
|
|
595
|
+
const regexpMember = regexpMemberText(ctx, operation.receiver, operation.key, operation.result.id, operation.result.representation, (fieldName, storage) => narrowedFieldReadText(ctx, operation, fieldName, storage)) ?? stringObjectMemberText(ctx, operation.receiver, operation.key, operation.result.representation);
|
|
596
|
+
if (regexpMember !== null) {
|
|
597
|
+
// An empty rendering is a deferred RegExp.prototype method read -- see
|
|
598
|
+
// the identical comment on the array-access branch above.
|
|
599
|
+
if (regexpMember === '')
|
|
600
|
+
return;
|
|
601
|
+
const name = defineValue(ctx, operation.result);
|
|
602
|
+
lines.push(`${name} = ${regexpMember};`);
|
|
603
|
+
return;
|
|
604
|
+
}
|
|
605
|
+
const promiseMember = promiseMemberText(ctx, operation.receiver, operation.key, operation.result.id);
|
|
606
|
+
if (promiseMember !== null) {
|
|
607
|
+
// An empty rendering is a deferred Promise.prototype method read -- see
|
|
608
|
+
// the identical comment on the array-access branch above.
|
|
609
|
+
if (promiseMember === '')
|
|
610
|
+
return;
|
|
611
|
+
const name = defineValue(ctx, operation.result);
|
|
612
|
+
lines.push(`${name} = ${promiseMember};`);
|
|
613
|
+
return;
|
|
614
|
+
}
|
|
615
|
+
const iteratorMember = iteratorMemberText(ctx, operation.receiver, operation.key, operation.result.id);
|
|
616
|
+
if (iteratorMember !== null) {
|
|
617
|
+
// An empty rendering is a deferred %GeneratorPrototype% method read --
|
|
618
|
+
// see the identical comment on the array-access branch above.
|
|
619
|
+
if (iteratorMember === '')
|
|
620
|
+
return;
|
|
621
|
+
const name = defineValue(ctx, operation.result);
|
|
622
|
+
lines.push(`${name} = ${iteratorMember};`);
|
|
623
|
+
return;
|
|
624
|
+
}
|
|
625
|
+
const collectionMember = keyedCollectionMemberText(ctx, operation.receiver, operation.key, operation.result.id);
|
|
626
|
+
if (collectionMember !== null) {
|
|
627
|
+
// An empty rendering is a deferred Map/Set prototype method read -- see
|
|
628
|
+
// the identical comment on the array-access branch above.
|
|
629
|
+
if (collectionMember === '')
|
|
630
|
+
return;
|
|
631
|
+
const name = defineValue(ctx, operation.result);
|
|
632
|
+
lines.push(`${name} = ${collectionMember};`);
|
|
633
|
+
return;
|
|
634
|
+
}
|
|
635
|
+
// A Date's members are all `Date.prototype` methods, so every claimed one
|
|
636
|
+
// defers and fuses with its call exactly as `substring` does off a string.
|
|
637
|
+
// Asked before the `native-record-ref` field fallback at the bottom of this
|
|
638
|
+
// function, which would otherwise spell `d->gea_field_getFullYear` for a
|
|
639
|
+
// struct that declares no such member.
|
|
640
|
+
const dateMember = dateMemberText(ctx, operation.receiver, operation.key, operation.result.id);
|
|
641
|
+
if (dateMember !== null) {
|
|
642
|
+
// An empty rendering is a deferred Date.prototype method read -- see the
|
|
643
|
+
// identical comment on the array-access branch above.
|
|
644
|
+
if (dateMember === '')
|
|
645
|
+
return;
|
|
646
|
+
const name = defineValue(ctx, operation.result);
|
|
647
|
+
lines.push(`${name} = ${dateMember};`);
|
|
648
|
+
return;
|
|
649
|
+
}
|
|
650
|
+
// An intrinsic Error's `toString`, asked before the `native-record-ref`
|
|
651
|
+
// field fallback below -- which would spell `e->gea_field_toString` for a
|
|
652
|
+
// layout that declares no such member -- and before the dynamic sidecar,
|
|
653
|
+
// whose Array.prototype guard used to claim the key and refuse under the
|
|
654
|
+
// wrong prototype's name.
|
|
655
|
+
const errorMember = nativeErrorMemberText(ctx, operation.receiver, operation.key, operation.result.id);
|
|
656
|
+
if (errorMember !== null) {
|
|
657
|
+
// An empty rendering is a deferred Error.prototype method read -- see the
|
|
658
|
+
// identical comment on the array-access branch above.
|
|
659
|
+
if (errorMember === '')
|
|
660
|
+
return;
|
|
661
|
+
const name = defineValue(ctx, operation.result);
|
|
662
|
+
lines.push(`${name} = ${errorMember};`);
|
|
663
|
+
return;
|
|
664
|
+
}
|
|
665
|
+
const nativeHostMember = nativeHostMemberText(ctx, operation.receiver, operation.key, operation.result);
|
|
666
|
+
if (nativeHostMember !== null) {
|
|
667
|
+
// An empty rendering is a deferred host method: the access itself produces
|
|
668
|
+
// no C++, and the call site renders the host's own spelling.
|
|
669
|
+
if (nativeHostMember === '')
|
|
670
|
+
return;
|
|
671
|
+
if (ctx.numericCallOnly.has(operation.result.id)) {
|
|
672
|
+
defineValueAlias(ctx, operation.result, nativeHostMember);
|
|
673
|
+
return;
|
|
674
|
+
}
|
|
675
|
+
const name = defineValue(ctx, operation.result);
|
|
676
|
+
// The host's own carrier for the value it hands back is not always the
|
|
677
|
+
// program's -- see `hostResultText`; a member declared `number[]` is a
|
|
678
|
+
// `std::vector<double>` on the far side of the bridge.
|
|
679
|
+
lines.push(`${name} = ${hostResultText(operation.result.representation, nativeHostMember)};`);
|
|
680
|
+
return;
|
|
681
|
+
}
|
|
682
|
+
// Before the table read, which would claim the key -- see that function.
|
|
683
|
+
if (dictionaryPrototypeMemberRead(ctx, operation))
|
|
684
|
+
return;
|
|
685
|
+
// `hasOwnProperty`/`propertyIsEnumerable` off a record/class-ref/generated
|
|
686
|
+
// `native-record-ref`, asked before the struct-field and sidecar fallbacks
|
|
687
|
+
// below would otherwise route them into `nativeSidecarGetText`'s boxed
|
|
688
|
+
// "unknown key" answer -- see `object-protocol.ts`'s own comment.
|
|
689
|
+
if (objectShapePrototypeMemberRead(ctx, operation))
|
|
690
|
+
return;
|
|
691
|
+
const dictionaryRead = dictionaryReadText(ctx, operation);
|
|
692
|
+
if (dictionaryRead !== null) {
|
|
693
|
+
const dictionaryName = defineValue(ctx, operation.result);
|
|
694
|
+
lines.push(`${dictionaryName} = ${dictionaryRead};`);
|
|
695
|
+
return;
|
|
696
|
+
}
|
|
697
|
+
const positionalRecordLength = positionalRecordLengthText(ctx, operation);
|
|
698
|
+
if (positionalRecordLength !== null) {
|
|
699
|
+
lines.push(`${defineValue(ctx, operation.result)} = ${positionalRecordLength};`);
|
|
700
|
+
return;
|
|
701
|
+
}
|
|
702
|
+
const recordWithIndexField = recordWithIndexFieldText(ctx, operation.receiver, operation.key);
|
|
703
|
+
if (recordWithIndexField !== null) {
|
|
704
|
+
const name = defineValue(ctx, operation.result);
|
|
705
|
+
const fieldName = staticKeyTextOf(ctx, operation.key, 'a "get" operation');
|
|
706
|
+
lines.push(`${name} = ${fixedFieldReadText(ctx, operation, fieldName)};`);
|
|
707
|
+
return;
|
|
708
|
+
}
|
|
709
|
+
const recordIndexSidecarRead = recordIndexSidecarReadText(ctx, operation);
|
|
710
|
+
if (recordIndexSidecarRead !== null) {
|
|
711
|
+
const name = defineValue(ctx, operation.result);
|
|
712
|
+
lines.push(`${name} = ${recordIndexSidecarRead};`);
|
|
713
|
+
return;
|
|
714
|
+
}
|
|
715
|
+
// `hasOwnProperty` off a receiver the program itself declared dynamic --
|
|
716
|
+
// asked before the generic dynamic property read below, which would
|
|
717
|
+
// otherwise read "hasOwnProperty" THROUGH the receiver's real
|
|
718
|
+
// `[[Prototype]]` chain and find nothing there. See `object-protocol.ts`'s
|
|
719
|
+
// own comment for why that chain can never answer it.
|
|
720
|
+
if (dynamicObjectPrototypeMemberRead(ctx, operation))
|
|
721
|
+
return;
|
|
722
|
+
// A receiver the program itself declared `any`/`unknown` carries its
|
|
723
|
+
// properties in the `gea::DynamicObject` its box owns. Asked after every
|
|
724
|
+
// native branch above, because a native receiver never reaches here at all
|
|
725
|
+
// and this arm must not shadow one.
|
|
726
|
+
const dynamicRead = dynamicGetText(ctx, operation);
|
|
727
|
+
if (dynamicRead !== null) {
|
|
728
|
+
lines.push(`${defineValue(ctx, operation.result)} = ${dynamicRead};`);
|
|
729
|
+
return;
|
|
730
|
+
}
|
|
731
|
+
// `add.call(x, 3, 4)` reads `Function.prototype.call` off a callable
|
|
732
|
+
// value, and this read renders nothing: `ir/lower-invocation.ts`'s
|
|
733
|
+
// `deferredFunctionCallCalleeOf` rewrites the CALL that follows to invoke
|
|
734
|
+
// the underlying receiver directly, with this result never referenced.
|
|
735
|
+
// `ir/lower.ts` still lowers every semantic operation once regardless of
|
|
736
|
+
// whether anything downstream reads its result, so this GET reaches emission
|
|
737
|
+
// anyway -- there is no C++ object anywhere that implements
|
|
738
|
+
// `Function.prototype.call` itself for a generic struct/handle fallback
|
|
739
|
+
// below to spell a member access against. Gated on the exact same receiver
|
|
740
|
+
// kind and key preflight certified. A callable constructor takes this same
|
|
741
|
+
// path for its [[Call]] half; neither path materializes a fake `.call` or
|
|
742
|
+
// `.apply` member object.
|
|
743
|
+
// Asked of the one authority rather than spelled a fifth time. This copy had
|
|
744
|
+
// drifted: it omitted `function-value-family`, so a cell holding one of a
|
|
745
|
+
// closed set of named functions missed the `.call`/`.apply`/`.bind` deferral
|
|
746
|
+
// and fell through to the sidecar read, which renders a `callableDynamicGet`
|
|
747
|
+
// for a value `projection/callee.ts` and the manifest both state renders
|
|
748
|
+
// nothing.
|
|
749
|
+
const callable = isNativeCallableCarrier(operation.receiver.representation.kind);
|
|
750
|
+
if (callable && functionSourceReadClaimOf(ctx.staticKeyTexts, operation) === 'direct') {
|
|
751
|
+
// The builtin's receiver is fixed before its arguments run, so the snapshot
|
|
752
|
+
// has to be taken HERE: an argument may replace the binding or field this
|
|
753
|
+
// function was read from. That position is the only thing this site still
|
|
754
|
+
// owns -- the claim, the snapshot's name and the text the following call
|
|
755
|
+
// reads are all settled by `function-source-reads.ts`.
|
|
756
|
+
const name = ctx.functionSourceSnapshotNames.get(operation.result.id);
|
|
757
|
+
if (name === undefined) {
|
|
758
|
+
throw createCppEmitBlockedError('call-abi:function-source', 'a settled function-source read reached its render with no snapshot name');
|
|
759
|
+
}
|
|
760
|
+
ctx.declarations.push({ name, type: cppTypeOf(operation.receiver.representation) });
|
|
761
|
+
lines.push(`${name} = ${operandText(ctx, operation.receiver)};`);
|
|
762
|
+
return;
|
|
763
|
+
}
|
|
764
|
+
// The identical deferral covers `.apply` (`Math.max.apply(null, [1, 5, 3])`,
|
|
765
|
+
// `deferredFunctionApplyCalleeOf`) and the direct `.bind` form (lowered to
|
|
766
|
+
// `bind-callable`): none of the three has a standalone native object to
|
|
767
|
+
// materialize, so a `get` left unread after lowering has nothing left to
|
|
768
|
+
// print. `deferredCallableBuiltinReadClaimOf` (`property-read-claims.ts`) is
|
|
769
|
+
// the one function for "which of the three builtins is this, if any" --
|
|
770
|
+
// this rung spells nothing but the fact that the claim matched.
|
|
771
|
+
if (deferredCallableBuiltinReadClaimOf(ctx.staticKeyTexts, ctx.unreadValues, operation) !== null) {
|
|
772
|
+
return;
|
|
773
|
+
}
|
|
774
|
+
const callableRead = callableSidecarGetText(ctx, operation);
|
|
775
|
+
if (callableRead !== null) {
|
|
776
|
+
// An empty rendering is a deferred Object.prototype method read
|
|
777
|
+
// (`callable-shape`): the call site renders it.
|
|
778
|
+
if (callableRead !== '')
|
|
779
|
+
lines.push(`${defineValue(ctx, operation.result)} = ${callableRead};`);
|
|
780
|
+
return;
|
|
781
|
+
}
|
|
782
|
+
// A statically typed receiver reached through a key only known at runtime.
|
|
783
|
+
// The receiver stays native -- this is the sidecar, not a widening -- and it
|
|
784
|
+
// is asked after every branch that resolves a callable's own fixed key, so a
|
|
785
|
+
// Function property never falls into an unrelated native-record path.
|
|
786
|
+
const sidecarRead = nativeSidecarGetText(ctx, operation);
|
|
787
|
+
if (sidecarRead !== null) {
|
|
788
|
+
lines.push(`${defineValue(ctx, operation.result, sidecarRead.spelling ?? undefined)} = ${sidecarRead.text};`);
|
|
789
|
+
return;
|
|
790
|
+
}
|
|
791
|
+
const fieldName = staticKeyTextOf(ctx, operation.key, 'a "get" operation');
|
|
792
|
+
const name = defineValue(ctx, operation.result);
|
|
793
|
+
// A qualifying arrow-function class field starts every instance empty
|
|
794
|
+
// (`class-layout.ts`'s `censusLazyArrowFields`) rather than built in the
|
|
795
|
+
// constructor. This `get` is the one read every consumer of such a field
|
|
796
|
+
// goes through -- a call's callee is read exactly like any other value, see
|
|
797
|
+
// `class-layout.ts`'s own comment -- so it is the one place that
|
|
798
|
+
// materializes it.
|
|
799
|
+
// An inherited field's plan is published under the DECLARING class, not
|
|
800
|
+
// every receiver a subclass instance may be typed as -- see
|
|
801
|
+
// `lazyArrowFieldGetPlanOf`'s own comment, and `fieldDeclaringStructOf`'s,
|
|
802
|
+
// for why that lookup walks to the owner rather than the receiver's own
|
|
803
|
+
// declaration.
|
|
804
|
+
const lazyField = lazyArrowFieldGetPlanOf(ctx, operation);
|
|
805
|
+
if (lazyField !== null) {
|
|
806
|
+
// A result `emit-callable.ts`'s `emitLazyArrowFieldCall` has already
|
|
807
|
+
// proved is read by nothing but its own call fusion (`class-layout.ts`'s
|
|
808
|
+
// `lazyCalleeReadsOf`) needs no `CallableObject` built at all: the fusion
|
|
809
|
+
// reads this copy's own `invoke` guard itself, at the point the ORIGINAL
|
|
810
|
+
// source read the field -- before any argument of that call can reassign
|
|
811
|
+
// it -- and either calls the census arrow's body directly or the copy's
|
|
812
|
+
// own `.call()`. Materializing here would build exactly the per-call heap
|
|
813
|
+
// environment this whole feature exists to avoid, for a value the fusion
|
|
814
|
+
// never even looks at as a completed `CallableObject`.
|
|
815
|
+
const rendering = ctx.lazyCalleeReads.has(operation.result.id)
|
|
816
|
+
? lazyFieldSnapshotReadText(ctx, operation, fieldName)
|
|
817
|
+
: lazyMaterializedFieldReadText(ctx, operation, fieldName, lazyField.plan);
|
|
818
|
+
lines.push(`${name} = ${rendering};`);
|
|
819
|
+
return;
|
|
820
|
+
}
|
|
821
|
+
// The property key names the field; `cppRecordFieldName` (types.ts) names
|
|
822
|
+
// the C++ member, and only that function may -- `renderStructDefinition`
|
|
823
|
+
// declared the member through it, so spelling the access from the raw key
|
|
824
|
+
// here would be a second opinion that agrees only for keys that happen to be
|
|
825
|
+
// identifiers already.
|
|
826
|
+
lines.push(`${name} = ${fixedFieldReadText(ctx, operation, fieldName)};`);
|
|
827
|
+
};
|
|
828
|
+
/**
|
|
829
|
+
* A qualifying arrow-function field's read: materialize it (call the SAME
|
|
830
|
+
* initializer thunk `cppFieldInitializerStatements` would have called eagerly)
|
|
831
|
+
* the first time anything reads it, then read the now-populated storage.
|
|
832
|
+
*
|
|
833
|
+
* The receiver is bound once, not repeated: `fixedFieldReadText`'s own comment
|
|
834
|
+
* documents why an SSA operand may render as a deferred conversion expression
|
|
835
|
+
* that must not be evaluated twice, and this reads it three times over (the
|
|
836
|
+
* guard, the store, and the return) if it did not bind a local first.
|
|
837
|
+
*
|
|
838
|
+
* Reassignment needs no separate branch here: `set`/`define-own-property`
|
|
839
|
+
* write the field directly, unchanged by this feature, and a reassigned
|
|
840
|
+
* field's `invoke` is no longer `nullptr` -- so a later read of THIS function
|
|
841
|
+
* sees the guard already false and returns whatever was stored, exactly as
|
|
842
|
+
* `c.json === c.json` and a property written onto the callable both require.
|
|
843
|
+
*/
|
|
844
|
+
const lazyMaterializedFieldReadText = (ctx, operation, fieldName, plan) => {
|
|
845
|
+
const accessor = memberAccessOperator(recordOwnershipOf(operation.receiver, 'a "get" operation'));
|
|
846
|
+
const receiver = operandText(ctx, operation.receiver);
|
|
847
|
+
return lazyMaterializedFieldText(receiver, accessor, fieldName, plan);
|
|
848
|
+
};
|
|
849
|
+
/**
|
|
850
|
+
* A RAW copy of a lazy arrow field's storage -- no materialization, no guard,
|
|
851
|
+
* just the `CallableObject` as it stands. Sound only where `ctx.lazyCalleeReads`
|
|
852
|
+
* has already proved the copy's one reader is `emit-callable.ts`'s
|
|
853
|
+
* `emitLazyArrowFieldCall`, which reads the copy's own `invoke` pointer to
|
|
854
|
+
* decide how to call it: an unmaterialized copy (`invoke == nullptr`) is the
|
|
855
|
+
* census arrow itself, a trivial struct copy with no allocation, and a
|
|
856
|
+
* materialized one is whatever the field was reassigned to.
|
|
857
|
+
*/
|
|
858
|
+
const lazyFieldSnapshotReadText = (ctx, operation, fieldName) => {
|
|
859
|
+
const accessor = memberAccessOperator(recordOwnershipOf(operation.receiver, 'a "get" operation'));
|
|
860
|
+
const receiver = operandText(ctx, operation.receiver);
|
|
861
|
+
return `${receiver}${accessor}${cppRecordFieldName(fieldName)}`;
|
|
862
|
+
};
|
|
863
|
+
/** A presence check and its payload load must evaluate the receiver only once. */
|
|
864
|
+
const fixedFieldReadText = (ctx, operation, fieldName) => {
|
|
865
|
+
const accessor = memberAccessOperator(recordOwnershipOf(operation.receiver, 'a "get" operation'));
|
|
866
|
+
const receiver = operandText(ctx, operation.receiver);
|
|
867
|
+
const field = cppRecordFieldName(fieldName);
|
|
868
|
+
const presence = fixedFieldPresenceText(ctx, operation.receiver, fieldName);
|
|
869
|
+
if (presence !== null && cppUndefinedIn(operation.result.representation) !== null) {
|
|
870
|
+
// An SSA operand may render as a deferred conversion expression. Repeating
|
|
871
|
+
// it in both branches duplicates that conversion (including checked native
|
|
872
|
+
// unboxing), despite the IR containing only one receiver evaluation.
|
|
873
|
+
const read = narrowedFieldReadText(ctx, operation, fieldName, `gea_read_receiver${accessor}${field}`, `gea_read_receiver${accessor}${cppRecordFieldPresenceName(fieldName)}`);
|
|
874
|
+
return `([&]() { const auto& gea_read_receiver = ${receiver}; return ${read}; })()`;
|
|
875
|
+
}
|
|
876
|
+
return narrowedFieldReadText(ctx, operation, fieldName, `${receiver}${accessor}${field}`, presence);
|
|
877
|
+
};
|
|
878
|
+
/** The independent own-property bit for every fixed field on generated storage. */
|
|
879
|
+
const fixedFieldPresenceText = (ctx, receiver, fieldName) => {
|
|
880
|
+
const representation = receiver.representation;
|
|
881
|
+
if (representation.kind === 'native-record-ref' && representation.native !== null)
|
|
882
|
+
return null;
|
|
883
|
+
const field = declaredRecordFieldOf(ctx.deriver, representation, fieldName, ctx.classes);
|
|
884
|
+
if (!field)
|
|
885
|
+
return null;
|
|
886
|
+
if (representation.kind !== 'record' &&
|
|
887
|
+
representation.kind !== 'record-with-index' &&
|
|
888
|
+
representation.kind !== 'native-record-ref' &&
|
|
889
|
+
representation.kind !== 'class-ref')
|
|
890
|
+
return null;
|
|
891
|
+
return `${operandText(ctx, receiver)}${memberAccessOperator(representation.ownership)}${cppRecordFieldPresenceName(fieldName)}`;
|
|
892
|
+
};
|
|
893
|
+
/**
|
|
894
|
+
* A field read whose published carrier is NARROWER than the field's storage.
|
|
895
|
+
*
|
|
896
|
+
* `interface Cell { v: number | null }` stores `Optional<double>`, and after
|
|
897
|
+
* `if (c.v !== null)` -- or after `c.v ??= 4` -- the checker types the very
|
|
898
|
+
* same access `number`. Both answers are true and they are about different
|
|
899
|
+
* things: one is what the struct member holds, the other is what this read
|
|
900
|
+
* yields on this branch. A reinterpretation between them does not exist, so
|
|
901
|
+
* emitting the bare member load produced `double = gea::Optional<double>` --
|
|
902
|
+
* a certified program clang rejects. It is the two-carrier narrowed read,
|
|
903
|
+
* on a record FIELD rather than on a cell.
|
|
904
|
+
*
|
|
905
|
+
* The conversion itself is not spelled here: `narrowedLoadText`
|
|
906
|
+
* (emit-narrowing.ts) is the one authority on what a read of a wider carrier
|
|
907
|
+
* at a narrower one looks like -- a dereference for an optional the branch
|
|
908
|
+
* proved present, an arm load for a tagged union, and the combination for
|
|
909
|
+
* both. It is the same function a narrowed CELL read goes through, which is
|
|
910
|
+
* the point: a field and a cell disagreeing about what narrowing means is how
|
|
911
|
+
* the original defect got in. A disagreement it declines to convert is a
|
|
912
|
+
* defect upstream, not a spelling this may invent, so that refuses by name.
|
|
913
|
+
*/
|
|
914
|
+
const narrowedFieldReadText = (ctx, operation, fieldName, storage, presence = null) => {
|
|
915
|
+
const declared = declaredFieldRepresentation(ctx, operation.receiver, fieldName);
|
|
916
|
+
if (declared === null)
|
|
917
|
+
return storage;
|
|
918
|
+
const published = operation.result.representation;
|
|
919
|
+
const present = (() => {
|
|
920
|
+
if (representationKey(declared) === representationKey(published))
|
|
921
|
+
return storage;
|
|
922
|
+
const classFamily = classFamilyLoadText(ctx, declared, published, storage);
|
|
923
|
+
if (classFamily !== null)
|
|
924
|
+
return classFamily;
|
|
925
|
+
const narrowed = narrowedLoadText(declared, published, storage);
|
|
926
|
+
if (narrowed !== null)
|
|
927
|
+
return narrowed;
|
|
928
|
+
return alignedValueText(ctx, 'emit-properties.ts:864', declared, published, storage);
|
|
929
|
+
})();
|
|
930
|
+
if (present !== null) {
|
|
931
|
+
const absent = presence === null ? null : cppUndefinedIn(published);
|
|
932
|
+
return absent === null ? present : `(${presence} ? ${present} : ${absent})`;
|
|
933
|
+
}
|
|
934
|
+
// Asked second, and only once narrowing has declined: a read whose published
|
|
935
|
+
// carrier is not NARROWER than the storage but merely a different spelling of
|
|
936
|
+
// it is a CONVERSION, and `convertedValueText` is this backend's one authority
|
|
937
|
+
// on those. A binding write already asks both -- `emit-bindings.ts` calls
|
|
938
|
+
// exactly this function for the store direction -- and a field read asking
|
|
939
|
+
// only one of the two is how a field holding `(c: Context) => Response` came
|
|
940
|
+
// to refuse against a read publishing `(c: Context) => Response |
|
|
941
|
+
// Promise<Response>`: an implicit converting constructor `gea::CallableObject`
|
|
942
|
+
// declares, licensed for a cell and refused for a struct member, over the
|
|
943
|
+
// identical pair of carriers.
|
|
944
|
+
//
|
|
945
|
+
// Still fail-closed: `convertedValueText` answers `null` for a pair it has no
|
|
946
|
+
// recipe for, and that is the refusal below rather than a bare member load.
|
|
947
|
+
throw createCppEmitBlockedError(`conversion:${representationKey(declared)}->${representationKey(published)}`, `field "${fieldName}" is stored as "${representationKey(declared)}" and this read publishes ` +
|
|
948
|
+
`"${representationKey(published)}"; no narrowing between those is licensed; ` +
|
|
949
|
+
carrierDifference(declared, published));
|
|
950
|
+
};
|
|
951
|
+
/**
|
|
952
|
+
* Whether a `define-own-property`'s own descriptor is the one every branch
|
|
953
|
+
* below already assumes -- a fresh, ordinary, writable/enumerable/
|
|
954
|
+
* configurable data property, ECMA-262 10.1.9.2 step 1.d.iii's default. A
|
|
955
|
+
* plain `set` carries no descriptor at all and always passes.
|
|
956
|
+
*
|
|
957
|
+
* `set` and `define-own-property` share every field-storing branch below,
|
|
958
|
+
* which is only sound because none of the C++ this file writes into -- a
|
|
959
|
+
* struct member, a dictionary entry, a dynamic object's own table -- can
|
|
960
|
+
* express anything BUT the default triple: a struct member has no
|
|
961
|
+
* enumerability flag, a `gea::Dictionary` entry has no writability flag.
|
|
962
|
+
* Collapsing a NON-default descriptor into the same store anyway would
|
|
963
|
+
* silently drop the very thing the program asked for -- installing a
|
|
964
|
+
* `configurable: false` field is not "install the field," it is a different,
|
|
965
|
+
* unrenderable operation -- so a defined property whose attributes are not
|
|
966
|
+
* this exact triple refuses by name here, once, rather than every branch
|
|
967
|
+
* below independently forgetting to ask.
|
|
968
|
+
*/
|
|
969
|
+
const isDefaultDataDescriptor = (operation) => operation.kind !== 'define-own-property' ||
|
|
970
|
+
(operation.attributes.writable && operation.attributes.enumerable && operation.attributes.configurable);
|
|
971
|
+
/**
|
|
972
|
+
* The emitted setter for an accessor-backed class member, or `null` when the
|
|
973
|
+
* key is an ordinary field (or the receiver is not a class instance at all).
|
|
974
|
+
*
|
|
975
|
+
* A member that the layout says is an accessor and whose setter is absent is
|
|
976
|
+
* refused rather than written as a field: `get`-only means the language itself
|
|
977
|
+
* has nowhere to put the value, and a struct member with that name does not
|
|
978
|
+
* exist to write into either.
|
|
979
|
+
*/
|
|
980
|
+
const classAccessorSetter = (ctx, receiver, key) => {
|
|
981
|
+
const representation = receiver.representation;
|
|
982
|
+
if (representation.kind !== 'class-ref')
|
|
983
|
+
return null;
|
|
984
|
+
// [[Set]] resolves the same inherited member as [[Get]]. Looking only at
|
|
985
|
+
// this class's own accessors mistakes a base setter for instance storage.
|
|
986
|
+
const site = classMemberOf(ctx.classes, representation.declaration, key);
|
|
987
|
+
if (site?.kind !== 'accessor')
|
|
988
|
+
return null;
|
|
989
|
+
const accessor = site.accessor;
|
|
990
|
+
if (!accessor.setter) {
|
|
991
|
+
throw createCppEmitBlockedError('property-access:class-ref:set:false', `accessor "${key}" of class ${representation.declaration} declares only a getter, so writing it has no body to call`);
|
|
992
|
+
}
|
|
993
|
+
return accessor.setter;
|
|
994
|
+
};
|
|
995
|
+
/**
|
|
996
|
+
* The representation a receiver's own declared shape says one field holds.
|
|
997
|
+
*
|
|
998
|
+
* A thin `IrOperand`-shaped wrapper over `records.ts`'s
|
|
999
|
+
* `declaredFieldRepresentationOf` -- the one authority both this file's field
|
|
1000
|
+
* STORE and `emit-allocation.ts`'s field INITIALIZER ask, so the two never
|
|
1001
|
+
* independently drift on what a field's declared carrier is. See that
|
|
1002
|
+
* function's own comment (and citations.md finding 1) for why a second table
|
|
1003
|
+
* here would be the wrong shape for this question.
|
|
1004
|
+
*/
|
|
1005
|
+
const declaredFieldRepresentation = (ctx, receiver, fieldName) => declaredFieldRepresentationOf(ctx.deriver, receiver.representation, fieldName, ctx.classes);
|
|
1006
|
+
/**
|
|
1007
|
+
* What a reactive RECORD-field read obliges a consumer to do.
|
|
1008
|
+
*
|
|
1009
|
+
* The record half of `reactiveClassFieldClaim`, kept beside the record layout
|
|
1010
|
+
* for the same reason that one is kept beside the class layout: a class
|
|
1011
|
+
* resolves the DECLARING class along its inheritance chain first, a record has
|
|
1012
|
+
* no chain, so this is the whole of it. Both are asked by the one walk that
|
|
1013
|
+
* settles the channel before the body renders.
|
|
1014
|
+
*
|
|
1015
|
+
* A class-ref receiver is excluded rather than merely losing a race: the class
|
|
1016
|
+
* layout is the authority for a class's fields, and `celled` is derived from
|
|
1017
|
+
* what JSX binds, which is a different question with a different answer.
|
|
1018
|
+
*/
|
|
1019
|
+
export const reactiveRecordFieldClaim = (ctx, operation) => {
|
|
1020
|
+
const receiver = operation.receiver.representation;
|
|
1021
|
+
if (receiver.kind === 'class-ref')
|
|
1022
|
+
return null;
|
|
1023
|
+
const struct = structNameOfReceiver(receiver);
|
|
1024
|
+
if (struct === null)
|
|
1025
|
+
return null;
|
|
1026
|
+
const key = ctx.staticKeyTexts.get(operation.key.value);
|
|
1027
|
+
if (key === undefined)
|
|
1028
|
+
return null;
|
|
1029
|
+
if (ctx.hosts.reactive.celled.get(struct)?.has(key) !== true)
|
|
1030
|
+
return null;
|
|
1031
|
+
return { struct, key, receiver: operation.receiver };
|
|
1032
|
+
};
|
|
1033
|
+
/**
|
|
1034
|
+
* A store, plus the revision tick a store into reactive array state owes.
|
|
1035
|
+
*
|
|
1036
|
+
* Wrapped rather than pushed inside `emitFieldStoreLines`, which returns from a
|
|
1037
|
+
* dozen places: a tick that some branches emit and others forget is a list that
|
|
1038
|
+
* re-renders for some writes and not others, which is worse than one that never
|
|
1039
|
+
* re-renders because the failure depends on which member you wrote.
|
|
1040
|
+
*/
|
|
1041
|
+
export const emitFieldStore = (ctx, lines, operation, label) => {
|
|
1042
|
+
emitFieldStoreLines(ctx, lines, operation, label);
|
|
1043
|
+
// REPLACING a revision-backed field, before the store-INTO-it rule below.
|
|
1044
|
+
// `this.pageAnchors = builder.anchors` is the largest change such a field can
|
|
1045
|
+
// undergo -- every element at once -- and it was the one change nothing
|
|
1046
|
+
// ticked: the revision cell is only reached through `reactiveOrigins`, which
|
|
1047
|
+
// is carried by a value read OUT of the array, and a whole-field assignment
|
|
1048
|
+
// reads nothing out of it. So the e-reader published a finished fourteen-
|
|
1049
|
+
// hundred page pagination over the one-page preview the reader had entered
|
|
1050
|
+
// on, and every slot bound to `pageAnchors__rev` kept rendering the preview.
|
|
1051
|
+
//
|
|
1052
|
+
// Asked of `revisions` -- the struct renderer's own record of which fields
|
|
1053
|
+
// GOT a revision cell -- so this cannot tick a companion that was never
|
|
1054
|
+
// rendered, and asked of the DECLARING struct for the reason the skip below
|
|
1055
|
+
// states.
|
|
1056
|
+
const storedKey = ctx.staticKeyTexts.get(operation.key.value);
|
|
1057
|
+
const storedStruct = storedKey === undefined ? null : fieldDeclaringStructOf(ctx.classes, operation.receiver.representation, storedKey);
|
|
1058
|
+
if (storedStruct !== null && storedKey !== undefined && ctx.hosts.reactive.revisions.get(storedStruct)?.has(storedKey) === true) {
|
|
1059
|
+
lines.push(`${reactiveRevisionText(ctx, { struct: storedStruct, key: storedKey, receiver: operation.receiver })}.notify();`);
|
|
1060
|
+
}
|
|
1061
|
+
// The receiver is either the array itself (`this.cells.length = 0`, an
|
|
1062
|
+
// element store) or something read out of it; both carry the same origin,
|
|
1063
|
+
// which is the point of carrying it on the value.
|
|
1064
|
+
const origin = ctx.reactiveOrigins.get(operation.receiver.value);
|
|
1065
|
+
if (origin === undefined)
|
|
1066
|
+
return;
|
|
1067
|
+
// ...unless the member being written is itself a cell. `cell.filled = 1`
|
|
1068
|
+
// writes a `Signal<double>`, whose `operator=` notifies exactly the props
|
|
1069
|
+
// that read it -- one row's, not the whole list's. Ticking the array's
|
|
1070
|
+
// revision as well would rebuild every row of the list for a change that
|
|
1071
|
+
// touched one field of one element: the same answer, arrived at by throwing
|
|
1072
|
+
// the list away and building it again.
|
|
1073
|
+
//
|
|
1074
|
+
// What still ticks the revision is what the element cells genuinely cannot
|
|
1075
|
+
// see: `push`, `length = 0`, `cells[i] = other` -- changes to which elements
|
|
1076
|
+
// the list HAS, rather than to what one of them holds.
|
|
1077
|
+
const key = ctx.staticKeyTexts.get(operation.key.value);
|
|
1078
|
+
// Asked of `fieldDeclaringStructOf`, not of the receiver's own class:
|
|
1079
|
+
// `celled` is keyed by the struct that DECLARES the field, so an inherited
|
|
1080
|
+
// celled field reached through a subclass-typed receiver used to find
|
|
1081
|
+
// nothing here, fail this skip, and tick the whole array's revision for a
|
|
1082
|
+
// write one element's own cell had already notified -- rebuilding every row
|
|
1083
|
+
// of the list to deliver a change that touched one field of one element.
|
|
1084
|
+
const struct = key === undefined ? null : fieldDeclaringStructOf(ctx.classes, operation.receiver.representation, key);
|
|
1085
|
+
if (struct !== null && key !== undefined && ctx.hosts.reactive.celled.get(struct)?.has(key) === true)
|
|
1086
|
+
return;
|
|
1087
|
+
// ...nor when NOTHING RENDERS the member. A revision tick exists to tell the
|
|
1088
|
+
// list its rows are stale; a member no row reads cannot have made one stale.
|
|
1089
|
+
// `syncCells()` writing `cell.piece = -1` -- a field the board never displays
|
|
1090
|
+
// -- was rebuilding all 200 rows every time a piece moved.
|
|
1091
|
+
//
|
|
1092
|
+
// Only for a RECORD receiver. A class field's reactivity is stated by the
|
|
1093
|
+
// plugin (`ReactiveCellPlan.fields`), and this map is not that authority;
|
|
1094
|
+
// an element record's is derived from what JSX binds, which is exactly this.
|
|
1095
|
+
const receiverKind = operation.receiver.representation.kind;
|
|
1096
|
+
if (struct !== null &&
|
|
1097
|
+
key !== undefined &&
|
|
1098
|
+
(receiverKind === 'record' || receiverKind === 'native-record-ref') &&
|
|
1099
|
+
ctx.hosts.reactive.boundRecordFields.get(struct)?.has(key) !== true) {
|
|
1100
|
+
return;
|
|
1101
|
+
}
|
|
1102
|
+
lines.push(`${reactiveRevisionText(ctx, origin)}.notify();`);
|
|
1103
|
+
};
|
|
1104
|
+
/**
|
|
1105
|
+
* `this[key] = value` where the key's type is a CLOSED set of string literals,
|
|
1106
|
+
* each naming a declared field.
|
|
1107
|
+
*
|
|
1108
|
+
* The receiver keeps its native C++ type here, so the store below would
|
|
1109
|
+
* otherwise reach the runtime field dispatcher
|
|
1110
|
+
* (`emitNativeSidecarSet` -> `gea_writeOwnField`), which goes through
|
|
1111
|
+
* `gea::Value` and therefore refuses at RUN TIME, by name, for any field whose
|
|
1112
|
+
* carrier has no tag: `refuseUnaddressableField`. A callable field is exactly
|
|
1113
|
+
* that -- which is what left `overloaded-callable-fields.ts` aborting with
|
|
1114
|
+
* "a declared field whose carrier this runtime cannot box or unbox" on a write
|
|
1115
|
+
* that was statically closed all along.
|
|
1116
|
+
*
|
|
1117
|
+
* The dispatch is rendered by RE-ENTERING this function once per key, with a
|
|
1118
|
+
* context in which that key is the operation's static key text. Nothing here
|
|
1119
|
+
* decides how a field is stored, converted, presence-flagged, setter-dispatched
|
|
1120
|
+
* or reactively ticked -- the constant-key renderer decides all of it, exactly
|
|
1121
|
+
* as it does for a source-literal store, and this is only the switch that
|
|
1122
|
+
* chooses which of its answers runs. Re-implementing the tail instead would be
|
|
1123
|
+
* a second authority on member storage, differing from the first the day one
|
|
1124
|
+
* of them learns something.
|
|
1125
|
+
*
|
|
1126
|
+
* The arms carry `result: null` so the receiver alias is defined ONCE, after
|
|
1127
|
+
* the dispatch: `defineValueAlias` forbids a second definition of one SSA
|
|
1128
|
+
* value, and every arm would otherwise publish the same one.
|
|
1129
|
+
*/
|
|
1130
|
+
const emitTypedComputedWrite = (ctx, lines, operation, label) => {
|
|
1131
|
+
const recipe = operation.typedComputedWrite;
|
|
1132
|
+
if (recipe === undefined)
|
|
1133
|
+
return false;
|
|
1134
|
+
const receiver = operation.receiver.representation;
|
|
1135
|
+
if (recipe.receiver !== representationKey(receiver) || recipe.keys.length === 0) {
|
|
1136
|
+
throw createCppEmitBlockedError(`property-access:${receiver.kind}:set:typed-computed-write`, 'the sealed computed-write recipe does not match the store receiver');
|
|
1137
|
+
}
|
|
1138
|
+
// An SSA id is not an identifier (`ssa|body|fn|decl|...`); the ordinal alone
|
|
1139
|
+
// distinguishes one closed dispatch from another nested inside it.
|
|
1140
|
+
const keyName = `gea_computed_key_${[...operation.key.value].reduce((hash, character) => (hash * 33 + character.charCodeAt(0)) >>> 0, 5381).toString(36)}`;
|
|
1141
|
+
const body = [`const std::string& ${keyName} = ${operandText(ctx, operation.key)};`];
|
|
1142
|
+
for (const key of recipe.keys) {
|
|
1143
|
+
const armContext = { ...ctx, staticKeyTexts: new Map(ctx.staticKeyTexts).set(operation.key.value, key) };
|
|
1144
|
+
const arm = [];
|
|
1145
|
+
const { typedComputedWrite: _sealed, ...constantKeyStore } = operation;
|
|
1146
|
+
emitFieldStoreLines(armContext, arm, { ...constantKeyStore, result: null }, label);
|
|
1147
|
+
body.push(`if (${keyName} == ${cppStringLiteral(key)}) {`, ...arm.map((line) => ` ${line}`), '}');
|
|
1148
|
+
}
|
|
1149
|
+
lines.push('{', ...body.map((line) => ` ${line}`), '}');
|
|
1150
|
+
// The store's result is the receiver threaded onward, the same fact every
|
|
1151
|
+
// branch of the constant-key renderer publishes -- see its own tail.
|
|
1152
|
+
if (operation.result)
|
|
1153
|
+
defineValueAlias(ctx, operation.result, operandText(ctx, operation.receiver));
|
|
1154
|
+
return true;
|
|
1155
|
+
};
|
|
1156
|
+
const emitFieldStoreLines = (ctx, lines, operation, label) => {
|
|
1157
|
+
// The write counterpart of `emitGet`'s checked unwrap. TypeScript accepts
|
|
1158
|
+
// `a!.b = x`, but its erased assertion does not prove runtime presence.
|
|
1159
|
+
// Every branch below requires the payload carrier; the shared helper checks
|
|
1160
|
+
// absence before exposing it to either a read or a write.
|
|
1161
|
+
const present = unwrapPresentValue(ctx, lines, operation.receiver);
|
|
1162
|
+
if (present !== operation.receiver) {
|
|
1163
|
+
emitFieldStoreLines(ctx, lines, { ...operation, receiver: present }, label);
|
|
1164
|
+
return;
|
|
1165
|
+
}
|
|
1166
|
+
if (!isDefaultDataDescriptor(operation)) {
|
|
1167
|
+
// Generated indexed records carry descriptor bits for both fixed slots
|
|
1168
|
+
// and each sidecar entry. Their fixed-first dispatcher can therefore
|
|
1169
|
+
// preserve a computed key collision exactly; the other storage families
|
|
1170
|
+
// below still have no place to retain non-default attributes.
|
|
1171
|
+
if (emitRecordIndexSidecarStore(ctx, lines, operation))
|
|
1172
|
+
return;
|
|
1173
|
+
// A dictionary is the second carrier that can. `gea::Dictionary` keeps the
|
|
1174
|
+
// three attributes for the keys that deviate from the ordinary ones, so a
|
|
1175
|
+
// non-default descriptor aimed at one is renderable and falls through to
|
|
1176
|
+
// the dictionary branch below rather than refusing here -- the same escape
|
|
1177
|
+
// the indexed record takes one line up, for the same reason.
|
|
1178
|
+
if (operation.receiver.representation.kind !== 'dictionary') {
|
|
1179
|
+
const attrs = operation.attributes;
|
|
1180
|
+
throw createCppEmitBlockedError(`property-access:${operation.receiver.representation.kind}:define-own-property:${String(ctx.staticKeyTexts.get(operation.key.value) === undefined)}`, `a "${label}" states a non-default descriptor (writable=${attrs.writable}, enumerable=${attrs.enumerable}, configurable=${attrs.configurable}); ` +
|
|
1181
|
+
'every store this backend renders installs the default writable/enumerable/configurable data property, and no C++ storage it writes into can ' +
|
|
1182
|
+
'express anything else, so a descriptor this compiler cannot honor is refused rather than silently applied as if it were the default');
|
|
1183
|
+
}
|
|
1184
|
+
}
|
|
1185
|
+
// `ClassName.KEY = value` on the class value itself -- three.js's own
|
|
1186
|
+
// spelling for a class static (`Object3D.DEFAULT_UP = new Vector3(0,1,0)`),
|
|
1187
|
+
// which the language admits as an ordinary property store and no `static`
|
|
1188
|
+
// member declares. The storage is the whole-program census's own global
|
|
1189
|
+
// (`class-layout.ts`), emitted before any body runs, and the census refused
|
|
1190
|
+
// outright any key two writes carried differently -- so a key that resolves
|
|
1191
|
+
// here is one whose carrier every write already agreed on, and nothing at
|
|
1192
|
+
// this site reconciles one. A key it declines falls through to the same
|
|
1193
|
+
// refusal it reached before.
|
|
1194
|
+
const staticFieldKey = ctx.staticKeyTexts.get(operation.key.value);
|
|
1195
|
+
const staticField = staticFieldKey === undefined ? null : classConstructorStaticFieldStorage(ctx, operation.receiver.representation, staticFieldKey);
|
|
1196
|
+
if (staticField !== null) {
|
|
1197
|
+
const rawStaticValue = operandText(ctx, operation.value);
|
|
1198
|
+
const converted = alignedValueText(ctx, 'emit-properties.ts:1079', operation.value.representation, staticField.representation, rawStaticValue);
|
|
1199
|
+
if (converted === null) {
|
|
1200
|
+
throw createCppEmitBlockedError(`conversion:${representationKey(operation.value.representation)}->${representationKey(staticField.representation)}`, `static field "${staticFieldKey}" is stored as "${representationKey(staticField.representation)}" and this write carries ` +
|
|
1201
|
+
`"${representationKey(operation.value.representation)}"; no conversion is installed between them`);
|
|
1202
|
+
}
|
|
1203
|
+
lines.push(`${staticField.name} = ${movedValueText(ctx, operation.value, staticField.representation, converted)};`);
|
|
1204
|
+
// A store's result is the receiver threaded onward, exactly as the record
|
|
1205
|
+
// branch below explains -- here that receiver is the class value itself.
|
|
1206
|
+
if (operation.result)
|
|
1207
|
+
defineValueAlias(ctx, operation.result, operandText(ctx, operation.receiver));
|
|
1208
|
+
return;
|
|
1209
|
+
}
|
|
1210
|
+
if (namespaceMemberStore(ctx, lines, operation))
|
|
1211
|
+
return;
|
|
1212
|
+
if (emitTaggedUnionSet(ctx, lines, operation))
|
|
1213
|
+
return;
|
|
1214
|
+
if (operation.receiver.representation.kind === 'array-object') {
|
|
1215
|
+
const arrayReceiver = operandText(ctx, operation.receiver);
|
|
1216
|
+
// A store's result threads the receiver onward the same way the
|
|
1217
|
+
// record/class branch below does -- see that branch's own comment for why
|
|
1218
|
+
// it is the object and not a success boolean.
|
|
1219
|
+
const finishArrayStore = () => {
|
|
1220
|
+
if (!operation.result)
|
|
1221
|
+
return;
|
|
1222
|
+
// The result IS the receiver -- the same object, not a copy of it -- so
|
|
1223
|
+
// it names the receiver's own storage rather than taking one. Copying it
|
|
1224
|
+
// out cost an atomic increment and a matching decrement per store, for a
|
|
1225
|
+
// value an object literal's own thread usually never reads.
|
|
1226
|
+
defineValueAlias(ctx, operation.result, arrayReceiver);
|
|
1227
|
+
};
|
|
1228
|
+
const key = ctx.staticKeyTexts.get(operation.key.value);
|
|
1229
|
+
if (key === 'length') {
|
|
1230
|
+
// `arr.length = n` is the Array exotic object's own truncate/extend
|
|
1231
|
+
// rule, not a field write: `setLength` in the runtime header is where
|
|
1232
|
+
// that rule lives, so nothing here decides truncation-vs-extension.
|
|
1233
|
+
lines.push(`${arrayReceiver}->setLength(${operandText(ctx, operation.value)});`);
|
|
1234
|
+
finishArrayStore();
|
|
1235
|
+
return;
|
|
1236
|
+
}
|
|
1237
|
+
// A field the array's extended interface declares (`array-object.extension`,
|
|
1238
|
+
// `array.hasTrailingComma = ...` on a `MutableNodeArray<T>`): stored into
|
|
1239
|
+
// the extension sidecar, allocated by this first write
|
|
1240
|
+
// (`extensionFieldsMut`) -- the read side (`arrayAccessText`) never
|
|
1241
|
+
// allocates, so a never-written array stays a plain array.
|
|
1242
|
+
const extensionField = key === undefined ? undefined : operation.receiver.representation.extension?.find((field) => field.key === key);
|
|
1243
|
+
if (extensionField !== undefined && operation.receiver.representation.extension) {
|
|
1244
|
+
const struct = cppArrayExtensionStructName(operation.receiver.representation.extension);
|
|
1245
|
+
const stored = alignedValueText(ctx, 'emit-properties.ts:1125', operation.value.representation, extensionField.value, operandText(ctx, operation.value));
|
|
1246
|
+
if (stored === null) {
|
|
1247
|
+
throw createCppEmitBlockedError(`conversion:${representationKey(operation.value.representation)}->${representationKey(extensionField.value)}`, `cannot convert "${representationKey(operation.value.representation)}" into the array's own field "${key}" ` +
|
|
1248
|
+
`("${representationKey(extensionField.value)}")`);
|
|
1249
|
+
}
|
|
1250
|
+
const fields = `${arrayReceiver}->template extensionFieldsMut<${struct}>()`;
|
|
1251
|
+
lines.push(`${fields}.${cppRecordFieldName(extensionField.key)} = ${stored};`);
|
|
1252
|
+
if (!extensionField.required)
|
|
1253
|
+
lines.push(`${fields}.${cppRecordFieldPresenceName(extensionField.key)} = true;`);
|
|
1254
|
+
finishArrayStore();
|
|
1255
|
+
return;
|
|
1256
|
+
}
|
|
1257
|
+
// A STATIC key that names neither `length` nor a declared extension field
|
|
1258
|
+
// is either a canonical index or an ORDINARY property of the Array
|
|
1259
|
+
// object (`dynamicStrings.extra = true` off a `TemplateStringsArray` cast
|
|
1260
|
+
// to `any` -- the physical carrier is still the array, so the write
|
|
1261
|
+
// reaches here, but "extra" is nobody's element). That question --
|
|
1262
|
+
// "does this key even name an element" -- has to be answered BEFORE the
|
|
1263
|
+
// value is aligned to the element's type: aligning first meant a boolean
|
|
1264
|
+
// written to an ordinary property of a string array refused as
|
|
1265
|
+
// "cannot convert an Array element from scalar(boolean) to string", which
|
|
1266
|
+
// is a true fact about a conversion nobody asked for, not the real
|
|
1267
|
+
// refusal -- there is no property table for an Array's ordinary
|
|
1268
|
+
// properties, and that is the message this should have raised.
|
|
1269
|
+
if (key !== undefined) {
|
|
1270
|
+
const index = canonicalIndexLiteral(key);
|
|
1271
|
+
if (index === null) {
|
|
1272
|
+
throw createCppEmitBlockedError(`property-access:array-object:${operation.kind}:false`, `writing the Array property "${key}" is an ordinary property of the Array object, and no property table is installed for one`);
|
|
1273
|
+
}
|
|
1274
|
+
const rawStored = operandText(ctx, operation.value);
|
|
1275
|
+
const storedValue = alignedValueText(ctx, 'emit-properties.ts:1140', operation.value.representation, operation.receiver.representation.element, rawStored);
|
|
1276
|
+
if (storedValue === null) {
|
|
1277
|
+
throw createCppEmitBlockedError(`conversion:${representationKey(operation.value.representation)}->${representationKey(operation.receiver.representation.element)}`, `cannot convert an Array element from "${representationKey(operation.value.representation)}" to ` +
|
|
1278
|
+
`"${representationKey(operation.receiver.representation.element)}"`);
|
|
1279
|
+
}
|
|
1280
|
+
lines.push(`${arrayReceiver}->setElement(${index}, ${storedValue});`);
|
|
1281
|
+
finishArrayStore();
|
|
1282
|
+
return;
|
|
1283
|
+
}
|
|
1284
|
+
const rawStored = operandText(ctx, operation.value);
|
|
1285
|
+
const storedValue = alignedValueText(ctx, 'emit-properties.ts:1140', operation.value.representation, operation.receiver.representation.element, rawStored);
|
|
1286
|
+
if (storedValue === null) {
|
|
1287
|
+
throw createCppEmitBlockedError(`conversion:${representationKey(operation.value.representation)}->${representationKey(operation.receiver.representation.element)}`, `cannot convert an Array element from "${representationKey(operation.value.representation)}" to ` +
|
|
1288
|
+
`"${representationKey(operation.receiver.representation.element)}"`);
|
|
1289
|
+
}
|
|
1290
|
+
// The store half of the string-keyed element access `emit-carrier-members.ts`
|
|
1291
|
+
// renders for a read: one CanonicalNumericIndexString conversion in front
|
|
1292
|
+
// of the ordinary `setElement`. No dense window is consulted -- a window is
|
|
1293
|
+
// admitted for a loop-bounded numeric index (`ir/dense-loops.ts`), and a
|
|
1294
|
+
// `for`-`in` key is not one.
|
|
1295
|
+
if (operation.key.representation.kind === 'string') {
|
|
1296
|
+
lines.push(`${arrayReceiver}->setElement(gea::detail::arrayIndexFromKeyText(${operandText(ctx, operation.key)}), ${storedValue});`);
|
|
1297
|
+
finishArrayStore();
|
|
1298
|
+
return;
|
|
1299
|
+
}
|
|
1300
|
+
if (operation.key.representation.kind !== 'scalar') {
|
|
1301
|
+
throw createCppEmitBlockedError(`property-access:array-object:${operation.kind}:true`, `an Array element store keyed by a "${operation.key.representation.kind}" carrier needs a ToPropertyKey conversion, which is not installed`);
|
|
1302
|
+
}
|
|
1303
|
+
const writer = isIntegerStorageValue(ctx, operation.key.value) ? 'setElementAtIndex' : 'setElement';
|
|
1304
|
+
// Each operand is rendered ONCE and named twice: a deferred operand's text
|
|
1305
|
+
// is an expression this emitter built, and asking for it again is a second
|
|
1306
|
+
// rendering of the same operation, not a second read of a name.
|
|
1307
|
+
const stored = storedValue;
|
|
1308
|
+
const dense = denseCellText(ctx, operation);
|
|
1309
|
+
const at = operandText(ctx, operation.key);
|
|
1310
|
+
const general = `${arrayReceiver}->${writer}(${at}, ${stored});`;
|
|
1311
|
+
// The general arm takes the stored value by REFERENCE, and an arm that
|
|
1312
|
+
// never runs still costs that: a value whose address is taken anywhere in
|
|
1313
|
+
// the loop cannot be kept in registers, so the record this iteration just
|
|
1314
|
+
// built is written to a stack slot and read back before every dense store.
|
|
1315
|
+
// Copying into the arm's own local is the whole cure -- `object_create`
|
|
1316
|
+
// 8.2ms to 4.5ms against 3.8ms for the hand-written baseline, from one
|
|
1317
|
+
// `auto` -- and it costs the cold path a copy it was already paying for.
|
|
1318
|
+
// The name is block-scoped, so every arm may reuse it.
|
|
1319
|
+
const cold = `{ auto gea_cold = ${stored}; ${arrayReceiver}->${writer}(${at}, gea_cold); }`;
|
|
1320
|
+
// The window's flag already says the array is writable -- `emit-arrays.ts`'s
|
|
1321
|
+
// `emitDenseSetup` folds `nativeOwnFieldsWritable` into it for every array
|
|
1322
|
+
// a window stores into -- so the store asks one loop-invariant local and
|
|
1323
|
+
// nothing else, which is what lets the backend unswitch and vectorize it.
|
|
1324
|
+
lines.push(dense === null ? general : `if (${dense.flag}) ${dense.text} = ${stored}; else ${cold}`);
|
|
1325
|
+
finishArrayStore();
|
|
1326
|
+
return;
|
|
1327
|
+
}
|
|
1328
|
+
if (operation.receiver.representation.kind === 'typed-array') {
|
|
1329
|
+
const typedArrayReceiver = operandText(ctx, operation.receiver);
|
|
1330
|
+
// A store's result threads the receiver onward, for the same reason the
|
|
1331
|
+
// Array branch above does.
|
|
1332
|
+
const finishTypedArrayStore = () => {
|
|
1333
|
+
if (!operation.result)
|
|
1334
|
+
return;
|
|
1335
|
+
defineValueAlias(ctx, operation.result, typedArrayReceiver);
|
|
1336
|
+
};
|
|
1337
|
+
const key = ctx.staticKeyTexts.get(operation.key.value);
|
|
1338
|
+
if (key === 'length') {
|
|
1339
|
+
// `Uint8Array.prototype.length` is a getter with no setter (ECMA-262
|
|
1340
|
+
// 23.2.7.2 defines no `[[Set]]` for it either), so the checker refuses
|
|
1341
|
+
// `buf.length = n` as a write to a readonly property before this
|
|
1342
|
+
// emitter is ever asked to render one -- there is no truncate/extend
|
|
1343
|
+
// rule to write here, unlike an Array's `length`.
|
|
1344
|
+
throw createCppEmitBlockedError(`property-access:typed-array:${operation.kind}:false`, 'writing "length" on a typed array has no meaning; ECMA-262 defines no setter for it and the checker refuses the assignment first');
|
|
1345
|
+
}
|
|
1346
|
+
if (key !== undefined) {
|
|
1347
|
+
const index = canonicalIndexLiteral(key);
|
|
1348
|
+
if (index === null) {
|
|
1349
|
+
throw createCppEmitBlockedError(`property-access:typed-array:${operation.kind}:false`, `writing the typed array property "${key}" is an ordinary property, and typed arrays have no ordinary-property table`);
|
|
1350
|
+
}
|
|
1351
|
+
lines.push(`${typedArrayReceiver}->setElement(${index}, ${operandText(ctx, operation.value)});`);
|
|
1352
|
+
finishTypedArrayStore();
|
|
1353
|
+
return;
|
|
1354
|
+
}
|
|
1355
|
+
if (operation.key.representation.kind !== 'scalar') {
|
|
1356
|
+
throw createCppEmitBlockedError(`property-access:typed-array:${operation.kind}:true`, `a typed array element store keyed by a "${operation.key.representation.kind}" carrier needs a ToPropertyKey conversion, which is not installed`);
|
|
1357
|
+
}
|
|
1358
|
+
const dense = denseCellText(ctx, operation);
|
|
1359
|
+
const value = operandText(ctx, operation.value);
|
|
1360
|
+
const general = `${typedArrayReceiver}->setElement(${operandText(ctx, operation.key)}, ${value});`;
|
|
1361
|
+
lines.push(dense === null
|
|
1362
|
+
? general
|
|
1363
|
+
: `if (${dense.flag}) gea::TypedArray<${cppScalarType(operation.receiver.representation.element)}>::writeInBounds(${dense.pointer}, ${dense.index}, ${value}); else ${general}`);
|
|
1364
|
+
finishTypedArrayStore();
|
|
1365
|
+
return;
|
|
1366
|
+
}
|
|
1367
|
+
const dictionaryTarget = dictionaryTableOf(ctx, operation.receiver, operation.key);
|
|
1368
|
+
if (dictionaryTarget !== null && operation.receiver.representation.kind === 'dictionary') {
|
|
1369
|
+
// `setProperty` and not `operator[]`: 10.1.9 refuses a store to a
|
|
1370
|
+
// non-writable property, and a dictionary can hold one since
|
|
1371
|
+
// `Object.defineProperty` on it began retaining attributes. `operator[]`
|
|
1372
|
+
// remains the unconditional insert-or-find every internal rewrite uses --
|
|
1373
|
+
// inserting a missing key is exactly the store rule for a key nothing has
|
|
1374
|
+
// restricted -- but a program's own assignment has to be able to fail.
|
|
1375
|
+
// `SetOperation.strict` has carried the consequence of that failure since
|
|
1376
|
+
// the IR was written; this carrier is the last one with a failure to
|
|
1377
|
+
// report it for.
|
|
1378
|
+
//
|
|
1379
|
+
// The value is reconciled against the table's *declared* value carrier for
|
|
1380
|
+
// the same reason a struct member is below: a `{ [key: string]: string |
|
|
1381
|
+
// number | boolean }` table holds one joined carrier, and a literal `true`
|
|
1382
|
+
// written into it is a `bool` that only becomes that carrier through the
|
|
1383
|
+
// union's own arm constructor. Without this the store spells `table[k] =
|
|
1384
|
+
// true` against a `TaggedUnion` and no overload accepts it.
|
|
1385
|
+
const dictionaryValueText = operandText(ctx, operation.value);
|
|
1386
|
+
const widened = alignedValueText(ctx, 'emit-properties.ts:1253', operation.value.representation, operation.receiver.representation.value, dictionaryValueText) ?? dictionaryValueText;
|
|
1387
|
+
if (operation.kind === 'define-own-property') {
|
|
1388
|
+
// `[[DefineOwnProperty]]`, which states all three attributes outright
|
|
1389
|
+
// and throws on 10.1.6.3's refusal whatever the surrounding strictness
|
|
1390
|
+
// -- `Object.defineProperty` is not an assignment and has no sloppy
|
|
1391
|
+
// discard. The three are bare booleans rather than `std::optional`
|
|
1392
|
+
// because this operation always states them; the optional overload is
|
|
1393
|
+
// for a descriptor object, which may not.
|
|
1394
|
+
const attrs = operation.attributes;
|
|
1395
|
+
const stated = `${attrs.writable}, ${attrs.enumerable}, ${attrs.configurable}`;
|
|
1396
|
+
lines.push(`if (!${dictionaryTarget.member}definePropertyFrom(${dictionaryTarget.key}, ${widened}, ${stated})) ` +
|
|
1397
|
+
'gea::host::throwRuntimeError("TypeError", "Cannot redefine property");');
|
|
1398
|
+
}
|
|
1399
|
+
else {
|
|
1400
|
+
const refused = `!${dictionaryTarget.member}setProperty(${dictionaryTarget.key}, ${widened})`;
|
|
1401
|
+
lines.push(operation.strict
|
|
1402
|
+
? `if (${refused}) gea::host::throwRuntimeError("TypeError", "Cannot assign to read only property");`
|
|
1403
|
+
: `(void)(${refused});`);
|
|
1404
|
+
}
|
|
1405
|
+
if (operation.result) {
|
|
1406
|
+
// Threaded onward as the receiver, for the reason the struct-member
|
|
1407
|
+
// branch below states: a store has no failure to report, and what a
|
|
1408
|
+
// consumer reads next is the object itself.
|
|
1409
|
+
defineValueAlias(ctx, operation.result, operandText(ctx, operation.receiver));
|
|
1410
|
+
}
|
|
1411
|
+
return;
|
|
1412
|
+
}
|
|
1413
|
+
if (emitNativeHostStore(ctx, lines, operation, label))
|
|
1414
|
+
return;
|
|
1415
|
+
// Every store into a regular-expression carrier except `lastIndex`, which
|
|
1416
|
+
// returns and falls through to the ordinary struct-member write below
|
|
1417
|
+
// because on this carrier it IS one. Placed here rather than at the end so
|
|
1418
|
+
// the dynamic and sidecar paths cannot claim the receiver first.
|
|
1419
|
+
// A capture-slot store, which is an ELEMENT store on the Array the match
|
|
1420
|
+
// result is -- see `regexpCaptureSlotStoreClaim`. Rendered here, beside the
|
|
1421
|
+
// other regexp store paths, so the refusal below cannot claim it first.
|
|
1422
|
+
const captureSlot = regexpCaptureSlotStoreClaim(ctx, operation);
|
|
1423
|
+
if (captureSlot !== null && operation.kind === 'set') {
|
|
1424
|
+
const receiverText = operandText(ctx, operation.receiver);
|
|
1425
|
+
const stored = alignedValueText(ctx, 'emit-properties.ts:capture-slot', operation.value.representation, { kind: 'string' }, operandText(ctx, operation.value));
|
|
1426
|
+
if (stored === null) {
|
|
1427
|
+
throw createCppEmitBlockedError(`property-access:${representationKey(operation.receiver.representation)}:set:true`, `a capture slot holds a string (ECMA-262 22.2.7.2 puts a string or \`undefined\` in every slot, and the declared element of both result ` +
|
|
1428
|
+
`interfaces is \`string\`), and this store's "${representationKey(operation.value.representation)}" carrier has no conversion into one`);
|
|
1429
|
+
}
|
|
1430
|
+
lines.push(`${receiverText}->setCapture(${captureSlot.slotText}, ${stored});`);
|
|
1431
|
+
// Threaded onward as the receiver, exactly as the Array and dictionary
|
|
1432
|
+
// stores above do: a store has no failure to report and what a consumer
|
|
1433
|
+
// reads next is the object itself.
|
|
1434
|
+
if (operation.result)
|
|
1435
|
+
defineValueAlias(ctx, operation.result, receiverText);
|
|
1436
|
+
return;
|
|
1437
|
+
}
|
|
1438
|
+
if (emitRegExpSet(ctx, lines, operation))
|
|
1439
|
+
return;
|
|
1440
|
+
regexpStoreRefusal(ctx, operation.receiver, operation.key);
|
|
1441
|
+
if (emitStringObjectSet(ctx, lines, operation))
|
|
1442
|
+
return;
|
|
1443
|
+
// The dynamic receiver's own property table. `define-own-property` reaches
|
|
1444
|
+
// it too and is rendered as the ordinary `[[Set]]` the descriptor-free case
|
|
1445
|
+
// reduces to: this operation's `attributes` are the default writable/
|
|
1446
|
+
// enumerable/configurable triple a fresh assignment creates, which is
|
|
1447
|
+
// exactly what `DynamicObject::set` installs.
|
|
1448
|
+
// Before the dynamic routes: a closed literal key set is a compile-time
|
|
1449
|
+
// dispatch over declared fields, and reaches carriers the runtime field
|
|
1450
|
+
// dispatcher below cannot address at all.
|
|
1451
|
+
if (operation.kind === 'set' && emitTypedComputedWrite(ctx, lines, operation, label))
|
|
1452
|
+
return;
|
|
1453
|
+
if (emitDynamicSet(ctx, lines, operation))
|
|
1454
|
+
return;
|
|
1455
|
+
// A CONSTANT key that names no declared field of a receiver whose shape
|
|
1456
|
+
// carries an index signature -- the store counterpart of the
|
|
1457
|
+
// `recordIndexSidecarReadText` branch in `emitGet` above, and rendered
|
|
1458
|
+
// beside it rather than here so one module owns both directions.
|
|
1459
|
+
if (emitRecordIndexSidecarStore(ctx, lines, operation))
|
|
1460
|
+
return;
|
|
1461
|
+
// The same sidecar as the read above, for a write: the declared member is
|
|
1462
|
+
// written IN PLACE through the struct's own field dispatcher, so a native
|
|
1463
|
+
// read of that member sees it, and only a key the struct does not declare
|
|
1464
|
+
// reaches the side table.
|
|
1465
|
+
if (emitNativeSidecarSet(ctx, lines, operation))
|
|
1466
|
+
return;
|
|
1467
|
+
const ownership = recordOwnershipOf(operation.receiver, `a "${label}" operation`);
|
|
1468
|
+
const accessor = memberAccessOperator(ownership);
|
|
1469
|
+
const receiverText = operandText(ctx, operation.receiver);
|
|
1470
|
+
const fieldName = staticKeyTextOf(ctx, operation.key, `a "${label}" operation`);
|
|
1471
|
+
const rawValueText = operandText(ctx, operation.value);
|
|
1472
|
+
// A field whose declared representation is `dynamic` (a program-declared
|
|
1473
|
+
// `any`, the one case this widens today) needs its concrete value boxed on
|
|
1474
|
+
// the way in -- the same "held vs written" reconciliation
|
|
1475
|
+
// `emit-bindings.ts` already applies to a binding cell, applied here to a
|
|
1476
|
+
// struct member instead. See citations.md finding 1.
|
|
1477
|
+
// Accessors have no field storage. Reconcile their argument against the
|
|
1478
|
+
// emitted setter parameter instead, including setters inherited from a base.
|
|
1479
|
+
const setter = classAccessorSetter(ctx, operation.receiver, fieldName) ?? recordAccessorBody(ctx, operation.receiver, fieldName, 'setter');
|
|
1480
|
+
const setterParameter = setter === null ? null : ctx.abiOfCallable(setter)?.parameters[0]?.value;
|
|
1481
|
+
if (setter !== null && !setterParameter) {
|
|
1482
|
+
throw createCppEmitBlockedError(`call-abi:accessor-setter:${fieldName}`, `setter "${fieldName}" has no emitted parameter convention`);
|
|
1483
|
+
}
|
|
1484
|
+
const held = setterParameter ?? declaredFieldRepresentation(ctx, operation.receiver, fieldName);
|
|
1485
|
+
// `convertedValueText` returns the text UNCHANGED when the carriers already
|
|
1486
|
+
// agree, where the `widenedStoreText` this replaced returned `null`. That
|
|
1487
|
+
// difference is load-bearing exactly here, because the `??` below reads
|
|
1488
|
+
// `null` as "nothing to reconcile, so this store may MOVE": taking the
|
|
1489
|
+
// unchanged text as a conversion silently dropped `std::move` from every
|
|
1490
|
+
// identity member store -- 39 programs' emitted C++, with the line count
|
|
1491
|
+
// unchanged so no column moved and nothing else would have caught it.
|
|
1492
|
+
// Folding it back to `null` restores the move and keeps the real
|
|
1493
|
+
// conversions, which is the whole point of the change.
|
|
1494
|
+
// The structural interface view, asked only where the ordinary conversion
|
|
1495
|
+
// has refused -- the same order `emit-callable.ts`'s argument path uses, and
|
|
1496
|
+
// for the same reason: the view does not preserve identity, so a pair with a
|
|
1497
|
+
// real conversion must never reach it. hono's `this.router = new
|
|
1498
|
+
// PatternRouter()` stores a class instance into a field declared as the
|
|
1499
|
+
// `Router` interface, which is a rebuild and not a cast.
|
|
1500
|
+
const reconciled = held === null
|
|
1501
|
+
? null
|
|
1502
|
+
: (alignedValueText(ctx, 'emit-properties.ts:1324', operation.value.representation, held, rawValueText) ??
|
|
1503
|
+
structuralRecordViewText(ctx, operation.value.representation, held, rawValueText));
|
|
1504
|
+
// FAIL CLOSED, the same rule `emit-bindings.ts`'s `emitBindingWrite` already
|
|
1505
|
+
// enforces for an identifier cell: a `held` carrier actually present with
|
|
1506
|
+
// `reconciled === null` means no recipe exists for this pair, not that none
|
|
1507
|
+
// was needed -- `held === null` (no record layout, or a key this program
|
|
1508
|
+
// never declares) is the only legitimate reason to fall through unconverted.
|
|
1509
|
+
//
|
|
1510
|
+
// This was gated on `setter !== null` alone until this fix, which reads as
|
|
1511
|
+
// "an accessor's argument must convert, but a PLAIN FIELD'S needn't" -- a
|
|
1512
|
+
// distinction the language does not draw. A `null`-declared JS record field
|
|
1513
|
+
// (`const state = { rectAreaLTC1: null }`, three's `WebGLLights.js`) later
|
|
1514
|
+
// stored from an optional class-ref falls through this exact gap: preflight
|
|
1515
|
+
// reports the store clean, a certificate mints, and the raw unconverted
|
|
1516
|
+
// `gea::Optional<gea::Ref<T>>` expression lands in a `std::nullptr_t` field
|
|
1517
|
+
// -- caught only by clang, and only because `std::nullptr_t` happens to
|
|
1518
|
+
// declare no such assignment operator. A plain field's own unconvertible
|
|
1519
|
+
// store is a refusal exactly as much as an accessor's is.
|
|
1520
|
+
if (held !== null && reconciled === null) {
|
|
1521
|
+
throw createCppEmitBlockedError(`conversion:${representationKey(operation.value.representation)}->${representationKey(held)}`, setter !== null
|
|
1522
|
+
? `setter "${fieldName}" has no conversion from its argument to its emitted parameter`
|
|
1523
|
+
: `writes "${fieldName}" as a ${shortCarrierText(operation.value.representation)} into a field held as ` +
|
|
1524
|
+
`${shortCarrierText(held)}, and no conversion is installed between them; ${carrierDifference(operation.value.representation, held)}`);
|
|
1525
|
+
}
|
|
1526
|
+
const widenedText = reconciled === rawValueText ? null : reconciled;
|
|
1527
|
+
// A member store is the same handover a call argument is: what the value
|
|
1528
|
+
// held is now the member's, and nothing reads the value again. The
|
|
1529
|
+
// constructor of a refcounted class is where this pays -- `this.left =
|
|
1530
|
+
// left` on a parameter the frame is about to drop.
|
|
1531
|
+
const valueText = widenedText ?? movedValueText(ctx, operation.value, held, rawValueText);
|
|
1532
|
+
// An accessor-backed member is written by *calling* its setter. The receiver
|
|
1533
|
+
// is still threaded onward below, because what a store publishes is the
|
|
1534
|
+
// object written into and not whatever the setter body happens to return.
|
|
1535
|
+
// An overridden setter dispatches through the object for the same reason an
|
|
1536
|
+
// overridden getter does: `rule.weight = v` on a receiver typed as the base
|
|
1537
|
+
// must reach the subclass's own setter, and binding the base's body would
|
|
1538
|
+
// write the wrong one with nothing to show for it at compile time.
|
|
1539
|
+
const setterDispatch = setter === null || operation.receiver.representation.kind !== 'class-ref'
|
|
1540
|
+
? undefined
|
|
1541
|
+
: ctx.virtualDispatch.get(virtualDispatchKey(operation.receiver.representation.declaration, fieldName, 'set'));
|
|
1542
|
+
if (setter !== null && setterDispatch !== undefined && !dispatchesStatically(ctx, operation.receiver)) {
|
|
1543
|
+
lines.push(`${receiverText}->${cppVirtualMemberName(fieldName, 'set')}(${valueText});`);
|
|
1544
|
+
}
|
|
1545
|
+
else if (setter !== null) {
|
|
1546
|
+
const environment = accessorEnvironmentArguments(ctx, operation.receiver.representation, fieldName, setter, 'setter', receiverText);
|
|
1547
|
+
lines.push(`${cppBodyName(setter)}(${[...environment, receiverText, valueText].join(', ')});`);
|
|
1548
|
+
}
|
|
1549
|
+
else if (isNativeError(operation.receiver.representation) && fieldName === 'cause') {
|
|
1550
|
+
lines.push(`${receiverText}->setCause(${valueText});`);
|
|
1551
|
+
}
|
|
1552
|
+
// `fieldName` stays the property key everywhere above: the three lookups
|
|
1553
|
+
// that consumed it match against `RecordField.key`. Only the text emitted
|
|
1554
|
+
// here is a C++ member, and that spelling has exactly one authority.
|
|
1555
|
+
else {
|
|
1556
|
+
const target = `${receiverText}${accessor}${cppRecordFieldName(fieldName)}`;
|
|
1557
|
+
const append = held?.kind === 'string' ? propertyAppendLines(ctx, operation, fieldName, target) : null;
|
|
1558
|
+
const field = declaredRecordFieldOf(ctx.deriver, operation.receiver.representation, fieldName, ctx.classes);
|
|
1559
|
+
const stores = append === null ? [`${target} = ${valueText};`] : [...append];
|
|
1560
|
+
// A member the NATIVE base owns (`name` on `gea::runtime::Error`) has the
|
|
1561
|
+
// one member and nothing beside it: no presence bit, no attribute triple,
|
|
1562
|
+
// and no way to be absent or read-only. Emitting the generated-struct
|
|
1563
|
+
// recipe for it named members no struct in the program declares.
|
|
1564
|
+
if (nativeBaseFieldOf(ctx.deriver, operation.receiver.representation, fieldName, ctx.classes)) {
|
|
1565
|
+
lines.push(stores.join(' '));
|
|
1566
|
+
if (operation.result)
|
|
1567
|
+
defineValueAlias(ctx, operation.result, receiverText);
|
|
1568
|
+
return;
|
|
1569
|
+
}
|
|
1570
|
+
// A required field the program can never delete is present for the
|
|
1571
|
+
// object's whole life (`ctx.fixedFieldStateConstant`), so there is no bit
|
|
1572
|
+
// to re-set -- `records.ts` declared it `static` on the same fact.
|
|
1573
|
+
if (field && !(field.required && ctx.fixedFieldStateConstant))
|
|
1574
|
+
stores.push(`${receiverText}${accessor}${cppRecordFieldPresenceName(fieldName)} = true;`);
|
|
1575
|
+
const fieldWritable = `${receiverText}${accessor}${cppRecordFieldAttributesName(fieldName)}.writable`;
|
|
1576
|
+
const present = field === undefined ? 'true' : `${receiverText}${accessor}${cppRecordFieldPresenceName(fieldName)}`;
|
|
1577
|
+
// With nothing in the unit able to freeze an object or redefine a field
|
|
1578
|
+
// (`ctx.nativeIntegrityRestricted`), the attribute bit is its default and
|
|
1579
|
+
// the object is extensible, so the guard is `true` and the store is the
|
|
1580
|
+
// store. See `ir/integrity-restrictions.ts` for what that buys a loop.
|
|
1581
|
+
const writable = !ctx.nativeIntegrityRestricted
|
|
1582
|
+
? 'true'
|
|
1583
|
+
: ownership === 'shared-refcount'
|
|
1584
|
+
? `(${present} ? (${fieldWritable} && gea::nativeOwnFieldsWritable(${receiverText})) : gea::nativeIsExtensible(${receiverText}))`
|
|
1585
|
+
: fieldWritable;
|
|
1586
|
+
const store = stores.join(' ');
|
|
1587
|
+
if (writable === 'true')
|
|
1588
|
+
lines.push(store);
|
|
1589
|
+
else if (operation.kind === 'set' && operation.strict) {
|
|
1590
|
+
lines.push(`if (!${writable}) gea::host::throwRuntimeError("TypeError", "Cannot assign to read only property"); else { ${store} }`);
|
|
1591
|
+
}
|
|
1592
|
+
else
|
|
1593
|
+
lines.push(`if (${writable}) { ${store} }`);
|
|
1594
|
+
}
|
|
1595
|
+
if (!operation.result)
|
|
1596
|
+
return;
|
|
1597
|
+
// A store's result is the receiver threaded onward, not the success boolean
|
|
1598
|
+
// the internal method nominally returns: a native field store has no failure
|
|
1599
|
+
// to report, and the value a consumer goes on to read is the object itself.
|
|
1600
|
+
// It therefore NAMES the receiver rather than copying it: three field stores
|
|
1601
|
+
// building one object literal were three refcount pairs on a value the
|
|
1602
|
+
// literal's own thread was the only reader of.
|
|
1603
|
+
defineValueAlias(ctx, operation.result, receiverText);
|
|
1604
|
+
};
|
|
1605
|
+
/**
|
|
1606
|
+
* A native field's own string update reuses either the field buffer when its
|
|
1607
|
+
* old-value read is deferred, or a materialized old-value snapshot when
|
|
1608
|
+
* ownership liveness proves that snapshot dies at the addition. The latter
|
|
1609
|
+
* preserves reads across intervening calls and moves the grown snapshot home.
|
|
1610
|
+
* Accessors keep their calls.
|
|
1611
|
+
*/
|
|
1612
|
+
const propertyAppendLines = (ctx, operation, field, target) => {
|
|
1613
|
+
if (operation.kind !== 'set')
|
|
1614
|
+
return null;
|
|
1615
|
+
const addition = ctx.computeOrigins.get(operation.value.value);
|
|
1616
|
+
if (!addition || addition.form !== 'binary' || addition.operator !== '+' || addition.result.representation.kind !== 'string')
|
|
1617
|
+
return null;
|
|
1618
|
+
const [left, ...suffix] = addition.operands;
|
|
1619
|
+
if (addition.operands.length < 2 || left?.representation.kind !== 'string')
|
|
1620
|
+
return null;
|
|
1621
|
+
if (suffix.some((operand) => operand.representation.kind !== 'string'))
|
|
1622
|
+
return null;
|
|
1623
|
+
if (!ctx.deferredTexts.has(addition.result.id))
|
|
1624
|
+
return null;
|
|
1625
|
+
const read = ctx.propertyReadOrigins.get(left.value);
|
|
1626
|
+
if (!read || ctx.staticKeyTexts.get(read.key.value) !== field || !isPlainMemberRead(ctx, read, field))
|
|
1627
|
+
return null;
|
|
1628
|
+
const sameReceiver = read.receiver.value === operation.receiver.value ||
|
|
1629
|
+
(ctx.receiverValues.has(read.receiver.value) && ctx.receiverValues.has(operation.receiver.value));
|
|
1630
|
+
if (!sameReceiver)
|
|
1631
|
+
return null;
|
|
1632
|
+
// Withheld or aliased to the field itself: see `compoundAppendLines`
|
|
1633
|
+
// (emit-bindings.ts) for why both forms read the storage in place.
|
|
1634
|
+
if (ctx.deferredTexts.has(left.value) || ctx.valueNames.get(left.value) === target)
|
|
1635
|
+
return [stringAppendStatement(ctx, target, suffix)];
|
|
1636
|
+
if (!ctx.ownedValues.has(left.value) || !ctx.ownedDyingValues.has(left.value))
|
|
1637
|
+
return null;
|
|
1638
|
+
const snapshot = operandText(ctx, left);
|
|
1639
|
+
return [stringAppendStatement(ctx, snapshot, suffix), `${target} = std::move(${snapshot});`];
|
|
1640
|
+
};
|