@scriptc/compiler 0.2.6 → 0.2.8
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/ambient/scriptc-node-fallback.d.ts +7 -18
- package/dist/backend/cycle-analysis.d.ts +21 -9
- package/dist/backend/cycle-analysis.js +139 -67
- package/dist/backend/cycle-analysis.js.map +1 -1
- package/dist/backend/cycle-analysis.test.js +283 -3
- package/dist/backend/cycle-analysis.test.js.map +1 -1
- package/dist/backend/cycle-mutability.d.ts +39 -0
- package/dist/backend/cycle-mutability.js +205 -0
- package/dist/backend/cycle-mutability.js.map +1 -0
- package/dist/backend/link-plan-core.d.ts +2 -1
- package/dist/backend/link-plan-core.js +15 -3
- package/dist/backend/link-plan-core.js.map +1 -1
- package/dist/backend/link-plan.d.ts +2 -1
- package/dist/backend/link-plan.js.map +1 -1
- package/dist/backend/llvm/alloc.d.ts +43 -0
- package/dist/backend/llvm/alloc.js +246 -0
- package/dist/backend/llvm/alloc.js.map +1 -0
- package/dist/backend/llvm/alloc.test.d.ts +1 -0
- package/dist/backend/llvm/alloc.test.js +102 -0
- package/dist/backend/llvm/alloc.test.js.map +1 -0
- package/dist/backend/llvm/blocks.d.ts +9 -0
- package/dist/backend/llvm/blocks.js +9 -0
- package/dist/backend/llvm/blocks.js.map +1 -1
- package/dist/backend/llvm/borrowed-receivers.d.ts +7 -0
- package/dist/backend/llvm/borrowed-receivers.js +39 -0
- package/dist/backend/llvm/borrowed-receivers.js.map +1 -1
- package/dist/backend/llvm/call-lifetimes.d.ts +18 -3
- package/dist/backend/llvm/call-lifetimes.js +54 -19
- package/dist/backend/llvm/call-lifetimes.js.map +1 -1
- package/dist/backend/llvm/call-lifetimes.test.js +178 -3
- package/dist/backend/llvm/call-lifetimes.test.js.map +1 -1
- package/dist/backend/llvm/checked-narrows.d.ts +24 -0
- package/dist/backend/llvm/checked-narrows.js +108 -0
- package/dist/backend/llvm/checked-narrows.js.map +1 -0
- package/dist/backend/llvm/checked-narrows.test.d.ts +1 -0
- package/dist/backend/llvm/checked-narrows.test.js +208 -0
- package/dist/backend/llvm/checked-narrows.test.js.map +1 -0
- package/dist/backend/llvm/classes.d.ts +16 -1
- package/dist/backend/llvm/classes.js +60 -49
- package/dist/backend/llvm/classes.js.map +1 -1
- package/dist/backend/llvm/classes.test.js +68 -6
- package/dist/backend/llvm/classes.test.js.map +1 -1
- package/dist/backend/llvm/common.d.ts +13 -0
- package/dist/backend/llvm/common.js +30 -0
- package/dist/backend/llvm/common.js.map +1 -1
- package/dist/backend/llvm/constant-callbacks.d.ts +19 -3
- package/dist/backend/llvm/constant-callbacks.js +289 -52
- package/dist/backend/llvm/constant-callbacks.js.map +1 -1
- package/dist/backend/llvm/constant-callbacks.test.js +140 -3
- package/dist/backend/llvm/constant-callbacks.test.js.map +1 -1
- package/dist/backend/llvm/debug-info.d.ts +6 -2
- package/dist/backend/llvm/debug-info.js +11 -1
- package/dist/backend/llvm/debug-info.js.map +1 -1
- package/dist/backend/llvm/dense-array-access.d.ts +29 -0
- package/dist/backend/llvm/dense-array-access.js +335 -0
- package/dist/backend/llvm/dense-array-access.js.map +1 -0
- package/dist/backend/llvm/dense-array-access.test.d.ts +1 -0
- package/dist/backend/llvm/dense-array-access.test.js +238 -0
- package/dist/backend/llvm/dense-array-access.test.js.map +1 -0
- package/dist/backend/llvm/dyn.d.ts +38 -0
- package/dist/backend/llvm/dyn.js +213 -14
- package/dist/backend/llvm/dyn.js.map +1 -1
- package/dist/backend/llvm/emitter.d.ts +308 -15
- package/dist/backend/llvm/emitter.js +1788 -206
- package/dist/backend/llvm/emitter.js.map +1 -1
- package/dist/backend/llvm/emitter.test.js +89 -7
- package/dist/backend/llvm/emitter.test.js.map +1 -1
- package/dist/backend/llvm/expr-async.js +62 -8
- package/dist/backend/llvm/expr-async.js.map +1 -1
- package/dist/backend/llvm/expr-async.test.d.ts +1 -0
- package/dist/backend/llvm/expr-async.test.js +62 -0
- package/dist/backend/llvm/expr-async.test.js.map +1 -0
- package/dist/backend/llvm/expr-bytes.d.ts +1 -1
- package/dist/backend/llvm/expr-bytes.js +85 -8
- package/dist/backend/llvm/expr-bytes.js.map +1 -1
- package/dist/backend/llvm/expr-callbacks.js +29 -21
- package/dist/backend/llvm/expr-callbacks.js.map +1 -1
- package/dist/backend/llvm/expr-calls.d.ts +5 -0
- package/dist/backend/llvm/expr-calls.js +118 -15
- package/dist/backend/llvm/expr-calls.js.map +1 -1
- package/dist/backend/llvm/expr-containers.d.ts +7 -1
- package/dist/backend/llvm/expr-containers.js +246 -32
- package/dist/backend/llvm/expr-containers.js.map +1 -1
- package/dist/backend/llvm/expr-control.js +113 -8
- package/dist/backend/llvm/expr-control.js.map +1 -1
- package/dist/backend/llvm/expr-dispatch.js +2 -0
- package/dist/backend/llvm/expr-dispatch.js.map +1 -1
- package/dist/backend/llvm/expr-dynamic.js +244 -44
- package/dist/backend/llvm/expr-dynamic.js.map +1 -1
- package/dist/backend/llvm/expr-island.js +3 -8
- package/dist/backend/llvm/expr-island.js.map +1 -1
- package/dist/backend/llvm/expr-primitives.d.ts +1 -1
- package/dist/backend/llvm/expr-primitives.js +93 -36
- package/dist/backend/llvm/expr-primitives.js.map +1 -1
- package/dist/backend/llvm/expr-primitives.test.js +51 -3
- package/dist/backend/llvm/expr-primitives.test.js.map +1 -1
- package/dist/backend/llvm/expr-records.js +31 -17
- package/dist/backend/llvm/expr-records.js.map +1 -1
- package/dist/backend/llvm/expr-stream-bridges.js +96 -29
- package/dist/backend/llvm/expr-stream-bridges.js.map +1 -1
- package/dist/backend/llvm/expr-stream-bridges.test.js +1 -1
- package/dist/backend/llvm/expr-stream-callbacks.js +6 -3
- package/dist/backend/llvm/expr-stream-callbacks.js.map +1 -1
- package/dist/backend/llvm/integer-remainder.d.ts +11 -0
- package/dist/backend/llvm/integer-remainder.js +91 -0
- package/dist/backend/llvm/integer-remainder.js.map +1 -1
- package/dist/backend/llvm/layouts.d.ts +3 -1
- package/dist/backend/llvm/layouts.js +3 -2
- package/dist/backend/llvm/layouts.js.map +1 -1
- package/dist/backend/llvm/lazy-captures.d.ts +16 -0
- package/dist/backend/llvm/lazy-captures.js +96 -0
- package/dist/backend/llvm/lazy-captures.js.map +1 -0
- package/dist/backend/llvm/lazy-captures.test.d.ts +1 -0
- package/dist/backend/llvm/lazy-captures.test.js +78 -0
- package/dist/backend/llvm/lazy-captures.test.js.map +1 -0
- package/dist/backend/llvm/lib-abi.js +10 -0
- package/dist/backend/llvm/lib-abi.js.map +1 -1
- package/dist/backend/llvm/lib-filesystem.js +10 -15
- package/dist/backend/llvm/lib-filesystem.js.map +1 -1
- package/dist/backend/llvm/lib-process.js +8 -8
- package/dist/backend/llvm/lib-process.js.map +1 -1
- package/dist/backend/llvm/lib-shared.js +1 -0
- package/dist/backend/llvm/lib-shared.js.map +1 -1
- package/dist/backend/llvm/local-array-reads.d.ts +5 -1
- package/dist/backend/llvm/local-array-reads.js +147 -26
- package/dist/backend/llvm/local-array-reads.js.map +1 -1
- package/dist/backend/llvm/local-array-reads.test.js +85 -4
- package/dist/backend/llvm/local-array-reads.test.js.map +1 -1
- package/dist/backend/llvm/local-union-storage.d.ts +5 -1
- package/dist/backend/llvm/local-union-storage.js +54 -8
- package/dist/backend/llvm/local-union-storage.js.map +1 -1
- package/dist/backend/llvm/local-union-storage.test.js +94 -6
- package/dist/backend/llvm/local-union-storage.test.js.map +1 -1
- package/dist/backend/llvm/map-number-lookup.d.ts +18 -0
- package/dist/backend/llvm/map-number-lookup.js +62 -0
- package/dist/backend/llvm/map-number-lookup.js.map +1 -0
- package/dist/backend/llvm/map-read-lifetimes.d.ts +6 -0
- package/dist/backend/llvm/map-read-lifetimes.js +24 -3
- package/dist/backend/llvm/map-read-lifetimes.js.map +1 -1
- package/dist/backend/llvm/map-read-lifetimes.test.js +39 -20
- package/dist/backend/llvm/map-read-lifetimes.test.js.map +1 -1
- package/dist/backend/llvm/nullable-fields.d.ts +28 -0
- package/dist/backend/llvm/nullable-fields.js +45 -0
- package/dist/backend/llvm/nullable-fields.js.map +1 -0
- package/dist/backend/llvm/nullable-fields.test.d.ts +1 -0
- package/dist/backend/llvm/nullable-fields.test.js +48 -0
- package/dist/backend/llvm/nullable-fields.test.js.map +1 -0
- package/dist/backend/llvm/nullable-unions.d.ts +68 -0
- package/dist/backend/llvm/nullable-unions.js +132 -0
- package/dist/backend/llvm/nullable-unions.js.map +1 -0
- package/dist/backend/llvm/publish.d.ts +58 -0
- package/dist/backend/llvm/publish.js +286 -0
- package/dist/backend/llvm/publish.js.map +1 -0
- package/dist/backend/llvm/rebound-parameters.d.ts +12 -0
- package/dist/backend/llvm/rebound-parameters.js +72 -0
- package/dist/backend/llvm/rebound-parameters.js.map +1 -0
- package/dist/backend/llvm/rebound-parameters.test.d.ts +1 -0
- package/dist/backend/llvm/rebound-parameters.test.js +67 -0
- package/dist/backend/llvm/rebound-parameters.test.js.map +1 -0
- package/dist/backend/llvm/reference-effects.d.ts +18 -2
- package/dist/backend/llvm/reference-effects.js +106 -16
- package/dist/backend/llvm/reference-effects.js.map +1 -1
- package/dist/backend/llvm/reference-effects.test.js +52 -1
- package/dist/backend/llvm/reference-effects.test.js.map +1 -1
- package/dist/backend/llvm/serialized-ir-emission.test.d.ts +1 -0
- package/dist/backend/llvm/serialized-ir-emission.test.js +52 -0
- package/dist/backend/llvm/serialized-ir-emission.test.js.map +1 -0
- package/dist/backend/llvm/shapes.d.ts +104 -9
- package/dist/backend/llvm/shapes.js +356 -46
- package/dist/backend/llvm/shapes.js.map +1 -1
- package/dist/backend/llvm/shapes.test.js +139 -5
- package/dist/backend/llvm/shapes.test.js.map +1 -1
- package/dist/backend/llvm/stack-callbacks.js +2 -3
- package/dist/backend/llvm/stack-callbacks.js.map +1 -1
- package/dist/backend/llvm/stack-captures.d.ts +3 -1
- package/dist/backend/llvm/stack-captures.js +5 -3
- package/dist/backend/llvm/stack-captures.js.map +1 -1
- package/dist/backend/llvm/stack-unions.test.js +43 -3
- package/dist/backend/llvm/stack-unions.test.js.map +1 -1
- package/dist/backend/llvm/string-construction.d.ts +10 -0
- package/dist/backend/llvm/string-construction.js +42 -0
- package/dist/backend/llvm/string-construction.js.map +1 -1
- package/dist/backend/llvm/string-construction.test.js +1 -1
- package/dist/backend/llvm/string-key-hash.d.ts +15 -0
- package/dist/backend/llvm/string-key-hash.js +76 -0
- package/dist/backend/llvm/string-key-hash.js.map +1 -0
- package/dist/backend/llvm/string-key-hash.test.d.ts +1 -0
- package/dist/backend/llvm/string-key-hash.test.js +45 -0
- package/dist/backend/llvm/string-key-hash.test.js.map +1 -0
- package/dist/backend/llvm/string-lifetimes.test.js +65 -15
- package/dist/backend/llvm/string-lifetimes.test.js.map +1 -1
- package/dist/backend/llvm/string-reads.d.ts +7 -0
- package/dist/backend/llvm/string-reads.js +76 -0
- package/dist/backend/llvm/string-reads.js.map +1 -0
- package/dist/backend/llvm/switch-dispatch.js +1 -1
- package/dist/backend/llvm/switch-dispatch.js.map +1 -1
- package/dist/backend/llvm/switch-dispatch.test.js +3 -3
- package/dist/backend/llvm/switch-dispatch.test.js.map +1 -1
- package/dist/backend/llvm/test-boxed-unions.d.ts +5 -0
- package/dist/backend/llvm/test-boxed-unions.js +13 -0
- package/dist/backend/llvm/test-boxed-unions.js.map +1 -0
- package/dist/backend/llvm/union-repr.d.ts +15 -0
- package/dist/backend/llvm/union-repr.js +89 -0
- package/dist/backend/llvm/union-repr.js.map +1 -0
- package/dist/backend/llvm/virtual-borrows.d.ts +31 -0
- package/dist/backend/llvm/virtual-borrows.js +82 -0
- package/dist/backend/llvm/virtual-borrows.js.map +1 -0
- package/dist/backend/llvm/walk-borrows.d.ts +43 -0
- package/dist/backend/llvm/walk-borrows.js +150 -0
- package/dist/backend/llvm/walk-borrows.js.map +1 -0
- package/dist/backend/llvm/walk-borrows.test.d.ts +1 -0
- package/dist/backend/llvm/walk-borrows.test.js +119 -0
- package/dist/backend/llvm/walk-borrows.test.js.map +1 -0
- package/dist/backend/llvm/walkers.d.ts +5 -1
- package/dist/backend/llvm/walkers.js +24 -21
- package/dist/backend/llvm/walkers.js.map +1 -1
- package/dist/backend/may-throw.d.ts +29 -1
- package/dist/backend/may-throw.js +349 -3
- package/dist/backend/may-throw.js.map +1 -1
- package/dist/backend/may-throw.test.js +114 -2
- package/dist/backend/may-throw.test.js.map +1 -1
- package/dist/backend/native/cache-warm.d.ts +2 -1
- package/dist/backend/native/cache-warm.js.map +1 -1
- package/dist/backend/native/contracts.d.ts +3 -2
- package/dist/backend/native/contracts.js.map +1 -1
- package/dist/backend/native/runtime-inputs.d.ts +1 -1
- package/dist/backend/native/runtime-inputs.js +2 -0
- package/dist/backend/native/runtime-inputs.js.map +1 -1
- package/dist/backend/native-codegen-core.d.ts +7 -4
- package/dist/backend/native-codegen-core.js +14 -9
- package/dist/backend/native-codegen-core.js.map +1 -1
- package/dist/backend/native-codegen.d.ts +9 -0
- package/dist/backend/native-codegen.js +53 -2
- package/dist/backend/native-codegen.js.map +1 -1
- package/dist/backend/native-codegen.test.js +64 -10
- package/dist/backend/native-codegen.test.js.map +1 -1
- package/dist/backend/native-link-info-core.d.ts +3 -2
- package/dist/backend/native-link-info-core.js.map +1 -1
- package/dist/backend/native-link-info.d.ts +2 -1
- package/dist/backend/native-link-info.js.map +1 -1
- package/dist/backend/native-link-info.test.js +2 -2
- package/dist/backend/native-link-info.test.js.map +1 -1
- package/dist/backend/native-tools.d.ts +5 -1
- package/dist/backend/native-tools.js +3 -1
- package/dist/backend/native-tools.js.map +1 -1
- package/dist/backend/optimization.d.ts +25 -0
- package/dist/backend/optimization.js +21 -0
- package/dist/backend/optimization.js.map +1 -0
- package/dist/backend/optimization.test.d.ts +1 -0
- package/dist/backend/optimization.test.js +24 -0
- package/dist/backend/optimization.test.js.map +1 -0
- package/dist/backend/publication.d.ts +28 -0
- package/dist/backend/publication.js +155 -0
- package/dist/backend/publication.js.map +1 -0
- package/dist/backend/publication.test.d.ts +1 -0
- package/dist/backend/publication.test.js +72 -0
- package/dist/backend/publication.test.js.map +1 -0
- package/dist/backend/runtime-abi.d.ts +2 -2
- package/dist/backend/runtime-abi.js +2 -2
- package/dist/backend/runtime-pack-core.d.ts +15 -4
- package/dist/backend/runtime-pack-core.js +23 -12
- package/dist/backend/runtime-pack-core.js.map +1 -1
- package/dist/backend/runtime-pack-native.d.ts +7 -3
- package/dist/backend/runtime-pack-native.js +0 -3
- package/dist/backend/runtime-pack-native.js.map +1 -1
- package/dist/backend/runtime-pack-targets.test.js +1 -1
- package/dist/backend/runtime-pack.d.ts +20 -2
- package/dist/backend/runtime-pack.js +23 -0
- package/dist/backend/runtime-pack.js.map +1 -1
- package/dist/backend/runtime-pack.test.js +115 -2
- package/dist/backend/runtime-pack.test.js.map +1 -1
- package/dist/backend/target-diagnostics.test.js +1 -1
- package/dist/backend/targets.d.ts +2 -1
- package/dist/backend/targets.js +1 -1
- package/dist/backend/targets.js.map +1 -1
- package/dist/cli/command.js +75 -11
- package/dist/cli/command.js.map +1 -1
- package/dist/cli/host.d.ts +2 -1
- package/dist/cli/usage.d.ts +4 -1
- package/dist/cli/usage.js +13 -3
- package/dist/cli/usage.js.map +1 -1
- package/dist/compile-types.d.ts +17 -5
- package/dist/coverage/report.d.ts +25 -2
- package/dist/coverage/report.js +161 -33
- package/dist/coverage/report.js.map +1 -1
- package/dist/coverage/verdict-cache.d.ts +63 -0
- package/dist/coverage/verdict-cache.js +193 -0
- package/dist/coverage/verdict-cache.js.map +1 -0
- package/dist/coverage/verdict-cache.test.d.ts +1 -0
- package/dist/coverage/verdict-cache.test.js +52 -0
- package/dist/coverage/verdict-cache.test.js.map +1 -0
- package/dist/coverage/verdict-semantic.d.ts +2 -0
- package/dist/coverage/verdict-semantic.js +24 -0
- package/dist/coverage/verdict-semantic.js.map +1 -0
- package/dist/coverage/verdict-startup.d.ts +15 -0
- package/dist/coverage/verdict-startup.js +66 -0
- package/dist/coverage/verdict-startup.js.map +1 -0
- package/dist/diagnostics/diagnostic.d.ts +29 -1
- package/dist/diagnostics/diagnostic.js +84 -12
- package/dist/diagnostics/diagnostic.js.map +1 -1
- package/dist/diagnostics/envelope.d.ts +130 -0
- package/dist/diagnostics/envelope.js +257 -0
- package/dist/diagnostics/envelope.js.map +1 -0
- package/dist/diagnostics/envelope.test.d.ts +1 -0
- package/dist/diagnostics/envelope.test.js +91 -0
- package/dist/diagnostics/envelope.test.js.map +1 -0
- package/dist/diagnostics/render.d.ts +3 -0
- package/dist/diagnostics/render.js +13 -2
- package/dist/diagnostics/render.js.map +1 -1
- package/dist/executable/executable-cache.d.ts +2 -2
- package/dist/executable/executable-cache.js +7 -4
- package/dist/executable/executable-cache.js.map +1 -1
- package/dist/executable/executable-cache.test.js +20 -0
- package/dist/executable/executable-cache.test.js.map +1 -1
- package/dist/executable/prepare.d.ts +4 -0
- package/dist/executable/prepare.js +7 -1
- package/dist/executable/prepare.js.map +1 -1
- package/dist/frontend/analysis.js +1 -0
- package/dist/frontend/analysis.js.map +1 -1
- package/dist/frontend/lowering/abstract-equality.js +5 -49
- package/dist/frontend/lowering/abstract-equality.js.map +1 -1
- package/dist/frontend/lowering/array-values.d.ts +30 -0
- package/dist/frontend/lowering/array-values.js +246 -1
- package/dist/frontend/lowering/array-values.js.map +1 -1
- package/dist/frontend/lowering/builtins/errors.js +17 -2
- package/dist/frontend/lowering/builtins/errors.js.map +1 -1
- package/dist/frontend/lowering/builtins/numbers.js +29 -1
- package/dist/frontend/lowering/builtins/numbers.js.map +1 -1
- package/dist/frontend/lowering/builtins/process.d.ts +10 -17
- package/dist/frontend/lowering/builtins/process.js +66 -29
- package/dist/frontend/lowering/builtins/process.js.map +1 -1
- package/dist/frontend/lowering/builtins/workers.js +4 -2
- package/dist/frontend/lowering/builtins/workers.js.map +1 -1
- package/dist/frontend/lowering/caught-value-dispatch.d.ts +11 -0
- package/dist/frontend/lowering/caught-value-dispatch.js +87 -0
- package/dist/frontend/lowering/caught-value-dispatch.js.map +1 -0
- package/dist/frontend/lowering/class-assertions.d.ts +12 -0
- package/dist/frontend/lowering/class-assertions.js +229 -5
- package/dist/frontend/lowering/class-assertions.js.map +1 -1
- package/dist/frontend/lowering/class-callbacks.d.ts +3 -3
- package/dist/frontend/lowering/class-callbacks.js +18 -5
- package/dist/frontend/lowering/class-callbacks.js.map +1 -1
- package/dist/frontend/lowering/class-dynamic-dispatch.d.ts +1 -0
- package/dist/frontend/lowering/class-dynamic-dispatch.js +12 -6
- package/dist/frontend/lowering/class-dynamic-dispatch.js.map +1 -1
- package/dist/frontend/lowering/class-method-mutations.d.ts +5 -0
- package/dist/frontend/lowering/class-method-mutations.js +472 -0
- package/dist/frontend/lowering/class-method-mutations.js.map +1 -0
- package/dist/frontend/lowering/class-method-values.js +25 -5
- package/dist/frontend/lowering/class-method-values.js.map +1 -1
- package/dist/frontend/lowering/class-prototypes.js +8 -2
- package/dist/frontend/lowering/class-prototypes.js.map +1 -1
- package/dist/frontend/lowering/class-unions.d.ts +16 -0
- package/dist/frontend/lowering/class-unions.js +127 -0
- package/dist/frontend/lowering/class-unions.js.map +1 -0
- package/dist/frontend/lowering/coercions/builders.js +8 -1
- package/dist/frontend/lowering/coercions/builders.js.map +1 -1
- package/dist/frontend/lowering/coercions/function-adapters.js +2 -0
- package/dist/frontend/lowering/coercions/function-adapters.js.map +1 -1
- package/dist/frontend/lowering/coercions/identity.d.ts +7 -0
- package/dist/frontend/lowering/coercions/identity.js +26 -0
- package/dist/frontend/lowering/coercions/identity.js.map +1 -0
- package/dist/frontend/lowering/coercions/state.d.ts +6 -0
- package/dist/frontend/lowering/coercions/state.js +2 -0
- package/dist/frontend/lowering/coercions/state.js.map +1 -1
- package/dist/frontend/lowering/coercions/structural.js +9 -6
- package/dist/frontend/lowering/coercions/structural.js.map +1 -1
- package/dist/frontend/lowering/coercions/unions.d.ts +8 -0
- package/dist/frontend/lowering/coercions/unions.js +67 -2
- package/dist/frontend/lowering/coercions/unions.js.map +1 -1
- package/dist/frontend/lowering/collation-repertoire.d.ts +1 -0
- package/dist/frontend/lowering/collation-repertoire.js +19 -0
- package/dist/frontend/lowering/collation-repertoire.js.map +1 -0
- package/dist/frontend/lowering/collection-narrowing.d.ts +6 -0
- package/dist/frontend/lowering/collection-narrowing.js +31 -0
- package/dist/frontend/lowering/collection-narrowing.js.map +1 -0
- package/dist/frontend/lowering/construction-escapes.d.ts +38 -0
- package/dist/frontend/lowering/construction-escapes.js +146 -0
- package/dist/frontend/lowering/construction-escapes.js.map +1 -0
- package/dist/frontend/lowering/construction-escapes.test.d.ts +1 -0
- package/dist/frontend/lowering/construction-escapes.test.js +150 -0
- package/dist/frontend/lowering/construction-escapes.test.js.map +1 -0
- package/dist/frontend/lowering/containers/array-callback-call.d.ts +7 -0
- package/dist/frontend/lowering/containers/array-callback-call.js +52 -0
- package/dist/frontend/lowering/containers/array-callback-call.js.map +1 -0
- package/dist/frontend/lowering/containers/array-callbacks.d.ts +1 -1
- package/dist/frontend/lowering/containers/array-callbacks.js +416 -65
- package/dist/frontend/lowering/containers/array-callbacks.js.map +1 -1
- package/dist/frontend/lowering/containers/array-concat.d.ts +7 -0
- package/dist/frontend/lowering/containers/array-concat.js +130 -0
- package/dist/frontend/lowering/containers/array-concat.js.map +1 -0
- package/dist/frontend/lowering/containers/array-construction.d.ts +2 -0
- package/dist/frontend/lowering/containers/array-construction.js +110 -5
- package/dist/frontend/lowering/containers/array-construction.js.map +1 -1
- package/dist/frontend/lowering/containers/array-methods.d.ts +1 -11
- package/dist/frontend/lowering/containers/array-methods.js +274 -144
- package/dist/frontend/lowering/containers/array-methods.js.map +1 -1
- package/dist/frontend/lowering/containers/callback-arguments.js +43 -1
- package/dist/frontend/lowering/containers/callback-arguments.js.map +1 -1
- package/dist/frontend/lowering/containers/collection-methods.js +10 -1
- package/dist/frontend/lowering/containers/collection-methods.js.map +1 -1
- package/dist/frontend/lowering/containers/indexed-objects.js +56 -70
- package/dist/frontend/lowering/containers/indexed-objects.js.map +1 -1
- package/dist/frontend/lowering/containers/string-and-regexp.js +7 -63
- package/dist/frontend/lowering/containers/string-and-regexp.js.map +1 -1
- package/dist/frontend/lowering/cycle-initialization.d.ts +46 -0
- package/dist/frontend/lowering/cycle-initialization.js +303 -0
- package/dist/frontend/lowering/cycle-initialization.js.map +1 -0
- package/dist/frontend/lowering/divergences.d.ts +9 -0
- package/dist/frontend/lowering/divergences.js +630 -0
- package/dist/frontend/lowering/divergences.js.map +1 -0
- package/dist/frontend/lowering/expressions/evaluation-safety.js +4 -0
- package/dist/frontend/lowering/expressions/evaluation-safety.js.map +1 -1
- package/dist/frontend/lowering/expressions/object-literals.js +178 -34
- package/dist/frontend/lowering/expressions/object-literals.js.map +1 -1
- package/dist/frontend/lowering/expressions/union-field-write.d.ts +4 -4
- package/dist/frontend/lowering/expressions/union-field-write.js +54 -44
- package/dist/frontend/lowering/expressions/union-field-write.js.map +1 -1
- package/dist/frontend/lowering/iterator-adapters.d.ts +20 -0
- package/dist/frontend/lowering/iterator-adapters.js +605 -0
- package/dist/frontend/lowering/iterator-adapters.js.map +1 -0
- package/dist/frontend/lowering/lower-array-sort.d.ts +1 -1
- package/dist/frontend/lowering/lower-array-sort.js +44 -5
- package/dist/frontend/lowering/lower-array-sort.js.map +1 -1
- package/dist/frontend/lowering/lower-array-sort.test.d.ts +1 -0
- package/dist/frontend/lowering/lower-array-sort.test.js +31 -0
- package/dist/frontend/lowering/lower-array-sort.test.js.map +1 -0
- package/dist/frontend/lowering/lower-assert.js +7 -0
- package/dist/frontend/lowering/lower-assert.js.map +1 -1
- package/dist/frontend/lowering/lower-builtin-values.js +1 -0
- package/dist/frontend/lowering/lower-builtin-values.js.map +1 -1
- package/dist/frontend/lowering/lower-calls.d.ts +8 -3
- package/dist/frontend/lowering/lower-calls.js +388 -278
- package/dist/frontend/lowering/lower-calls.js.map +1 -1
- package/dist/frontend/lowering/lower-classes.d.ts +6 -0
- package/dist/frontend/lowering/lower-classes.js +117 -65
- package/dist/frontend/lowering/lower-classes.js.map +1 -1
- package/dist/frontend/lowering/lower-exprs.d.ts +22 -2
- package/dist/frontend/lowering/lower-exprs.js +811 -254
- package/dist/frontend/lowering/lower-exprs.js.map +1 -1
- package/dist/frontend/lowering/lower-functions.js +32 -19
- package/dist/frontend/lowering/lower-functions.js.map +1 -1
- package/dist/frontend/lowering/lower-generators.d.ts +19 -13
- package/dist/frontend/lowering/lower-generators.js +67 -44
- package/dist/frontend/lowering/lower-generators.js.map +1 -1
- package/dist/frontend/lowering/lower-inspect.js +29 -4
- package/dist/frontend/lowering/lower-inspect.js.map +1 -1
- package/dist/frontend/lowering/lower-island.d.ts +1 -1
- package/dist/frontend/lowering/lower-island.js +24 -7
- package/dist/frontend/lowering/lower-island.js.map +1 -1
- package/dist/frontend/lowering/lower-modules.js +100 -3
- package/dist/frontend/lowering/lower-modules.js.map +1 -1
- package/dist/frontend/lowering/lower-stmts.js +82 -64
- package/dist/frontend/lowering/lower-stmts.js.map +1 -1
- package/dist/frontend/lowering/lowerer.d.ts +115 -2
- package/dist/frontend/lowering/lowerer.js +1266 -88
- package/dist/frontend/lowering/lowerer.js.map +1 -1
- package/dist/frontend/lowering/native-ffi.js +3 -1
- package/dist/frontend/lowering/native-ffi.js.map +1 -1
- package/dist/frontend/lowering/runtime-optional-bounds.d.ts +19 -0
- package/dist/frontend/lowering/runtime-optional-bounds.js +354 -0
- package/dist/frontend/lowering/runtime-optional-bounds.js.map +1 -0
- package/dist/frontend/lowering/runtime-optional-bounds.test.d.ts +1 -0
- package/dist/frontend/lowering/runtime-optional-bounds.test.js +66 -0
- package/dist/frontend/lowering/runtime-optional-bounds.test.js.map +1 -0
- package/dist/frontend/lowering/runtime-optional-elements.d.ts +117 -0
- package/dist/frontend/lowering/runtime-optional-elements.js +738 -0
- package/dist/frontend/lowering/runtime-optional-elements.js.map +1 -0
- package/dist/frontend/lowering/runtime-optional-guards.d.ts +36 -0
- package/dist/frontend/lowering/runtime-optional-guards.js +375 -0
- package/dist/frontend/lowering/runtime-optional-guards.js.map +1 -0
- package/dist/frontend/lowering/runtime-optional-guards.test.d.ts +1 -0
- package/dist/frontend/lowering/runtime-optional-guards.test.js +92 -0
- package/dist/frontend/lowering/runtime-optional-guards.test.js.map +1 -0
- package/dist/frontend/lowering/runtime-optional-ownership.d.ts +63 -0
- package/dist/frontend/lowering/runtime-optional-ownership.js +382 -0
- package/dist/frontend/lowering/runtime-optional-ownership.js.map +1 -0
- package/dist/frontend/lowering/runtime-optional-provenance.d.ts +16 -0
- package/dist/frontend/lowering/runtime-optional-provenance.js +41 -0
- package/dist/frontend/lowering/runtime-optional-provenance.js.map +1 -0
- package/dist/frontend/lowering/sanitize-class-types.test.js +2 -2
- package/dist/frontend/lowering/strict-equality.d.ts +9 -0
- package/dist/frontend/lowering/strict-equality.js +116 -0
- package/dist/frontend/lowering/strict-equality.js.map +1 -0
- package/dist/frontend/lowering/string-index-bounds.d.ts +36 -0
- package/dist/frontend/lowering/string-index-bounds.js +537 -0
- package/dist/frontend/lowering/string-index-bounds.js.map +1 -0
- package/dist/frontend/lowering/string-index-bounds.test.d.ts +1 -0
- package/dist/frontend/lowering/string-index-bounds.test.js +223 -0
- package/dist/frontend/lowering/string-index-bounds.test.js.map +1 -0
- package/dist/frontend/lowering/surfaces.js +3 -0
- package/dist/frontend/lowering/surfaces.js.map +1 -1
- package/dist/frontend/lowering/union-comparison.d.ts +5 -0
- package/dist/frontend/lowering/union-comparison.js +47 -0
- package/dist/frontend/lowering/union-comparison.js.map +1 -0
- package/dist/frontend/lowering/union-narrow.d.ts +2 -0
- package/dist/frontend/lowering/union-narrow.js +10 -6
- package/dist/frontend/lowering/union-narrow.js.map +1 -1
- package/dist/frontend/program-analysis.d.ts +10 -0
- package/dist/frontend/program-analysis.js +7 -0
- package/dist/frontend/program-analysis.js.map +1 -1
- package/dist/frontend/program.d.ts +63 -2
- package/dist/frontend/program.js +1038 -61
- package/dist/frontend/program.js.map +1 -1
- package/dist/frontend/program.test.js +122 -6
- package/dist/frontend/program.test.js.map +1 -1
- package/dist/frontend/resolve.d.ts +6 -0
- package/dist/frontend/resolve.js +14 -0
- package/dist/frontend/resolve.js.map +1 -1
- package/dist/frontend/threads-import.d.ts +5 -0
- package/dist/frontend/threads-import.js +21 -0
- package/dist/frontend/threads-import.js.map +1 -0
- package/dist/frontend/type-mapper.d.ts +4 -1
- package/dist/frontend/type-mapper.js +161 -20
- package/dist/frontend/type-mapper.js.map +1 -1
- package/dist/frontend/type-mapper.test.js +15 -3
- package/dist/frontend/type-mapper.test.js.map +1 -1
- package/dist/frontend/worker-target.d.ts +4 -0
- package/dist/frontend/worker-target.js +8 -1
- package/dist/frontend/worker-target.js.map +1 -1
- package/dist/index.d.ts +6 -1
- package/dist/index.js +70 -16
- package/dist/index.js.map +1 -1
- package/dist/ir/analysis.d.ts +3 -1
- package/dist/ir/analysis.js +4 -0
- package/dist/ir/analysis.js.map +1 -1
- package/dist/ir/build.d.ts +5 -0
- package/dist/ir/build.js +7 -0
- package/dist/ir/build.js.map +1 -1
- package/dist/ir/builtin-signatures.d.ts +1 -1
- package/dist/ir/builtin-signatures.js +5 -3
- package/dist/ir/builtin-signatures.js.map +1 -1
- package/dist/ir/constant-tables.test.js +1 -1
- package/dist/ir/initializer-bindings.test.js +1 -1
- package/dist/ir/int32-slots.d.ts +72 -0
- package/dist/ir/int32-slots.js +837 -0
- package/dist/ir/int32-slots.js.map +1 -0
- package/dist/ir/int32-slots.test.d.ts +1 -0
- package/dist/ir/int32-slots.test.js +222 -0
- package/dist/ir/int32-slots.test.js.map +1 -0
- package/dist/ir/integer-ranges.d.ts +19 -3
- package/dist/ir/integer-ranges.js +168 -23
- package/dist/ir/integer-ranges.js.map +1 -1
- package/dist/ir/integer-ranges.test.js +74 -2
- package/dist/ir/integer-ranges.test.js.map +1 -1
- package/dist/ir/ir.d.ts +101 -20
- package/dist/ir/ir.js +20 -6
- package/dist/ir/ir.js.map +1 -1
- package/dist/ir/scalar-records.test.js +1 -1
- package/dist/ir/serialize.d.ts +1 -1
- package/dist/ir/serialize.js +3 -3
- package/dist/ir/serialize.js.map +1 -1
- package/dist/ir/traverse.js +8 -0
- package/dist/ir/traverse.js.map +1 -1
- package/dist/ir/validate.js +139 -22
- package/dist/ir/validate.js.map +1 -1
- package/dist/ir/validate.test.js +308 -8
- package/dist/ir/validate.test.js.map +1 -1
- package/dist/library/fence-eval.test.js +1 -1
- package/dist/library/int-infer.test.js +4 -4
- package/dist/library/library-cache.test.js +5 -5
- package/dist/library/library-profile.d.ts +2 -1
- package/dist/library/library-profile.js +4 -3
- package/dist/library/library-profile.js.map +1 -1
- package/dist/native/cache.d.ts +3 -0
- package/dist/native/cache.js +49 -1
- package/dist/native/cache.js.map +1 -1
- package/dist/native/cache.test.js +21 -1
- package/dist/native/cache.test.js.map +1 -1
- package/dist/native/cli.js +1 -1
- package/dist/native/cli.js.map +1 -1
- package/dist/native/compiler.d.ts +5 -0
- package/dist/native/compiler.js +51 -4
- package/dist/native/compiler.js.map +1 -1
- package/dist/native/compiler.test.js +2 -2
- package/dist/native/library.d.ts +2 -1
- package/dist/native/library.js.map +1 -1
- package/dist/native/prepare.d.ts +4 -0
- package/dist/native/prepare.js +28 -3
- package/dist/native/prepare.js.map +1 -1
- package/dist/native/sanitizer.d.ts +3 -2
- package/dist/native/sanitizer.js +3 -13
- package/dist/native/sanitizer.js.map +1 -1
- package/dist/startup-cache.d.ts +2 -0
- package/dist/startup-cache.js +2 -0
- package/dist/startup-cache.js.map +1 -1
- package/package.json +20 -20
- package/surface-manifest.json +8 -2
|
@@ -1,7 +1,10 @@
|
|
|
1
1
|
import { boolLit, countedFor, numLit, varRef } from "../../../ir/build.js";
|
|
2
|
+
import { transformStmtList } from "../../../ir/traverse.js";
|
|
2
3
|
import { InternalCompilerError } from "../../../errors.js";
|
|
4
|
+
import { canAssertClassValue, checkedClassAssertion } from "../class-assertions.js";
|
|
3
5
|
import * as ts from "../../ts7/adapter.js";
|
|
4
|
-
import {
|
|
6
|
+
import { PoisonError } from "../lowerer.js";
|
|
7
|
+
import { BOOL, DYN, F64, STRING, UNDEFINED_T, VOID, arrayOf, funcOf, isSortValuesElement, isUnitType, typeEquals, } from "../../../ir/ir.js";
|
|
5
8
|
import { isJsSourceFile, locOf } from "../../program.js";
|
|
6
9
|
import { buildArraySortFn } from "../lower-array-sort.js";
|
|
7
10
|
import { arrayIndexPresent, arrayValueRead, arrayValueStore, arrayValueType, currentArrayIndexPresent, } from "../array-values.js";
|
|
@@ -30,7 +33,8 @@ export function lowerArrayHofCall(lowerer, call, access, method, elem) {
|
|
|
30
33
|
ts.isIdentifier(argNode) &&
|
|
31
34
|
argNode.text === "Boolean" &&
|
|
32
35
|
lowerer.isStdlibSymbol(lowerer.resolveValueSymbol(argNode) ?? undefined);
|
|
33
|
-
const
|
|
36
|
+
const present = !booleanFilter && presentElements(lowerer, call, elem);
|
|
37
|
+
const valueT = callbackValueType(lowerer, elem, present);
|
|
34
38
|
if (booleanFilter) {
|
|
35
39
|
if (valueT.kind === "union")
|
|
36
40
|
lowerer.requireTruthyUnion(valueT.unionId, argNode);
|
|
@@ -70,9 +74,19 @@ export function lowerArrayHofCall(lowerer, call, access, method, elem) {
|
|
|
70
74
|
const outElem = method === "filter"
|
|
71
75
|
? filterResultElem(lowerer, call, argNode, elem, valueT, booleanFilter)
|
|
72
76
|
: callbackArrayElement(lowerer, call, fnRet);
|
|
73
|
-
|
|
77
|
+
// A filter that re-tags its elements keeps the single union-typed visit.
|
|
78
|
+
const fast = present || booleanFilter || (method === "filter" && !typeEquals(outElem, elem))
|
|
79
|
+
? null
|
|
80
|
+
: lowerFastCallback(lowerer, argNode, [valueT], 0, elem, arrayOf(elem), callback);
|
|
81
|
+
const helper = arrayHofHelper(lowerer, method, elem, fnRet, arity, loc, outElem, callbackSite(fast ?? fnArg), fast?.type ?? null, present);
|
|
74
82
|
const resultType = method === "map" || method === "filter" ? arrayOf(outElem) : VOID;
|
|
75
|
-
return {
|
|
83
|
+
return {
|
|
84
|
+
kind: "call",
|
|
85
|
+
callee: helper,
|
|
86
|
+
args: [receiver, fnArg, ...(fast ? [fast] : [])],
|
|
87
|
+
type: resultType,
|
|
88
|
+
loc,
|
|
89
|
+
};
|
|
76
90
|
}
|
|
77
91
|
/** The checker-selected element of a filter result, with the same trust
|
|
78
92
|
* boundary as the historical narrowing filter: an inferred inline type
|
|
@@ -112,13 +126,15 @@ function filterResultElem(lowerer, call, argNode, elem, valueT, booleanFilter) {
|
|
|
112
126
|
`unchecked assertion nothing validates at runtime — ${annotateEscape})`);
|
|
113
127
|
}
|
|
114
128
|
}
|
|
115
|
-
|
|
129
|
+
const classRefinement = !booleanFilter && outElem.kind === "object" && canAssertClassValue(lowerer, valueT, outElem);
|
|
130
|
+
if (!classRefinement &&
|
|
131
|
+
(valueT.kind !== "union" || lowerer.armTag(valueT.unionId, outElem) < 0)) {
|
|
116
132
|
const multiArm = outElem.kind === "union";
|
|
117
133
|
lowerer.unsupported("SC1090", call, `'.filter' narrowing '${lowerer.fmt(elem)}' elements to ` +
|
|
118
134
|
`${multiArm ? `the multi-arm '${lowerer.fmt(outElem)}'` : `'${lowerer.fmt(outElem)}'`} ` +
|
|
119
135
|
`(${multiArm ? "only a SINGLE arm re-tags" : "only a single runtime arm re-tags"} — ${annotateEscape})`);
|
|
120
136
|
}
|
|
121
|
-
if (booleanFilter) {
|
|
137
|
+
if (booleanFilter && valueT.kind === "union") {
|
|
122
138
|
const arms = lowerer.unions.get(valueT.unionId)?.arms ?? [];
|
|
123
139
|
if (arms.some((arm) => !typeEquals(arm, outElem) && !isUnitType(arm))) {
|
|
124
140
|
lowerer.unsupported("SC1090", call, `'.filter(Boolean)' narrowing '${lowerer.fmt(elem)}' to '${lowerer.fmt(outElem)}' ` +
|
|
@@ -194,18 +210,214 @@ function filterCond(call, fnRet, loc) {
|
|
|
194
210
|
// the runtime's kind-aware ToBoolean.
|
|
195
211
|
return { kind: "toBool", operand: call, type: BOOL, loc };
|
|
196
212
|
}
|
|
213
|
+
/** Nested HOFs inside a fast lowering keep their single union visit, so
|
|
214
|
+
* duplication stays linear in nesting depth. */
|
|
215
|
+
let fastLoweringDepth = 0;
|
|
216
|
+
/** Array reads widen elements with undefined so holes and present
|
|
217
|
+
* undefined stay observable, which makes every callback parameter a boxed
|
|
218
|
+
* `T | undefined`. For an inline arrow over a plain element type, lower the
|
|
219
|
+
* callback a second time with the element type itself. The helper then
|
|
220
|
+
* splits each visit on the element state: a present value calls this fast
|
|
221
|
+
* closure with the plain element (no union box, no per-use undefined
|
|
222
|
+
* test), and a hole or present undefined calls the original closure with
|
|
223
|
+
* the undefined arm. Both closures share the same capture boxes and body,
|
|
224
|
+
* so every observable effect is the same; arrows have no own `this`,
|
|
225
|
+
* `arguments` or self binding that could tell the two apart. Any refusal
|
|
226
|
+
* in the second lowering is discarded and keeps the single visit. */
|
|
227
|
+
function lowerFastCallback(lowerer, argNode, lead, elemIndex, elem, arrT, slow, bindUntyped = false, expectedReturn) {
|
|
228
|
+
const valueT = lead[elemIndex];
|
|
229
|
+
if (fastLoweringDepth > 0 ||
|
|
230
|
+
slow.arity <= elemIndex ||
|
|
231
|
+
!ts.isArrowFunction(argNode) ||
|
|
232
|
+
isJsSourceFile(argNode.getSourceFile()) ||
|
|
233
|
+
valueT?.kind !== "union" ||
|
|
234
|
+
typeEquals(valueT, elem) ||
|
|
235
|
+
elem.kind === "union" ||
|
|
236
|
+
elem.kind === "dyn" ||
|
|
237
|
+
elem.kind === "jsval" ||
|
|
238
|
+
isUnitType(elem))
|
|
239
|
+
return null;
|
|
240
|
+
const fastLead = lead.slice();
|
|
241
|
+
fastLead[elemIndex] = elem;
|
|
242
|
+
// The optional-read prepass binds an unannotated element parameter to
|
|
243
|
+
// the array's runtime value type. Rebind it to the plain element for
|
|
244
|
+
// this lowering only.
|
|
245
|
+
const param = argNode.parameters[elemIndex];
|
|
246
|
+
if (!param || param.initializer || param.dotDotDotToken || !ts.isIdentifier(param.name))
|
|
247
|
+
return null;
|
|
248
|
+
const symbol = param.type ? undefined : lowerer.checker.getSymbolAtLocation(param.name);
|
|
249
|
+
const previousBinding = symbol ? lowerer.runtimeOptionalBindingTypes.get(symbol) : undefined;
|
|
250
|
+
if (symbol)
|
|
251
|
+
lowerer.runtimeOptionalBindingTypes.set(symbol, elem);
|
|
252
|
+
const sink = [];
|
|
253
|
+
const previousSink = lowerer.diagSink;
|
|
254
|
+
lowerer.diagSink = sink;
|
|
255
|
+
fastLoweringDepth++;
|
|
256
|
+
let fast;
|
|
257
|
+
try {
|
|
258
|
+
fast = lowerArrayCallback(lowerer, argNode, fastLead, arrT, bindUntyped, expectedReturn);
|
|
259
|
+
}
|
|
260
|
+
catch (e) {
|
|
261
|
+
if (e instanceof PoisonError)
|
|
262
|
+
return null;
|
|
263
|
+
throw e;
|
|
264
|
+
}
|
|
265
|
+
finally {
|
|
266
|
+
fastLoweringDepth--;
|
|
267
|
+
lowerer.diagSink = previousSink;
|
|
268
|
+
if (symbol) {
|
|
269
|
+
if (previousBinding === undefined)
|
|
270
|
+
lowerer.runtimeOptionalBindingTypes.delete(symbol);
|
|
271
|
+
else
|
|
272
|
+
lowerer.runtimeOptionalBindingTypes.set(symbol, previousBinding);
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
const fastT = fast.fnArg.type;
|
|
276
|
+
const slowT = slow.fnArg.type;
|
|
277
|
+
if (fast.fnArg.kind !== "closure" ||
|
|
278
|
+
fast.arity !== slow.arity ||
|
|
279
|
+
!typeEquals(fastT.ret, slowT.ret) ||
|
|
280
|
+
!fastT.params.every((param, i) => typeEquals(param, i === elemIndex ? elem : slowT.params[i])))
|
|
281
|
+
return null;
|
|
282
|
+
return fast.fnArg;
|
|
283
|
+
}
|
|
284
|
+
/** `a[i]` holds a value (array state 1): neither a hole nor a present
|
|
285
|
+
* undefined. */
|
|
286
|
+
function presentValue(arr, index, loc) {
|
|
287
|
+
return {
|
|
288
|
+
kind: "bin",
|
|
289
|
+
op: "===",
|
|
290
|
+
left: { kind: "arrayState", arr, index, type: F64, loc },
|
|
291
|
+
right: numLit(1, loc),
|
|
292
|
+
type: BOOL,
|
|
293
|
+
loc,
|
|
294
|
+
};
|
|
295
|
+
}
|
|
296
|
+
/** Route a helper's callback calls through the split visit: every
|
|
297
|
+
* `f(<arrayValueRead a[i]>, ...)` becomes
|
|
298
|
+
* `state(a, i) === 1 ? fast(a[i], ...) : f(undefined, ...)`. The read is
|
|
299
|
+
* the call's only effectful operand (the rest are the loop's index and
|
|
300
|
+
* array locals), so evaluation order is unchanged. The fast closure is an
|
|
301
|
+
* extra trailing parameter. */
|
|
302
|
+
function withFastCallback(fn, fastT, elem) {
|
|
303
|
+
if (!fastT)
|
|
304
|
+
return fn;
|
|
305
|
+
const isValueRead = (e) => e.kind === "ternary" &&
|
|
306
|
+
e.cond.kind === "bin" &&
|
|
307
|
+
e.cond.op === "===" &&
|
|
308
|
+
e.cond.left.kind === "arrayState" &&
|
|
309
|
+
e.cond.right.kind === "numLit" &&
|
|
310
|
+
e.cond.right.value === 1;
|
|
311
|
+
const split = (e) => {
|
|
312
|
+
if (e.kind !== "callValue" || e.callee.kind !== "varRef" || e.callee.localId !== "f.0")
|
|
313
|
+
return null;
|
|
314
|
+
const at = e.args.findIndex(isValueRead);
|
|
315
|
+
if (at < 0)
|
|
316
|
+
return null;
|
|
317
|
+
const read = e.args[at];
|
|
318
|
+
if (read.kind !== "ternary")
|
|
319
|
+
return null;
|
|
320
|
+
const condition = read.cond;
|
|
321
|
+
if (condition.kind !== "bin")
|
|
322
|
+
return null;
|
|
323
|
+
const state = condition.left;
|
|
324
|
+
if (state.kind !== "arrayState")
|
|
325
|
+
return null;
|
|
326
|
+
const fastArgs = e.args.slice();
|
|
327
|
+
fastArgs[at] = {
|
|
328
|
+
kind: "arrayGet",
|
|
329
|
+
arr: state.arr,
|
|
330
|
+
index: state.index,
|
|
331
|
+
type: elem,
|
|
332
|
+
loc: read.loc,
|
|
333
|
+
};
|
|
334
|
+
const slowArgs = e.args.slice();
|
|
335
|
+
slowArgs[at] = read.else_;
|
|
336
|
+
return {
|
|
337
|
+
cond: read.cond,
|
|
338
|
+
fast: { ...e, callee: varRef("fast.0", fastT, e.callee.loc), args: fastArgs },
|
|
339
|
+
slow: { ...e, args: slowArgs },
|
|
340
|
+
};
|
|
341
|
+
};
|
|
342
|
+
const body = transformStmtList(fn.body, {
|
|
343
|
+
stmt: (stmt) => {
|
|
344
|
+
if (stmt.kind !== "exprStmt")
|
|
345
|
+
return stmt;
|
|
346
|
+
const parts = split(stmt.expr);
|
|
347
|
+
if (!parts)
|
|
348
|
+
return stmt;
|
|
349
|
+
return {
|
|
350
|
+
kind: "if",
|
|
351
|
+
cond: parts.cond,
|
|
352
|
+
then: [{ kind: "exprStmt", expr: parts.fast, loc: stmt.loc }],
|
|
353
|
+
else_: [{ kind: "exprStmt", expr: parts.slow, loc: stmt.loc }],
|
|
354
|
+
loc: stmt.loc,
|
|
355
|
+
};
|
|
356
|
+
},
|
|
357
|
+
expr: (expr) => {
|
|
358
|
+
const parts = split(expr);
|
|
359
|
+
if (!parts)
|
|
360
|
+
return expr;
|
|
361
|
+
return {
|
|
362
|
+
kind: "ternary",
|
|
363
|
+
cond: parts.cond,
|
|
364
|
+
then: parts.fast,
|
|
365
|
+
else_: parts.slow,
|
|
366
|
+
type: expr.type,
|
|
367
|
+
loc: expr.loc,
|
|
368
|
+
};
|
|
369
|
+
},
|
|
370
|
+
});
|
|
371
|
+
return {
|
|
372
|
+
...fn,
|
|
373
|
+
params: [...fn.params, { localId: "fast.0", name: "fast", type: fastT }],
|
|
374
|
+
locals: [...fn.locals, { id: "fast.0", name: "fast", type: fastT, mutable: true }],
|
|
375
|
+
body,
|
|
376
|
+
};
|
|
377
|
+
}
|
|
378
|
+
/** The interning suffix for a callback argument. A literal closure (an
|
|
379
|
+
* inline arrow or function expression) gets a helper of its own, so the
|
|
380
|
+
* helper's only incoming callback is one known function: the backend's
|
|
381
|
+
* constant-callback census then calls it directly and LLVM can inline the
|
|
382
|
+
* callback into the loop (TurboFan's builtin+callback inlining). Callback
|
|
383
|
+
* values keep the shared, type-interned helper. */
|
|
384
|
+
function callbackSite(fnArg) {
|
|
385
|
+
return fnArg.kind === "closure" ? `@${fnArg.fnName}` : "";
|
|
386
|
+
}
|
|
387
|
+
/** The optional-read analysis proved this call's receiver never holds an
|
|
388
|
+
* explicit undefined (or, for the find family, a hole): its callback takes
|
|
389
|
+
* the element type itself, read without a state test. A missing value the
|
|
390
|
+
* proof excluded would make the element read trap instead of producing a
|
|
391
|
+
* wrong value. */
|
|
392
|
+
function presentElements(lowerer, call, elem) {
|
|
393
|
+
return (lowerer.presentElementCalls.has(call) &&
|
|
394
|
+
elem.kind !== "dyn" &&
|
|
395
|
+
elem.kind !== "jsval" &&
|
|
396
|
+
elem.kind !== "void" &&
|
|
397
|
+
!isUnitType(elem));
|
|
398
|
+
}
|
|
399
|
+
/** The value a helper passes its callback for one visited index. */
|
|
400
|
+
function callbackValueType(lowerer, elem, present) {
|
|
401
|
+
return present ? elem : arrayValueType(lowerer, elem);
|
|
402
|
+
}
|
|
403
|
+
function callbackValueRead(lowerer, arr, index, elem, present, loc) {
|
|
404
|
+
return present
|
|
405
|
+
? { kind: "arrayGet", arr, index, type: elem, loc }
|
|
406
|
+
: arrayValueRead(lowerer, arr, index, elem, loc);
|
|
407
|
+
}
|
|
197
408
|
/** Interned synthetic loop function for one (method, elem, fnRet, arity)
|
|
198
409
|
* combo. Named `%arr.<method>.<n>` ('%' keeps it out of the user
|
|
199
410
|
* namespace); rides `liftedFns` into the module like a lifted lambda (it
|
|
200
411
|
* is a plain function — no captures). */
|
|
201
|
-
function arrayHofHelper(lowerer, method, elem, fnRet, arity, loc, outElem = fnRet) {
|
|
202
|
-
const key = `${method}:${typeKey(elem)}:${typeKey(fnRet)}:${arity}:${typeKey(outElem)}`;
|
|
412
|
+
function arrayHofHelper(lowerer, method, elem, fnRet, arity, loc, outElem = fnRet, site = "", fastT = null, present = false) {
|
|
413
|
+
const key = `${method}:${typeKey(elem)}:${typeKey(fnRet)}:${arity}:${typeKey(outElem)}${site}${fastT ? ":split" : ""}${present ? ":present" : ""}`;
|
|
203
414
|
const existing = lowerer.arrHofHelpers.get(key);
|
|
204
415
|
if (existing)
|
|
205
416
|
return existing;
|
|
206
417
|
const name = `%arr.${method}.${lowerer.arrHofHelpers.size}`;
|
|
207
418
|
lowerer.arrHofHelpers.set(key, name);
|
|
208
|
-
|
|
419
|
+
const fn = buildArrayHofFn(lowerer, name, method, elem, fnRet, arity, loc, outElem, fastT, present);
|
|
420
|
+
lowerer.liftedFns.push(fastT ? withFastCallback(fn, fastT, elem) : fn);
|
|
209
421
|
return name;
|
|
210
422
|
}
|
|
211
423
|
/** The TS 5.2+ callable-union array rule: a `T[] | U[]` receiver exposes
|
|
@@ -363,14 +575,14 @@ function arrayUnionHofHelper(lowerer, method, receiverT, arrays, callbackT, arit
|
|
|
363
575
|
* `arity` is the callback's declared parameter count (1–3): the loop
|
|
364
576
|
* passes the index and the receiver itself after the element when the
|
|
365
577
|
* callback names them, exactly the arguments JS supplies. */
|
|
366
|
-
function buildArrayHofFn(lowerer, name, method, elem, fnRet, arity, loc, outElem) {
|
|
578
|
+
function buildArrayHofFn(lowerer, name, method, elem, fnRet, arity, loc, outElem, fastT = null, present = false) {
|
|
367
579
|
const arrT = arrayOf(elem);
|
|
368
|
-
const valueT =
|
|
369
|
-
const fnT = funcOf([
|
|
580
|
+
const valueT = callbackValueType(lowerer, elem, present);
|
|
581
|
+
const fnT = funcOf([valueT, F64, arrT].slice(0, arity), fnRet);
|
|
370
582
|
const locals = arrayCallbackLocals(arrT, fnT);
|
|
371
583
|
const params = arrayCallbackParams(arrT, fnT);
|
|
372
584
|
const callF = (arg) => callArrayCallback(arrT, fnT, fnRet, arity, arg, loc);
|
|
373
|
-
const getElem =
|
|
585
|
+
const getElem = callbackValueRead(lowerer, varRef("a.0", arrT, loc), varRef("i.0", F64, loc), elem, present, loc);
|
|
374
586
|
const hasElem = {
|
|
375
587
|
kind: "arrayHas",
|
|
376
588
|
arr: varRef("a.0", arrT, loc),
|
|
@@ -428,22 +640,111 @@ function buildArrayHofFn(lowerer, name, method, elem, fnRet, arity, loc, outElem
|
|
|
428
640
|
{ kind: "return", value: varRef("out.0", outT, loc), loc },
|
|
429
641
|
];
|
|
430
642
|
}
|
|
643
|
+
else if (method === "filter" && fastT) {
|
|
644
|
+
// Split visit (outElem === elem): a present value goes to the fast
|
|
645
|
+
// callback as a plain element and is kept as-is; a present undefined
|
|
646
|
+
// goes to the original callback and is kept as undefined.
|
|
647
|
+
const outT = arrayOf(outElem);
|
|
648
|
+
locals.push({ id: "out.0", name: "out", type: outT, mutable: false }, { id: "e.0", name: "e", type: elem, mutable: false });
|
|
649
|
+
returnType = outT;
|
|
650
|
+
const a = varRef("a.0", arrT, loc);
|
|
651
|
+
const i = varRef("i.0", F64, loc);
|
|
652
|
+
const outLength = {
|
|
653
|
+
kind: "arrIntrinsic",
|
|
654
|
+
method: "length",
|
|
655
|
+
receiver: varRef("out.0", outT, loc),
|
|
656
|
+
args: [],
|
|
657
|
+
type: F64,
|
|
658
|
+
loc,
|
|
659
|
+
};
|
|
660
|
+
const missing = getElem.else_;
|
|
661
|
+
const callFast = (arg) => ({
|
|
662
|
+
kind: "callValue",
|
|
663
|
+
callee: varRef("fast.0", fastT, loc),
|
|
664
|
+
args: [arg, i, a].slice(0, arity),
|
|
665
|
+
type: fnRet,
|
|
666
|
+
loc,
|
|
667
|
+
});
|
|
668
|
+
body = [
|
|
669
|
+
{
|
|
670
|
+
kind: "varDecl",
|
|
671
|
+
localId: "out.0",
|
|
672
|
+
init: { kind: "arrayLit", elems: [], type: outT, loc },
|
|
673
|
+
loc,
|
|
674
|
+
},
|
|
675
|
+
readLen,
|
|
676
|
+
forLoop([
|
|
677
|
+
{
|
|
678
|
+
kind: "if",
|
|
679
|
+
cond: hasElem,
|
|
680
|
+
then: [
|
|
681
|
+
{
|
|
682
|
+
kind: "if",
|
|
683
|
+
cond: presentValue(a, i, loc),
|
|
684
|
+
then: [
|
|
685
|
+
{
|
|
686
|
+
kind: "varDecl",
|
|
687
|
+
localId: "e.0",
|
|
688
|
+
init: { kind: "arrayGet", arr: a, index: i, type: elem, loc },
|
|
689
|
+
loc,
|
|
690
|
+
},
|
|
691
|
+
{
|
|
692
|
+
kind: "if",
|
|
693
|
+
cond: filterCond(callFast(varRef("e.0", elem, loc)), fnRet, loc),
|
|
694
|
+
then: [
|
|
695
|
+
arrayValueStore(lowerer, varRef("out.0", outT, loc), outLength, varRef("e.0", elem, loc), outElem, loc),
|
|
696
|
+
],
|
|
697
|
+
else_: null,
|
|
698
|
+
loc,
|
|
699
|
+
},
|
|
700
|
+
],
|
|
701
|
+
else_: [
|
|
702
|
+
{
|
|
703
|
+
kind: "if",
|
|
704
|
+
cond: filterCond(callF(missing), fnRet, loc),
|
|
705
|
+
then: [
|
|
706
|
+
{
|
|
707
|
+
kind: "arraySetUndefined",
|
|
708
|
+
arr: varRef("out.0", outT, loc),
|
|
709
|
+
index: outLength,
|
|
710
|
+
loc,
|
|
711
|
+
},
|
|
712
|
+
],
|
|
713
|
+
else_: null,
|
|
714
|
+
loc,
|
|
715
|
+
},
|
|
716
|
+
],
|
|
717
|
+
loc,
|
|
718
|
+
},
|
|
719
|
+
],
|
|
720
|
+
else_: null,
|
|
721
|
+
loc,
|
|
722
|
+
},
|
|
723
|
+
]),
|
|
724
|
+
{ kind: "return", value: varRef("out.0", outT, loc), loc },
|
|
725
|
+
];
|
|
726
|
+
}
|
|
431
727
|
else if (method === "filter") {
|
|
432
728
|
const outT = arrayOf(outElem);
|
|
433
729
|
locals.push({ id: "out.0", name: "out", type: outT, mutable: false }, { id: "v.0", name: "v", type: valueT, mutable: false });
|
|
434
730
|
returnType = outT;
|
|
731
|
+
const classView = !typeEquals(outElem, elem) && outElem.kind === "object"
|
|
732
|
+
? checkedClassAssertion(lowerer, varRef("v.0", valueT, loc), outElem, loc)
|
|
733
|
+
: null;
|
|
435
734
|
const retained = typeEquals(outElem, elem)
|
|
436
735
|
? varRef("v.0", valueT, loc)
|
|
437
|
-
:
|
|
438
|
-
?
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
736
|
+
: classView !== null
|
|
737
|
+
? classView
|
|
738
|
+
: valueT.kind === "union"
|
|
739
|
+
? {
|
|
740
|
+
kind: "unionNarrow",
|
|
741
|
+
unionId: valueT.unionId,
|
|
742
|
+
tag: lowerer.armTag(valueT.unionId, outElem),
|
|
743
|
+
value: varRef("v.0", valueT, loc),
|
|
744
|
+
type: outElem,
|
|
745
|
+
loc,
|
|
746
|
+
}
|
|
747
|
+
: varRef("v.0", valueT, loc);
|
|
447
748
|
body = [
|
|
448
749
|
{
|
|
449
750
|
kind: "varDecl",
|
|
@@ -519,7 +820,12 @@ export function lowerArrayFindLikeCall(lowerer, call, access, method, elem, bind
|
|
|
519
820
|
const argNode = call.arguments[0];
|
|
520
821
|
if (!argNode)
|
|
521
822
|
lowerer.unsupported("SC1090", call, "this call form"); // tsc-guarded
|
|
522
|
-
|
|
823
|
+
// find's result must be reachable from the element itself; a predicate
|
|
824
|
+
// that narrows to another layout keeps the optional element visit.
|
|
825
|
+
const present = presentElements(lowerer, call, elem) &&
|
|
826
|
+
((method !== "find" && method !== "findLast") ||
|
|
827
|
+
(!bindUntyped && lowerer.coercibleValue(elem, lowerer.irTypeOf(call))));
|
|
828
|
+
const { fnArg, arity } = lowerArrayCallback(lowerer, argNode, [callbackValueType(lowerer, elem, present)], arrT, bindUntyped);
|
|
523
829
|
// JS takes the ToBoolean of the predicate's result — allowed wherever
|
|
524
830
|
// that ToBoolean has a static answer (bool passes through; f64/string
|
|
525
831
|
// by value; a truthy-answerable union by its arm — the
|
|
@@ -539,13 +845,17 @@ export function lowerArrayFindLikeCall(lowerer, call, access, method, elem, bind
|
|
|
539
845
|
method === "every" ||
|
|
540
846
|
method === "findIndex" ||
|
|
541
847
|
method === "findLastIndex") {
|
|
848
|
+
const fast = present
|
|
849
|
+
? null
|
|
850
|
+
: lowerFastCallback(lowerer, argNode, [arrayValueType(lowerer, elem)], 0, elem, arrT, { fnArg, arity }, bindUntyped);
|
|
851
|
+
const fastT = fast?.type ?? null;
|
|
542
852
|
const helper = method === "findIndex" || method === "findLastIndex"
|
|
543
|
-
? findIndexHelper(lowerer, elem, fnRet, arity, last, loc)
|
|
544
|
-
: someEveryHelper(lowerer, method, elem, fnRet, arity, loc);
|
|
853
|
+
? findIndexHelper(lowerer, elem, fnRet, arity, last, loc, callbackSite(fast ?? fnArg), fastT, present)
|
|
854
|
+
: someEveryHelper(lowerer, method, elem, fnRet, arity, loc, callbackSite(fast ?? fnArg), fastT, present);
|
|
545
855
|
return {
|
|
546
856
|
kind: "call",
|
|
547
857
|
callee: helper,
|
|
548
|
-
args: [receiver, fnArg],
|
|
858
|
+
args: [receiver, fnArg, ...(fast ? [fast] : [])],
|
|
549
859
|
type: method === "findIndex" || method === "findLastIndex" ? F64 : BOOL,
|
|
550
860
|
loc,
|
|
551
861
|
};
|
|
@@ -555,7 +865,7 @@ export function lowerArrayFindLikeCall(lowerer, call, access, method, elem, bind
|
|
|
555
865
|
// element inherits that earlier refinement. Otherwise only an inline,
|
|
556
866
|
// inferred predicate proves a new narrowing; explicit assertions keep
|
|
557
867
|
// the same refusal boundary as filter.
|
|
558
|
-
const valueT =
|
|
868
|
+
const valueT = callbackValueType(lowerer, elem, present);
|
|
559
869
|
const checkerReceiver = lowerer.mapTypeOf(lowerer.typeOf(access.expression));
|
|
560
870
|
const checkerResult = lowerer.irTypeOf(call);
|
|
561
871
|
const unchangedElement = checkerReceiver?.kind === "array" &&
|
|
@@ -581,10 +891,12 @@ export function lowerArrayFindLikeCall(lowerer, call, access, method, elem, bind
|
|
|
581
891
|
lowerer.unsupported("SC1090", call, `'.${method}' result narrowing without a predicate over its element`);
|
|
582
892
|
}
|
|
583
893
|
retag = lowerer.narrowedRetagHelper(call, valueT.unionId, resultT.unionId, loc);
|
|
584
|
-
|
|
894
|
+
const present = lowerer.stripUndefinedArm(resultT);
|
|
895
|
+
if (retag === null &&
|
|
896
|
+
!(present.kind === "object" && canAssertClassValue(lowerer, valueT, present)))
|
|
585
897
|
lowerer.unsupported("SC1090", call, `'.${method}' narrowing to an incompatible result layout`);
|
|
586
898
|
}
|
|
587
|
-
const helper = findHelper(lowerer, elem, resultT, undefTag, fnRet, arity, last, loc, retag);
|
|
899
|
+
const helper = findHelper(lowerer, elem, resultT, undefTag, fnRet, arity, last, loc, retag, callbackSite(fnArg), present);
|
|
588
900
|
return { kind: "call", callee: helper, args: [receiver, fnArg], type: resultT, loc };
|
|
589
901
|
}
|
|
590
902
|
/** ToBoolean of a predicate result inside a synthesized HOF helper — the
|
|
@@ -603,20 +915,26 @@ function predicateToBoolean(e) {
|
|
|
603
915
|
* for (i = 0; i < n; i++) { v = a[i]; if (f(v)) return <v as result arm>; }
|
|
604
916
|
* return <undefined arm>;
|
|
605
917
|
*/
|
|
606
|
-
function findHelper(lowerer, elem, resultT, undefTag, fnRet, arity, last, loc, retag) {
|
|
918
|
+
function findHelper(lowerer, elem, resultT, undefTag, fnRet, arity, last, loc, retag, site = "", present = false) {
|
|
607
919
|
const method = last ? "findLast" : "find";
|
|
608
|
-
const key = `${method}:${typeKey(elem)}:${typeKey(resultT)}:${typeKey(fnRet)}:${arity}`;
|
|
920
|
+
const key = `${method}:${typeKey(elem)}:${typeKey(resultT)}:${typeKey(fnRet)}:${arity}${site}${present ? ":present" : ""}`;
|
|
609
921
|
const existing = lowerer.arrHofHelpers.get(key);
|
|
610
922
|
if (existing)
|
|
611
923
|
return existing;
|
|
612
924
|
const name = `%arr.${method}.${lowerer.arrHofHelpers.size}`;
|
|
613
925
|
lowerer.arrHofHelpers.set(key, name);
|
|
614
926
|
const arrT = arrayOf(elem);
|
|
615
|
-
const
|
|
616
|
-
const
|
|
927
|
+
const valueT = callbackValueType(lowerer, elem, present);
|
|
928
|
+
const fnT = funcOf([valueT, F64, arrT].slice(0, arity), fnRet);
|
|
617
929
|
const v = varRef("v.0", valueT, loc);
|
|
930
|
+
const presentArm = lowerer.stripUndefinedArm(resultT);
|
|
931
|
+
// A successful inferred class predicate may select a descendant of a
|
|
932
|
+
// stored base arm. Keep the value read before the callback mutated the array.
|
|
933
|
+
const classView = retag === null && !lowerer.coercibleValue(valueT, resultT) && presentArm.kind === "object"
|
|
934
|
+
? checkedClassAssertion(lowerer, v, presentArm, loc)
|
|
935
|
+
: null;
|
|
618
936
|
const found = retag === null
|
|
619
|
-
? lowerer.coerceToExpected(v, resultT)
|
|
937
|
+
? lowerer.coerceToExpected(classView ?? v, resultT)
|
|
620
938
|
: { kind: "call", callee: retag, args: [v], type: resultT, loc };
|
|
621
939
|
const miss = {
|
|
622
940
|
kind: "unionWrap",
|
|
@@ -630,7 +948,7 @@ function findHelper(lowerer, elem, resultT, undefTag, fnRet, arity, last, loc, r
|
|
|
630
948
|
{
|
|
631
949
|
kind: "varDecl",
|
|
632
950
|
localId: "v.0",
|
|
633
|
-
init:
|
|
951
|
+
init: callbackValueRead(lowerer, varRef("a.0", arrT, loc), varRef("i.0", F64, loc), elem, present, loc),
|
|
634
952
|
loc,
|
|
635
953
|
},
|
|
636
954
|
{
|
|
@@ -668,20 +986,20 @@ function findHelper(lowerer, elem, resultT, undefTag, fnRet, arity, last, loc, r
|
|
|
668
986
|
*
|
|
669
987
|
* n = a.length; for (...) if (f(a[i], i, a)) return i; return -1;
|
|
670
988
|
*/
|
|
671
|
-
function findIndexHelper(lowerer, elem, fnRet, arity, last, loc) {
|
|
989
|
+
function findIndexHelper(lowerer, elem, fnRet, arity, last, loc, site = "", fastT = null, present = false) {
|
|
672
990
|
const method = last ? "findLastIndex" : "findIndex";
|
|
673
|
-
const key = `${method}:${typeKey(elem)}:${typeKey(fnRet)}:${arity}`;
|
|
991
|
+
const key = `${method}:${typeKey(elem)}:${typeKey(fnRet)}:${arity}${site}${fastT ? ":split" : ""}${present ? ":present" : ""}`;
|
|
674
992
|
const existing = lowerer.arrHofHelpers.get(key);
|
|
675
993
|
if (existing)
|
|
676
994
|
return existing;
|
|
677
995
|
const name = `%arr.${method}.${lowerer.arrHofHelpers.size}`;
|
|
678
996
|
lowerer.arrHofHelpers.set(key, name);
|
|
679
997
|
const arrT = arrayOf(elem);
|
|
680
|
-
const fnT = funcOf([
|
|
998
|
+
const fnT = funcOf([callbackValueType(lowerer, elem, present), F64, arrT].slice(0, arity), fnRet);
|
|
681
999
|
const visit = [
|
|
682
1000
|
{
|
|
683
1001
|
kind: "if",
|
|
684
|
-
cond: predicateToBoolean(callArrayCallback(arrT, fnT, fnRet, arity,
|
|
1002
|
+
cond: predicateToBoolean(callArrayCallback(arrT, fnT, fnRet, arity, callbackValueRead(lowerer, varRef("a.0", arrT, loc), varRef("i.0", F64, loc), elem, present, loc), loc)),
|
|
685
1003
|
then: [{ kind: "return", value: varRef("i.0", F64, loc), loc }],
|
|
686
1004
|
else_: null,
|
|
687
1005
|
loc,
|
|
@@ -695,14 +1013,14 @@ function findIndexHelper(lowerer, elem, fnRet, arity, last, loc) {
|
|
|
695
1013
|
loop,
|
|
696
1014
|
{ kind: "return", value: { kind: "numLit", value: -1, type: F64, loc }, loc },
|
|
697
1015
|
];
|
|
698
|
-
lowerer.liftedFns.push({
|
|
1016
|
+
lowerer.liftedFns.push(withFastCallback({
|
|
699
1017
|
name,
|
|
700
1018
|
params: arrayCallbackParams(arrT, fnT),
|
|
701
1019
|
returnType: F64,
|
|
702
1020
|
locals: [...arrayCallbackLocals(arrT, fnT)],
|
|
703
1021
|
body,
|
|
704
1022
|
loc,
|
|
705
|
-
});
|
|
1023
|
+
}, fastT, elem));
|
|
706
1024
|
return name;
|
|
707
1025
|
}
|
|
708
1026
|
/** The some/every loops — short-circuit early returns, JS-exact:
|
|
@@ -710,16 +1028,16 @@ function findIndexHelper(lowerer, elem, fnRet, arity, last, loc) {
|
|
|
710
1028
|
* some: n = a.length; for (...) if (f(a[i])) return true; return false;
|
|
711
1029
|
* every: n = a.length; for (...) if (!f(a[i])) return false; return true;
|
|
712
1030
|
*/
|
|
713
|
-
function someEveryHelper(lowerer, method, elem, fnRet, arity, loc) {
|
|
714
|
-
const key = `${method}:${typeKey(elem)}:${typeKey(fnRet)}:${arity}`;
|
|
1031
|
+
function someEveryHelper(lowerer, method, elem, fnRet, arity, loc, site = "", fastT = null, present = false) {
|
|
1032
|
+
const key = `${method}:${typeKey(elem)}:${typeKey(fnRet)}:${arity}${site}${fastT ? ":split" : ""}${present ? ":present" : ""}`;
|
|
715
1033
|
const existing = lowerer.arrHofHelpers.get(key);
|
|
716
1034
|
if (existing)
|
|
717
1035
|
return existing;
|
|
718
1036
|
const name = `%arr.${method}.${lowerer.arrHofHelpers.size}`;
|
|
719
1037
|
lowerer.arrHofHelpers.set(key, name);
|
|
720
1038
|
const arrT = arrayOf(elem);
|
|
721
|
-
const fnT = funcOf([
|
|
722
|
-
const callF = predicateToBoolean(callArrayCallback(arrT, fnT, fnRet, arity,
|
|
1039
|
+
const fnT = funcOf([callbackValueType(lowerer, elem, present), F64, arrT].slice(0, arity), fnRet);
|
|
1040
|
+
const callF = predicateToBoolean(callArrayCallback(arrT, fnT, fnRet, arity, callbackValueRead(lowerer, varRef("a.0", arrT, loc), varRef("i.0", F64, loc), elem, present, loc), loc));
|
|
723
1041
|
const body = [
|
|
724
1042
|
arrayLengthDeclaration(arrT, loc),
|
|
725
1043
|
countedFor(loc, varRef("n.0", F64, loc), () => [
|
|
@@ -743,14 +1061,14 @@ function someEveryHelper(lowerer, method, elem, fnRet, arity, loc) {
|
|
|
743
1061
|
]),
|
|
744
1062
|
{ kind: "return", value: boolLit(method !== "some", loc), loc },
|
|
745
1063
|
];
|
|
746
|
-
lowerer.liftedFns.push({
|
|
1064
|
+
lowerer.liftedFns.push(withFastCallback({
|
|
747
1065
|
name,
|
|
748
1066
|
params: arrayCallbackParams(arrT, fnT),
|
|
749
1067
|
returnType: BOOL,
|
|
750
1068
|
locals: [...arrayCallbackLocals(arrT, fnT)],
|
|
751
1069
|
body,
|
|
752
1070
|
loc,
|
|
753
|
-
});
|
|
1071
|
+
}, fastT, elem));
|
|
754
1072
|
return name;
|
|
755
1073
|
}
|
|
756
1074
|
/** `a.flatMap(f)` — map plus a one-level flatten. A callback returning
|
|
@@ -766,7 +1084,8 @@ export function lowerArrayFlatMapCall(lowerer, call, access, elem) {
|
|
|
766
1084
|
const argNode = call.arguments[0];
|
|
767
1085
|
if (!argNode)
|
|
768
1086
|
lowerer.unsupported("SC1090", call, "this call form"); // tsc-guarded
|
|
769
|
-
const
|
|
1087
|
+
const present = presentElements(lowerer, call, elem);
|
|
1088
|
+
const { fnArg, arity } = lowerArrayCallback(lowerer, argNode, [callbackValueType(lowerer, elem, present)], arrT);
|
|
770
1089
|
const fnRet = fnArg.type.ret;
|
|
771
1090
|
if (fnRet.kind === "dyn" ||
|
|
772
1091
|
fnRet.kind === "jsval" ||
|
|
@@ -794,11 +1113,35 @@ export function lowerArrayFlatMapCall(lowerer, call, access, elem) {
|
|
|
794
1113
|
lowerer.badType(call, lowerer.typeOf(call));
|
|
795
1114
|
requireProducedArrayElement(lowerer, call, "'.flatMap()'", fnRet);
|
|
796
1115
|
const outElem = callbackArrayElement(lowerer, call, fnRet);
|
|
797
|
-
const
|
|
798
|
-
|
|
1116
|
+
const fast = present
|
|
1117
|
+
? null
|
|
1118
|
+
: lowerFastCallback(lowerer, argNode, [arrayValueType(lowerer, elem)], 0, elem, arrT, {
|
|
1119
|
+
fnArg,
|
|
1120
|
+
arity,
|
|
1121
|
+
});
|
|
1122
|
+
const helper = arrayHofHelper(lowerer, "flatMap", elem, fnRet, arity, loc, outElem, callbackSite(fast ?? fnArg), fast?.type ?? null, present);
|
|
1123
|
+
return {
|
|
1124
|
+
kind: "call",
|
|
1125
|
+
callee: helper,
|
|
1126
|
+
args: [receiver, fnArg, ...(fast ? [fast] : [])],
|
|
1127
|
+
type: arrayOf(outElem),
|
|
1128
|
+
loc,
|
|
1129
|
+
};
|
|
799
1130
|
}
|
|
800
|
-
const
|
|
801
|
-
|
|
1131
|
+
const fast = present
|
|
1132
|
+
? null
|
|
1133
|
+
: lowerFastCallback(lowerer, argNode, [arrayValueType(lowerer, elem)], 0, elem, arrT, {
|
|
1134
|
+
fnArg,
|
|
1135
|
+
arity,
|
|
1136
|
+
});
|
|
1137
|
+
const helper = flatMapHelper(lowerer, elem, fnRet, arity, loc, callbackSite(fast ?? fnArg), fast?.type ?? null, present);
|
|
1138
|
+
return {
|
|
1139
|
+
kind: "call",
|
|
1140
|
+
callee: helper,
|
|
1141
|
+
args: [receiver, fnArg, ...(fast ? [fast] : [])],
|
|
1142
|
+
type: fnRet,
|
|
1143
|
+
loc,
|
|
1144
|
+
};
|
|
802
1145
|
}
|
|
803
1146
|
/** The flatMap loop (array-returning callback), from existing IR nodes:
|
|
804
1147
|
*
|
|
@@ -809,8 +1152,8 @@ export function lowerArrayFlatMapCall(lowerer, call, access, elem) {
|
|
|
809
1152
|
* }
|
|
810
1153
|
* return out;
|
|
811
1154
|
*/
|
|
812
|
-
function flatMapHelper(lowerer, elem, fnRet, arity, loc) {
|
|
813
|
-
const key = `flatMap:${typeKey(elem)}:${typeKey(fnRet)}:${arity}`;
|
|
1155
|
+
function flatMapHelper(lowerer, elem, fnRet, arity, loc, site = "", fastT = null, present = false) {
|
|
1156
|
+
const key = `flatMap:${typeKey(elem)}:${typeKey(fnRet)}:${arity}${site}${fastT ? ":split" : ""}${present ? ":present" : ""}`;
|
|
814
1157
|
const existing = lowerer.arrHofHelpers.get(key);
|
|
815
1158
|
if (existing)
|
|
816
1159
|
return existing;
|
|
@@ -818,7 +1161,7 @@ function flatMapHelper(lowerer, elem, fnRet, arity, loc) {
|
|
|
818
1161
|
lowerer.arrHofHelpers.set(key, name);
|
|
819
1162
|
const arrT = arrayOf(elem);
|
|
820
1163
|
const inner = fnRet.elem;
|
|
821
|
-
const fnT = funcOf([
|
|
1164
|
+
const fnT = funcOf([callbackValueType(lowerer, elem, present), F64, arrT].slice(0, arity), fnRet);
|
|
822
1165
|
const innerLoop = {
|
|
823
1166
|
kind: "for",
|
|
824
1167
|
init: { kind: "varDecl", localId: "j.0", init: numLit(0, loc), loc },
|
|
@@ -885,7 +1228,7 @@ function flatMapHelper(lowerer, elem, fnRet, arity, loc) {
|
|
|
885
1228
|
{
|
|
886
1229
|
kind: "varDecl",
|
|
887
1230
|
localId: "r.0",
|
|
888
|
-
init: callArrayCallback(arrT, fnT, fnRet, arity,
|
|
1231
|
+
init: callArrayCallback(arrT, fnT, fnRet, arity, callbackValueRead(lowerer, varRef("a.0", arrT, loc), varRef("i.0", F64, loc), elem, present, loc), loc),
|
|
889
1232
|
loc,
|
|
890
1233
|
},
|
|
891
1234
|
{
|
|
@@ -909,7 +1252,7 @@ function flatMapHelper(lowerer, elem, fnRet, arity, loc) {
|
|
|
909
1252
|
]),
|
|
910
1253
|
{ kind: "return", value: varRef("out.0", fnRet, loc), loc },
|
|
911
1254
|
];
|
|
912
|
-
lowerer.liftedFns.push({
|
|
1255
|
+
lowerer.liftedFns.push(withFastCallback({
|
|
913
1256
|
name,
|
|
914
1257
|
params: arrayCallbackParams(arrT, fnT),
|
|
915
1258
|
returnType: fnRet,
|
|
@@ -923,7 +1266,7 @@ function flatMapHelper(lowerer, elem, fnRet, arity, loc) {
|
|
|
923
1266
|
],
|
|
924
1267
|
body,
|
|
925
1268
|
loc,
|
|
926
|
-
});
|
|
1269
|
+
}, fastT, elem));
|
|
927
1270
|
return name;
|
|
928
1271
|
}
|
|
929
1272
|
/** `a.reduce(f)` / `a.reduce(f, init)` and reduceRight — both declared
|
|
@@ -944,10 +1287,15 @@ export function lowerArrayReduceCall(lowerer, call, access, method, elem) {
|
|
|
944
1287
|
if (accT.kind === "void" || accT.kind === "func")
|
|
945
1288
|
lowerer.badType(call, lowerer.typeOf(call));
|
|
946
1289
|
const { fnArg, arity } = lowerArrayCallback(lowerer, argNode, [accT, arrayValueType(lowerer, elem)], arrT, false, accT);
|
|
947
|
-
const
|
|
1290
|
+
const fast = lowerFastCallback(lowerer, argNode, [accT, arrayValueType(lowerer, elem)], 1, elem, arrT, { fnArg, arity }, false, accT);
|
|
1291
|
+
const helper = reduceHelper(lowerer, method, elem, accT, fnArg.type.ret, arity, hasInit, loc, callbackSite(fast ?? fnArg), fast?.type ?? null);
|
|
948
1292
|
const args = [receiver, fnArg];
|
|
949
1293
|
if (hasInit)
|
|
950
1294
|
args.push(lowerer.lowerExprExpecting(call.arguments[1], accT));
|
|
1295
|
+
// The fast closure is created last; making a closure has no observable
|
|
1296
|
+
// effect, so the initial value still evaluates right after the callback.
|
|
1297
|
+
if (fast)
|
|
1298
|
+
args.push(fast);
|
|
951
1299
|
return { kind: "call", callee: helper, args, type: accT, loc };
|
|
952
1300
|
}
|
|
953
1301
|
/** The reduce/reduceRight loops, from existing IR nodes:
|
|
@@ -960,8 +1308,8 @@ export function lowerArrayReduceCall(lowerer, call, access, method, elem) {
|
|
|
960
1308
|
* reduce walks 0→n-1, reduceRight n-1→0; the seed without an initial
|
|
961
1309
|
* value is a[0] / a[n-1] and the loop starts one past it. The empty-array
|
|
962
1310
|
* TypeError message is Node's, byte for byte. */
|
|
963
|
-
function reduceHelper(lowerer, method, elem, accT, fnRet, arity, hasInit, loc) {
|
|
964
|
-
const key = `${method}:${typeKey(elem)}:${typeKey(accT)}:${typeKey(fnRet)}:${arity}:${hasInit ? "init" : "seed"}`;
|
|
1311
|
+
function reduceHelper(lowerer, method, elem, accT, fnRet, arity, hasInit, loc, site = "", fastT = null) {
|
|
1312
|
+
const key = `${method}:${typeKey(elem)}:${typeKey(accT)}:${typeKey(fnRet)}:${arity}:${hasInit ? "init" : "seed"}${site}${fastT ? ":split" : ""}`;
|
|
965
1313
|
const existing = lowerer.arrHofHelpers.get(key);
|
|
966
1314
|
if (existing)
|
|
967
1315
|
return existing;
|
|
@@ -1101,7 +1449,7 @@ function reduceHelper(lowerer, method, elem, accT, fnRet, arity, hasInit, loc) {
|
|
|
1101
1449
|
loop,
|
|
1102
1450
|
{ kind: "return", value: varRef("acc.0", accT, loc), loc },
|
|
1103
1451
|
];
|
|
1104
|
-
lowerer.liftedFns.push({ name, params, returnType: accT, locals, body, loc });
|
|
1452
|
+
lowerer.liftedFns.push(withFastCallback({ name, params, returnType: accT, locals, body, loc }, fastT, elem));
|
|
1105
1453
|
return name;
|
|
1106
1454
|
}
|
|
1107
1455
|
/** `a.sort(cmp)` / `a.toSorted(cmp)`, desugared to an interned synthetic
|
|
@@ -1196,13 +1544,16 @@ export function lowerArraySortCall(lowerer, call, access, elem, arrT) {
|
|
|
1196
1544
|
lowerer.badType(argNode, lowerer.typeOf(argNode));
|
|
1197
1545
|
}
|
|
1198
1546
|
const arity = fnArg.type.params.length;
|
|
1199
|
-
|
|
1547
|
+
// The runtime sorts raw slots without per-move reference counting; this
|
|
1548
|
+
// beats the IR merge sort even when its comparator call becomes direct.
|
|
1549
|
+
const native = isSortValuesElement(elem, elem.kind === "union" ? lowerer.unions.get(elem.unionId)?.arms : undefined);
|
|
1550
|
+
const key = `${method}:${typeKey(elem)}:${arity}${native ? ":native" : ""}`;
|
|
1200
1551
|
let helper = lowerer.arrHofHelpers.get(key);
|
|
1201
1552
|
if (!helper) {
|
|
1202
1553
|
helper = `%arr.${method}.${lowerer.arrHofHelpers.size}`;
|
|
1203
1554
|
lowerer.arrHofHelpers.set(key, helper);
|
|
1204
1555
|
const undefinedTag = elem.kind === "union" ? lowerer.armTag(elem.unionId, UNDEFINED_T) : -1;
|
|
1205
|
-
lowerer.liftedFns.push(buildArraySortFn(helper, elem, arity, copyFirst, undefinedTag >= 0 ? undefinedTag : null, loc));
|
|
1556
|
+
lowerer.liftedFns.push(buildArraySortFn(helper, elem, arity, copyFirst, undefinedTag >= 0 ? undefinedTag : null, loc, native));
|
|
1206
1557
|
}
|
|
1207
1558
|
return { kind: "call", callee: helper, args: [receiver, fnArg], type: arrT, loc };
|
|
1208
1559
|
}
|