@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
package/dist/ir/lower.js
ADDED
|
@@ -0,0 +1,1346 @@
|
|
|
1
|
+
import { classLayoutOfCopy } from '../projection/classes.js';
|
|
2
|
+
import { operationOfResult, physicalBodyId } from '../identity/ids.js';
|
|
3
|
+
import { representationKey } from '../representation/model.js';
|
|
4
|
+
import { operandOf, resultOf } from '../semantics/model/operands.js';
|
|
5
|
+
import { createIrBodyBuilder } from './build.js';
|
|
6
|
+
import { collectConditionalMembership, groupOperationsByOwner, IrLoweringBlockedError, orderOwnerOperations, collectRegionParts } from './lower-graph.js';
|
|
7
|
+
import { completionTargetOf, findCompletionTargetBlock } from './lower-completion.js';
|
|
8
|
+
import { lowerBoundary, thrownValueCarrier } from './lower-exceptions.js';
|
|
9
|
+
import { mergeIncoming } from './lower-narrow.js';
|
|
10
|
+
import { settleShortCircuits } from './lower-short-circuit.js';
|
|
11
|
+
import { lowerDestructuring } from './lower-destructuring.js';
|
|
12
|
+
import { lowerElement } from './lower-element.js';
|
|
13
|
+
import { lowerInvocation } from './lower-invocation.js';
|
|
14
|
+
import { lowerAllocation } from './lower-allocation.js';
|
|
15
|
+
import { lowerProperty } from './lower-property.js';
|
|
16
|
+
import { lowerProtocol } from './lower-protocol.js';
|
|
17
|
+
import { createFlowController } from './lower-flow.js';
|
|
18
|
+
import { namesVoidResult, namedOperand, optionalResultRepresentation, registerResult, requireLineage, requireResultRepresentation, resolveOptionalOperand, resolveRequiredOperand, resolveResultValue, singleValueOperand, abiOfCallee, convertOrDrift, enter, narrowedBindingRead, enterRequiredOperand } from './lower-operands.js';
|
|
19
|
+
import { allOperationsOf } from './model.js';
|
|
20
|
+
/**
|
|
21
|
+
* Arithmetic, bitwise, relational, and the unary operators.
|
|
22
|
+
*
|
|
23
|
+
* Only `unary`/`binary` reach a primitive. The other forms the computation
|
|
24
|
+
* family publishes are not operators over evaluated operands at all: `logical`
|
|
25
|
+
* and `conditional` select without evaluating one side, `template` and
|
|
26
|
+
* `coercion` need conversions, `update` and `assignment` write a binding, and
|
|
27
|
+
* `typeof`/`instanceof`/`in` interrogate the object substrate. Each of those is
|
|
28
|
+
* its own missing primitive, named as such rather than folded into this one.
|
|
29
|
+
*/
|
|
30
|
+
const lowerComputation = (ctx, flow, block, operation) => {
|
|
31
|
+
// An assignment expression's own value is the value it assigned, and a comma
|
|
32
|
+
// expression's is its last operand's. Neither computes anything: the write
|
|
33
|
+
// and the operands are already operations of their own, so minting an IR
|
|
34
|
+
// instruction here would be a second copy of a value already in hand.
|
|
35
|
+
if (operation.form === 'assignment' || operation.form === 'comma') {
|
|
36
|
+
const lineage = requireLineage(operation);
|
|
37
|
+
const runtime = operation.operands.filter((operand) => operand.evaluation.kind !== 'provenance');
|
|
38
|
+
const last = runtime[runtime.length - 1];
|
|
39
|
+
if (!last)
|
|
40
|
+
throw new IrLoweringBlockedError(`a ${operation.form} computation has no operand to take its value from`);
|
|
41
|
+
// ...through `mergeIncoming`, which is the identical question a merge arm
|
|
42
|
+
// asks: the value is the operand's, and the carrier is the one the plan
|
|
43
|
+
// published for THIS operation. The two part company at an erased
|
|
44
|
+
// assertion -- `x = e as T` evaluates to the assertion's type while `e`
|
|
45
|
+
// still carries its own -- and registering the operand's SSA under a
|
|
46
|
+
// result the plan gave a different carrier is one value wearing two
|
|
47
|
+
// carriers, which `ir/verify.ts` rejects (correctly) with a message that
|
|
48
|
+
// names neither the assertion nor the assignment. So the carrier change
|
|
49
|
+
// is an explicit conversion here, rendered by the one authority on what a
|
|
50
|
+
// carrier change loads, and refused by name at emission if that authority
|
|
51
|
+
// has no load for the pair.
|
|
52
|
+
const representation = requireResultRepresentation(ctx, operation, 'value', `a ${operation.form} computation`);
|
|
53
|
+
registerResult(ctx, operation, mergeIncoming(ctx, block, lineage, operation, 'value', last, representation).value);
|
|
54
|
+
return;
|
|
55
|
+
}
|
|
56
|
+
// ToNumeric over a value the plan already carries as a number is the identity
|
|
57
|
+
// conversion: the language's step runs, and its answer is the operand. Minting
|
|
58
|
+
// an instruction would copy a value already in hand; registering the operand
|
|
59
|
+
// is what keeps one value with one name.
|
|
60
|
+
//
|
|
61
|
+
// One non-identity pair IS a real primitive, minted as an ordinary `unary`
|
|
62
|
+
// compute instruction rather than a new `ComputeOperation.form` (`ir/
|
|
63
|
+
// model.ts` is unchanged): postfix `x++`/`x--`'s own coercion
|
|
64
|
+
// (`semantics/normalize/producers/computations.ts`'s `contributeUpdate`,
|
|
65
|
+
// the ONLY producer that ever mints `form: 'coercion'`, and always with
|
|
66
|
+
// `operator: 'ToNumeric'`) over a `dynamic` operand landing on
|
|
67
|
+
// `scalar(number)` -- three.js's `let i` / an untyped loop counter
|
|
68
|
+
// incremented with `++`. `targets/cpp/emit.ts`'s `emitCompute` renders it
|
|
69
|
+
// (operator `'ToNumeric'`, checked before the ordinary numeric-unary table)
|
|
70
|
+
// via `targets/cpp/emit-tonumber.ts`'s `dynamicToNumericText`, which
|
|
71
|
+
// switches on the boxed value's own runtime tag -- see that function's own
|
|
72
|
+
// comment for why this is a real per-tag ToNumber and not the "assert one
|
|
73
|
+
// declared tag" narrowing `emit-narrowing.ts` already has.
|
|
74
|
+
//
|
|
75
|
+
// An `optional` operand landing on `scalar(number)` is a second, unrelated
|
|
76
|
+
// non-identity pair: `l[1]!++` under `noUncheckedIndexedAccess` cites the
|
|
77
|
+
// element access's own `[[Get]]`, which honestly publishes `T | undefined`
|
|
78
|
+
// regardless of the `!` outside it (the assertion is a compile-time promise,
|
|
79
|
+
// not a narrower runtime read) -- so the operand this coercion sees really is
|
|
80
|
+
// optional, the same shape a mixed-carrier `+`'s own ToNumber operand can be
|
|
81
|
+
// (`projection/slots.ts`'s `binarySlot`). That sibling already resolves
|
|
82
|
+
// through `ir/lower-operands.ts`'s `enter`/`convertTo`, which asks the
|
|
83
|
+
// conversion census's `coercionFor` for a `ToNumber` node and gets a REAL one
|
|
84
|
+
// back: `targets/cpp/emit-tonumber.ts`'s `toNumberText` renders an
|
|
85
|
+
// `optional` source as `has_value() ? number : NaN`, ECMA-262 7.1.4's own
|
|
86
|
+
// answer for `Number(undefined)`. `l[1]! += 5` already takes exactly that
|
|
87
|
+
// path (`computations.ts`'s compound-assignment operand), so `l[1]!++`
|
|
88
|
+
// refusing here was one operation asking the shared census a question its
|
|
89
|
+
// sibling operation already asks and already gets answered -- not a missing
|
|
90
|
+
// capability, a missing call. This form never went through `enter` at all
|
|
91
|
+
// (`projection/slots.ts` deliberately routes `'coercion'`/`'update'` to
|
|
92
|
+
// `raw('compute-operand')`, since ONLY this ToNumeric case ever needs a real
|
|
93
|
+
// conversion here), so the call is made directly rather than through `enter`.
|
|
94
|
+
// A BigInt operand stays refused: `coercionFor` reports `never` for it
|
|
95
|
+
// (`emit-tonumber.ts`'s `toNumberText` returns `null` for `domain ===
|
|
96
|
+
// 'bigint'`, matching ECMA-262's own TypeError for `ToNumber` of a BigInt),
|
|
97
|
+
// which is the same silent-nothing this branch already left alone before --
|
|
98
|
+
// no fail-open coercion is added, only the one ECMA-262 already states as
|
|
99
|
+
// total for a possibly-absent Number.
|
|
100
|
+
//
|
|
101
|
+
// Every other non-identity pair is still a real conversion this layer has no
|
|
102
|
+
// primitive for, and stays refused by name.
|
|
103
|
+
if (operation.form === 'coercion') {
|
|
104
|
+
const lineage = requireLineage(operation);
|
|
105
|
+
const runtime = operation.operands.filter((operand) => operand.evaluation.kind !== 'provenance');
|
|
106
|
+
const only = runtime[0];
|
|
107
|
+
if (!only || runtime.length !== 1) {
|
|
108
|
+
throw new IrLoweringBlockedError(`a coercion with ${runtime.length} operand(s) has no IR primitive`);
|
|
109
|
+
}
|
|
110
|
+
const resolved = resolveRequiredOperand(ctx, block, lineage, only);
|
|
111
|
+
const representation = requireResultRepresentation(ctx, operation, 'value', 'a coercion computation');
|
|
112
|
+
if (representationKey(resolved.representation) === representationKey(representation)) {
|
|
113
|
+
registerResult(ctx, operation, resolved.value);
|
|
114
|
+
return;
|
|
115
|
+
}
|
|
116
|
+
if (operation.operator === 'ToNumeric' &&
|
|
117
|
+
resolved.representation.kind === 'dynamic' &&
|
|
118
|
+
representation.kind === 'scalar' &&
|
|
119
|
+
representation.domain === 'number') {
|
|
120
|
+
registerResult(ctx, operation, ctx.builder.compute(block, lineage, 'unary', 'ToNumeric', [resolved], representation));
|
|
121
|
+
return;
|
|
122
|
+
}
|
|
123
|
+
if (operation.operator === 'ToNumeric' && representation.kind === 'scalar' && representation.domain === 'number') {
|
|
124
|
+
const node = ctx.program.conversions.coercionFor(resolved.representation, 'ToNumber');
|
|
125
|
+
if (node.capability.kind === 'identity') {
|
|
126
|
+
registerResult(ctx, operation, resolved.value);
|
|
127
|
+
return;
|
|
128
|
+
}
|
|
129
|
+
if (node.capability.kind !== 'never') {
|
|
130
|
+
registerResult(ctx, operation, ctx.builder.convert(block, lineage, node.id, resolved, node.target));
|
|
131
|
+
return;
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
throw new IrLoweringBlockedError(`no IR primitive performs "${operation.operator}" from ${representationKey(resolved.representation)} ` +
|
|
135
|
+
`to ${representationKey(representation)}`);
|
|
136
|
+
}
|
|
137
|
+
// `?:` evaluates exactly one arm, so its value is a merge, not an operator
|
|
138
|
+
// over two evaluated operands. The arms already ran in their own blocks --
|
|
139
|
+
// the conditional edges the producer published put them there -- and this
|
|
140
|
+
// runs unconditionally, which means the flow controller has already closed
|
|
141
|
+
// both arms into the join by the time it reaches here.
|
|
142
|
+
// `a && b` and `a || b` are the same merge as `?:` with the guard doubling as
|
|
143
|
+
// one of the arms: `a && b` is `a` on the falsy side and `b` on the truthy
|
|
144
|
+
// one.
|
|
145
|
+
//
|
|
146
|
+
// `a ?? b` is the same merge again, over a different question: presence, not
|
|
147
|
+
// truth -- `0 ?? 1` is `0` where `0 || 1` is `1` -- and `branchArmOf`
|
|
148
|
+
// (lower-flow.ts) already carries that on the test rather than the branch, so
|
|
149
|
+
// the kept side is `sources.truthy` exactly as for `||`. Only the carrier
|
|
150
|
+
// differs, and `mergeIncoming` makes that unwrap an explicit conversion
|
|
151
|
+
// rather than something the phi assumes.
|
|
152
|
+
if (operation.form === 'logical' && (operation.operator === '&&' || operation.operator === '||' || operation.operator === '??')) {
|
|
153
|
+
const lineage = requireLineage(operation);
|
|
154
|
+
const left = namedOperand(operation, 'left');
|
|
155
|
+
if (left.source.kind !== 'result')
|
|
156
|
+
throw new IrLoweringBlockedError('a logical computation has no guard result to merge over');
|
|
157
|
+
const sources = flow.requireMergeSources(left.source.result);
|
|
158
|
+
const shortCircuit = operation.operator === '&&' ? sources.falsy : sources.truthy;
|
|
159
|
+
const evaluated = operation.operator === '&&' ? sources.truthy : sources.falsy;
|
|
160
|
+
const representation = requireResultRepresentation(ctx, operation, 'value', 'a logical computation');
|
|
161
|
+
// Same as the conditional below: a merge whose carrier is `void` has no
|
|
162
|
+
// value to merge.
|
|
163
|
+
if (representation.kind === 'void')
|
|
164
|
+
return;
|
|
165
|
+
const incoming = [
|
|
166
|
+
{ block: shortCircuit, value: mergeIncoming(ctx, shortCircuit, lineage, operation, 'kept', left, representation) },
|
|
167
|
+
{
|
|
168
|
+
block: evaluated,
|
|
169
|
+
value: mergeIncoming(ctx, evaluated, lineage, operation, 'taken', namedOperand(operation, 'right'), representation)
|
|
170
|
+
}
|
|
171
|
+
];
|
|
172
|
+
registerResult(ctx, operation, ctx.builder.phi(sources.join, lineage, incoming, representation));
|
|
173
|
+
return;
|
|
174
|
+
}
|
|
175
|
+
if (operation.form === 'conditional') {
|
|
176
|
+
const lineage = requireLineage(operation);
|
|
177
|
+
const guard = namedOperand(operation, 'condition').source;
|
|
178
|
+
if (guard.kind !== 'result')
|
|
179
|
+
throw new IrLoweringBlockedError('a conditional computation has no guard result to merge over');
|
|
180
|
+
const sources = flow.requireMergeSources(guard.result);
|
|
181
|
+
// Each arm's value is materialized in that arm's own block: a constant
|
|
182
|
+
// placed in the join would be an incoming value the predecessor never had.
|
|
183
|
+
const representation = requireResultRepresentation(ctx, operation, 'value', 'a conditional computation');
|
|
184
|
+
// `cond ? f() : g()` where both calls return `void` merges nothing: `void`
|
|
185
|
+
// is the carrier for "there is no value", so neither arm minted an SSA name
|
|
186
|
+
// and a phi here would merge two names nobody wrote. The branch itself is
|
|
187
|
+
// already built -- the flow controller opened and closed both arms from the
|
|
188
|
+
// conditional edges the producer published -- and the arms' own operations
|
|
189
|
+
// ran inside them. What is left is only the value, and there is none.
|
|
190
|
+
if (representation.kind === 'void')
|
|
191
|
+
return;
|
|
192
|
+
const consequent = mergeIncoming(ctx, sources.truthy, lineage, operation, 'consequent', namedOperand(operation, 'consequent'), representation);
|
|
193
|
+
const alternate = mergeIncoming(ctx, sources.falsy, lineage, operation, 'alternate', namedOperand(operation, 'alternate'), representation);
|
|
194
|
+
registerResult(ctx, operation, ctx.builder.phi(sources.join, lineage, [
|
|
195
|
+
{ block: sources.truthy, value: consequent },
|
|
196
|
+
{ block: sources.falsy, value: alternate }
|
|
197
|
+
], representation));
|
|
198
|
+
return;
|
|
199
|
+
}
|
|
200
|
+
// `k in o` is `[[HasProperty]]` -- ECMA-262 13.10.1 step 7 names the internal
|
|
201
|
+
// method outright -- so it lowers to the same IR primitive a property access
|
|
202
|
+
// uses rather than to a compute form of its own. One primitive means one
|
|
203
|
+
// renderer: a receiver that owns a runtime property table answers from that
|
|
204
|
+
// table, a closed layout answers from its own required fields, and neither
|
|
205
|
+
// spelling can drift from the other because there is only one.
|
|
206
|
+
//
|
|
207
|
+
// The operand roles are the operator's, not the internal method's, and they
|
|
208
|
+
// are the reverse of each other: `in`'s LEFT operand is the key and its RIGHT
|
|
209
|
+
// is the object. They are resolved by role rather than by position so that
|
|
210
|
+
// reversal is stated once, here, instead of being re-derived by every reader
|
|
211
|
+
// of a two-operand list.
|
|
212
|
+
if (operation.form === 'in') {
|
|
213
|
+
const lineage = requireLineage(operation);
|
|
214
|
+
const key = operandOf(operation, 'left');
|
|
215
|
+
const receiver = operandOf(operation, 'right');
|
|
216
|
+
if (!key || !receiver)
|
|
217
|
+
throw new IrLoweringBlockedError('an "in" computation is missing its key operand or its object operand');
|
|
218
|
+
const representation = requireResultRepresentation(ctx, operation, 'value', 'an "in" computation');
|
|
219
|
+
registerResult(ctx, operation, ctx.builder.hasProperty(block, lineage, resolveRequiredOperand(ctx, block, lineage, receiver), resolveRequiredOperand(ctx, block, lineage, key), representation));
|
|
220
|
+
return;
|
|
221
|
+
}
|
|
222
|
+
// `void x` is the one operator that never READS its operand: it orders the
|
|
223
|
+
// operand's evaluation and then yields `undefined` (ECMA-262 13.5.2). The
|
|
224
|
+
// evaluation is already the operand's own operation in this graph, so all
|
|
225
|
+
// that is left here is the constant -- and that matters for `void f()` where
|
|
226
|
+
// `f` returns nothing, because `void` is the carrier for "there is no value"
|
|
227
|
+
// and `build.ts` mints no SSA name for one. Citing that operand would be
|
|
228
|
+
// asking for a name nobody wrote; the operator's answer is `undefined`
|
|
229
|
+
// either way, so it is dropped rather than resolved. This is the same
|
|
230
|
+
// question `return f()` already asks in a `void` function, asked by the same
|
|
231
|
+
// predicate, so the two cannot drift.
|
|
232
|
+
if (operation.form === 'unary' && operation.operator === 'void') {
|
|
233
|
+
const lineage = requireLineage(operation);
|
|
234
|
+
const discarded = namedOperand(operation, 'operand');
|
|
235
|
+
const operands = namesVoidResult(ctx, discarded) ? [] : [resolveRequiredOperand(ctx, block, lineage, discarded)];
|
|
236
|
+
const representation = requireResultRepresentation(ctx, operation, 'value', 'a unary "void" computation');
|
|
237
|
+
registerResult(ctx, operation, ctx.builder.compute(block, lineage, 'unary', 'void', operands, representation));
|
|
238
|
+
return;
|
|
239
|
+
}
|
|
240
|
+
// `typeof` and `template` join the operator forms rather than getting paths
|
|
241
|
+
// of their own: each takes its evaluated operands and produces one value,
|
|
242
|
+
// which is exactly the shape this tail already lowers. What they *render* as
|
|
243
|
+
// differs -- a constant for most `typeof`s, a concatenation for a template --
|
|
244
|
+
// but that is the target's answer to give, not this layer's.
|
|
245
|
+
if (operation.form !== 'unary' &&
|
|
246
|
+
operation.form !== 'binary' &&
|
|
247
|
+
operation.form !== 'update' &&
|
|
248
|
+
operation.form !== 'equality' &&
|
|
249
|
+
operation.form !== 'typeof' &&
|
|
250
|
+
operation.form !== 'instanceof' &&
|
|
251
|
+
operation.form !== 'template') {
|
|
252
|
+
throw new IrLoweringBlockedError(`no IR primitive lowers a computation of form "${operation.form}"`);
|
|
253
|
+
}
|
|
254
|
+
const lineage = requireLineage(operation);
|
|
255
|
+
// A compute operand is raw for every form but one: a mixed-carrier
|
|
256
|
+
// `binary` operator's operands are coerced (ToNumber/ToString, 13.15.3 and
|
|
257
|
+
// 7.2.13) before the operator runs, and the slot census states which
|
|
258
|
+
// (`projection/slots.ts`'s `binarySlot`), so they enter like any slot.
|
|
259
|
+
const operands = operation.operands
|
|
260
|
+
.filter((operand) => operand.evaluation.kind !== 'provenance' && !(operation.operator === 'ObjectTag' && operand.role === 'ignored-argument'))
|
|
261
|
+
.map((operand) => enter(ctx, block, lineage, operation, operand, resolveRequiredOperand(ctx, block, lineage, operand)));
|
|
262
|
+
const representation = requireResultRepresentation(ctx, operation, 'value', `a ${operation.form} computation`);
|
|
263
|
+
registerResult(ctx, operation, ctx.builder.compute(block, lineage, operation.form, operation.operator, operands, representation));
|
|
264
|
+
};
|
|
265
|
+
const lowerBinding = (ctx, block, operation) => {
|
|
266
|
+
switch (operation.action) {
|
|
267
|
+
case 'declare':
|
|
268
|
+
// A binding cell coming into existence has no runtime value of its own
|
|
269
|
+
// to materialize; TDZ behavior is carried on the *read* operation
|
|
270
|
+
// instead (`BindingOperation.temporalDeadZone`), not on this event.
|
|
271
|
+
return;
|
|
272
|
+
case 'read': {
|
|
273
|
+
const lineage = requireLineage(operation);
|
|
274
|
+
const representation = requireResultRepresentation(ctx, operation, 'value', 'a binding read');
|
|
275
|
+
if (operation.commonJs) {
|
|
276
|
+
registerResult(ctx, operation, ctx.builder.commonJsBinding(block, lineage, operation.commonJs.global, operation.commonJs.owner, representation));
|
|
277
|
+
return;
|
|
278
|
+
}
|
|
279
|
+
// A generic function named as a VALUE has no cell to read: nothing
|
|
280
|
+
// instantiated it here, so no copy's callable exists. What the name
|
|
281
|
+
// denotes is which member of the choice it is, and that is a constant
|
|
282
|
+
// -- the index the set's carrier tags it by (`generic-function-set`,
|
|
283
|
+
// representation/model.ts).
|
|
284
|
+
if (representation.kind === 'generic-function-set') {
|
|
285
|
+
const index = representation.members.indexOf(operation.declaration);
|
|
286
|
+
if (index >= 0) {
|
|
287
|
+
registerResult(ctx, operation, ctx.builder.constant(block, lineage, String(index), 'number', representation));
|
|
288
|
+
return;
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
registerResult(ctx, operation, narrowedBindingRead(ctx, block, lineage, operation, operation.declaration, representation));
|
|
292
|
+
return;
|
|
293
|
+
}
|
|
294
|
+
case 'write':
|
|
295
|
+
case 'initialize': {
|
|
296
|
+
const lineage = requireLineage(operation);
|
|
297
|
+
const value = enterRequiredOperand(ctx, block, lineage, operation, singleValueOperand(operation));
|
|
298
|
+
if (operation.commonJs) {
|
|
299
|
+
ctx.builder.commonJsBindingSet(block, lineage, operation.commonJs.global, operation.commonJs.owner, value);
|
|
300
|
+
registerResult(ctx, operation, value.value);
|
|
301
|
+
return;
|
|
302
|
+
}
|
|
303
|
+
ctx.builder.bindingWrite(block, lineage, operation.declaration, value);
|
|
304
|
+
// An assignment expression's own value is exactly the value it wrote:
|
|
305
|
+
// reusing that SSA id is exact, not approximate, and avoids a second IR
|
|
306
|
+
// instruction that would just restate a value already in hand.
|
|
307
|
+
registerResult(ctx, operation, value.value);
|
|
308
|
+
return;
|
|
309
|
+
}
|
|
310
|
+
}
|
|
311
|
+
};
|
|
312
|
+
/**
|
|
313
|
+
* Whether a body's result slot holds nothing at all -- a `void` result, or
|
|
314
|
+
* the async/generator wrappers around one (`promise(void)`, an iterator whose
|
|
315
|
+
* completion is `void`) -- so a `return f()` of a void call has nothing to
|
|
316
|
+
* hand back. Mirrors `buildReturnObligations`' own payload selection
|
|
317
|
+
* (`preflight/obligations-graph.ts`).
|
|
318
|
+
*/
|
|
319
|
+
const returnsNoValue = (abi) => {
|
|
320
|
+
if (!abi)
|
|
321
|
+
return true;
|
|
322
|
+
const result = abi.result;
|
|
323
|
+
const payload = result.kind === 'promise' ? result.value : result.kind === 'iterator' ? result.completion : result;
|
|
324
|
+
return payload.kind === 'void';
|
|
325
|
+
};
|
|
326
|
+
const lowerControl = (ctx, flow, blockStarts, block, operation) => {
|
|
327
|
+
switch (operation.form) {
|
|
328
|
+
case 'debugger':
|
|
329
|
+
case 'branch':
|
|
330
|
+
// `debugger` has no observable effect worth carrying into the IR;
|
|
331
|
+
// `branch` is a pure marker -- its actual control transfer is already
|
|
332
|
+
// built from `ConditionalEdge` membership by the flow controller.
|
|
333
|
+
return;
|
|
334
|
+
case 'return': {
|
|
335
|
+
const lineage = requireLineage(operation);
|
|
336
|
+
const returned = operandOf(operation, 'value', 0);
|
|
337
|
+
// `() => f()` where `f` returns `void` returns *nothing*: the call minted
|
|
338
|
+
// no value because `void` is the carrier for "there is none". Unless the
|
|
339
|
+
// enclosing function's own result HOLDS something -- `return
|
|
340
|
+
// sys.exit(code)` in a `number | void` function -- where the language
|
|
341
|
+
// hands the caller `undefined`, the stored form of "no value"
|
|
342
|
+
// (`representation/primitives.ts`'s `storedCarrier`), converted into
|
|
343
|
+
// the result exactly as a written
|
|
344
|
+
// `return undefined` would be.
|
|
345
|
+
const value = namesVoidResult(ctx, returned) &&
|
|
346
|
+
(returnsNoValue(ctx.abi) || (returned !== undefined && ctx.constantDeriver.isNeverType(returned.type)))
|
|
347
|
+
? null
|
|
348
|
+
: resolveOptionalOperand(ctx, block, lineage, returned);
|
|
349
|
+
ctx.builder.return(block, lineage, value !== null && returned !== undefined ? enter(ctx, block, lineage, operation, returned, value) : value);
|
|
350
|
+
return;
|
|
351
|
+
}
|
|
352
|
+
case 'throw': {
|
|
353
|
+
const lineage = requireLineage(operation);
|
|
354
|
+
const value = resolveRequiredOperand(ctx, block, lineage, namedOperand(operation, 'value'));
|
|
355
|
+
// Into the one carrier a handler catches, never the operand's own. See
|
|
356
|
+
// `thrownValueCarrier` (`lower-exceptions.ts`) for why a native C++
|
|
357
|
+
// `throw` cannot be left carrying the thrown expression's static type:
|
|
358
|
+
// C++ matches a handler BY TYPE, so `throw "boom"` emitting
|
|
359
|
+
// `throw v0;` of a `std::string` simply walked past the
|
|
360
|
+
// `catch (const gea::Value&)` the same source program wrote. That
|
|
361
|
+
// compiled clean and certified clean, and terminated the process.
|
|
362
|
+
const thrown = convertOrDrift(ctx, block, lineage, operation.id, 'value', 0, value, thrownValueCarrier);
|
|
363
|
+
ctx.builder.throw(block, lineage, thrown);
|
|
364
|
+
return;
|
|
365
|
+
}
|
|
366
|
+
case 'break':
|
|
367
|
+
case 'continue': {
|
|
368
|
+
const lineage = requireLineage(operation);
|
|
369
|
+
// A transfer out of a loop names the loop, and the loop's own header,
|
|
370
|
+
// latch and exit are the flow controller's to know -- `blockStarts`
|
|
371
|
+
// records where an operation was *lowered*, which for the loop marker
|
|
372
|
+
// is the header, and taking that for a `break` would restart the loop
|
|
373
|
+
// instead of leaving it.
|
|
374
|
+
//
|
|
375
|
+
// `continue` prefers the latch over the header: a `for` loop's own
|
|
376
|
+
// incrementor must run before the condition is re-tested (ECMA-262
|
|
377
|
+
// `ForStatement` evaluation re-enters at the update expression, not the
|
|
378
|
+
// test), and `loopLatchOf` is `null` for exactly the loops that have no
|
|
379
|
+
// incrementor to run first -- a `while`, or a `for` with an empty
|
|
380
|
+
// update clause -- where jumping straight to the header is already
|
|
381
|
+
// correct.
|
|
382
|
+
const loop = completionTargetOf(ctx.graph, operation.id, operation.form);
|
|
383
|
+
// `break` out of a SWITCH is not a jump at all here. A switch lowers as a
|
|
384
|
+
// chain of guards, so leaving a clause is leaving that clause's arm --
|
|
385
|
+
// which is exactly what closing the arm's frame already does, at the join
|
|
386
|
+
// every other arm also reaches. Emitting a jump of our own would either
|
|
387
|
+
// duplicate that one or skip the intermediate joins a variable written in
|
|
388
|
+
// the clause needs its merge in.
|
|
389
|
+
//
|
|
390
|
+
// That is only true for a `break` at the END of its arm. One with
|
|
391
|
+
// statements after it inside the same arm -- `if (x) break; more()` --
|
|
392
|
+
// would have to skip them, and doing nothing runs them instead. The
|
|
393
|
+
// ordering keeps a scope's operations contiguous, so "nothing later
|
|
394
|
+
// shares this scope" is the whole question, and it is refused by name
|
|
395
|
+
// when the answer is no rather than compiled into a fall-through.
|
|
396
|
+
const targeted = loop === null ? null : ctx.graph.operations.get(loop);
|
|
397
|
+
if (targeted?.family === 'boundary' && targeted.boundary === 'label-target') {
|
|
398
|
+
throw new IrLoweringBlockedError('a break to a non-iteration label needs a post-label join block, which this CFG does not yet model');
|
|
399
|
+
}
|
|
400
|
+
if (targeted?.family === 'control' && targeted.form === 'switch') {
|
|
401
|
+
if (operation.form === 'continue') {
|
|
402
|
+
throw new IrLoweringBlockedError('a "continue" cannot name a switch; the graph resolved one to a switch operation');
|
|
403
|
+
}
|
|
404
|
+
// A `break` out of a switch is a jump to the statement's own exit --
|
|
405
|
+
// reserved by this very ask -- because a clause's arm end is no
|
|
406
|
+
// longer where the switch ends: a clause may fall through into the
|
|
407
|
+
// next one, and a statement may follow the break in its own clause.
|
|
408
|
+
ctx.builder.jump(block, lineage, flow.switchExitOf(targeted.id));
|
|
409
|
+
return;
|
|
410
|
+
}
|
|
411
|
+
const structural = loop === null ? null : operation.form === 'break' ? flow.loopExitOf(loop) : (flow.loopLatchOf(loop) ?? flow.loopHeaderOf(loop));
|
|
412
|
+
const target = structural ?? findCompletionTargetBlock(ctx.graph, blockStarts, operation.id, operation.form);
|
|
413
|
+
ctx.builder.jump(block, lineage, target);
|
|
414
|
+
return;
|
|
415
|
+
}
|
|
416
|
+
case 'loop': {
|
|
417
|
+
// A head-tested loop's blocks are the guard's own, plus the back edge the
|
|
418
|
+
// flow controller adds when it closes the taken arm -- so there is nothing
|
|
419
|
+
// left for this operation to lower. A conditionless `for (;;)` has the
|
|
420
|
+
// other loop shape the same controller already owns: opening its loop
|
|
421
|
+
// frame reserves a header, closing it emits an unconditional back edge,
|
|
422
|
+
// and the first `break` lazily reserves its exit. It therefore has no
|
|
423
|
+
// condition operand by construction and likewise places nothing here.
|
|
424
|
+
return;
|
|
425
|
+
}
|
|
426
|
+
case 'loop-tail':
|
|
427
|
+
// A tail-tested loop's blocks are entirely the flow controller's:
|
|
428
|
+
// `gating.ts` puts the body in the loop scope and the condition in that
|
|
429
|
+
// loop's latch, and `closeBackEdge` turns the latch's own end into the
|
|
430
|
+
// conditional back edge. Unlike the head-tested case there is nothing to
|
|
431
|
+
// check here -- a missing `condition` operand is not a gap but the
|
|
432
|
+
// `do { ... } while (true)` shape, whose back edge is unconditional.
|
|
433
|
+
return;
|
|
434
|
+
case 'await': {
|
|
435
|
+
// No suspension primitive backs this -- see `AwaitOperation`'s own
|
|
436
|
+
// comment (`ir/model.ts`) for why reading the operand's value right now
|
|
437
|
+
// is this backend's honest answer. The paired `async-resume` boundary
|
|
438
|
+
// (`lowerBoundary` below) publishes no value of its own: every consumer
|
|
439
|
+
// of `await x` cites this operation's own result instead
|
|
440
|
+
// (`producers/control.ts`'s `contributeAwait`).
|
|
441
|
+
const lineage = requireLineage(operation);
|
|
442
|
+
const operand = resolveRequiredOperand(ctx, block, lineage, namedOperand(operation, 'operand'));
|
|
443
|
+
const representation = optionalResultRepresentation(ctx, operation, 'value');
|
|
444
|
+
registerResult(ctx, operation, ctx.builder.await(block, lineage, operand, representation));
|
|
445
|
+
return;
|
|
446
|
+
}
|
|
447
|
+
case 'try':
|
|
448
|
+
// Every block a try statement needs -- the try body's, the catch
|
|
449
|
+
// handler's, the finally clause's, and the join the non-finally parts
|
|
450
|
+
// rejoin at on ordinary completion -- is built generically by the flow
|
|
451
|
+
// controller from this owner's "region" scope membership, exactly as an
|
|
452
|
+
// `if`'s arms are built from "guard" membership. The try marker itself
|
|
453
|
+
// computes nothing and writes no value.
|
|
454
|
+
//
|
|
455
|
+
// A `finally` clause needs no completion record here and no dispatch
|
|
456
|
+
// after it: `targets/cpp/emit-exceptions.ts` renders it as a SCOPE
|
|
457
|
+
// GUARD's destructor around the whole region, and C++ already runs a
|
|
458
|
+
// destructor on every way out of the scope it guards -- falling off the
|
|
459
|
+
// end, `return`, a `goto` past it (which is what `break`/`continue`
|
|
460
|
+
// lower to), and an exception unwinding. That is exactly ECMAScript's
|
|
461
|
+
// "the finally block runs whatever the completion", so the completions
|
|
462
|
+
// stay ordinary and only the SHAPES C++ cannot express refuse, by name,
|
|
463
|
+
// at emission: a `return`/`break`/`continue` written INSIDE the finally
|
|
464
|
+
// clause, which would leave the guard body rather than the function.
|
|
465
|
+
return;
|
|
466
|
+
case 'yield': {
|
|
467
|
+
// A real suspension: the enclosing body is emitted as a C++20 coroutine
|
|
468
|
+
// and this becomes `co_yield`. `yield*` never reaches here --
|
|
469
|
+
// `producers/control.ts` refuses it by name, because delegation is a loop
|
|
470
|
+
// and this position is the middle of an expression.
|
|
471
|
+
const lineage = requireLineage(operation);
|
|
472
|
+
const value = resolveOptionalOperand(ctx, block, lineage, operandOf(operation, 'value', 0));
|
|
473
|
+
const representation = optionalResultRepresentation(ctx, operation, 'value');
|
|
474
|
+
registerResult(ctx, operation, ctx.builder.yield(block, lineage, value, representation));
|
|
475
|
+
return;
|
|
476
|
+
}
|
|
477
|
+
case 'switch':
|
|
478
|
+
// A marker, ordered after everything inside the statement. A switch's
|
|
479
|
+
// dispatch IS the chain of guards `gating.ts` builds from the per-clause
|
|
480
|
+
// tests `producers/control.ts` mints, so the flow controller has already
|
|
481
|
+
// built every block and every transfer by the time this is reached; the
|
|
482
|
+
// one thing left is the statement's own exit, which the breaks inside it
|
|
483
|
+
// may have reserved and which control falling out of the last clause
|
|
484
|
+
// must now join.
|
|
485
|
+
flow.closeSwitch(operation.id, null);
|
|
486
|
+
return;
|
|
487
|
+
case 'label':
|
|
488
|
+
// A label around an iteration resolves at normalization to that loop's
|
|
489
|
+
// own completion target. The marker itself has no runtime work.
|
|
490
|
+
return;
|
|
491
|
+
}
|
|
492
|
+
};
|
|
493
|
+
/**
|
|
494
|
+
* The run-time half of a modelled `Object.setPrototypeOf(C.prototype,
|
|
495
|
+
* B.prototype)`. The base is read off the heritage value's carrier the same
|
|
496
|
+
* way `projection/classes.ts` reads it, so the class layout and this step
|
|
497
|
+
* name one class: the family's only member, or -- for a slot that also holds
|
|
498
|
+
* subclasses -- its declared class.
|
|
499
|
+
*/
|
|
500
|
+
const lowerPrototypeReparenting = (ctx, block, operation) => {
|
|
501
|
+
const classOperand = operandOf(operation, 'constructor');
|
|
502
|
+
const heritageOperand = operandOf(operation, 'heritage');
|
|
503
|
+
if (!classOperand || !heritageOperand || heritageOperand.source.kind !== 'result' || classOperand.source.kind !== 'result') {
|
|
504
|
+
throw new IrLoweringBlockedError('a prototype re-parenting names no evaluated class values to link');
|
|
505
|
+
}
|
|
506
|
+
const lineage = heritageOperand.source.result;
|
|
507
|
+
const classValue = resolveRequiredOperand(ctx, block, lineage, classOperand);
|
|
508
|
+
const heritage = resolveRequiredOperand(ctx, block, lineage, heritageOperand);
|
|
509
|
+
const carrier = heritage.representation;
|
|
510
|
+
const declared = carrier.kind === 'constructor-family' && carrier.abi.result.kind === 'class-ref' ? carrier.abi.result.declaration : null;
|
|
511
|
+
const base = carrier.kind !== 'constructor-family'
|
|
512
|
+
? null
|
|
513
|
+
: carrier.members.length === 1
|
|
514
|
+
? carrier.members[0]
|
|
515
|
+
: declared !== null && carrier.members.includes(declared)
|
|
516
|
+
? declared
|
|
517
|
+
: null;
|
|
518
|
+
if (base === null) {
|
|
519
|
+
throw new IrLoweringBlockedError(`a prototype re-parenting's heritage is carried as ${representationKey(carrier)}, which names no single class to inherit from`);
|
|
520
|
+
}
|
|
521
|
+
const classCarrier = classValue.representation;
|
|
522
|
+
if (!familyNamesClassCopy(ctx, classCarrier, operation.classDeclaration)) {
|
|
523
|
+
throw new IrLoweringBlockedError(`a prototype re-parenting's class value is carried as ${representationKey(classCarrier)}, not ${operation.classDeclaration}'s constructor`);
|
|
524
|
+
}
|
|
525
|
+
ctx.builder.reparentConstructor(block, lineage, operation.classDeclaration, base, classValue, heritage);
|
|
526
|
+
};
|
|
527
|
+
/**
|
|
528
|
+
* Whether a constructor-family names the class a census COPY belongs to.
|
|
529
|
+
*
|
|
530
|
+
* `class-lifecycle` events are minted inside the census's per-copy walk and
|
|
531
|
+
* name the copy (`decl|f0|1@0`), while a class VALUE's carrier names the
|
|
532
|
+
* physical class the copy was published under (`projection/classes.ts`) --
|
|
533
|
+
* the generic root when every copy shares one layout, and the copy's own
|
|
534
|
+
* layout when the generic is instantiated at several. Comparing the two
|
|
535
|
+
* spellings directly refused every static-side lowering of a generic class:
|
|
536
|
+
* a `static count = 0` on `class Box<T>` blocked with "declares receiver
|
|
537
|
+
* ... rather than that class's constructor value" for a class the program
|
|
538
|
+
* instantiates perfectly well.
|
|
539
|
+
*/
|
|
540
|
+
const familyNamesClassCopy = (ctx, carrier, copy) => {
|
|
541
|
+
if (carrier === null || carrier.kind !== 'constructor-family')
|
|
542
|
+
return false;
|
|
543
|
+
if (carrier.members.includes(copy))
|
|
544
|
+
return true;
|
|
545
|
+
const physical = classLayoutOfCopy(ctx.program.classes, copy)?.declaration;
|
|
546
|
+
return physical !== undefined && carrier.members.includes(physical);
|
|
547
|
+
};
|
|
548
|
+
/**
|
|
549
|
+
* The runtime half of class evaluation that a fixed class layout does not
|
|
550
|
+
* absorb.
|
|
551
|
+
*
|
|
552
|
+
* Methods and instance fields become emitted layout metadata, but a static
|
|
553
|
+
* field initializer is an expression the language evaluates once, in source
|
|
554
|
+
* order, with the class constructor as `this`. Lower it to the same ordinary
|
|
555
|
+
* call and constructor-property store that an authored `Class.key = value`
|
|
556
|
+
* uses. That keeps evaluation order in the enclosing region and lets the
|
|
557
|
+
* static-field storage census see one uniform IR operation for both source
|
|
558
|
+
* spellings.
|
|
559
|
+
*/
|
|
560
|
+
const lowerClassLifecycle = (ctx, block, operation) => {
|
|
561
|
+
if (operation.event === 'reparent-prototype') {
|
|
562
|
+
lowerPrototypeReparenting(ctx, block, operation);
|
|
563
|
+
return;
|
|
564
|
+
}
|
|
565
|
+
if (operation.event !== 'define-field' || operation.placement !== 'static')
|
|
566
|
+
return;
|
|
567
|
+
const initializerOperand = operandOf(operation, 'initializer');
|
|
568
|
+
if (!initializerOperand || initializerOperand.source.kind !== 'result')
|
|
569
|
+
return;
|
|
570
|
+
const lineage = initializerOperand.source.result;
|
|
571
|
+
const callee = resolveRequiredOperand(ctx, block, lineage, initializerOperand);
|
|
572
|
+
const abi = abiOfCallee(callee.representation);
|
|
573
|
+
if (!abi) {
|
|
574
|
+
throw new IrLoweringBlockedError(`a static field initializer is carried as ${representationKey(callee.representation)}, which declares no callable convention`);
|
|
575
|
+
}
|
|
576
|
+
const receiverRepresentation = abi.receiver;
|
|
577
|
+
if (!familyNamesClassCopy(ctx, receiverRepresentation, operation.classDeclaration)) {
|
|
578
|
+
throw new IrLoweringBlockedError(`a static field initializer for ${operation.classDeclaration} declares receiver ${receiverRepresentation ? representationKey(receiverRepresentation) : 'none'} rather than that class's constructor value`);
|
|
579
|
+
}
|
|
580
|
+
const constructorAllocation = [...ctx.graph.operations.values()].find((entry) => entry.family === 'allocation' &&
|
|
581
|
+
entry.allocated === 'class-constructor-object' &&
|
|
582
|
+
entry.classDeclaration === operation.classDeclaration);
|
|
583
|
+
const constructorValue = constructorAllocation ? resultOf(constructorAllocation, 'value') : undefined;
|
|
584
|
+
if (!constructorValue || constructorAllocation?.family !== 'allocation') {
|
|
585
|
+
throw new IrLoweringBlockedError(`a static field initializer for ${operation.classDeclaration} has no evaluated constructor object`);
|
|
586
|
+
}
|
|
587
|
+
const receiver = resolveRequiredOperand(ctx, block, lineage, {
|
|
588
|
+
role: 'receiver',
|
|
589
|
+
ordinal: 0,
|
|
590
|
+
evaluation: { kind: 'runtime' },
|
|
591
|
+
source: { kind: 'result', result: constructorValue.id },
|
|
592
|
+
type: constructorAllocation.shape
|
|
593
|
+
});
|
|
594
|
+
const result = ctx.builder.call(block, lineage, callee, receiver, [], abi.result);
|
|
595
|
+
if (result === null) {
|
|
596
|
+
throw new IrLoweringBlockedError(`a static field initializer for ${operation.classDeclaration} produces no value to store`);
|
|
597
|
+
}
|
|
598
|
+
const key = resolveRequiredOperand(ctx, block, lineage, namedOperand(operation, 'key'));
|
|
599
|
+
const stored = enter(ctx, block, lineage, operation, initializerOperand, { value: result, representation: abi.result });
|
|
600
|
+
ctx.builder.set(block, lineage, receiver, key, stored, true, null);
|
|
601
|
+
};
|
|
602
|
+
const lowerOneOperation = (ctx, flow, blockStarts, block, operation, plugins) => {
|
|
603
|
+
for (const plugin of plugins) {
|
|
604
|
+
if (plugin.lower(ctx, block, operation))
|
|
605
|
+
return;
|
|
606
|
+
}
|
|
607
|
+
switch (operation.family) {
|
|
608
|
+
case 'property':
|
|
609
|
+
lowerProperty(ctx, block, operation);
|
|
610
|
+
return;
|
|
611
|
+
case 'invocation':
|
|
612
|
+
lowerInvocation(ctx, block, operation);
|
|
613
|
+
return;
|
|
614
|
+
case 'computation':
|
|
615
|
+
lowerComputation(ctx, flow, block, operation);
|
|
616
|
+
return;
|
|
617
|
+
case 'protocol':
|
|
618
|
+
lowerProtocol(ctx, block, operation);
|
|
619
|
+
return;
|
|
620
|
+
case 'binding':
|
|
621
|
+
lowerBinding(ctx, block, operation);
|
|
622
|
+
return;
|
|
623
|
+
case 'allocation':
|
|
624
|
+
lowerAllocation(ctx, block, operation);
|
|
625
|
+
return;
|
|
626
|
+
case 'control':
|
|
627
|
+
lowerControl(ctx, flow, blockStarts, block, operation);
|
|
628
|
+
return;
|
|
629
|
+
case 'boundary':
|
|
630
|
+
lowerBoundary(ctx, block, operation);
|
|
631
|
+
return;
|
|
632
|
+
case 'class-lifecycle':
|
|
633
|
+
lowerClassLifecycle(ctx, block, operation);
|
|
634
|
+
return;
|
|
635
|
+
case 'element':
|
|
636
|
+
lowerElement(ctx, block, operation, plugins);
|
|
637
|
+
return;
|
|
638
|
+
case 'destructuring':
|
|
639
|
+
lowerDestructuring(ctx, flow, block, operation);
|
|
640
|
+
return;
|
|
641
|
+
case 'declaration-lifecycle':
|
|
642
|
+
// Linking and initializing a module binding are not runtime steps in a
|
|
643
|
+
// program laid out as one translation unit: an imported name resolves to
|
|
644
|
+
// the very cell the exporting module declares, so there is no second cell
|
|
645
|
+
// to copy into and no indirection to resolve at run time. What these
|
|
646
|
+
// events do carry is *order* -- a module body runs before the bodies that
|
|
647
|
+
// import it -- and order is already carried by the evaluation edges the
|
|
648
|
+
// producer publishes, which the block layout consumes before this point.
|
|
649
|
+
//
|
|
650
|
+
// The `value` result an `initialize` publishes is deliberately left
|
|
651
|
+
// unregistered rather than aliased to something plausible. Nothing that
|
|
652
|
+
// reads an imported name cites it (a read is a `binding` operation naming
|
|
653
|
+
// the same declaration), and if some consumer ever did, resolving its
|
|
654
|
+
// operand would find no SSA id and refuse -- which is the answer we want
|
|
655
|
+
// from a fact this layer cannot supply, instead of a value it invented.
|
|
656
|
+
return;
|
|
657
|
+
case 'reference': {
|
|
658
|
+
if (operation.form === 'global-this') {
|
|
659
|
+
const lineage = requireLineage(operation);
|
|
660
|
+
const representation = requireResultRepresentation(ctx, operation, 'value', `a globalThis reference (${operation.id})`);
|
|
661
|
+
const value = ctx.builder.globalThis(block, lineage, representation);
|
|
662
|
+
registerResult(ctx, operation, value);
|
|
663
|
+
return;
|
|
664
|
+
}
|
|
665
|
+
// `this` is one reference form that publishes a value, so it is one
|
|
666
|
+
// that lowers: the frame's receiver becomes an SSA value every
|
|
667
|
+
// consumer of `this` then cites like any other result.
|
|
668
|
+
if (operation.form === 'this') {
|
|
669
|
+
const lineage = requireLineage(operation);
|
|
670
|
+
// Ordinarily `receiver`; `captured-receiver` for the one case
|
|
671
|
+
// `semantics/normalize/producers/references.ts`'s `buildThisReference`
|
|
672
|
+
// mints it instead -- a `this` inside an arrow that already-confirmed
|
|
673
|
+
// resolves to an enclosing class's own instance. Both name the same
|
|
674
|
+
// `{kind: 'receiver'}`-sourced operand; only the role differs, and only
|
|
675
|
+
// so `ir/lower-operands.ts`'s `resolveRequiredOperand` can tell a
|
|
676
|
+
// proven capture apart from a receiver this body's own convention
|
|
677
|
+
// simply never declared.
|
|
678
|
+
const operand = operandOf(operation, 'receiver', 0) ??
|
|
679
|
+
operandOf(operation, 'captured-receiver', 0) ??
|
|
680
|
+
namedOperand(operation, 'static-class-receiver');
|
|
681
|
+
const resolved = resolveRequiredOperand(ctx, block, lineage, operand);
|
|
682
|
+
registerResult(ctx, operation, resolved.value);
|
|
683
|
+
return;
|
|
684
|
+
}
|
|
685
|
+
if (operation.form === 'super-property') {
|
|
686
|
+
// `references.ts`'s `buildSuperReference` reads the same physical
|
|
687
|
+
// frame receiver `this` does, but the checker types bare `super` as
|
|
688
|
+
// the BASE class, so the plan selects a base-class `class-ref` --
|
|
689
|
+
// unlike the derived carrier the receiver slot physically is.
|
|
690
|
+
// Aliasing `this`'s own SSA id (as above) would publish this result
|
|
691
|
+
// under an id whose definition is derived-shaped, and
|
|
692
|
+
// `ir/verify.ts`'s `representationConsistencyGuard` requires every
|
|
693
|
+
// citing operand to match its definition exactly -- a `get`/`call`
|
|
694
|
+
// receiver citing this result states the base carrier, not `this`'s.
|
|
695
|
+
// So a genuinely new SSA definition is minted, at the plan's base
|
|
696
|
+
// representation -- the same `receiver` primitive `this` uses,
|
|
697
|
+
// called again. Emission (`emitReceiver`) declares the C++ local
|
|
698
|
+
// from the frame's ABI receiver slot, not this representation
|
|
699
|
+
// (`defineValue`'s spelling override), so the local is genuinely
|
|
700
|
+
// the derived C++ type and the base carrier is plan-level only --
|
|
701
|
+
// the implicit upcast (`derivesFrom`, `emit-callable.ts`) is free
|
|
702
|
+
// wherever this value is later read into a base-declared slot.
|
|
703
|
+
const lineage = requireLineage(operation);
|
|
704
|
+
const representation = requireResultRepresentation(ctx, operation, 'value', `a super reference (${operation.id})`);
|
|
705
|
+
const value = ctx.builder.receiver(block, lineage, representation);
|
|
706
|
+
registerResult(ctx, operation, value);
|
|
707
|
+
return;
|
|
708
|
+
}
|
|
709
|
+
// `parameter-value` is the other reference form that publishes a value:
|
|
710
|
+
// the raw argument a defaulted parameter's own guard tests, before
|
|
711
|
+
// `default-value` (`ir/lower-destructuring.ts`) runs the initializer
|
|
712
|
+
// over it. Resolving its one `{kind: 'parameter'}` operand is exactly
|
|
713
|
+
// what a non-defaulted parameter's own binding read already does; the
|
|
714
|
+
// only difference is that this result exists to be a guard, not a named
|
|
715
|
+
// binding.
|
|
716
|
+
if (operation.form === 'parameter-value') {
|
|
717
|
+
const lineage = requireLineage(operation);
|
|
718
|
+
const resolved = resolveRequiredOperand(ctx, block, lineage, namedOperand(operation, 'argument'));
|
|
719
|
+
registerResult(ctx, operation, resolved.value);
|
|
720
|
+
return;
|
|
721
|
+
}
|
|
722
|
+
// A name with no declaration anywhere is the fourth reference form that
|
|
723
|
+
// publishes a value, for the same reason `this` does: there is no cell,
|
|
724
|
+
// so `references.ts`'s `buildReference` publishes the `value` result
|
|
725
|
+
// directly rather than minting a `binding` read nothing could ever
|
|
726
|
+
// satisfy (`hasNoCell`; see that file's own citation-side comment for
|
|
727
|
+
// why this is honest, not a fiction). A citing operand -- an argument, a
|
|
728
|
+
// callee slot -- still needs a real SSA id either way; which id it gets
|
|
729
|
+
// splits on `unresolvableThrows`, the one case ECMA-262 does not make
|
|
730
|
+
// this a throw (13.5.1.2's `typeof` carve-out, `references.ts`'s
|
|
731
|
+
// `isTypeofOperand`) kept apart from the ordinary case by
|
|
732
|
+
// `ReferenceOperation.hasNoCell`'s own comment.
|
|
733
|
+
if (operation.hasNoCell && operation.form === 'identifier') {
|
|
734
|
+
const lineage = requireLineage(operation);
|
|
735
|
+
const representation = requireResultRepresentation(ctx, operation, 'value', `an unresolvable reference (${operation.id})`);
|
|
736
|
+
// `GetValue` (6.2.5.6) throws before a Reference Record's usual
|
|
737
|
+
// read/write pair would even apply -- `emitUnresolvableReference`
|
|
738
|
+
// (`targets/cpp/emit.ts`) is where the citer's SSA id gets a value: a
|
|
739
|
+
// call to a `[[noreturn]]` templated runtime helper, well-typed at
|
|
740
|
+
// whatever carrier the plan selected, that throws the ReferenceError
|
|
741
|
+
// this read really is when the C++ actually reaches it.
|
|
742
|
+
if (operation.unresolvableThrows) {
|
|
743
|
+
const value = ctx.builder.unresolvableReference(block, lineage, representation);
|
|
744
|
+
registerResult(ctx, operation, value);
|
|
745
|
+
return;
|
|
746
|
+
}
|
|
747
|
+
// The one case that is NOT a throw: `typeof` on an unresolvable
|
|
748
|
+
// reference returns `"undefined"` (13.5.1.2) without ever calling
|
|
749
|
+
// `GetValue` -- so the citer's SSA id is a plain constant `undefined`,
|
|
750
|
+
// materialized directly at whatever carrier the plan selected for this
|
|
751
|
+
// result. An untyped global's carrier is ordinarily `dynamic`, which
|
|
752
|
+
// is why `targets/cpp/types.ts`'s `cppConstantLiteral` had to gain a
|
|
753
|
+
// `dynamic` case for the `undefined`/`null` literal forms alongside
|
|
754
|
+
// this: a boxed `gea::Value()` for exactly this constant, not
|
|
755
|
+
// something specific to this call site. `three.js`'s `typeof
|
|
756
|
+
// Float16Array !== 'undefined'` is exactly this shape, and is the
|
|
757
|
+
// reason this branch exists at all rather than falling to the refusal
|
|
758
|
+
// below: reaching that refusal here would silently withhold every
|
|
759
|
+
// host-absence feature-detection guard in the corpus, the defect
|
|
760
|
+
// `unresolvable-names.ts`'s own doc comment is about.
|
|
761
|
+
const value = ctx.builder.constant(block, lineage, 'undefined', 'undefined', representation);
|
|
762
|
+
registerResult(ctx, operation, value);
|
|
763
|
+
return;
|
|
764
|
+
}
|
|
765
|
+
// Resolving a BOUND name is not an operation the substrate performs: the
|
|
766
|
+
// Reference Record it publishes exists so a read or a write can name the
|
|
767
|
+
// binding, and both carry the declaration themselves. Nothing here can
|
|
768
|
+
// cite the reference as a value -- an operand that tried would find no
|
|
769
|
+
// registered SSA id and be refused, which is the answer we want. (The
|
|
770
|
+
// one exception, an UNBOUND name, is handled above rather than here.)
|
|
771
|
+
return;
|
|
772
|
+
}
|
|
773
|
+
default:
|
|
774
|
+
throw new IrLoweringBlockedError(`no IR primitive lowers a semantic operation of family "${operation.family}"`);
|
|
775
|
+
}
|
|
776
|
+
};
|
|
777
|
+
/**
|
|
778
|
+
* Where a generator's own `FunctionDeclarationInstantiation` work ends --
|
|
779
|
+
* `null` when there is nothing to run early, or when the prologue's own
|
|
780
|
+
* operations do not form a clean prefix of `order` (a hoisted function
|
|
781
|
+
* declaration sharing the entry scope with the formals is the one shape that
|
|
782
|
+
* can do this; `lower-graph.ts`'s `parameterPrologue` only orders the
|
|
783
|
+
* prologue ahead of such a declaration, never ahead of arbitrary later code)
|
|
784
|
+
* -- in which case this owner keeps the single, unsplit coroutine shape it
|
|
785
|
+
* always had rather than risk cutting at a point that is not actually safe.
|
|
786
|
+
*
|
|
787
|
+
* `generatorPrologueBoundary` is a MARKER, not a transform: `ir/generator-
|
|
788
|
+
* split.ts` is what actually carves the body, once `placements` -- which
|
|
789
|
+
* this stage does not have -- is available to give the inner coroutine's own
|
|
790
|
+
* copy of each bridged cell its own identity.
|
|
791
|
+
*/
|
|
792
|
+
const generatorPrologueBoundaryOf = (graph, order, parameterPrologue, blockStarts, body) => {
|
|
793
|
+
// The gate: a plain `parameter` binding with nothing to run early (no
|
|
794
|
+
// default, no destructured pattern) needs no split -- the frame copy a
|
|
795
|
+
// coroutine's own parameters already get before `initial_suspend` runs is
|
|
796
|
+
// every one of those. Only a `destructuring` family operation -- the
|
|
797
|
+
// default's own guarded merge, or a pattern's extraction steps -- means
|
|
798
|
+
// there is real work here (`contributeDefaultedParameter`/`contributeParameter`
|
|
799
|
+
// mint one for a plain defaulted identifier too, so this also gates a bare
|
|
800
|
+
// `v = 5` correctly).
|
|
801
|
+
const hasRealWork = [...parameterPrologue].some((id) => graph.operations.get(id)?.family === 'destructuring');
|
|
802
|
+
if (!hasRealWork)
|
|
803
|
+
return null;
|
|
804
|
+
let lastPrologueIndex = -1;
|
|
805
|
+
for (let index = 0; index < order.length; index += 1)
|
|
806
|
+
if (parameterPrologue.has(order[index]))
|
|
807
|
+
lastPrologueIndex = index;
|
|
808
|
+
if (lastPrologueIndex < 0)
|
|
809
|
+
return null;
|
|
810
|
+
for (let index = 0; index <= lastPrologueIndex; index += 1) {
|
|
811
|
+
if (!parameterPrologue.has(order[index]))
|
|
812
|
+
return null;
|
|
813
|
+
}
|
|
814
|
+
const lastPrologueOperationId = order[lastPrologueIndex];
|
|
815
|
+
const cutBlockId = blockStarts.get(lastPrologueOperationId);
|
|
816
|
+
if (cutBlockId === undefined)
|
|
817
|
+
return null;
|
|
818
|
+
const cutBlock = body.blocks.get(cutBlockId);
|
|
819
|
+
if (!cutBlock)
|
|
820
|
+
return null;
|
|
821
|
+
// The block a prologue-marked SEMANTIC operation's own top-level
|
|
822
|
+
// `lowerOneOperation` call started in is only ever the block active when
|
|
823
|
+
// that call BEGAN -- a `default-value`/pattern-extraction operation that
|
|
824
|
+
// desugars to a guard and a merge (`lower-destructuring.ts`) opens its own
|
|
825
|
+
// arm blocks *inside* that one call, and nothing here ever records a
|
|
826
|
+
// `blockStarts` entry for them (`blockStarts` is populated once per
|
|
827
|
+
// semantic operation id in the owner's `order` loop, not once per physical
|
|
828
|
+
// block a single operation's own lowering happens to open). Walking
|
|
829
|
+
// `blockStarts` over `order`'s prefix therefore finds the guard's own block
|
|
830
|
+
// and the merge's, but silently drops the arm blocks the guard branches
|
|
831
|
+
// into -- an `if (has_value) { A } else { B }` split with only `A` or `B`
|
|
832
|
+
// marked outer, corrupting the cut. The forward CFG walk below asks the
|
|
833
|
+
// question `blockStarts` cannot: which physical blocks does execution
|
|
834
|
+
// actually pass through between the function's entry and the cut, and does
|
|
835
|
+
// every operation in each one belong to the prologue -- checked through
|
|
836
|
+
// `operationOfResult(operation.lineage)`, which resolves an IR-only
|
|
837
|
+
// synthesized step (this arm's own representation `convert`, say) back to
|
|
838
|
+
// the semantic operation that caused it to exist, exactly as the
|
|
839
|
+
// `cutBlock` scan below already relies on for its own, narrower question.
|
|
840
|
+
const successorsOf = (terminator) => {
|
|
841
|
+
switch (terminator.kind) {
|
|
842
|
+
case 'branch':
|
|
843
|
+
return [terminator.whenTrue, terminator.whenFalse];
|
|
844
|
+
case 'jump':
|
|
845
|
+
return [terminator.target];
|
|
846
|
+
case 'switch':
|
|
847
|
+
return [...terminator.cases.map((c) => c.target), terminator.defaultTarget];
|
|
848
|
+
case 'return':
|
|
849
|
+
case 'throw':
|
|
850
|
+
return [];
|
|
851
|
+
}
|
|
852
|
+
};
|
|
853
|
+
const outerBlocks = new Set();
|
|
854
|
+
const visited = new Set();
|
|
855
|
+
const queue = [body.entry];
|
|
856
|
+
let reachedCut = false;
|
|
857
|
+
while (queue.length > 0) {
|
|
858
|
+
const id = queue.shift();
|
|
859
|
+
if (visited.has(id))
|
|
860
|
+
continue;
|
|
861
|
+
visited.add(id);
|
|
862
|
+
const block = body.blocks.get(id);
|
|
863
|
+
if (!block)
|
|
864
|
+
return null;
|
|
865
|
+
if (id === cutBlockId) {
|
|
866
|
+
// The cut block's own tail -- the operations after `operationIndex`,
|
|
867
|
+
// computed below -- belongs to the inner half; this walk stops here
|
|
868
|
+
// rather than following its terminator, so nothing past the cut is
|
|
869
|
+
// ever asked to justify itself as prologue-owned.
|
|
870
|
+
outerBlocks.add(id);
|
|
871
|
+
reachedCut = true;
|
|
872
|
+
continue;
|
|
873
|
+
}
|
|
874
|
+
for (const operation of allOperationsOf(block)) {
|
|
875
|
+
if (operation.lineage !== null && !parameterPrologue.has(operationOfResult(operation.lineage)))
|
|
876
|
+
return null;
|
|
877
|
+
}
|
|
878
|
+
outerBlocks.add(id);
|
|
879
|
+
for (const next of successorsOf(block.terminator))
|
|
880
|
+
queue.push(next);
|
|
881
|
+
}
|
|
882
|
+
if (!reachedCut)
|
|
883
|
+
return null;
|
|
884
|
+
// The cut inside `cutBlock` itself: everything up to and including the
|
|
885
|
+
// block's own last prologue-owned operation stays outer; the rest -- and
|
|
886
|
+
// the block's terminator -- becomes the inner coroutine's own entry.
|
|
887
|
+
// Scanned from the front so a non-prologue operation interleaved BEFORE the
|
|
888
|
+
// last prologue one -- which should not happen, given the prefix check
|
|
889
|
+
// above, but is not this function's only safeguard against it -- stops the
|
|
890
|
+
// cut at the first such gap rather than past it.
|
|
891
|
+
let operationIndex = 0;
|
|
892
|
+
for (const operation of cutBlock.operations) {
|
|
893
|
+
if (!parameterPrologue.has(operationOfResult(operation.lineage)))
|
|
894
|
+
break;
|
|
895
|
+
operationIndex += 1;
|
|
896
|
+
}
|
|
897
|
+
return { block: cutBlockId, operationIndex, outerBlocks };
|
|
898
|
+
};
|
|
899
|
+
/** Iterator cleanup regions for complete for-of iterations and finite destructuring sequences. */
|
|
900
|
+
const iteratorCloseRegionsOf = (graph, membership, order, blockStarts, flow, ctx, blockOrder, successorsOfBlock, finiteBoundaries) => {
|
|
901
|
+
const regions = [];
|
|
902
|
+
const predecessors = new Map();
|
|
903
|
+
for (const block of blockOrder) {
|
|
904
|
+
for (const next of successorsOfBlock(block)) {
|
|
905
|
+
const known = predecessors.get(next);
|
|
906
|
+
if (known)
|
|
907
|
+
known.push(block);
|
|
908
|
+
else
|
|
909
|
+
predecessors.set(next, [block]);
|
|
910
|
+
}
|
|
911
|
+
}
|
|
912
|
+
/**
|
|
913
|
+
* Close a region's membership over the graph.
|
|
914
|
+
*
|
|
915
|
+
* `renderIteratorCloseRegion` emits the region as ONE C++ scope --
|
|
916
|
+
* `entry: { CompletionGuard g{...}; try { <every member block> } catch ... }`
|
|
917
|
+
* -- so the entry label is the only legal way in. A `goto` from outside into
|
|
918
|
+
* any OTHER member is rejected by clang twice over: it bypasses the guard's
|
|
919
|
+
* initialization and it jumps into a try block.
|
|
920
|
+
*
|
|
921
|
+
* The scan above seeds membership from OPERATIONS whose required scope names
|
|
922
|
+
* the loop, and a block that carries no operation of its own is named by
|
|
923
|
+
* none of them. `for (const v of xs) { if (v === 1) break }` lowers its empty
|
|
924
|
+
* `else` arm to exactly such a block: one `goto` to the loop's continue
|
|
925
|
+
* block and nothing else. Its successor was inside the region and it was
|
|
926
|
+
* left outside, which is the illegal edge itself -- so membership is a
|
|
927
|
+
* property of the GRAPH, not of what a block happens to hold.
|
|
928
|
+
*
|
|
929
|
+
* The fixed point pulls every predecessor of a non-entry member in. A
|
|
930
|
+
* predecessor that is not reachable FROM the entry cannot be pulled in
|
|
931
|
+
* without making the region multi-entry, so that refuses by name instead:
|
|
932
|
+
* emitting the region anyway would produce C++ that does not compile, and
|
|
933
|
+
* dropping the member would silently stop closing an iterator.
|
|
934
|
+
*/
|
|
935
|
+
const closeRegionOverGraph = (seen, entry, loop) => {
|
|
936
|
+
const reachableFromEntry = new Set([entry]);
|
|
937
|
+
const queue = [entry];
|
|
938
|
+
while (queue.length > 0) {
|
|
939
|
+
for (const next of successorsOfBlock(queue.pop())) {
|
|
940
|
+
if (reachableFromEntry.has(next))
|
|
941
|
+
continue;
|
|
942
|
+
reachableFromEntry.add(next);
|
|
943
|
+
queue.push(next);
|
|
944
|
+
}
|
|
945
|
+
}
|
|
946
|
+
const pending = [...seen];
|
|
947
|
+
while (pending.length > 0) {
|
|
948
|
+
const member = pending.pop();
|
|
949
|
+
if (member === entry)
|
|
950
|
+
continue;
|
|
951
|
+
for (const predecessor of predecessors.get(member) ?? []) {
|
|
952
|
+
if (seen.has(predecessor))
|
|
953
|
+
continue;
|
|
954
|
+
if (!reachableFromEntry.has(predecessor)) {
|
|
955
|
+
throw new IrLoweringBlockedError(`iterator-close region ${loop} is entered at ${member} from ${predecessor}, which its continue block ${entry} does not reach; ` +
|
|
956
|
+
'a cleanup region renders as one C++ scope whose guard and try block only the entry may pass');
|
|
957
|
+
}
|
|
958
|
+
seen.add(predecessor);
|
|
959
|
+
pending.push(predecessor);
|
|
960
|
+
}
|
|
961
|
+
}
|
|
962
|
+
};
|
|
963
|
+
for (const loop of order) {
|
|
964
|
+
const operation = graph.operations.get(loop);
|
|
965
|
+
if (!operation)
|
|
966
|
+
continue;
|
|
967
|
+
if (operation.family !== 'control' ||
|
|
968
|
+
operation.form !== 'loop' ||
|
|
969
|
+
operation.iteratorClose === null ||
|
|
970
|
+
operation.iteratorClose === undefined)
|
|
971
|
+
continue;
|
|
972
|
+
const close = graph.operations.get(operation.iteratorClose);
|
|
973
|
+
if (!close || close.family !== 'protocol' || close.step !== 'close') {
|
|
974
|
+
throw new IrLoweringBlockedError(`iterator loop ${loop} names no protocol close operation`);
|
|
975
|
+
}
|
|
976
|
+
const record = operandOf(close, 'iterator-record');
|
|
977
|
+
if (!record || record.source.kind !== 'result') {
|
|
978
|
+
throw new IrLoweringBlockedError(`iterator close ${close.id} has no iterator-record result to preserve`);
|
|
979
|
+
}
|
|
980
|
+
const iterator = resolveResultValue(ctx, record.source.result, `iterator-close region for ${loop}`);
|
|
981
|
+
if (iterator.representation.kind !== 'dynamic' &&
|
|
982
|
+
iterator.representation.kind !== 'record' &&
|
|
983
|
+
iterator.representation.kind !== 'native-record-ref' &&
|
|
984
|
+
iterator.representation.kind !== 'iterator') {
|
|
985
|
+
throw new IrLoweringBlockedError(`iterator-close region ${loop} received a ${iterator.representation.kind} carrier; only dynamic, concrete record, or generator iterators can close`);
|
|
986
|
+
}
|
|
987
|
+
const guard = membership.guardOfLoop(loop);
|
|
988
|
+
const continueTarget = flow.loopHeaderOf(loop);
|
|
989
|
+
const normalExitTarget = flow.loopNormalExitOf(loop);
|
|
990
|
+
const bodyEntry = flow.loopBodyEntryOf(loop);
|
|
991
|
+
if (guard === null || continueTarget === null || normalExitTarget === null || bodyEntry === null) {
|
|
992
|
+
throw new IrLoweringBlockedError(`iterator loop ${loop} has no head-test body or continuation block`);
|
|
993
|
+
}
|
|
994
|
+
const seen = new Set([continueTarget, bodyEntry]);
|
|
995
|
+
for (const id of order) {
|
|
996
|
+
const scope = membership.requiredScopeOf(id);
|
|
997
|
+
if (!scope.some((ref) => ref.kind === 'loop' && ref.loop === loop))
|
|
998
|
+
continue;
|
|
999
|
+
const block = blockStarts.get(id);
|
|
1000
|
+
if (block !== undefined)
|
|
1001
|
+
seen.add(block);
|
|
1002
|
+
}
|
|
1003
|
+
closeRegionOverGraph(seen, continueTarget, loop);
|
|
1004
|
+
const blocks = blockOrder.filter((block) => seen.has(block));
|
|
1005
|
+
const lineage = resultOf(close, 'completion')?.id;
|
|
1006
|
+
if (!lineage)
|
|
1007
|
+
throw new IrLoweringBlockedError(`iterator-close ${close.id} published no completion lineage`);
|
|
1008
|
+
regions.push({
|
|
1009
|
+
loop,
|
|
1010
|
+
lineage,
|
|
1011
|
+
iterator,
|
|
1012
|
+
entry: continueTarget,
|
|
1013
|
+
blocks,
|
|
1014
|
+
dismissTargets: [continueTarget, normalExitTarget],
|
|
1015
|
+
onlyIfOpen: false,
|
|
1016
|
+
bodyEntry
|
|
1017
|
+
});
|
|
1018
|
+
}
|
|
1019
|
+
for (const boundary of finiteBoundaries) {
|
|
1020
|
+
const close = graph.operations.get(boundary.close);
|
|
1021
|
+
if (!close || close.family !== 'destructuring' || close.form !== 'array-pattern-close')
|
|
1022
|
+
continue;
|
|
1023
|
+
const operand = operandOf(close, 'iterator');
|
|
1024
|
+
if (!operand || operand.source.kind !== 'result') {
|
|
1025
|
+
throw new IrLoweringBlockedError(`finite iterator close ${close.id} has no iterator result to preserve`);
|
|
1026
|
+
}
|
|
1027
|
+
const iterator = resolveResultValue(ctx, operand.source.result, `finite iterator-close region ${close.id}`);
|
|
1028
|
+
const lineage = resultOf(close, 'completion')?.id;
|
|
1029
|
+
if (!lineage)
|
|
1030
|
+
throw new IrLoweringBlockedError(`finite iterator close ${close.id} published no completion lineage`);
|
|
1031
|
+
const first = blockOrder.indexOf(boundary.entry);
|
|
1032
|
+
const last = blockOrder.indexOf(boundary.exit);
|
|
1033
|
+
if (first < 0 || last < first)
|
|
1034
|
+
throw new IrLoweringBlockedError(`finite iterator close ${close.id} has an invalid block interval`);
|
|
1035
|
+
regions.push({
|
|
1036
|
+
loop: close.id,
|
|
1037
|
+
lineage,
|
|
1038
|
+
iterator,
|
|
1039
|
+
entry: boundary.entry,
|
|
1040
|
+
blocks: blockOrder.slice(first, last + 1),
|
|
1041
|
+
dismissTargets: [],
|
|
1042
|
+
onlyIfOpen: true,
|
|
1043
|
+
// A finite pattern has no body to separate from its step. Its own
|
|
1044
|
+
// step/default split is the same question one level down and is not
|
|
1045
|
+
// answered here; see `IrIteratorCloseRegion.bodyEntry`.
|
|
1046
|
+
bodyEntry: null
|
|
1047
|
+
});
|
|
1048
|
+
}
|
|
1049
|
+
return regions;
|
|
1050
|
+
};
|
|
1051
|
+
const lowerOwner = (graph, plan, constantDeriver, program, abi, construct, abiRefusal, owner, operationIds, plugins, ownerEdges, regionParts, deferredIteratorCloses,
|
|
1052
|
+
/** Whether this owner is a `function*` -- see `generatorPrologueBoundary` below. */
|
|
1053
|
+
isGenerator) => {
|
|
1054
|
+
// Membership first: the execution order below keeps each branch's operations
|
|
1055
|
+
// contiguous, which it can only do once every operation's scope chain is
|
|
1056
|
+
// known. Nothing in the membership reads a position from the list it is
|
|
1057
|
+
// given, so this is a dependency, not a cycle.
|
|
1058
|
+
const membership = collectConditionalMembership(graph, operationIds, ownerEdges);
|
|
1059
|
+
const { order, parameterPrologue } = orderOwnerOperations(graph, operationIds, membership, ownerEdges, regionParts);
|
|
1060
|
+
const builder = createIrBodyBuilder(physicalBodyId(owner, 'default'), owner, abi, construct);
|
|
1061
|
+
const ctx = {
|
|
1062
|
+
graph,
|
|
1063
|
+
plan,
|
|
1064
|
+
constantDeriver,
|
|
1065
|
+
program,
|
|
1066
|
+
abi,
|
|
1067
|
+
abiRefusal,
|
|
1068
|
+
builder,
|
|
1069
|
+
values: new Map(),
|
|
1070
|
+
shortCircuits: new Map()
|
|
1071
|
+
};
|
|
1072
|
+
const blockStarts = new Map();
|
|
1073
|
+
const finiteCloseStarts = new Map();
|
|
1074
|
+
const finiteCloseByStart = new Map();
|
|
1075
|
+
for (const id of order) {
|
|
1076
|
+
const close = graph.operations.get(id);
|
|
1077
|
+
if (!close || close.family !== 'destructuring' || close.form !== 'array-pattern-close')
|
|
1078
|
+
continue;
|
|
1079
|
+
const iterator = operandOf(close, 'iterator');
|
|
1080
|
+
if (!iterator || iterator.source.kind !== 'result')
|
|
1081
|
+
continue;
|
|
1082
|
+
const source = operationOfResult(iterator.source.result);
|
|
1083
|
+
const first = ownerEdges.find((edge) => edge.kind === 'evaluation' && edge.from === source)?.to;
|
|
1084
|
+
if (first && first !== close.id) {
|
|
1085
|
+
finiteCloseStarts.set(close.id, first);
|
|
1086
|
+
finiteCloseByStart.set(first, close.id);
|
|
1087
|
+
}
|
|
1088
|
+
}
|
|
1089
|
+
const finiteEntries = new Map();
|
|
1090
|
+
const finiteBoundaries = [];
|
|
1091
|
+
const flow = createFlowController({
|
|
1092
|
+
builder,
|
|
1093
|
+
membership,
|
|
1094
|
+
resolveGuardOperand: (guard) => resolveResultValue(ctx, guard, `conditional guard ${guard}`)
|
|
1095
|
+
});
|
|
1096
|
+
for (const operationId of order) {
|
|
1097
|
+
const operation = graph.operations.get(operationId);
|
|
1098
|
+
if (!operation)
|
|
1099
|
+
continue;
|
|
1100
|
+
// IteratorClose is owned by its `for`-`of` completion region. Positioning
|
|
1101
|
+
// it in ordinary flow would invoke `.return()` before the loop body.
|
|
1102
|
+
if (operation.family === 'protocol' && operation.step === 'close' && deferredIteratorCloses.has(operation.id))
|
|
1103
|
+
continue;
|
|
1104
|
+
// A resume boundary that publishes nothing places nothing: `await` and
|
|
1105
|
+
// `yield` both fall straight through here (`lowerBoundary`), so resolving a
|
|
1106
|
+
// scope for one only risks `enterScope`'s "still terminated" fallback
|
|
1107
|
+
// manufacturing a stray block, read downstream as a body that falls off its
|
|
1108
|
+
// end -- a bogus `return`.
|
|
1109
|
+
//
|
|
1110
|
+
// An `exception-region` is the opposite and is excluded by name: it does
|
|
1111
|
+
// not sit inside the handler, it OPENS it. It is the only operation a
|
|
1112
|
+
// `catch {}` with an empty body owns, so skipping its scope resolution left
|
|
1113
|
+
// the catch part never entered, `IrTryRegion.catchEntry` null, and the whole
|
|
1114
|
+
// try statement refused at emission -- "no catch clause and no finally
|
|
1115
|
+
// primitive to explain the gap", a message describing an internal
|
|
1116
|
+
// inconsistency for what is an ordinary ES2019 program (`maps`'s network
|
|
1117
|
+
// handler, and `test/fixtures/try-catch-empty.ts`). The ordering hazard that
|
|
1118
|
+
// motivated skipping it is gone: `orderOwnerOperations` now schedules a
|
|
1119
|
+
// catch part's own opener before every non-prologue member of that part
|
|
1120
|
+
// (`lower-graph.ts`), so the scope is entered before anything in the
|
|
1121
|
+
// handler can terminate the block.
|
|
1122
|
+
if (operation.family === 'boundary' && operation.results.length === 0 && operation.boundary !== 'exception-region') {
|
|
1123
|
+
lowerOneOperation(ctx, flow, blockStarts, flow.currentBlock(), operation, plugins);
|
|
1124
|
+
continue;
|
|
1125
|
+
}
|
|
1126
|
+
const scope = membership.requiredScopeOf(operationId);
|
|
1127
|
+
// `branch`, `switch`, `debugger` and the two LOOP markers compute nothing
|
|
1128
|
+
// and place nothing: the transfers they stand for are built by the flow
|
|
1129
|
+
// controller out of scope membership, so `lowerControl` returns on sight.
|
|
1130
|
+
// They still have to be POSITIONED -- unwinding the frames their scope
|
|
1131
|
+
// leaves is what closes the arms of the very construct they mark -- but
|
|
1132
|
+
// they must not be given a block of their own once every path has already
|
|
1133
|
+
// ended, because that block is an orphan `lower.ts` then terminates with a
|
|
1134
|
+
// valueless `return`. See `enterScope`.
|
|
1135
|
+
//
|
|
1136
|
+
// The loop markers belong here for a reason a head-tested loop never
|
|
1137
|
+
// shows: a statement's marker is ordered after everything inside it, so a
|
|
1138
|
+
// loop whose body cannot fall out of the bottom reaches its own marker
|
|
1139
|
+
// with every path already terminated. `while (true)` inside a `try`, with
|
|
1140
|
+
// the only ways out a `return` and a `yield`, is exactly that shape --
|
|
1141
|
+
// mongodb's `AbstractCursor[Symbol.asyncIterator]` and
|
|
1142
|
+
// `test/fixtures/loop-iteration-helper-repro.ts`. The block opened for the
|
|
1143
|
+
// marker there held zero operations and was reached from nothing, and
|
|
1144
|
+
// `builder.seal` rejected the whole body: certified clean, 0 lines of C++.
|
|
1145
|
+
const placesNothing = operation.family === 'control' &&
|
|
1146
|
+
(operation.form === 'branch' ||
|
|
1147
|
+
operation.form === 'switch' ||
|
|
1148
|
+
operation.form === 'debugger' ||
|
|
1149
|
+
operation.form === 'loop' ||
|
|
1150
|
+
operation.form === 'loop-tail');
|
|
1151
|
+
// An optional chain's own value is a merge, and a merge needs both arms
|
|
1152
|
+
// closed. That is true exactly once this operation's own guards have
|
|
1153
|
+
// unwound, because unwinding is what closes them -- asking any earlier finds
|
|
1154
|
+
// the guard still open and blocks. It must also run *before* any guard this
|
|
1155
|
+
// operation's own scope newly opens, because a guard whose boolean test is
|
|
1156
|
+
// itself a short-circuit result -- `options?.mirror ? a() : b()`, whose
|
|
1157
|
+
// ternary guard is the property access's own `short-circuit` result --
|
|
1158
|
+
// resolves that test while `enterScope` is still running, not after it
|
|
1159
|
+
// returns. Passing the settle step in as a callback `enterScope` runs at
|
|
1160
|
+
// exactly that point keeps `lower-flow.ts` ignorant of what a short circuit
|
|
1161
|
+
// is, while still settling at the one moment that is safe.
|
|
1162
|
+
let block = flow.enterScope(scope, () => settleShortCircuits(ctx, flow, ctx.shortCircuits, scope), placesNothing);
|
|
1163
|
+
const finiteCloseAtStart = finiteCloseByStart.get(operationId);
|
|
1164
|
+
if (finiteCloseAtStart) {
|
|
1165
|
+
const close = graph.operations.get(finiteCloseAtStart);
|
|
1166
|
+
const lineage = close ? (resultOf(close, 'completion')?.id ?? null) : null;
|
|
1167
|
+
block = flow.splitCurrentBlock(lineage);
|
|
1168
|
+
finiteEntries.set(finiteCloseAtStart, { start: operationId, entry: block });
|
|
1169
|
+
}
|
|
1170
|
+
blockStarts.set(operationId, block);
|
|
1171
|
+
const finiteStart = finiteCloseStarts.get(operationId);
|
|
1172
|
+
if (operation.family === 'destructuring' && operation.form === 'array-pattern-close' && finiteStart) {
|
|
1173
|
+
const entry = finiteEntries.get(operation.id);
|
|
1174
|
+
if (!entry)
|
|
1175
|
+
throw new IrLoweringBlockedError(`finite iterator close ${operation.id} has no opened cleanup entry`);
|
|
1176
|
+
finiteBoundaries.push({ close: operation.id, start: entry.start, entry: entry.entry, exit: block });
|
|
1177
|
+
flow.splitCurrentBlock(resultOf(operation, 'completion')?.id ?? null);
|
|
1178
|
+
continue;
|
|
1179
|
+
}
|
|
1180
|
+
lowerOneOperation(ctx, flow, blockStarts, block, operation, plugins);
|
|
1181
|
+
}
|
|
1182
|
+
// Anything still pending is a chain whose value no operation outside its
|
|
1183
|
+
// guard ever consumed, so there is nothing to merge into. It is left unbuilt
|
|
1184
|
+
// rather than forced: `flow.finish()` is the only thing that can close those
|
|
1185
|
+
// arms, and after it there is no block left to put a join in. A read of an
|
|
1186
|
+
// unbuilt merge is not silent -- `resolveRequiredOperand` refuses by name.
|
|
1187
|
+
const finalState = flow.finish();
|
|
1188
|
+
if (!finalState.alreadyTerminated) {
|
|
1189
|
+
// A body that runs off its end completes normally -- that is what a module
|
|
1190
|
+
// body and a `void` function do, and neither writes a `return` for it. The
|
|
1191
|
+
// terminator is synthesized because the CFG needs one, and it cites nothing
|
|
1192
|
+
// because nothing in the source authored it; attributing it to whichever
|
|
1193
|
+
// operation happened to be last would be the fabrication this refuses.
|
|
1194
|
+
builder.return(finalState.block, null, null);
|
|
1195
|
+
}
|
|
1196
|
+
try {
|
|
1197
|
+
const iteratorCloseRegions = iteratorCloseRegionsOf(graph, membership, order, blockStarts, flow, ctx, builder.blockOrder(), builder.successorsOfBlock, finiteBoundaries);
|
|
1198
|
+
const sealed = builder.seal(flow.regionsOpened().map((info) => ({
|
|
1199
|
+
region: info.region,
|
|
1200
|
+
tryEntry: info.tryEntry,
|
|
1201
|
+
catchEntry: info.catchEntry,
|
|
1202
|
+
finallyEntry: info.finallyEntry,
|
|
1203
|
+
finallyExit: info.finallyExit,
|
|
1204
|
+
join: info.join
|
|
1205
|
+
})), iteratorCloseRegions);
|
|
1206
|
+
if (!isGenerator)
|
|
1207
|
+
return sealed;
|
|
1208
|
+
const boundary = generatorPrologueBoundaryOf(graph, order, parameterPrologue, blockStarts, sealed);
|
|
1209
|
+
return boundary === null ? sealed : { ...sealed, generatorPrologueBoundary: boundary };
|
|
1210
|
+
}
|
|
1211
|
+
catch (error) {
|
|
1212
|
+
throw new IrLoweringBlockedError(`IR verification failed for owner ${owner}: ${error.message}`);
|
|
1213
|
+
}
|
|
1214
|
+
};
|
|
1215
|
+
/**
|
|
1216
|
+
* The plugins' reactive-field statement, merged the identical way
|
|
1217
|
+
* `compiler.ts` merges it into `HostSpellings.reactive.fields` (later plugin
|
|
1218
|
+
* wins per class, same as every other plugin table there) -- but gated on a
|
|
1219
|
+
* plugin also naming a cell to hold one in, empty otherwise. Recomputed here
|
|
1220
|
+
* rather than threaded in from `compiler.ts`'s `hosts.reactive.fields`
|
|
1221
|
+
* because `lowerToIr` already receives `plugins` and nothing else in
|
|
1222
|
+
* `IrLoweringInput` depends on the target's `HostSpellings`; adding that
|
|
1223
|
+
* dependency to gain one table would make lowering depend on a target
|
|
1224
|
+
* concern for a fact both sides can derive from the same plugins.
|
|
1225
|
+
*/
|
|
1226
|
+
const mergedReactiveClassFields = (plugins) => {
|
|
1227
|
+
const cell = plugins.reduce((claimed, plugin) => plugin.capabilities.nativeReactiveCell ?? claimed, null);
|
|
1228
|
+
return cell === null ? new Map() : new Map(plugins.flatMap((plugin) => [...plugin.capabilities.reactiveClassFields]));
|
|
1229
|
+
};
|
|
1230
|
+
/**
|
|
1231
|
+
* The reverse of `mergedReactiveClassFields`: the FIELD declarations it
|
|
1232
|
+
* names, rather than the class declarations it is keyed by -- see
|
|
1233
|
+
* `LoweringProgram.reactiveFieldDeclarations`.
|
|
1234
|
+
*/
|
|
1235
|
+
const reactiveFieldDeclarationsOf = (classes, reactiveFields) => {
|
|
1236
|
+
const declarations = new Set();
|
|
1237
|
+
for (const layout of classes.values()) {
|
|
1238
|
+
const owned = reactiveFields.get(layout.declaration);
|
|
1239
|
+
if (!owned || owned.size === 0)
|
|
1240
|
+
continue;
|
|
1241
|
+
for (const field of layout.fields)
|
|
1242
|
+
if (owned.has(field.key))
|
|
1243
|
+
declarations.add(field.declaration);
|
|
1244
|
+
}
|
|
1245
|
+
return declarations;
|
|
1246
|
+
};
|
|
1247
|
+
export const lowerToIr = (input) => {
|
|
1248
|
+
const constantDeriver = input.deriver;
|
|
1249
|
+
const reactiveFields = mergedReactiveClassFields(input.plugins);
|
|
1250
|
+
const program = {
|
|
1251
|
+
abis: input.abis,
|
|
1252
|
+
constructs: input.constructs,
|
|
1253
|
+
callableOrigins: input.callableOrigins,
|
|
1254
|
+
callableOwnPropertyWrites: input.callableOwnPropertyWrites,
|
|
1255
|
+
functionPrototypePropertyWrites: input.functionPrototypePropertyWrites,
|
|
1256
|
+
classes: input.classes,
|
|
1257
|
+
slots: input.slots,
|
|
1258
|
+
conversions: input.conversions,
|
|
1259
|
+
drift: [],
|
|
1260
|
+
methodValueReceivers: new Map(),
|
|
1261
|
+
reactiveFields,
|
|
1262
|
+
reactiveFieldDeclarations: reactiveFieldDeclarationsOf(input.classes, reactiveFields)
|
|
1263
|
+
};
|
|
1264
|
+
const groups = groupOperationsByOwner(input.graph);
|
|
1265
|
+
const bodies = new Map();
|
|
1266
|
+
const blocked = [];
|
|
1267
|
+
const functionFacts = new Map();
|
|
1268
|
+
// The graph is sealed: its loop-owned closes are identical for every body.
|
|
1269
|
+
// Collect once instead of scanning the entire program for each function.
|
|
1270
|
+
const deferredIteratorCloses = new Set();
|
|
1271
|
+
for (const operation of input.graph.operations.values()) {
|
|
1272
|
+
if (operation.family === 'control' && operation.form === 'loop' && operation.iteratorClose)
|
|
1273
|
+
deferredIteratorCloses.add(operation.iteratorClose);
|
|
1274
|
+
if (operation.family === 'allocation' && operation.callable && operation.functionSource !== undefined) {
|
|
1275
|
+
functionFacts.set(operation.callable, {
|
|
1276
|
+
functionSource: operation.functionSource,
|
|
1277
|
+
functionName: operation.functionName ?? '',
|
|
1278
|
+
functionLength: operation.functionLength ?? 0,
|
|
1279
|
+
generator: operation.generatorFunction === true
|
|
1280
|
+
});
|
|
1281
|
+
}
|
|
1282
|
+
}
|
|
1283
|
+
// A function whose body is empty owns no operations, so grouping the graph by
|
|
1284
|
+
// owner never mentions it -- and yet it is a real function with a real
|
|
1285
|
+
// convention that a `CallableObject` still names the thunk of.
|
|
1286
|
+
// `Settings.absorbTouch() {}` is the shape that proved it: two apps emitted a
|
|
1287
|
+
// reference to a symbol nothing defined, with no refusal recorded anywhere,
|
|
1288
|
+
// because a body that is never built cannot refuse. The projected ABI table
|
|
1289
|
+
// is the authority on which functions this program has, so an owner it names
|
|
1290
|
+
// and the graph does not is lowered from no operations rather than dropped.
|
|
1291
|
+
const owners = new Map(groups);
|
|
1292
|
+
for (const owner of input.abis.keys())
|
|
1293
|
+
if (!owners.has(owner))
|
|
1294
|
+
owners.set(owner, []);
|
|
1295
|
+
// The edge table, dealt to the owner that holds each edge's target, once.
|
|
1296
|
+
//
|
|
1297
|
+
// Both per-owner passes below are filters over the whole table that keep only
|
|
1298
|
+
// the edges landing inside the owner (`collectConditionalMembership` tests
|
|
1299
|
+
// `members.has(edge.to)`; `orderOwnerOperations` reaches the table only
|
|
1300
|
+
// through `addPrecedence`, which refuses any pair with an endpoint outside
|
|
1301
|
+
// `members`). Running them against the whole table made lowering cost
|
|
1302
|
+
// owners x edges, three scans per body, which is the same shape the capability
|
|
1303
|
+
// census carried until it was dealt the same way. The share is dealt in
|
|
1304
|
+
// `graph.edges` order, so each pass sees the identical subsequence it selected
|
|
1305
|
+
// for itself before, and emits the identical order.
|
|
1306
|
+
const ownerOfOperation = new Map();
|
|
1307
|
+
for (const [owner, operationIds] of owners)
|
|
1308
|
+
for (const id of operationIds)
|
|
1309
|
+
ownerOfOperation.set(id, owner);
|
|
1310
|
+
const edgesByOwner = new Map();
|
|
1311
|
+
for (const edge of input.graph.edges) {
|
|
1312
|
+
const owner = ownerOfOperation.get(edge.to);
|
|
1313
|
+
if (owner === undefined)
|
|
1314
|
+
continue;
|
|
1315
|
+
const bucket = edgesByOwner.get(owner);
|
|
1316
|
+
if (bucket)
|
|
1317
|
+
bucket.push(edge);
|
|
1318
|
+
else
|
|
1319
|
+
edgesByOwner.set(owner, [edge]);
|
|
1320
|
+
}
|
|
1321
|
+
// Global on purpose -- see `collectRegionParts`. Splitting this one per owner
|
|
1322
|
+
// would change which operation each group's opener is, and with it the order
|
|
1323
|
+
// the bodies emit.
|
|
1324
|
+
const regionParts = collectRegionParts(input.graph);
|
|
1325
|
+
const noEdges = [];
|
|
1326
|
+
for (const [owner, operationIds] of owners) {
|
|
1327
|
+
try {
|
|
1328
|
+
// A region is not called, so it has no convention; a function that has one
|
|
1329
|
+
// must use the projected one, and a function whose projection was blocked
|
|
1330
|
+
// gets `null` -- which its first parameter read then refuses, naming the
|
|
1331
|
+
// ABI position it could not resolve rather than inventing a frame.
|
|
1332
|
+
const abi = input.abis.get(owner) ?? null;
|
|
1333
|
+
const construct = input.constructs.get(owner) ?? null;
|
|
1334
|
+
const abiRefusal = input.abiBlockers.get(owner) ?? null;
|
|
1335
|
+
const facts = functionFacts.get(owner);
|
|
1336
|
+
const body = lowerOwner(input.graph, input.plan, constantDeriver, program, abi, construct, abiRefusal, owner, operationIds, input.plugins, edgesByOwner.get(owner) ?? noEdges, regionParts, deferredIteratorCloses, facts?.generator === true);
|
|
1337
|
+
bodies.set(body.owner, facts === undefined ? body : { ...body, ...facts });
|
|
1338
|
+
}
|
|
1339
|
+
catch (error) {
|
|
1340
|
+
if (!(error instanceof IrLoweringBlockedError))
|
|
1341
|
+
throw error;
|
|
1342
|
+
blocked.push({ owner, reason: error.message });
|
|
1343
|
+
}
|
|
1344
|
+
}
|
|
1345
|
+
return { bodies, blocked: Object.freeze(blocked), slotDrift: Object.freeze(program.drift) };
|
|
1346
|
+
};
|