@scriptc/compiler 0.4.2 → 0.4.4
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 +470 -66
- package/dist/backend/cycle-analysis.d.ts +4 -1
- package/dist/backend/cycle-analysis.js +6 -4
- package/dist/backend/cycle-analysis.js.map +1 -1
- package/dist/backend/cycle-analysis.test.js +55 -0
- package/dist/backend/cycle-analysis.test.js.map +1 -1
- package/dist/backend/cycle-mutability.d.ts +7 -0
- package/dist/backend/cycle-mutability.js +19 -1
- package/dist/backend/cycle-mutability.js.map +1 -1
- package/dist/backend/executable-features.js +2 -0
- package/dist/backend/executable-features.js.map +1 -1
- package/dist/backend/immutability.d.ts +6 -3
- package/dist/backend/immutability.js +33 -29
- package/dist/backend/immutability.js.map +1 -1
- package/dist/backend/library-pack.js +1 -0
- package/dist/backend/library-pack.js.map +1 -1
- package/dist/backend/llvm/alloc.d.ts +16 -1
- package/dist/backend/llvm/alloc.js +54 -4
- package/dist/backend/llvm/alloc.js.map +1 -1
- package/dist/backend/llvm/appended-array-literals.d.ts +2 -1
- package/dist/backend/llvm/appended-array-literals.js +44 -36
- package/dist/backend/llvm/appended-array-literals.js.map +1 -1
- package/dist/backend/llvm/appended-array-literals.test.js +4 -3
- package/dist/backend/llvm/appended-array-literals.test.js.map +1 -1
- package/dist/backend/llvm/array-search.d.ts +4 -3
- package/dist/backend/llvm/array-search.js +21 -9
- package/dist/backend/llvm/array-search.js.map +1 -1
- package/dist/backend/llvm/blocks.d.ts +1 -1
- package/dist/backend/llvm/blocks.js +2 -2
- package/dist/backend/llvm/blocks.js.map +1 -1
- package/dist/backend/llvm/byte-windows.js +2 -0
- package/dist/backend/llvm/byte-windows.js.map +1 -1
- package/dist/backend/llvm/bytes-alias.d.ts +6 -1
- package/dist/backend/llvm/bytes-alias.js +8 -2
- package/dist/backend/llvm/bytes-alias.js.map +1 -1
- package/dist/backend/llvm/bytes-loop-versions.d.ts +47 -5
- package/dist/backend/llvm/bytes-loop-versions.js +479 -32
- package/dist/backend/llvm/bytes-loop-versions.js.map +1 -1
- package/dist/backend/llvm/bytes-loop-versions.test.js +263 -2
- package/dist/backend/llvm/bytes-loop-versions.test.js.map +1 -1
- package/dist/backend/llvm/checked-value-lifetimes.js +2 -0
- package/dist/backend/llvm/checked-value-lifetimes.js.map +1 -1
- package/dist/backend/llvm/classes.d.ts +7 -5
- package/dist/backend/llvm/classes.js +44 -20
- package/dist/backend/llvm/classes.js.map +1 -1
- package/dist/backend/llvm/classes.test.js +167 -7
- package/dist/backend/llvm/classes.test.js.map +1 -1
- package/dist/backend/llvm/common.d.ts +9 -3
- package/dist/backend/llvm/common.js +9 -3
- package/dist/backend/llvm/common.js.map +1 -1
- package/dist/backend/llvm/constant-callbacks.d.ts +2 -1
- package/dist/backend/llvm/constant-callbacks.js +83 -52
- package/dist/backend/llvm/constant-callbacks.js.map +1 -1
- package/dist/backend/llvm/counted-loops.d.ts +7 -0
- package/dist/backend/llvm/counted-loops.js +18 -0
- package/dist/backend/llvm/counted-loops.js.map +1 -1
- package/dist/backend/llvm/debug-info.js +2 -5
- package/dist/backend/llvm/debug-info.js.map +1 -1
- package/dist/backend/llvm/dense-array-access.d.ts +39 -8
- package/dist/backend/llvm/dense-array-access.js +222 -52
- package/dist/backend/llvm/dense-array-access.js.map +1 -1
- package/dist/backend/llvm/dense-array-access.test.js +36 -0
- package/dist/backend/llvm/dense-array-access.test.js.map +1 -1
- package/dist/backend/llvm/dense-array-loops.d.ts +17 -1
- package/dist/backend/llvm/dense-array-loops.js +194 -5
- package/dist/backend/llvm/dense-array-loops.js.map +1 -1
- package/dist/backend/llvm/dense-array-loops.test.js +90 -1
- package/dist/backend/llvm/dense-array-loops.test.js.map +1 -1
- package/dist/backend/llvm/dyn-handle-tags.test.js +6 -1
- package/dist/backend/llvm/dyn-handle-tags.test.js.map +1 -1
- package/dist/backend/llvm/dyn.d.ts +30 -0
- package/dist/backend/llvm/dyn.js +373 -70
- package/dist/backend/llvm/dyn.js.map +1 -1
- package/dist/backend/llvm/emit-function.js +13 -28
- package/dist/backend/llvm/emit-function.js.map +1 -1
- package/dist/backend/llvm/emit-journal.d.ts +93 -0
- package/dist/backend/llvm/emit-journal.js +170 -0
- package/dist/backend/llvm/emit-journal.js.map +1 -0
- package/dist/backend/llvm/emit-module.js +211 -33
- package/dist/backend/llvm/emit-module.js.map +1 -1
- package/dist/backend/llvm/emit-statements.d.ts +0 -4
- package/dist/backend/llvm/emit-statements.js +268 -84
- package/dist/backend/llvm/emit-statements.js.map +1 -1
- package/dist/backend/llvm/emitter-state.d.ts +7 -0
- package/dist/backend/llvm/emitter-state.js +14 -0
- package/dist/backend/llvm/emitter-state.js.map +1 -0
- package/dist/backend/llvm/emitter.d.ts +186 -37
- package/dist/backend/llvm/emitter.js +733 -90
- package/dist/backend/llvm/emitter.js.map +1 -1
- package/dist/backend/llvm/emitter.test.js +65 -7
- package/dist/backend/llvm/emitter.test.js.map +1 -1
- package/dist/backend/llvm/expr-async.js +11 -13
- package/dist/backend/llvm/expr-async.js.map +1 -1
- package/dist/backend/llvm/expr-bytes.js +48 -20
- package/dist/backend/llvm/expr-bytes.js.map +1 -1
- package/dist/backend/llvm/expr-callbacks.js +47 -0
- package/dist/backend/llvm/expr-callbacks.js.map +1 -1
- package/dist/backend/llvm/expr-calls.js +28 -14
- package/dist/backend/llvm/expr-calls.js.map +1 -1
- package/dist/backend/llvm/expr-containers.d.ts +14 -2
- package/dist/backend/llvm/expr-containers.js +143 -37
- package/dist/backend/llvm/expr-containers.js.map +1 -1
- package/dist/backend/llvm/expr-context.d.ts +14 -0
- package/dist/backend/llvm/expr-dynamic.js +18 -11
- package/dist/backend/llvm/expr-dynamic.js.map +1 -1
- package/dist/backend/llvm/expr-primitives.js +119 -38
- package/dist/backend/llvm/expr-primitives.js.map +1 -1
- package/dist/backend/llvm/expr-primitives.test.js +11 -6
- package/dist/backend/llvm/expr-primitives.test.js.map +1 -1
- package/dist/backend/llvm/expr-records.d.ts +12 -0
- package/dist/backend/llvm/expr-records.js +106 -0
- package/dist/backend/llvm/expr-records.js.map +1 -1
- package/dist/backend/llvm/expr-stream-bridges.d.ts +2 -2
- package/dist/backend/llvm/expr-stream-bridges.js +210 -69
- 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-bridges.test.js.map +1 -1
- package/dist/backend/llvm/expr-stream-callbacks.d.ts +2 -2
- package/dist/backend/llvm/expr-stream-callbacks.js +74 -20
- package/dist/backend/llvm/expr-stream-callbacks.js.map +1 -1
- package/dist/backend/llvm/int32-kind-loops.d.ts +39 -0
- package/dist/backend/llvm/int32-kind-loops.js +106 -0
- package/dist/backend/llvm/int32-kind-loops.js.map +1 -0
- package/dist/backend/llvm/integer-or-nan-indexes.test.d.ts +1 -0
- package/dist/backend/llvm/integer-or-nan-indexes.test.js +118 -0
- package/dist/backend/llvm/integer-or-nan-indexes.test.js.map +1 -0
- package/dist/backend/llvm/integer-values.d.ts +25 -1
- package/dist/backend/llvm/integer-values.js +95 -0
- package/dist/backend/llvm/integer-values.js.map +1 -1
- package/dist/backend/llvm/js-ic.d.ts +1 -1
- package/dist/backend/llvm/js-ic.js +1 -1
- package/dist/backend/llvm/js-ic.js.map +1 -1
- package/dist/backend/llvm/key-orders.d.ts +7 -0
- package/dist/backend/llvm/key-orders.js +33 -0
- package/dist/backend/llvm/key-orders.js.map +1 -0
- package/dist/backend/llvm/lib-connect.js +4 -0
- package/dist/backend/llvm/lib-connect.js.map +1 -1
- package/dist/backend/llvm/lib-datagram.js +11 -0
- package/dist/backend/llvm/lib-datagram.js.map +1 -1
- package/dist/backend/llvm/lib-dispatch.js +213 -5
- package/dist/backend/llvm/lib-dispatch.js.map +1 -1
- package/dist/backend/llvm/lib-filesystem.js +4 -4
- package/dist/backend/llvm/lib-filesystem.js.map +1 -1
- package/dist/backend/llvm/lib-http2.js +4 -0
- package/dist/backend/llvm/lib-http2.js.map +1 -1
- package/dist/backend/llvm/lib-lookup.js +16 -6
- package/dist/backend/llvm/lib-lookup.js.map +1 -1
- package/dist/backend/llvm/lib-process.js +37 -1
- package/dist/backend/llvm/lib-process.js.map +1 -1
- package/dist/backend/llvm/lib-shared.js +94 -2
- package/dist/backend/llvm/lib-shared.js.map +1 -1
- package/dist/backend/llvm/lib-stream.js +35 -5
- package/dist/backend/llvm/lib-stream.js.map +1 -1
- package/dist/backend/llvm/local-array-reads.js +115 -19
- package/dist/backend/llvm/local-array-reads.js.map +1 -1
- package/dist/backend/llvm/local-array-reads.test.js +14 -0
- package/dist/backend/llvm/local-array-reads.test.js.map +1 -1
- package/dist/backend/llvm/loop-state.d.ts +33 -0
- package/dist/backend/llvm/loop-state.js +42 -0
- package/dist/backend/llvm/loop-state.js.map +1 -0
- package/dist/backend/llvm/map-number-lookup.d.ts +26 -8
- package/dist/backend/llvm/map-number-lookup.js +91 -31
- package/dist/backend/llvm/map-number-lookup.js.map +1 -1
- package/dist/backend/llvm/map-number-lookup.test.js +55 -0
- package/dist/backend/llvm/map-number-lookup.test.js.map +1 -1
- package/dist/backend/llvm/map-read-lifetimes.js +4 -2
- package/dist/backend/llvm/map-read-lifetimes.js.map +1 -1
- package/dist/backend/llvm/nullable-unions.d.ts +2 -1
- package/dist/backend/llvm/nullable-unions.js +15 -3
- package/dist/backend/llvm/nullable-unions.js.map +1 -1
- package/dist/backend/llvm/publish.d.ts +10 -0
- package/dist/backend/llvm/publish.js +15 -3
- package/dist/backend/llvm/publish.js.map +1 -1
- package/dist/backend/llvm/receivers.js +6 -1
- package/dist/backend/llvm/receivers.js.map +1 -1
- package/dist/backend/llvm/record-results.d.ts +1 -9
- package/dist/backend/llvm/record-results.js +2 -11
- package/dist/backend/llvm/record-results.js.map +1 -1
- package/dist/backend/llvm/reference-effects.js +3 -0
- package/dist/backend/llvm/reference-effects.js.map +1 -1
- package/dist/backend/llvm/reference-writes.d.ts +7 -2
- package/dist/backend/llvm/reference-writes.js +89 -72
- package/dist/backend/llvm/reference-writes.js.map +1 -1
- package/dist/backend/llvm/running-extrema.d.ts +11 -0
- package/dist/backend/llvm/running-extrema.js +115 -0
- package/dist/backend/llvm/running-extrema.js.map +1 -0
- package/dist/backend/llvm/running-extrema.test.d.ts +1 -0
- package/dist/backend/llvm/running-extrema.test.js +89 -0
- package/dist/backend/llvm/running-extrema.test.js.map +1 -0
- package/dist/backend/llvm/shapes.d.ts +71 -15
- package/dist/backend/llvm/shapes.js +224 -40
- package/dist/backend/llvm/shapes.js.map +1 -1
- package/dist/backend/llvm/shapes.test.js +53 -7
- package/dist/backend/llvm/shapes.test.js.map +1 -1
- package/dist/backend/llvm/speculative-integers.d.ts +6 -0
- package/dist/backend/llvm/speculative-integers.js +2 -2
- package/dist/backend/llvm/speculative-integers.js.map +1 -1
- package/dist/backend/llvm/stack-captures.js +1 -5
- package/dist/backend/llvm/stack-captures.js.map +1 -1
- package/dist/backend/llvm/stack-objects.d.ts +3 -2
- package/dist/backend/llvm/stack-objects.js +5 -2
- package/dist/backend/llvm/stack-objects.js.map +1 -1
- package/dist/backend/llvm/string-reads.d.ts +12 -0
- package/dist/backend/llvm/string-reads.js +44 -0
- package/dist/backend/llvm/string-reads.js.map +1 -1
- package/dist/backend/llvm/union-repr.d.ts +4 -3
- package/dist/backend/llvm/union-repr.js +6 -5
- package/dist/backend/llvm/union-repr.js.map +1 -1
- package/dist/backend/llvm/walk-borrows.d.ts +3 -0
- package/dist/backend/llvm/walk-borrows.js +46 -41
- package/dist/backend/llvm/walk-borrows.js.map +1 -1
- package/dist/backend/llvm/walkers.d.ts +3 -0
- package/dist/backend/llvm/walkers.js +101 -65
- package/dist/backend/llvm/walkers.js.map +1 -1
- package/dist/backend/llvm/wrapping-sums.d.ts +16 -1
- package/dist/backend/llvm/wrapping-sums.js +126 -0
- package/dist/backend/llvm/wrapping-sums.js.map +1 -1
- package/dist/backend/may-throw.d.ts +8 -10
- package/dist/backend/may-throw.js +14 -10
- package/dist/backend/may-throw.js.map +1 -1
- package/dist/backend/native/contracts.d.ts +5 -0
- package/dist/backend/native/executable.js +7 -0
- package/dist/backend/native/executable.js.map +1 -1
- package/dist/backend/native/runtime-inputs.d.ts +1 -1
- package/dist/backend/native/runtime-inputs.js +1 -0
- package/dist/backend/native/runtime-inputs.js.map +1 -1
- package/dist/backend/native-codegen-core.d.ts +5 -3
- package/dist/backend/native-codegen-core.js +13 -6
- package/dist/backend/native-codegen-core.js.map +1 -1
- package/dist/backend/native-codegen.test.js +6 -4
- package/dist/backend/native-codegen.test.js.map +1 -1
- package/dist/backend/native-link-info-core.d.ts +4 -0
- package/dist/backend/native-link-info-core.js.map +1 -1
- package/dist/backend/publication.d.ts +12 -1
- package/dist/backend/publication.js +37 -14
- package/dist/backend/publication.js.map +1 -1
- package/dist/backend/publication.test.js +30 -0
- package/dist/backend/publication.test.js.map +1 -1
- package/dist/backend/result-slots.d.ts +16 -0
- package/dist/backend/result-slots.js +23 -0
- package/dist/backend/result-slots.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 +1 -0
- package/dist/backend/runtime-pack-core.js +1 -0
- package/dist/backend/runtime-pack-core.js.map +1 -1
- package/dist/backend/runtime-pack-targets.test.js +2 -1
- package/dist/backend/runtime-pack-targets.test.js.map +1 -1
- package/dist/backend/runtime-pack.test.js +2 -1
- package/dist/backend/runtime-pack.test.js.map +1 -1
- package/dist/backend/stack-observations.d.ts +2 -1
- package/dist/backend/stack-observations.js +67 -42
- package/dist/backend/stack-observations.js.map +1 -1
- package/dist/backend/target-cpu.d.ts +26 -0
- package/dist/backend/target-cpu.js +98 -0
- package/dist/backend/target-cpu.js.map +1 -0
- package/dist/backend/target-cpu.test.d.ts +1 -0
- package/dist/backend/target-cpu.test.js +38 -0
- package/dist/backend/target-cpu.test.js.map +1 -0
- package/dist/backend/target-diagnostics.js +5 -3
- package/dist/backend/target-diagnostics.js.map +1 -1
- package/dist/backend/warm-cache.js +1 -0
- package/dist/backend/warm-cache.js.map +1 -1
- package/dist/cli/command.js +20 -1
- package/dist/cli/command.js.map +1 -1
- package/dist/cli/usage.d.ts +4 -1
- package/dist/cli/usage.js +10 -3
- package/dist/cli/usage.js.map +1 -1
- package/dist/compat/fetch-profile.js +1 -1
- package/dist/compat/fetch-profile.js.map +1 -1
- package/dist/compile-types.d.ts +7 -0
- package/dist/contracts/check.js +4 -3
- package/dist/contracts/check.js.map +1 -1
- package/dist/contracts/int32-elements.js +10 -2
- package/dist/contracts/int32-elements.js.map +1 -1
- package/dist/coverage/report.js +12 -3
- package/dist/coverage/report.js.map +1 -1
- package/dist/diagnostics/diagnostic.d.ts +4 -0
- package/dist/diagnostics/diagnostic.js +1 -1
- package/dist/diagnostics/diagnostic.js.map +1 -1
- package/dist/diagnostics/envelope.d.ts +3 -0
- package/dist/diagnostics/envelope.js +1 -0
- package/dist/diagnostics/envelope.js.map +1 -1
- package/dist/executable/executable-cache.d.ts +5 -0
- package/dist/executable/executable-cache.js +5 -0
- package/dist/executable/executable-cache.js.map +1 -1
- package/dist/executable/executable-cache.test.js +3 -0
- package/dist/executable/executable-cache.test.js.map +1 -1
- package/dist/frontend/decl-projection.d.ts +41 -0
- package/dist/frontend/decl-projection.js +949 -0
- package/dist/frontend/decl-projection.js.map +1 -0
- package/dist/frontend/decl-projection.test.d.ts +1 -0
- package/dist/frontend/decl-projection.test.js +30 -0
- package/dist/frontend/decl-projection.test.js.map +1 -0
- package/dist/frontend/dts-paths.d.ts +15 -0
- package/dist/frontend/dts-paths.js +25 -0
- package/dist/frontend/dts-paths.js.map +1 -1
- package/dist/frontend/input-tracker.d.ts +6 -0
- package/dist/frontend/input-tracker.js +51 -28
- package/dist/frontend/input-tracker.js.map +1 -1
- package/dist/frontend/input-tracker.test.js +19 -0
- package/dist/frontend/input-tracker.test.js.map +1 -1
- package/dist/frontend/lowering/array-values.js +100 -2
- package/dist/frontend/lowering/array-values.js.map +1 -1
- package/dist/frontend/lowering/builtins/async-context.d.ts +8 -2
- package/dist/frontend/lowering/builtins/async-context.js +62 -3
- package/dist/frontend/lowering/builtins/async-context.js.map +1 -1
- package/dist/frontend/lowering/builtins/child-process-methods.js +46 -15
- package/dist/frontend/lowering/builtins/child-process-methods.js.map +1 -1
- package/dist/frontend/lowering/builtins/child-process.js +13 -2
- package/dist/frontend/lowering/builtins/child-process.js.map +1 -1
- package/dist/frontend/lowering/builtins/crypto.js +87 -10
- package/dist/frontend/lowering/builtins/crypto.js.map +1 -1
- package/dist/frontend/lowering/builtins/dates.js +4 -1
- package/dist/frontend/lowering/builtins/dates.js.map +1 -1
- package/dist/frontend/lowering/builtins/filesystem-calls.js +3 -3
- package/dist/frontend/lowering/builtins/filesystem-calls.js.map +1 -1
- package/dist/frontend/lowering/builtins/fs-glob.js +6 -3
- package/dist/frontend/lowering/builtins/fs-glob.js.map +1 -1
- package/dist/frontend/lowering/builtins/fs-paths.d.ts +43 -5
- package/dist/frontend/lowering/builtins/fs-paths.js +245 -93
- package/dist/frontend/lowering/builtins/fs-paths.js.map +1 -1
- package/dist/frontend/lowering/builtins/global-namespace-keys.d.ts +3 -0
- package/dist/frontend/lowering/builtins/global-namespace-keys.js +122 -0
- package/dist/frontend/lowering/builtins/global-namespace-keys.js.map +1 -0
- package/dist/frontend/lowering/builtins/module-calls.js +6 -3
- package/dist/frontend/lowering/builtins/module-calls.js.map +1 -1
- package/dist/frontend/lowering/builtins/numbers.js +9 -1
- package/dist/frontend/lowering/builtins/numbers.js.map +1 -1
- package/dist/frontend/lowering/builtins/promises.d.ts +7 -1
- package/dist/frontend/lowering/builtins/promises.js +236 -139
- package/dist/frontend/lowering/builtins/promises.js.map +1 -1
- package/dist/frontend/lowering/builtins/readline.d.ts +5 -1
- package/dist/frontend/lowering/builtins/readline.js +35 -3
- package/dist/frontend/lowering/builtins/readline.js.map +1 -1
- package/dist/frontend/lowering/builtins/url.js +24 -1
- package/dist/frontend/lowering/builtins/url.js.map +1 -1
- package/dist/frontend/lowering/builtins/webassembly.js +6 -3
- package/dist/frontend/lowering/builtins/webassembly.js.map +1 -1
- package/dist/frontend/lowering/call-signatures.js +0 -1
- package/dist/frontend/lowering/call-signatures.js.map +1 -1
- package/dist/frontend/lowering/cjs-exports-object.js +1 -1
- package/dist/frontend/lowering/cjs-exports-object.js.map +1 -1
- package/dist/frontend/lowering/cjs-inline-require.d.ts +32 -0
- package/dist/frontend/lowering/cjs-inline-require.js +307 -4
- package/dist/frontend/lowering/cjs-inline-require.js.map +1 -1
- package/dist/frontend/lowering/class-callbacks.d.ts +5 -2
- package/dist/frontend/lowering/class-callbacks.js +82 -12
- package/dist/frontend/lowering/class-callbacks.js.map +1 -1
- package/dist/frontend/lowering/class-construction.d.ts +4 -1
- package/dist/frontend/lowering/class-construction.js +17 -3
- package/dist/frontend/lowering/class-construction.js.map +1 -1
- package/dist/frontend/lowering/class-dynamic-dispatch.d.ts +49 -2
- package/dist/frontend/lowering/class-dynamic-dispatch.js +880 -108
- package/dist/frontend/lowering/class-dynamic-dispatch.js.map +1 -1
- package/dist/frontend/lowering/class-dynamic-dispatch.test.js +47 -0
- package/dist/frontend/lowering/class-dynamic-dispatch.test.js.map +1 -1
- package/dist/frontend/lowering/class-iterables.d.ts +2 -1
- package/dist/frontend/lowering/class-iterables.js +9 -1
- package/dist/frontend/lowering/class-iterables.js.map +1 -1
- package/dist/frontend/lowering/class-method-mutations.js +83 -24
- package/dist/frontend/lowering/class-method-mutations.js.map +1 -1
- package/dist/frontend/lowering/class-protocols.d.ts +25 -0
- package/dist/frontend/lowering/class-protocols.js +183 -1
- package/dist/frontend/lowering/class-protocols.js.map +1 -1
- package/dist/frontend/lowering/class-prototypes.js +31 -2
- package/dist/frontend/lowering/class-prototypes.js.map +1 -1
- package/dist/frontend/lowering/class-runtime-statics.d.ts +9 -3
- package/dist/frontend/lowering/class-runtime-statics.js +29 -4
- package/dist/frontend/lowering/class-runtime-statics.js.map +1 -1
- package/dist/frontend/lowering/coercions/structural-plans.js +48 -1
- package/dist/frontend/lowering/coercions/structural-plans.js.map +1 -1
- package/dist/frontend/lowering/coercions/structural.js +91 -1
- package/dist/frontend/lowering/coercions/structural.js.map +1 -1
- package/dist/frontend/lowering/completion-callbacks.d.ts +4 -0
- package/dist/frontend/lowering/completion-callbacks.js +146 -0
- package/dist/frontend/lowering/completion-callbacks.js.map +1 -0
- package/dist/frontend/lowering/containers/array-callback-call.js +2 -2
- package/dist/frontend/lowering/containers/array-callback-call.js.map +1 -1
- package/dist/frontend/lowering/containers/array-callbacks.d.ts +5 -4
- package/dist/frontend/lowering/containers/array-callbacks.js +345 -24
- package/dist/frontend/lowering/containers/array-callbacks.js.map +1 -1
- package/dist/frontend/lowering/containers/array-concat.js +10 -0
- package/dist/frontend/lowering/containers/array-concat.js.map +1 -1
- package/dist/frontend/lowering/containers/array-construction.js +5 -0
- package/dist/frontend/lowering/containers/array-construction.js.map +1 -1
- package/dist/frontend/lowering/containers/array-methods.js +26 -3
- package/dist/frontend/lowering/containers/array-methods.js.map +1 -1
- package/dist/frontend/lowering/containers/array-pipelines.js +19 -8
- package/dist/frontend/lowering/containers/array-pipelines.js.map +1 -1
- package/dist/frontend/lowering/containers/bytes.d.ts +25 -17
- package/dist/frontend/lowering/containers/bytes.js +455 -46
- package/dist/frontend/lowering/containers/bytes.js.map +1 -1
- package/dist/frontend/lowering/containers/callback-arguments.js +3 -0
- package/dist/frontend/lowering/containers/callback-arguments.js.map +1 -1
- package/dist/frontend/lowering/containers/collection-methods.js +7 -2
- package/dist/frontend/lowering/containers/collection-methods.js.map +1 -1
- package/dist/frontend/lowering/containers/filter-predicates.d.ts +6 -0
- package/dist/frontend/lowering/containers/filter-predicates.js +205 -0
- package/dist/frontend/lowering/containers/filter-predicates.js.map +1 -0
- package/dist/frontend/lowering/containers/indexed-objects.d.ts +0 -12
- package/dist/frontend/lowering/containers/indexed-objects.js +46 -7
- package/dist/frontend/lowering/containers/indexed-objects.js.map +1 -1
- package/dist/frontend/lowering/containers/string-and-regexp.js +55 -9
- package/dist/frontend/lowering/containers/string-and-regexp.js.map +1 -1
- package/dist/frontend/lowering/containers/string-replacement.js +43 -19
- package/dist/frontend/lowering/containers/string-replacement.js.map +1 -1
- package/dist/frontend/lowering/date-values.d.ts +11 -0
- package/dist/frontend/lowering/date-values.js +207 -0
- package/dist/frontend/lowering/date-values.js.map +1 -0
- package/dist/frontend/lowering/dispatch-sites.js +15 -1
- package/dist/frontend/lowering/dispatch-sites.js.map +1 -1
- package/dist/frontend/lowering/divergences.js +9 -1
- package/dist/frontend/lowering/divergences.js.map +1 -1
- package/dist/frontend/lowering/error-methods.js +47 -2
- package/dist/frontend/lowering/error-methods.js.map +1 -1
- package/dist/frontend/lowering/expressions/array-literals.js +53 -0
- package/dist/frontend/lowering/expressions/array-literals.js.map +1 -1
- package/dist/frontend/lowering/expressions/binary.js +100 -28
- package/dist/frontend/lowering/expressions/binary.js.map +1 -1
- package/dist/frontend/lowering/expressions/element-access.js +169 -13
- package/dist/frontend/lowering/expressions/element-access.js.map +1 -1
- package/dist/frontend/lowering/expressions/identifiers.js +64 -5
- package/dist/frontend/lowering/expressions/identifiers.js.map +1 -1
- package/dist/frontend/lowering/expressions/narrowing.js +95 -1
- package/dist/frontend/lowering/expressions/narrowing.js.map +1 -1
- package/dist/frontend/lowering/expressions/nullish-assignment.js +3 -1
- package/dist/frontend/lowering/expressions/nullish-assignment.js.map +1 -1
- package/dist/frontend/lowering/expressions/object-literals.d.ts +10 -0
- package/dist/frontend/lowering/expressions/object-literals.js +138 -51
- package/dist/frontend/lowering/expressions/object-literals.js.map +1 -1
- package/dist/frontend/lowering/expressions/optional-chains.js +12 -0
- package/dist/frontend/lowering/expressions/optional-chains.js.map +1 -1
- package/dist/frontend/lowering/expressions/property-access.js +168 -10
- package/dist/frontend/lowering/expressions/property-access.js.map +1 -1
- package/dist/frontend/lowering/expressions/relational.js +212 -33
- package/dist/frontend/lowering/expressions/relational.js.map +1 -1
- package/dist/frontend/lowering/expressions/typeof.js +6 -0
- package/dist/frontend/lowering/expressions/typeof.js.map +1 -1
- package/dist/frontend/lowering/expressions/union-fields.js +4 -0
- package/dist/frontend/lowering/expressions/union-fields.js.map +1 -1
- package/dist/frontend/lowering/expressions/updates.js +39 -3
- package/dist/frontend/lowering/expressions/updates.js.map +1 -1
- package/dist/frontend/lowering/frozen-records.d.ts +28 -0
- package/dist/frontend/lowering/frozen-records.js +322 -0
- package/dist/frontend/lowering/frozen-records.js.map +1 -0
- package/dist/frontend/lowering/function-returns.js +64 -0
- package/dist/frontend/lowering/function-returns.js.map +1 -1
- package/dist/frontend/lowering/generic-functions.js +7 -2
- package/dist/frontend/lowering/generic-functions.js.map +1 -1
- package/dist/frontend/lowering/indexed-unions.d.ts +54 -0
- package/dist/frontend/lowering/indexed-unions.js +401 -0
- package/dist/frontend/lowering/indexed-unions.js.map +1 -0
- package/dist/frontend/lowering/iterable-values.d.ts +49 -0
- package/dist/frontend/lowering/iterable-values.js +297 -0
- package/dist/frontend/lowering/iterable-values.js.map +1 -0
- package/dist/frontend/lowering/iterator-adapters.js +186 -1
- package/dist/frontend/lowering/iterator-adapters.js.map +1 -1
- package/dist/frontend/lowering/js-class-fields.d.ts +8 -0
- package/dist/frontend/lowering/js-class-fields.js +45 -10
- package/dist/frontend/lowering/js-class-fields.js.map +1 -1
- package/dist/frontend/lowering/key-order-witness.d.ts +18 -3
- package/dist/frontend/lowering/key-order-witness.js +974 -48
- package/dist/frontend/lowering/key-order-witness.js.map +1 -1
- package/dist/frontend/lowering/key-order-witness.test.js +530 -10
- package/dist/frontend/lowering/key-order-witness.test.js.map +1 -1
- package/dist/frontend/lowering/lower-assert.js +15 -3
- package/dist/frontend/lowering/lower-assert.js.map +1 -1
- package/dist/frontend/lowering/lower-async-iteration.js +4 -1
- package/dist/frontend/lowering/lower-async-iteration.js.map +1 -1
- package/dist/frontend/lowering/lower-calls.d.ts +7 -0
- package/dist/frontend/lowering/lower-calls.js +462 -44
- package/dist/frontend/lowering/lower-calls.js.map +1 -1
- package/dist/frontend/lowering/lower-classes.d.ts +11 -2
- package/dist/frontend/lowering/lower-classes.js +324 -69
- package/dist/frontend/lowering/lower-classes.js.map +1 -1
- package/dist/frontend/lowering/lower-dgram.js +3 -1
- package/dist/frontend/lowering/lower-dgram.js.map +1 -1
- package/dist/frontend/lowering/lower-exprs.js +215 -3
- package/dist/frontend/lowering/lower-exprs.js.map +1 -1
- package/dist/frontend/lowering/lower-functions.d.ts +11 -0
- package/dist/frontend/lowering/lower-functions.js +83 -0
- package/dist/frontend/lowering/lower-functions.js.map +1 -1
- package/dist/frontend/lowering/lower-generators.js +42 -32
- package/dist/frontend/lowering/lower-generators.js.map +1 -1
- package/dist/frontend/lowering/lower-global-value.js +6 -3
- package/dist/frontend/lowering/lower-global-value.js.map +1 -1
- package/dist/frontend/lowering/lower-inspect.d.ts +1 -1
- package/dist/frontend/lowering/lower-inspect.js +53 -17
- package/dist/frontend/lowering/lower-inspect.js.map +1 -1
- package/dist/frontend/lowering/lower-modules.js +53 -5
- package/dist/frontend/lowering/lower-modules.js.map +1 -1
- package/dist/frontend/lowering/lower-namespaces.js +5 -1
- package/dist/frontend/lowering/lower-namespaces.js.map +1 -1
- package/dist/frontend/lowering/lower-server.js +2 -2
- package/dist/frontend/lowering/lower-server.js.map +1 -1
- package/dist/frontend/lowering/lower-stdlib.d.ts +5 -0
- package/dist/frontend/lowering/lower-stdlib.js +30 -0
- package/dist/frontend/lowering/lower-stdlib.js.map +1 -1
- package/dist/frontend/lowering/lower-stmts.d.ts +23 -0
- package/dist/frontend/lowering/lower-stmts.js +553 -81
- package/dist/frontend/lowering/lower-stmts.js.map +1 -1
- package/dist/frontend/lowering/lower-stream.d.ts +20 -2
- package/dist/frontend/lowering/lower-stream.js +1483 -156
- package/dist/frontend/lowering/lower-stream.js.map +1 -1
- package/dist/frontend/lowering/lowerer.d.ts +107 -8
- package/dist/frontend/lowering/lowerer.js +381 -36
- package/dist/frontend/lowering/lowerer.js.map +1 -1
- package/dist/frontend/lowering/module-namespace-elements.d.ts +11 -1
- package/dist/frontend/lowering/module-namespace-elements.js +82 -5
- package/dist/frontend/lowering/module-namespace-elements.js.map +1 -1
- package/dist/frontend/lowering/new-target.d.ts +12 -0
- package/dist/frontend/lowering/new-target.js +280 -0
- package/dist/frontend/lowering/new-target.js.map +1 -0
- package/dist/frontend/lowering/object-factory-new.d.ts +5 -0
- package/dist/frontend/lowering/object-factory-new.js +20 -6
- package/dist/frontend/lowering/object-factory-new.js.map +1 -1
- package/dist/frontend/lowering/overload-choice.d.ts +33 -0
- package/dist/frontend/lowering/overload-choice.js +190 -0
- package/dist/frontend/lowering/overload-choice.js.map +1 -0
- package/dist/frontend/lowering/surfaces.d.ts +3 -0
- package/dist/frontend/lowering/surfaces.js +73 -8
- package/dist/frontend/lowering/surfaces.js.map +1 -1
- package/dist/frontend/lowering/undefined-index.d.ts +27 -0
- package/dist/frontend/lowering/undefined-index.js +82 -0
- package/dist/frontend/lowering/undefined-index.js.map +1 -0
- package/dist/frontend/lowering/var-hoisting.js +29 -13
- package/dist/frontend/lowering/var-hoisting.js.map +1 -1
- package/dist/frontend/lowering/width-lift.d.ts +18 -0
- package/dist/frontend/npm-static-bundled-chunks.js +9 -11
- package/dist/frontend/npm-static-bundled-chunks.js.map +1 -1
- package/dist/frontend/npm-static-bundled-chunks.test.js +6 -5
- package/dist/frontend/npm-static-bundled-chunks.test.js.map +1 -1
- package/dist/frontend/npm-static-rewrite-syntax.js +9 -1
- package/dist/frontend/npm-static-rewrite-syntax.js.map +1 -1
- package/dist/frontend/npm-static.js +4 -20
- package/dist/frontend/npm-static.js.map +1 -1
- package/dist/frontend/package-shims.d.ts +3 -0
- package/dist/frontend/package-shims.js +71 -8
- package/dist/frontend/package-shims.js.map +1 -1
- package/dist/frontend/pipeline.js +19 -11
- package/dist/frontend/pipeline.js.map +1 -1
- package/dist/frontend/process-fork.d.ts +25 -0
- package/dist/frontend/process-fork.js +2 -0
- package/dist/frontend/process-fork.js.map +1 -0
- package/dist/frontend/program-analysis.d.ts +5 -1
- package/dist/frontend/program-analysis.js +5 -0
- package/dist/frontend/program-analysis.js.map +1 -1
- package/dist/frontend/program.d.ts +21 -6
- package/dist/frontend/program.js +681 -83
- package/dist/frontend/program.js.map +1 -1
- package/dist/frontend/program.test.js +43 -3
- package/dist/frontend/program.test.js.map +1 -1
- package/dist/frontend/token-equivalence.d.ts +3 -0
- package/dist/frontend/token-equivalence.js +409 -0
- package/dist/frontend/token-equivalence.js.map +1 -0
- package/dist/frontend/token-equivalence.test.d.ts +1 -0
- package/dist/frontend/token-equivalence.test.js +67 -0
- package/dist/frontend/token-equivalence.test.js.map +1 -0
- package/dist/frontend/ts7/ast-node.d.ts +22 -0
- package/dist/frontend/ts7/ast-node.js +1048 -103
- package/dist/frontend/ts7/ast-node.js.map +1 -1
- package/dist/frontend/ts7/ast-node.test.js +24 -0
- package/dist/frontend/ts7/ast-node.test.js.map +1 -1
- package/dist/frontend/ts7/ast-wire.d.ts +4 -3
- package/dist/frontend/ts7/ast-wire.js +34 -24
- package/dist/frontend/ts7/ast-wire.js.map +1 -1
- package/dist/frontend/ts7/ast-wire.test.js +23 -0
- package/dist/frontend/ts7/ast-wire.test.js.map +1 -1
- package/dist/frontend/ts7/checker-backend.d.ts +3 -4
- package/dist/frontend/ts7/checker-backend.js +2 -2
- package/dist/frontend/ts7/checker-backend.js.map +1 -1
- package/dist/frontend/ts7/checker-backend.test.js +5 -9
- package/dist/frontend/ts7/checker-backend.test.js.map +1 -1
- package/dist/frontend/ts7/checker.d.ts +4 -0
- package/dist/frontend/ts7/checker.js +7 -0
- package/dist/frontend/ts7/checker.js.map +1 -1
- package/dist/frontend/ts7/lib-diagnostics.d.ts +24 -0
- package/dist/frontend/ts7/lib-diagnostics.js +307 -0
- package/dist/frontend/ts7/lib-diagnostics.js.map +1 -0
- package/dist/frontend/ts7/lib-diagnostics.test.d.ts +1 -0
- package/dist/frontend/ts7/lib-diagnostics.test.js +199 -0
- package/dist/frontend/ts7/lib-diagnostics.test.js.map +1 -0
- package/dist/frontend/ts7/program-host.d.ts +7 -0
- package/dist/frontend/ts7/program-host.js +25 -2
- package/dist/frontend/ts7/program-host.js.map +1 -1
- package/dist/frontend/ts7/semantic-model.d.ts +3 -0
- package/dist/frontend/ts7/semantic-model.js +5 -0
- package/dist/frontend/ts7/semantic-model.js.map +1 -1
- package/dist/frontend/ts7/semantic-model.test.js +6 -1
- package/dist/frontend/ts7/semantic-model.test.js.map +1 -1
- package/dist/frontend/ts7/semantic-types.d.ts +1 -1
- package/dist/frontend/ts7/semantic-types.js +1 -1
- package/dist/frontend/ts7/semantic-types.js.map +1 -1
- package/dist/frontend/ts7/session.d.ts +14 -1
- package/dist/frontend/ts7/session.js +22 -0
- package/dist/frontend/ts7/session.js.map +1 -1
- package/dist/frontend/type-mapper.d.ts +13 -1
- package/dist/frontend/type-mapper.js +229 -20
- package/dist/frontend/type-mapper.js.map +1 -1
- package/dist/index.d.ts +0 -5
- package/dist/index.js +46 -4
- package/dist/index.js.map +1 -1
- package/dist/ir/analysis.js +5 -3
- package/dist/ir/analysis.js.map +1 -1
- package/dist/ir/array-length-stability.d.ts +4 -0
- package/dist/ir/array-length-stability.js +19 -6
- package/dist/ir/array-length-stability.js.map +1 -1
- package/dist/ir/array-length-stability.test.js +24 -0
- package/dist/ir/array-length-stability.test.js.map +1 -1
- package/dist/ir/builtin-effects.d.ts +7 -0
- package/dist/ir/builtin-effects.js +60 -0
- package/dist/ir/builtin-effects.js.map +1 -1
- package/dist/ir/builtin-signatures.d.ts +6 -4
- package/dist/ir/builtin-signatures.js +222 -13
- package/dist/ir/builtin-signatures.js.map +1 -1
- package/dist/ir/callback-specialization.d.ts +2 -1
- package/dist/ir/callback-specialization.js +23 -18
- package/dist/ir/callback-specialization.js.map +1 -1
- package/dist/ir/char-unit-locals.d.ts +19 -0
- package/dist/ir/char-unit-locals.js +185 -0
- package/dist/ir/char-unit-locals.js.map +1 -0
- package/dist/ir/char-unit-locals.test.d.ts +1 -0
- package/dist/ir/char-unit-locals.test.js +94 -0
- package/dist/ir/char-unit-locals.test.js.map +1 -0
- package/dist/ir/final-fields.d.ts +2 -1
- package/dist/ir/final-fields.js +14 -16
- package/dist/ir/final-fields.js.map +1 -1
- package/dist/ir/function-references.d.ts +2 -0
- package/dist/ir/function-references.js +2 -0
- package/dist/ir/function-references.js.map +1 -1
- package/dist/ir/function-references.test.js +3 -0
- package/dist/ir/function-references.test.js.map +1 -1
- package/dist/ir/initializer-bindings.d.ts +2 -1
- package/dist/ir/initializer-bindings.js +27 -20
- package/dist/ir/initializer-bindings.js.map +1 -1
- package/dist/ir/int32-arrays.d.ts +108 -0
- package/dist/ir/int32-arrays.js +831 -0
- package/dist/ir/int32-arrays.js.map +1 -0
- package/dist/ir/int32-slots.d.ts +24 -2
- package/dist/ir/int32-slots.js +266 -57
- package/dist/ir/int32-slots.js.map +1 -1
- package/dist/ir/int32-slots.test.js +33 -0
- package/dist/ir/int32-slots.test.js.map +1 -1
- package/dist/ir/integer-loops.d.ts +3 -3
- package/dist/ir/integer-loops.js +28 -10
- package/dist/ir/integer-loops.js.map +1 -1
- package/dist/ir/integer-loops.test.js +10 -0
- package/dist/ir/integer-loops.test.js.map +1 -1
- package/dist/ir/integer-ranges.d.ts +5 -0
- package/dist/ir/integer-ranges.js +125 -12
- package/dist/ir/integer-ranges.js.map +1 -1
- package/dist/ir/integer-ranges.test.js +30 -0
- package/dist/ir/integer-ranges.test.js.map +1 -1
- package/dist/ir/ir.d.ts +83 -10
- package/dist/ir/ir.js +77 -6
- package/dist/ir/ir.js.map +1 -1
- package/dist/ir/ir.test.js +23 -2
- package/dist/ir/ir.test.js.map +1 -1
- package/dist/ir/js-ic.d.ts +4 -0
- package/dist/ir/js-ic.js +17 -1
- package/dist/ir/js-ic.js.map +1 -1
- package/dist/ir/js-ic.test.js +46 -0
- package/dist/ir/js-ic.test.js.map +1 -1
- package/dist/ir/node-index.d.ts +57 -0
- package/dist/ir/node-index.js +215 -0
- package/dist/ir/node-index.js.map +1 -0
- package/dist/ir/paired-while-loops.d.ts +25 -0
- package/dist/ir/paired-while-loops.js +335 -0
- package/dist/ir/paired-while-loops.js.map +1 -0
- package/dist/ir/paired-while-loops.test.d.ts +1 -0
- package/dist/ir/paired-while-loops.test.js +163 -0
- package/dist/ir/paired-while-loops.test.js.map +1 -0
- package/dist/ir/parameter-versions.d.ts +25 -0
- package/dist/ir/parameter-versions.js +300 -0
- package/dist/ir/parameter-versions.js.map +1 -0
- package/dist/ir/runtime-features.d.ts +34 -13
- package/dist/ir/runtime-features.js +177 -39
- package/dist/ir/runtime-features.js.map +1 -1
- package/dist/ir/serialize.d.ts +12 -2
- package/dist/ir/serialize.js +16 -3
- package/dist/ir/serialize.js.map +1 -1
- package/dist/ir/serialize.test.js +17 -0
- package/dist/ir/serialize.test.js.map +1 -1
- package/dist/ir/traverse.js +18 -6
- package/dist/ir/traverse.js.map +1 -1
- package/dist/ir/validate.js +167 -40
- package/dist/ir/validate.js.map +1 -1
- package/dist/library/ir-policy.js +3 -0
- package/dist/library/ir-policy.js.map +1 -1
- package/dist/native/cache.d.ts +6 -1
- package/dist/native/cache.js +28 -5
- package/dist/native/cache.js.map +1 -1
- package/dist/native/cache.test.js +16 -2
- package/dist/native/cache.test.js.map +1 -1
- package/dist/native/cli.js +21 -1
- package/dist/native/cli.js.map +1 -1
- package/dist/native/compiler.js +8 -6
- package/dist/native/compiler.js.map +1 -1
- package/dist/native/executable-cache.d.ts +1 -1
- package/dist/native/executable-cache.js +2 -2
- package/dist/native/executable-cache.js.map +1 -1
- package/dist/native/prepare.d.ts +4 -2
- package/dist/native/prepare.js +130 -32
- package/dist/native/prepare.js.map +1 -1
- package/dist/native/prepare.test.js +96 -20
- package/dist/native/prepare.test.js.map +1 -1
- package/dist/native/sanitizer.test.js +2 -0
- package/dist/native/sanitizer.test.js.map +1 -1
- package/dist/native/text-file.d.ts +13 -3
- package/dist/native/text-file.js +63 -9
- package/dist/native/text-file.js.map +1 -1
- package/dist/native/text-file.test.d.ts +1 -0
- package/dist/native/text-file.test.js +49 -0
- package/dist/native/text-file.test.js.map +1 -0
- package/dist/native/toolchain.js +4 -4
- package/dist/native/toolchain.js.map +1 -1
- package/dist/native/toolchain.test.js +3 -3
- package/dist/native/toolchain.test.js.map +1 -1
- package/package.json +21 -21
- package/shims/chalk/v5.ts +688 -0
- package/shims/hono-node-server/v2.ts +645 -0
- package/shims/hot-shots/client.ts +1126 -0
- package/shims/hot-shots/v8-unix-dgram.ts +8 -0
- package/shims/hot-shots/v8.ts +8 -0
- package/surface-manifest.json +27 -7
|
@@ -1,5 +1,35 @@
|
|
|
1
|
-
import { shapeHasAccessorSlots, typeEquals, UNDEFINED_T } from "../../ir/ir.js";
|
|
2
|
-
import { everyExprChild, everyStmtChild, everyTypeChild } from "../../ir/traverse.js";
|
|
1
|
+
import { BOOL, F64, KEY_ORDER_FIELD, shapeHasAccessorSlots, typeEquals, UNDEFINED_T, VOID, } from "../../ir/ir.js";
|
|
2
|
+
import { everyExprChild, everyStmtChild, everyTypeChild, transformStmtList, } from "../../ir/traverse.js";
|
|
3
|
+
import * as ts from "../ts7/adapter.js";
|
|
4
|
+
import { ALWAYS_THROW_LIB_FNS } from "../../ir/builtin-effects.js";
|
|
5
|
+
import { recordMayKeepSource } from "./record-sources.js";
|
|
6
|
+
/** The statements a key-order helper runs for record `ref`: `walks[0]`,
|
|
7
|
+
* its walk over the shape's table, or, for a shape with orderVariants, a
|
|
8
|
+
* branch per order (walks[i] for order i) on the value's KEY_ORDER_FIELD.
|
|
9
|
+
* `walks` follows shapeKeyOrders. */
|
|
10
|
+
export function perKeyOrder(shape, ref, walks, loc) {
|
|
11
|
+
let tail = walks[0];
|
|
12
|
+
for (let i = walks.length - 1; i >= 1; i--) {
|
|
13
|
+
const index = {
|
|
14
|
+
kind: "recordGet",
|
|
15
|
+
obj: ref,
|
|
16
|
+
shapeId: shape.id,
|
|
17
|
+
field: KEY_ORDER_FIELD,
|
|
18
|
+
type: F64,
|
|
19
|
+
loc,
|
|
20
|
+
};
|
|
21
|
+
const cond = {
|
|
22
|
+
kind: "bin",
|
|
23
|
+
op: "===",
|
|
24
|
+
left: index,
|
|
25
|
+
right: { kind: "numLit", value: i, type: F64, loc },
|
|
26
|
+
type: BOOL,
|
|
27
|
+
loc,
|
|
28
|
+
};
|
|
29
|
+
tail = [{ kind: "if", cond, then: walks[i], else_: tail, loc }];
|
|
30
|
+
}
|
|
31
|
+
return tail;
|
|
32
|
+
}
|
|
3
33
|
/** Witness notes the lowering attaches to the IR nodes it builds. Keyed by
|
|
4
34
|
* node identity, so nodes a speculative lowering discards are never walked.
|
|
5
35
|
* Literals the IR rewriters rebuild (traverse.ts mapExprChildren) carry
|
|
@@ -8,6 +38,7 @@ import { everyExprChild, everyStmtChild, everyTypeChild } from "../../ir/travers
|
|
|
8
38
|
export class KeyOrderNotes {
|
|
9
39
|
literals = new Map();
|
|
10
40
|
copies = new Map();
|
|
41
|
+
methodResults = new Map();
|
|
11
42
|
/** Shapes a frontend order surface (keys, values/entries, inspect,
|
|
12
43
|
* index-signature merges) walks. */
|
|
13
44
|
observed = new Set();
|
|
@@ -21,8 +52,14 @@ export class KeyOrderNotes {
|
|
|
21
52
|
this.copies.set(node, sourceShapeId);
|
|
22
53
|
return node;
|
|
23
54
|
}
|
|
55
|
+
/** The checked result of a typed call of method `name`, which the program
|
|
56
|
+
* may replace on its instance (class-callbacks.ts classCallbackCall). */
|
|
57
|
+
methodResult(node, name) {
|
|
58
|
+
this.methodResults.set(node, name);
|
|
59
|
+
return node;
|
|
60
|
+
}
|
|
24
61
|
/** A pass rebuilt `from` as `to` (traverse.ts mapExprChildren): the
|
|
25
|
-
* rebuilt
|
|
62
|
+
* rebuilt node is the same construction, so it keeps the witness. */
|
|
26
63
|
follow(from, to) {
|
|
27
64
|
const segments = this.literals.get(from);
|
|
28
65
|
if (segments !== undefined)
|
|
@@ -30,6 +67,9 @@ export class KeyOrderNotes {
|
|
|
30
67
|
const source = this.copies.get(from);
|
|
31
68
|
if (source !== undefined)
|
|
32
69
|
this.copies.set(to, source);
|
|
70
|
+
const method = this.methodResults.get(from);
|
|
71
|
+
if (method !== undefined)
|
|
72
|
+
this.methodResults.set(to, method);
|
|
33
73
|
}
|
|
34
74
|
observe(type) {
|
|
35
75
|
if (type.kind === "record")
|
|
@@ -41,6 +81,10 @@ export class KeyOrderNotes {
|
|
|
41
81
|
copyOf(node) {
|
|
42
82
|
return this.copies.get(node);
|
|
43
83
|
}
|
|
84
|
+
/** The method whose checked result `node` is, if it is one. */
|
|
85
|
+
methodResultOf(node) {
|
|
86
|
+
return this.methodResults.get(node);
|
|
87
|
+
}
|
|
44
88
|
}
|
|
45
89
|
const isArrayIndex = (name) => {
|
|
46
90
|
const n = Number(name);
|
|
@@ -55,6 +99,70 @@ function orderPreservingClone(node) {
|
|
|
55
99
|
const source = value.args[0];
|
|
56
100
|
return (source !== undefined && source.kind === "dynFrom" && typeEquals(source.value.type, node.type));
|
|
57
101
|
}
|
|
102
|
+
const PRIMITIVE_KINDS = new Set([
|
|
103
|
+
"f64",
|
|
104
|
+
"bigint",
|
|
105
|
+
"string",
|
|
106
|
+
"bool",
|
|
107
|
+
"undefinedT",
|
|
108
|
+
"nullT",
|
|
109
|
+
"symbol",
|
|
110
|
+
]);
|
|
111
|
+
/** A checked conversion of a boxed primitive (the `undefined` a dynamic
|
|
112
|
+
* construction passes for a missing argument) answers that primitive or
|
|
113
|
+
* throws: it builds no record. */
|
|
114
|
+
function primitiveSource(node) {
|
|
115
|
+
return node.value.kind === "dynFrom" && PRIMITIVE_KINDS.has(node.value.value.type.kind);
|
|
116
|
+
}
|
|
117
|
+
/** Whether a census site for a method name can only read the method or
|
|
118
|
+
* install a replacement whose result holds no object: a read
|
|
119
|
+
* (`C.prototype.m`, `obj.m`) outside an assignment target, or an assignment
|
|
120
|
+
* of a function expression whose return type is primitive. Other sites (a
|
|
121
|
+
* computed write of another value, a reflection call, a property bag) may
|
|
122
|
+
* install a replacement that returns a record. */
|
|
123
|
+
function replacesWithoutRecords(lowerer, site) {
|
|
124
|
+
const parent = site.parent;
|
|
125
|
+
if (ts.isPropertyAccessExpression(site) || ts.isElementAccessExpression(site))
|
|
126
|
+
return !(parent !== undefined &&
|
|
127
|
+
ts.isBinaryExpression(parent) &&
|
|
128
|
+
parent.left === site &&
|
|
129
|
+
parent.operatorToken.kind >= ts.SyntaxKind.FirstAssignment &&
|
|
130
|
+
parent.operatorToken.kind <= ts.SyntaxKind.LastAssignment);
|
|
131
|
+
if (!ts.isBinaryExpression(site) || site.operatorToken.kind !== ts.SyntaxKind.EqualsToken)
|
|
132
|
+
return false;
|
|
133
|
+
let value = site.right;
|
|
134
|
+
while (ts.isParenthesizedExpression(value))
|
|
135
|
+
value = value.expression;
|
|
136
|
+
if (!ts.isArrowFunction(value) && !ts.isFunctionExpression(value))
|
|
137
|
+
return false;
|
|
138
|
+
const signatures = lowerer.checker.getCallSignatures(lowerer.typeOf(value));
|
|
139
|
+
return (signatures.length > 0 &&
|
|
140
|
+
signatures.every((signature) => primitiveOnly(lowerer.checker.getReturnTypeOfSignature(signature))));
|
|
141
|
+
}
|
|
142
|
+
/** A compiler helper that boxes a class's own state for JavaScript's reads:
|
|
143
|
+
* its prototype data and the property and method dispatch over boxed
|
|
144
|
+
* instances. */
|
|
145
|
+
function boxesOwnState(fnName) {
|
|
146
|
+
return (fnName.startsWith("%prototype.data.") ||
|
|
147
|
+
fnName.startsWith("%dyn.class.") ||
|
|
148
|
+
fnName.startsWith("%class."));
|
|
149
|
+
}
|
|
150
|
+
/** A type whose values are primitives (or void): it holds no record. */
|
|
151
|
+
function primitiveOnly(type) {
|
|
152
|
+
if (type.isUnionType())
|
|
153
|
+
return ts.constituentTypes(type).every(primitiveOnly);
|
|
154
|
+
return ((type.flags &
|
|
155
|
+
(ts.TypeFlags.StringLike |
|
|
156
|
+
ts.TypeFlags.NumberLike |
|
|
157
|
+
ts.TypeFlags.BooleanLike |
|
|
158
|
+
ts.TypeFlags.BigIntLike |
|
|
159
|
+
ts.TypeFlags.ESSymbolLike |
|
|
160
|
+
ts.TypeFlags.Null |
|
|
161
|
+
ts.TypeFlags.Undefined |
|
|
162
|
+
ts.TypeFlags.Void |
|
|
163
|
+
ts.TypeFlags.Never)) !==
|
|
164
|
+
0);
|
|
165
|
+
}
|
|
58
166
|
/** Chooses each in-scope record shape's enumeration table from its
|
|
59
167
|
* witnesses. Runs once retained reachability has settled the historical
|
|
60
168
|
* tables and derived metadata, before the order-snapshotting helper bodies
|
|
@@ -90,56 +198,110 @@ export function applyKeyOrderWitnesses(lowerer, fns) {
|
|
|
90
198
|
/** Every record shape a type can hold, through fields, arms, elements,
|
|
91
199
|
* callables, promises and class fields. */
|
|
92
200
|
/** Each walk shares one `seen` set per result set, so every type graph
|
|
93
|
-
* is walked once however many roots reach it.
|
|
94
|
-
|
|
95
|
-
|
|
201
|
+
* is walked once however many roots reach it.
|
|
202
|
+
*
|
|
203
|
+
* `produced` walks only what a checked conversion into the type can
|
|
204
|
+
* build. It answers an existing native instance for a class type (a plain
|
|
205
|
+
* object cannot acquire a class brand; only %Error rebuilds), so the
|
|
206
|
+
* records the instance's fields hold come from the class's own writes and
|
|
207
|
+
* its checked field setters, each a witness of its own. A checked
|
|
208
|
+
* function's parameters receive native values: a record parameter is
|
|
209
|
+
* passed out, never built, though a callback among them receives values
|
|
210
|
+
* built from JavaScript again. `built` false starts the walk at a value
|
|
211
|
+
* passed out (a native value boxed for JavaScript); `writes` false leaves
|
|
212
|
+
* out what JavaScript could write into the containers passed out, so the
|
|
213
|
+
* walk counts only what the functions among them receive. */
|
|
214
|
+
const shapesIn = (type, out, seen, produced = false, built = true, writes = true) => {
|
|
215
|
+
const visit = (t, built) => {
|
|
216
|
+
const mark = built ? "" : "-";
|
|
217
|
+
// A container JavaScript builds converts into fresh native storage, so
|
|
218
|
+
// its children are built too. One passed out stays shared: JavaScript
|
|
219
|
+
// writes into it (built children) and reads native values out of it,
|
|
220
|
+
// such as callbacks whose parameters it then builds (children passed
|
|
221
|
+
// out). Those children count in both directions.
|
|
222
|
+
const child = (type) => {
|
|
223
|
+
if (built || writes)
|
|
224
|
+
visit(type, true);
|
|
225
|
+
if (!built)
|
|
226
|
+
visit(type, false);
|
|
227
|
+
return true;
|
|
228
|
+
};
|
|
96
229
|
if (t.kind === "record") {
|
|
97
|
-
if (seen.has("r:" + t.shapeId))
|
|
230
|
+
if (seen.has(mark + "r:" + t.shapeId))
|
|
98
231
|
return true;
|
|
99
|
-
seen.add("r:" + t.shapeId);
|
|
100
|
-
|
|
232
|
+
seen.add(mark + "r:" + t.shapeId);
|
|
233
|
+
if (built)
|
|
234
|
+
out.add(t.shapeId);
|
|
101
235
|
const shape = shapes.get(t.shapeId);
|
|
102
236
|
if (shape) {
|
|
103
237
|
for (const f of shape.fields)
|
|
104
|
-
|
|
238
|
+
child(f.type);
|
|
105
239
|
if (shape.indexValue)
|
|
106
|
-
|
|
240
|
+
child(shape.indexValue);
|
|
107
241
|
}
|
|
108
242
|
return true;
|
|
109
243
|
}
|
|
110
244
|
if (t.kind === "union") {
|
|
111
|
-
if (seen.has("u:" + t.unionId))
|
|
245
|
+
if (seen.has(mark + "u:" + t.unionId))
|
|
112
246
|
return true;
|
|
113
|
-
seen.add("u:" + t.unionId);
|
|
247
|
+
seen.add(mark + "u:" + t.unionId);
|
|
114
248
|
for (const arm of lowerer.unions.get(t.unionId)?.arms ?? [])
|
|
115
|
-
visit(arm);
|
|
249
|
+
visit(arm, built);
|
|
116
250
|
return true;
|
|
117
251
|
}
|
|
118
252
|
if (t.kind === "object") {
|
|
119
|
-
if (
|
|
253
|
+
if (produced && t.className !== "%Error")
|
|
254
|
+
return true;
|
|
255
|
+
if (seen.has(mark + "c:" + t.className))
|
|
120
256
|
return true;
|
|
121
|
-
seen.add("c:" + t.className);
|
|
257
|
+
seen.add(mark + "c:" + t.className);
|
|
122
258
|
for (const f of lowerer.classes.get(t.className)?.def.fields ?? [])
|
|
123
|
-
|
|
259
|
+
child(f.type);
|
|
124
260
|
return true;
|
|
125
261
|
}
|
|
126
|
-
|
|
262
|
+
if (produced && t.kind === "func") {
|
|
263
|
+
for (const param of t.params)
|
|
264
|
+
visit(param, !built);
|
|
265
|
+
return visit(t.ret, built);
|
|
266
|
+
}
|
|
267
|
+
return everyTypeChild(t, child);
|
|
127
268
|
};
|
|
128
|
-
visit(type);
|
|
269
|
+
visit(type, built);
|
|
129
270
|
};
|
|
130
271
|
const opaqueShapes = new Set();
|
|
131
272
|
const opaqueSeen = new Set();
|
|
132
273
|
const runtimeShapes = new Set();
|
|
133
274
|
const runtimeSeen = new Set();
|
|
275
|
+
/** Shapes the declaration-typed boundary converts into (adopting casts):
|
|
276
|
+
* their values come from package code that builds them in the
|
|
277
|
+
* declaration's order, the order their table holds. */
|
|
278
|
+
const declaredShapes = new Set();
|
|
279
|
+
const declaredSeen = new Set();
|
|
280
|
+
const boxedSeen = new Set();
|
|
281
|
+
/** The checked result of a replaceable method call while every site that
|
|
282
|
+
* can replace the method installs functions that return no record. */
|
|
283
|
+
const unchangedMethodResult = (node) => {
|
|
284
|
+
const name = notes.methodResultOf(node);
|
|
285
|
+
if (name === undefined)
|
|
286
|
+
return false;
|
|
287
|
+
const sites = lowerer.methodAccessSites.get(name) ?? [];
|
|
288
|
+
return sites.every((site) => replacesWithoutRecords(lowerer, site));
|
|
289
|
+
};
|
|
134
290
|
const producedBy = (type, opaque) => {
|
|
135
291
|
if (opaque)
|
|
136
292
|
shapesIn(type, opaqueShapes, opaqueSeen);
|
|
137
293
|
else
|
|
138
|
-
shapesIn(type, runtimeShapes, runtimeSeen);
|
|
294
|
+
shapesIn(type, runtimeShapes, runtimeSeen, true);
|
|
139
295
|
};
|
|
140
296
|
// ── collection ──────────────────────────────────────────────────────
|
|
141
297
|
let pos = 0;
|
|
142
298
|
let fnName = "";
|
|
299
|
+
let currentFn = null;
|
|
300
|
+
/** Literals that start by spreading a binding, by their witness: where
|
|
301
|
+
* each one is built. A literal's notes are shared by its rebuilt copies,
|
|
302
|
+
* so `literalSites` counts every literal of each witness. */
|
|
303
|
+
const leadingSpreads = new Map();
|
|
304
|
+
const literalSites = new Map();
|
|
143
305
|
const loops = [];
|
|
144
306
|
let loopIds = 0;
|
|
145
307
|
const loopKey = () => loops.join("/");
|
|
@@ -197,8 +359,10 @@ export function applyKeyOrderWitnesses(lowerer, fns) {
|
|
|
197
359
|
}
|
|
198
360
|
const segments = notes.literalOf(e);
|
|
199
361
|
const copy = notes.copyOf(e);
|
|
200
|
-
if (segments !== undefined)
|
|
362
|
+
if (segments !== undefined) {
|
|
201
363
|
f.literals.push(segments);
|
|
364
|
+
literalSites.set(segments, (literalSites.get(segments) ?? 0) + 1);
|
|
365
|
+
}
|
|
202
366
|
else if (copy !== undefined)
|
|
203
367
|
f.copies.push({ source: copy, keys: presentKeys });
|
|
204
368
|
else
|
|
@@ -217,9 +381,33 @@ export function applyKeyOrderWitnesses(lowerer, fns) {
|
|
|
217
381
|
case "assignExpr":
|
|
218
382
|
noteInit(e.localId, e.value);
|
|
219
383
|
return;
|
|
384
|
+
case "seqExpr": {
|
|
385
|
+
// A spread literal evaluates its sources into bindings first.
|
|
386
|
+
const literal = e.result;
|
|
387
|
+
if (literal.kind !== "recordLit" || currentFn === null)
|
|
388
|
+
return;
|
|
389
|
+
const segments = notes.literalOf(literal);
|
|
390
|
+
const first = segments?.[0];
|
|
391
|
+
if (segments === undefined || first?.kind !== "spread" || first.value === undefined)
|
|
392
|
+
return;
|
|
393
|
+
const list = leadingSpreads.get(segments) ?? [];
|
|
394
|
+
list.push({ wrapper: e, literal, fn: currentFn });
|
|
395
|
+
leadingSpreads.set(segments, list);
|
|
396
|
+
return;
|
|
397
|
+
}
|
|
220
398
|
case "jsonStringify":
|
|
221
399
|
case "dynFrom":
|
|
222
400
|
observedRoots.push(e.value.type);
|
|
401
|
+
// A native value the program hands to JavaScript: the callbacks it
|
|
402
|
+
// holds (itself, a field, an element) receive records JavaScript
|
|
403
|
+
// builds. The helpers that box the program's own state for
|
|
404
|
+
// JavaScript's reads (a class's prototype slots and property
|
|
405
|
+
// dispatch) hand out the class's methods, whose arguments the
|
|
406
|
+
// program's own calls pass as native values, as a replaceable
|
|
407
|
+
// method's result above. Writes through the boxed value are left
|
|
408
|
+
// out: reading a boxed value creates no record.
|
|
409
|
+
if (!boxesOwnState(fnName))
|
|
410
|
+
shapesIn(e.value.type, runtimeShapes, boxedSeen, true, false, false);
|
|
223
411
|
return;
|
|
224
412
|
case "recordKeyGet":
|
|
225
413
|
observedRoots.push(e.obj.type);
|
|
@@ -229,7 +417,12 @@ export function applyKeyOrderWitnesses(lowerer, fns) {
|
|
|
229
417
|
// record may walk its keys; runtime builders make new records.
|
|
230
418
|
for (const arg of e.args)
|
|
231
419
|
observedRoots.push(arg.type);
|
|
232
|
-
|
|
420
|
+
// An always-throwing call stands in for a value (`error.nodeThrow`
|
|
421
|
+
// in a narrowing ternary) and never produces one. Other calls
|
|
422
|
+
// whose signature result is VOID are typed by their use site and
|
|
423
|
+
// build the record at run time (`server.address()`).
|
|
424
|
+
if (!ALWAYS_THROW_LIB_FNS.has(e.fn))
|
|
425
|
+
producedBy(e.type, true);
|
|
233
426
|
return;
|
|
234
427
|
case "intrinsic":
|
|
235
428
|
// Intrinsics hand back values built elsewhere, except allSettled's
|
|
@@ -242,10 +435,33 @@ export function applyKeyOrderWitnesses(lowerer, fns) {
|
|
|
242
435
|
case "strIntrinsic":
|
|
243
436
|
case "regexIntrinsic":
|
|
244
437
|
case "bytesIntrinsic":
|
|
438
|
+
// Promise.withResolvers records are built by the backend in a fixed
|
|
439
|
+
// layout.
|
|
440
|
+
case "promiseWithResolvers":
|
|
245
441
|
producedBy(e.type, true);
|
|
246
442
|
return;
|
|
443
|
+
case "genResume": {
|
|
444
|
+
// A resume builds at most its IteratorResult record ({ done, value }
|
|
445
|
+
// in a fixed layout; an async generator's settles a promise of it).
|
|
446
|
+
// The value it carries is the generator's own yielded or returned
|
|
447
|
+
// value, which the generator's body constructs. The record-free
|
|
448
|
+
// drives build nothing: `value` moves that value out, and step,
|
|
449
|
+
// close and a record-free delegate answer a boolean or nothing.
|
|
450
|
+
if (e.mode === "step" || e.mode === "value" || e.mode === "close")
|
|
451
|
+
return;
|
|
452
|
+
const result = e.type.kind === "promise" ? e.type.inner : e.type;
|
|
453
|
+
if (result.kind === "record")
|
|
454
|
+
opaqueShapes.add(result.shapeId);
|
|
455
|
+
return;
|
|
456
|
+
}
|
|
247
457
|
case "dynCheck":
|
|
248
|
-
if (
|
|
458
|
+
if (e.adopt === true)
|
|
459
|
+
shapesIn(e.type, declaredShapes, declaredSeen);
|
|
460
|
+
// Conversions that build no record: a boxed primitive, and a
|
|
461
|
+
// replaceable method's result while no replacement the program can
|
|
462
|
+
// install returns a record: then it is the method's own value,
|
|
463
|
+
// boxed and checked back unchanged.
|
|
464
|
+
else if (!orderPreservingClone(e) && !primitiveSource(e) && !unchangedMethodResult(e))
|
|
249
465
|
producedBy(e.type, false);
|
|
250
466
|
return;
|
|
251
467
|
case "dynDestrCheck":
|
|
@@ -300,6 +516,7 @@ export function applyKeyOrderWitnesses(lowerer, fns) {
|
|
|
300
516
|
};
|
|
301
517
|
for (const fn of fns) {
|
|
302
518
|
fnName = fn.name;
|
|
519
|
+
currentFn = fn;
|
|
303
520
|
for (const st of fn.body)
|
|
304
521
|
stmt(st);
|
|
305
522
|
}
|
|
@@ -310,6 +527,9 @@ export function applyKeyOrderWitnesses(lowerer, fns) {
|
|
|
310
527
|
}
|
|
311
528
|
for (const id of runtimeShapes)
|
|
312
529
|
factsOf(id).runtime = true;
|
|
530
|
+
for (const id of declaredShapes)
|
|
531
|
+
if (!runtimeShapes.has(id))
|
|
532
|
+
factsOf(id).pinned = true;
|
|
313
533
|
// ── scope ───────────────────────────────────────────────────────────
|
|
314
534
|
// Only plain declared-field shapes with a table take part.
|
|
315
535
|
const inScope = (shape) => shape !== undefined &&
|
|
@@ -425,13 +645,63 @@ export function applyKeyOrderWitnesses(lowerer, fns) {
|
|
|
425
645
|
}
|
|
426
646
|
return edges;
|
|
427
647
|
};
|
|
648
|
+
// ── ordered spreads ─────────────────────────────────────────────────
|
|
649
|
+
// A value a checked conversion builds keeps its source's key order in
|
|
650
|
+
// its record source when that order is not the table's (record-
|
|
651
|
+
// sources.ts), so every value of a shape enumerates in the table's order
|
|
652
|
+
// or in the order its record source holds. A literal that starts with
|
|
653
|
+
// `...value` creates the value's keys first, in the value's order. When
|
|
654
|
+
// the value's shape is one checked conversions build, the literal
|
|
655
|
+
// carries that order over: after it builds the record it gives the
|
|
656
|
+
// record a source holding the value's order (record.sourceSpread), and
|
|
657
|
+
// the keys the value lacks follow in the table's order, which every
|
|
658
|
+
// literal sequence of the shape agrees with. Such a literal resolves as
|
|
659
|
+
// if its source were in the source's table order, and its own shape
|
|
660
|
+
// counts as built at run time too, since its values may now carry a
|
|
661
|
+
// source. It qualifies when every value of the source has all of the
|
|
662
|
+
// source's keys, both shapes can keep a source, and every later spread
|
|
663
|
+
// whose values may carry a source only overwrites the source's keys
|
|
664
|
+
// (its own order cannot move them).
|
|
665
|
+
const orderedSpreads = new Set();
|
|
666
|
+
const keepsSource = (shapeId) => recordMayKeepSource(lowerer, { kind: "record", shapeId });
|
|
667
|
+
const userKeys = (shapeId) => (shapes.get(shapeId)?.fields ?? []).map((x) => x.name).filter((k) => !k.startsWith("%"));
|
|
668
|
+
const ordersSpread = (segments, sites) => {
|
|
669
|
+
const first = segments[0];
|
|
670
|
+
if (first?.kind !== "spread" || first.maybeAbsent || first.value === undefined)
|
|
671
|
+
return false;
|
|
672
|
+
const sourceId = first.shapeId;
|
|
673
|
+
if (facts.get(sourceId)?.runtime !== true || sites.length !== literalSites.get(segments))
|
|
674
|
+
return false;
|
|
675
|
+
const target = sites[0].literal.type;
|
|
676
|
+
if (target.kind !== "record" || !keepsSource(sourceId) || !keepsSource(target.shapeId))
|
|
677
|
+
return false;
|
|
678
|
+
const localId = first.value.localId;
|
|
679
|
+
const bound = ({ wrapper, literal }) => typeEquals(literal.type, target) &&
|
|
680
|
+
wrapper.stmts.some((st) => st.kind === "varDecl" &&
|
|
681
|
+
st.localId === localId &&
|
|
682
|
+
st.init !== null &&
|
|
683
|
+
st.init.type.kind === "record" &&
|
|
684
|
+
st.init.type.shapeId === sourceId);
|
|
685
|
+
if (!sites.every(bound))
|
|
686
|
+
return false;
|
|
687
|
+
const sourceKeys = new Set(userKeys(sourceId));
|
|
688
|
+
if ([...sourceKeys].some((k) => maybeAbsent(sourceId, k)))
|
|
689
|
+
return false;
|
|
690
|
+
return segments
|
|
691
|
+
.slice(1)
|
|
692
|
+
.every((s) => s.kind === "key" ||
|
|
693
|
+
(s.kind === "spread" &&
|
|
694
|
+
(facts.get(s.shapeId)?.runtime !== true ||
|
|
695
|
+
userKeys(s.shapeId).every((k) => sourceKeys.has(k)))));
|
|
696
|
+
};
|
|
428
697
|
// ── witness sequences ───────────────────────────────────────────────
|
|
429
698
|
/** The key sequences one literal can create, or null when a spread
|
|
430
699
|
* source's order is unknown. A key sits at its first occurrence that
|
|
431
700
|
* certainly defines it; each earlier occurrence that may define it is
|
|
432
701
|
* another possible position. */
|
|
433
|
-
const literalSequences = (segments, keySet, resolved) => {
|
|
702
|
+
const literalSequences = (segments, keySet, resolved, raw) => {
|
|
434
703
|
const occurrences = [];
|
|
704
|
+
const ordered = orderedSpreads.has(segments);
|
|
435
705
|
for (const s of segments) {
|
|
436
706
|
if (s.kind === "opaque")
|
|
437
707
|
return null;
|
|
@@ -440,7 +710,9 @@ export function applyKeyOrderWitnesses(lowerer, fns) {
|
|
|
440
710
|
occurrences.push({ key: s.name, definite: s.definite });
|
|
441
711
|
continue;
|
|
442
712
|
}
|
|
443
|
-
|
|
713
|
+
// An ordered spread's values without a source enumerate in the
|
|
714
|
+
// source's table; the others carry their order over.
|
|
715
|
+
const source = ordered && s === segments[0] ? raw(s.shapeId) : resolved(s.shapeId);
|
|
444
716
|
if (source === "unknown")
|
|
445
717
|
return null;
|
|
446
718
|
for (const k of source.order) {
|
|
@@ -524,8 +796,24 @@ export function applyKeyOrderWitnesses(lowerer, fns) {
|
|
|
524
796
|
deps.add(c.source);
|
|
525
797
|
return [...deps];
|
|
526
798
|
};
|
|
799
|
+
/** `{ ...value, ...rest }` that starts with a spread of a value of the
|
|
800
|
+
* literal's own shape holding every key: it creates its keys in the
|
|
801
|
+
* value's order, and the later segments only overwrite them. With no
|
|
802
|
+
* checked conversion building the shape, every value enumerates in the
|
|
803
|
+
* one table this pass chooses, so the copy agrees with any choice and
|
|
804
|
+
* adds no edge. */
|
|
805
|
+
const copiesItself = (id, f, table, segments) => {
|
|
806
|
+
const first = segments[0];
|
|
807
|
+
return (first !== undefined &&
|
|
808
|
+
first.kind === "spread" &&
|
|
809
|
+
first.shapeId === id &&
|
|
810
|
+
!first.maybeAbsent &&
|
|
811
|
+
(!f.runtime || orderedSpreads.has(segments)) &&
|
|
812
|
+
segments.every((s) => s.kind !== "opaque") &&
|
|
813
|
+
table.every((k) => !maybeAbsent(id, k)));
|
|
814
|
+
};
|
|
527
815
|
/** One shape's order given its sources' current orders. */
|
|
528
|
-
const resolveOne = (id, current) => {
|
|
816
|
+
const resolveOne = (id, current, raw) => {
|
|
529
817
|
const shape = shapes.get(id);
|
|
530
818
|
if (!inScope(shape))
|
|
531
819
|
return "unknown";
|
|
@@ -544,7 +832,9 @@ export function applyKeyOrderWitnesses(lowerer, fns) {
|
|
|
544
832
|
if (f.pinned)
|
|
545
833
|
chain(table, edges);
|
|
546
834
|
for (const segments of f.literals) {
|
|
547
|
-
|
|
835
|
+
if (copiesItself(id, f, table, segments))
|
|
836
|
+
continue;
|
|
837
|
+
const sequences = literalSequences(segments, keySet, current, raw);
|
|
548
838
|
if (sequences === null)
|
|
549
839
|
return "unknown";
|
|
550
840
|
for (const seq of sequences)
|
|
@@ -608,31 +898,59 @@ export function applyKeyOrderWitnesses(lowerer, fns) {
|
|
|
608
898
|
const known = result.get(id);
|
|
609
899
|
return known === undefined ? "unknown" : asSource(id, known);
|
|
610
900
|
};
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
for (const
|
|
615
|
-
const
|
|
616
|
-
guess
|
|
617
|
-
}
|
|
618
|
-
const lookup = (id) => members.has(id) ? asSource(id, guess.get(id)) : external(id);
|
|
619
|
-
let stable = false;
|
|
620
|
-
for (let round = 0; round < scc.length + 3 && !stable; round++) {
|
|
621
|
-
stable = true;
|
|
901
|
+
const resolveAll = () => {
|
|
902
|
+
result.clear();
|
|
903
|
+
late.clear();
|
|
904
|
+
for (const scc of sccs) {
|
|
905
|
+
const members = new Set(scc);
|
|
906
|
+
const guess = new Map();
|
|
622
907
|
for (const id of scc) {
|
|
623
|
-
const
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
908
|
+
const shape = shapes.get(id);
|
|
909
|
+
guess.set(id, inScope(shape) ? { order: tableOf(shape) } : "unknown");
|
|
910
|
+
}
|
|
911
|
+
const lookup = (id) => members.has(id) ? asSource(id, guess.get(id)) : external(id);
|
|
912
|
+
const rawLookup = (id) => members.has(id) ? guess.get(id) : (result.get(id) ?? "unknown");
|
|
913
|
+
let stable = false;
|
|
914
|
+
for (let round = 0; round < scc.length + 3 && !stable; round++) {
|
|
915
|
+
stable = true;
|
|
916
|
+
for (const id of scc) {
|
|
917
|
+
const next = resolveOne(id, lookup, rawLookup);
|
|
918
|
+
const prev = guess.get(id);
|
|
919
|
+
const same = next === "unknown"
|
|
920
|
+
? prev === "unknown"
|
|
921
|
+
: prev !== "unknown" && prev.order.join("\0") === next.order.join("\0");
|
|
922
|
+
if (!same) {
|
|
923
|
+
stable = false;
|
|
924
|
+
guess.set(id, next);
|
|
925
|
+
}
|
|
631
926
|
}
|
|
632
927
|
}
|
|
928
|
+
for (const id of scc)
|
|
929
|
+
result.set(id, stable ? guess.get(id) : "unknown");
|
|
930
|
+
}
|
|
931
|
+
};
|
|
932
|
+
// Ordered spreads join once their source resolves; each one can let its
|
|
933
|
+
// own shape resolve, which a later spread of it needs.
|
|
934
|
+
resolveAll();
|
|
935
|
+
for (let grew = true; grew;) {
|
|
936
|
+
grew = false;
|
|
937
|
+
for (const [segments, sites] of leadingSpreads) {
|
|
938
|
+
const first = segments[0];
|
|
939
|
+
if (first?.kind !== "spread" || orderedSpreads.has(segments))
|
|
940
|
+
continue;
|
|
941
|
+
// A self copy resolves with its own shape.
|
|
942
|
+
const target = sites[0].literal.type;
|
|
943
|
+
const source = result.get(first.shapeId) ?? "unknown";
|
|
944
|
+
const self = target.kind === "record" && target.shapeId === first.shapeId;
|
|
945
|
+
if ((source === "unknown" && !self) || !ordersSpread(segments, sites))
|
|
946
|
+
continue;
|
|
947
|
+
orderedSpreads.add(segments);
|
|
948
|
+
if (target.kind === "record")
|
|
949
|
+
factsOf(target.shapeId).runtime = true;
|
|
950
|
+
grew = true;
|
|
633
951
|
}
|
|
634
|
-
|
|
635
|
-
|
|
952
|
+
if (grew)
|
|
953
|
+
resolveAll();
|
|
636
954
|
}
|
|
637
955
|
// ── observation ─────────────────────────────────────────────────────
|
|
638
956
|
const observed = new Set();
|
|
@@ -641,6 +959,19 @@ export function applyKeyOrderWitnesses(lowerer, fns) {
|
|
|
641
959
|
shapesIn({ kind: "record", shapeId: id }, observed, observedSeen);
|
|
642
960
|
for (const root of observedRoots)
|
|
643
961
|
shapesIn(root, observed, observedSeen);
|
|
962
|
+
// An ordered spread's copies of values without a source take the source's
|
|
963
|
+
// order from its table, which must then hold the resolved order.
|
|
964
|
+
const orderedTarget = (sites) => {
|
|
965
|
+
const target = sites[0].literal.type;
|
|
966
|
+
return target.kind === "record" && (result.get(target.shapeId) ?? "unknown") !== "unknown"
|
|
967
|
+
? target.shapeId
|
|
968
|
+
: null;
|
|
969
|
+
};
|
|
970
|
+
for (const [segments, sites] of leadingSpreads) {
|
|
971
|
+
const first = segments[0];
|
|
972
|
+
if (orderedSpreads.has(segments) && first?.kind === "spread" && orderedTarget(sites) !== null)
|
|
973
|
+
observed.add(first.shapeId);
|
|
974
|
+
}
|
|
644
975
|
// ── apply ───────────────────────────────────────────────────────────
|
|
645
976
|
for (const [id, resolved] of result) {
|
|
646
977
|
if (resolved === "unknown" || !observed.has(id))
|
|
@@ -654,5 +985,600 @@ export function applyKeyOrderWitnesses(lowerer, fns) {
|
|
|
654
985
|
shape.declaredOrder = [...shape.declaredOrder.filter(isArrayIndex), ...resolved.order];
|
|
655
986
|
notes.changed.add(id);
|
|
656
987
|
}
|
|
988
|
+
// Ordered spreads carry their source's order over (see above).
|
|
989
|
+
let orderedResults = 0;
|
|
990
|
+
const rewritten = new Set();
|
|
991
|
+
for (const [segments, sites] of leadingSpreads) {
|
|
992
|
+
const first = segments[0];
|
|
993
|
+
if (!orderedSpreads.has(segments) || first?.kind !== "spread" || first.value === undefined)
|
|
994
|
+
continue;
|
|
995
|
+
// A shape that did not resolve keeps today's table for every value.
|
|
996
|
+
if (orderedTarget(sites) === null)
|
|
997
|
+
continue;
|
|
998
|
+
for (const { wrapper, literal, fn } of sites) {
|
|
999
|
+
if (rewritten.has(wrapper))
|
|
1000
|
+
continue;
|
|
1001
|
+
rewritten.add(wrapper);
|
|
1002
|
+
const loc = literal.loc;
|
|
1003
|
+
const localId = `%orderedSpread.${orderedResults++}`;
|
|
1004
|
+
fn.locals.push({ id: localId, name: "%orderedSpread", type: literal.type, mutable: false });
|
|
1005
|
+
const built = { kind: "varRef", localId, type: literal.type, loc };
|
|
1006
|
+
const source = {
|
|
1007
|
+
kind: "varRef",
|
|
1008
|
+
localId: first.value.localId,
|
|
1009
|
+
type: { kind: "record", shapeId: first.shapeId },
|
|
1010
|
+
loc,
|
|
1011
|
+
};
|
|
1012
|
+
wrapper.stmts.push({ kind: "varDecl", localId, init: literal, loc }, {
|
|
1013
|
+
kind: "exprStmt",
|
|
1014
|
+
expr: {
|
|
1015
|
+
kind: "libCall",
|
|
1016
|
+
fn: "record.sourceSpread",
|
|
1017
|
+
args: [built, source],
|
|
1018
|
+
type: VOID,
|
|
1019
|
+
loc,
|
|
1020
|
+
},
|
|
1021
|
+
loc,
|
|
1022
|
+
});
|
|
1023
|
+
wrapper.result = { kind: "varRef", localId, type: literal.type, loc };
|
|
1024
|
+
}
|
|
1025
|
+
}
|
|
1026
|
+
// ── per-instance orders ─────────────────────────────────────────────
|
|
1027
|
+
// A shape whose literals write its keys in more than one order has no
|
|
1028
|
+
// one table. Each value then records which of the orders it was written
|
|
1029
|
+
// in (KEY_ORDER_FIELD), when every construction's order is known
|
|
1030
|
+
// statically or copied from a value that records its own:
|
|
1031
|
+
// - a literal of explicit keys writes its order;
|
|
1032
|
+
// - a copy from a shape with one resolved order writes that order;
|
|
1033
|
+
// - a copy from a value of a shape with orders writes the source's
|
|
1034
|
+
// order, filtered to the copy's keys (rest bindings, width copies);
|
|
1035
|
+
// - clones copy the field, and every other construction (synthesized
|
|
1036
|
+
// literals, checked conversions, runtime producers) leaves 0, today's
|
|
1037
|
+
// table, as before.
|
|
1038
|
+
// A write of an optional key a value lacks moves the key to the end of
|
|
1039
|
+
// the value's order, as in Node: the orders include every order such
|
|
1040
|
+
// writes reach, and each write site updates the index after it evaluates
|
|
1041
|
+
// the value and before it writes the key.
|
|
1042
|
+
const MAX_ORDERS = 16;
|
|
1043
|
+
const unresolved = (id) => result.get(id) === "unknown";
|
|
1044
|
+
/** `order` over every key of `table`: keys the order lacks follow it. */
|
|
1045
|
+
const complete = (order, table) => {
|
|
1046
|
+
const keys = new Set(table);
|
|
1047
|
+
const out = order.filter((k) => keys.has(k));
|
|
1048
|
+
const seen = new Set(out);
|
|
1049
|
+
return [...out, ...table.filter((k) => !seen.has(k))];
|
|
1050
|
+
};
|
|
1051
|
+
const literalOrder = (segments) => {
|
|
1052
|
+
const out = [];
|
|
1053
|
+
for (const segment of segments) {
|
|
1054
|
+
if (segment.kind !== "key" || !segment.definite)
|
|
1055
|
+
return null;
|
|
1056
|
+
if (!isArrayIndex(segment.name))
|
|
1057
|
+
out.push(segment.name);
|
|
1058
|
+
}
|
|
1059
|
+
return out;
|
|
1060
|
+
};
|
|
1061
|
+
/** `{ ...value }` of a value of the literal's own shape: a copy of the
|
|
1062
|
+
* value's order. */
|
|
1063
|
+
const selfSpread = (segments, id) => segments.length === 1 &&
|
|
1064
|
+
segments[0].kind === "spread" &&
|
|
1065
|
+
segments[0].shapeId === id &&
|
|
1066
|
+
!segments[0].maybeAbsent;
|
|
1067
|
+
const sameOrder = (a, b) => a.join("\0") === b.join("\0");
|
|
1068
|
+
const indexOfOrder = (orders, order) => orders.findIndex((o) => sameOrder(o, order));
|
|
1069
|
+
/** The keys writes can add to a value of the shape, or null when a
|
|
1070
|
+
* clone override can (the clone's order is its source's). */
|
|
1071
|
+
const movingKeys = (id, f, table) => {
|
|
1072
|
+
const keys = new Set(table);
|
|
1073
|
+
const moving = new Set();
|
|
1074
|
+
for (const w of f.writes) {
|
|
1075
|
+
if (w.kind === "delete" || !keys.has(w.field) || !maybeAbsent(id, w.field))
|
|
1076
|
+
continue;
|
|
1077
|
+
if (w.kind === "clone")
|
|
1078
|
+
return null;
|
|
1079
|
+
moving.add(w.field);
|
|
1080
|
+
}
|
|
1081
|
+
return [...moving];
|
|
1082
|
+
};
|
|
1083
|
+
/** `values[i]` for the order index `current` holds, as a chain of
|
|
1084
|
+
* tests. */
|
|
1085
|
+
const indexChain = (current, values, loc) => {
|
|
1086
|
+
let out = { kind: "numLit", value: values[values.length - 1], type: F64, loc };
|
|
1087
|
+
for (let i = values.length - 2; i >= 0; i--) {
|
|
1088
|
+
if (out.kind === "numLit" && out.value === values[i])
|
|
1089
|
+
continue;
|
|
1090
|
+
out = {
|
|
1091
|
+
kind: "ternary",
|
|
1092
|
+
cond: {
|
|
1093
|
+
kind: "bin",
|
|
1094
|
+
op: "===",
|
|
1095
|
+
left: current,
|
|
1096
|
+
right: { kind: "numLit", value: i, type: F64, loc },
|
|
1097
|
+
type: BOOL,
|
|
1098
|
+
loc,
|
|
1099
|
+
},
|
|
1100
|
+
then: { kind: "numLit", value: values[i], type: F64, loc },
|
|
1101
|
+
else_: out,
|
|
1102
|
+
type: F64,
|
|
1103
|
+
loc,
|
|
1104
|
+
};
|
|
1105
|
+
}
|
|
1106
|
+
return out;
|
|
1107
|
+
};
|
|
1108
|
+
const moves = new Map();
|
|
1109
|
+
/** Adds to `orders` every order writes of `moving` keys reach from them
|
|
1110
|
+
* and records each key's transitions; false past MAX_ORDERS. */
|
|
1111
|
+
const closeUnderMoves = (id, orders, moving) => {
|
|
1112
|
+
const transitions = new Map(moving.map((k) => [k, []]));
|
|
1113
|
+
for (let i = 0; i < orders.length; i++) {
|
|
1114
|
+
for (const key of moving) {
|
|
1115
|
+
const moved = [...orders[i].filter((k) => k !== key), key];
|
|
1116
|
+
let index = indexOfOrder(orders, moved);
|
|
1117
|
+
if (index < 0) {
|
|
1118
|
+
if (orders.length === MAX_ORDERS)
|
|
1119
|
+
return false;
|
|
1120
|
+
index = orders.push(moved) - 1;
|
|
1121
|
+
}
|
|
1122
|
+
transitions.get(key)[i] = index;
|
|
1123
|
+
}
|
|
1124
|
+
}
|
|
1125
|
+
if (moving.length > 0)
|
|
1126
|
+
moves.set(id, transitions);
|
|
1127
|
+
return true;
|
|
1128
|
+
};
|
|
1129
|
+
// Observed shapes, and the shapes their values copy their orders from.
|
|
1130
|
+
const wanted = new Set(observed);
|
|
1131
|
+
const pending = [...observed];
|
|
1132
|
+
while (pending.length > 0) {
|
|
1133
|
+
const f = facts.get(pending.pop());
|
|
1134
|
+
if (f === undefined)
|
|
1135
|
+
continue;
|
|
1136
|
+
const sources = [
|
|
1137
|
+
...f.copies.map((c) => c.source),
|
|
1138
|
+
...f.literals.flatMap((segments) => segments.flatMap((s) => (s.kind === "spread" ? [s.shapeId] : []))),
|
|
1139
|
+
];
|
|
1140
|
+
for (const source of sources) {
|
|
1141
|
+
if (wanted.has(source))
|
|
1142
|
+
continue;
|
|
1143
|
+
wanted.add(source);
|
|
1144
|
+
pending.push(source);
|
|
1145
|
+
}
|
|
1146
|
+
}
|
|
1147
|
+
const orderable = (id, f) => {
|
|
1148
|
+
const shape = shapes.get(id);
|
|
1149
|
+
if (!wanted.has(id) || !unresolved(id) || !inScope(shape))
|
|
1150
|
+
return null;
|
|
1151
|
+
const moving = movingKeys(id, f, tableOf(shape));
|
|
1152
|
+
return moving === null ? null : { shape, moving };
|
|
1153
|
+
};
|
|
1154
|
+
const variants = new Map();
|
|
1155
|
+
for (const [id, f] of facts) {
|
|
1156
|
+
const candidate = orderable(id, f);
|
|
1157
|
+
// A runtime producer builds the shape's values in its fixed layout,
|
|
1158
|
+
// which has no KEY_ORDER_FIELD.
|
|
1159
|
+
if (candidate === null || f.literals.length === 0 || f.opaque)
|
|
1160
|
+
continue;
|
|
1161
|
+
const table = tableOf(candidate.shape);
|
|
1162
|
+
const orders = [table];
|
|
1163
|
+
let ok = true;
|
|
1164
|
+
const add = (order) => {
|
|
1165
|
+
const full = complete(order, table);
|
|
1166
|
+
if (indexOfOrder(orders, full) < 0)
|
|
1167
|
+
orders.push(full);
|
|
1168
|
+
};
|
|
1169
|
+
for (const segments of f.literals) {
|
|
1170
|
+
if (selfSpread(segments, id))
|
|
1171
|
+
continue;
|
|
1172
|
+
const order = literalOrder(segments);
|
|
1173
|
+
if (order === null)
|
|
1174
|
+
ok = false;
|
|
1175
|
+
else
|
|
1176
|
+
add(order);
|
|
1177
|
+
}
|
|
1178
|
+
for (const c of f.copies) {
|
|
1179
|
+
if (c.source === id)
|
|
1180
|
+
continue;
|
|
1181
|
+
const source = result.get(c.source);
|
|
1182
|
+
if (source === undefined || source === "unknown")
|
|
1183
|
+
ok = false;
|
|
1184
|
+
else
|
|
1185
|
+
add(source.order.filter((k) => c.keys.has(k)));
|
|
1186
|
+
}
|
|
1187
|
+
if (!ok || orders.length > MAX_ORDERS || !closeUnderMoves(id, orders, candidate.moving))
|
|
1188
|
+
continue;
|
|
1189
|
+
if (orders.length > 1)
|
|
1190
|
+
variants.set(id, orders);
|
|
1191
|
+
else
|
|
1192
|
+
moves.delete(id);
|
|
1193
|
+
}
|
|
1194
|
+
const templateOf = (segments, id) => {
|
|
1195
|
+
const prefix = [];
|
|
1196
|
+
const suffix = [];
|
|
1197
|
+
let source = null;
|
|
1198
|
+
for (const segment of segments) {
|
|
1199
|
+
if (segment.kind === "opaque")
|
|
1200
|
+
return null;
|
|
1201
|
+
if (segment.kind === "spread") {
|
|
1202
|
+
if (source !== null || segment.maybeAbsent || segment.shapeId === id)
|
|
1203
|
+
return null;
|
|
1204
|
+
source = segment.shapeId;
|
|
1205
|
+
continue;
|
|
1206
|
+
}
|
|
1207
|
+
if (!segment.definite)
|
|
1208
|
+
return null;
|
|
1209
|
+
(source === null ? prefix : suffix).push(segment.name);
|
|
1210
|
+
}
|
|
1211
|
+
return source === null ? null : { source, prefix, suffix };
|
|
1212
|
+
};
|
|
1213
|
+
const templateKey = (t) => JSON.stringify([t.source, t.prefix, t.suffix]);
|
|
1214
|
+
const copyTemplate = (source) => ({ source, prefix: [], suffix: [] });
|
|
1215
|
+
const mirrors = new Map();
|
|
1216
|
+
for (const [id, f] of facts) {
|
|
1217
|
+
if (variants.has(id) || f.pinned || f.runtime || f.opaque)
|
|
1218
|
+
continue;
|
|
1219
|
+
const candidate = orderable(id, f);
|
|
1220
|
+
if (candidate === null || f.literals.length + f.copies.length === 0)
|
|
1221
|
+
continue;
|
|
1222
|
+
const templates = f.literals.map((segments) => templateOf(segments, id));
|
|
1223
|
+
for (const c of f.copies)
|
|
1224
|
+
templates.push(copyTemplate(c.source));
|
|
1225
|
+
const first = templates[0];
|
|
1226
|
+
if (first === null ||
|
|
1227
|
+
first === undefined ||
|
|
1228
|
+
templates.some((t) => t === null || templateKey(t) !== templateKey(first)))
|
|
1229
|
+
continue;
|
|
1230
|
+
const orders = variants.get(first.source);
|
|
1231
|
+
if (orders === undefined || mirrors.has(first.source))
|
|
1232
|
+
continue;
|
|
1233
|
+
const table = tableOf(candidate.shape);
|
|
1234
|
+
const tested = first.suffix.filter((k) => maybeAbsent(first.source, k));
|
|
1235
|
+
if (tested.length > 4)
|
|
1236
|
+
continue;
|
|
1237
|
+
const mirrorOf = (o, lacks) => {
|
|
1238
|
+
const order = [...first.prefix];
|
|
1239
|
+
for (const k of o)
|
|
1240
|
+
if (!lacks.has(k) && !order.includes(k))
|
|
1241
|
+
order.push(k);
|
|
1242
|
+
for (const k of first.suffix)
|
|
1243
|
+
if (!order.includes(k))
|
|
1244
|
+
order.push(k);
|
|
1245
|
+
return complete(order, table);
|
|
1246
|
+
};
|
|
1247
|
+
let mirrored;
|
|
1248
|
+
let template = first;
|
|
1249
|
+
if (tested.length === 0)
|
|
1250
|
+
mirrored = orders.map((o) => mirrorOf(o, new Set()));
|
|
1251
|
+
else {
|
|
1252
|
+
mirrored = [];
|
|
1253
|
+
const index = [];
|
|
1254
|
+
for (let present = 0; present < 1 << tested.length; present++) {
|
|
1255
|
+
const lacks = new Set(tested.filter((_, j) => (present & (1 << j)) === 0));
|
|
1256
|
+
const row = [];
|
|
1257
|
+
for (const o of orders) {
|
|
1258
|
+
const order = mirrorOf(o, lacks);
|
|
1259
|
+
let i = indexOfOrder(mirrored, order);
|
|
1260
|
+
if (i < 0)
|
|
1261
|
+
i = mirrored.push(order) - 1;
|
|
1262
|
+
row.push(i);
|
|
1263
|
+
}
|
|
1264
|
+
index.push(row);
|
|
1265
|
+
}
|
|
1266
|
+
if (mirrored.length > MAX_ORDERS)
|
|
1267
|
+
continue;
|
|
1268
|
+
template = {
|
|
1269
|
+
source: first.source,
|
|
1270
|
+
prefix: first.prefix,
|
|
1271
|
+
suffix: first.suffix,
|
|
1272
|
+
select: { keys: tested, index },
|
|
1273
|
+
};
|
|
1274
|
+
}
|
|
1275
|
+
if (!closeUnderMoves(id, mirrored, candidate.moving))
|
|
1276
|
+
continue;
|
|
1277
|
+
if (mirrored.every((o) => sameOrder(o, mirrored[0]))) {
|
|
1278
|
+
// Every order of the source agrees over these keys: one table.
|
|
1279
|
+
moves.delete(id);
|
|
1280
|
+
const shape = candidate.shape;
|
|
1281
|
+
const only = mirrored[0] ?? table;
|
|
1282
|
+
if (!sameOrder(only, table))
|
|
1283
|
+
shape.declaredOrder = [...shape.declaredOrder.filter(isArrayIndex), ...only];
|
|
1284
|
+
continue;
|
|
1285
|
+
}
|
|
1286
|
+
variants.set(id, mirrored);
|
|
1287
|
+
mirrors.set(id, template);
|
|
1288
|
+
}
|
|
1289
|
+
if (variants.size === 0)
|
|
1290
|
+
return;
|
|
1291
|
+
// Every construction of those shapes, to give each its order index. A
|
|
1292
|
+
// copy reads its source's index, so its source must be a plain binding.
|
|
1293
|
+
const sites = new Map();
|
|
1294
|
+
/** The statements a spread literal's sequence evaluates first: the
|
|
1295
|
+
* spread value's binding, then its fields. */
|
|
1296
|
+
const prologues = new Map();
|
|
1297
|
+
const siteOf = (e) => {
|
|
1298
|
+
if (e.kind === "seqExpr" && e.result.kind === "recordLit")
|
|
1299
|
+
prologues.set(e.result, e.stmts);
|
|
1300
|
+
if (e.kind === "recordLit" && e.type.kind === "record" && variants.has(e.type.shapeId)) {
|
|
1301
|
+
const list = sites.get(e.type.shapeId) ?? [];
|
|
1302
|
+
list.push(e);
|
|
1303
|
+
sites.set(e.type.shapeId, list);
|
|
1304
|
+
}
|
|
1305
|
+
return everyExprChild(e, siteOf, siteStmt);
|
|
1306
|
+
};
|
|
1307
|
+
const siteStmt = (st) => everyStmtChild(st, siteOf, siteStmt);
|
|
1308
|
+
/** The function each literal with a prologue is built in. */
|
|
1309
|
+
const owners = new Map();
|
|
1310
|
+
for (const fn of fns) {
|
|
1311
|
+
const before = new Set(prologues.keys());
|
|
1312
|
+
for (const st of fn.body)
|
|
1313
|
+
siteStmt(st);
|
|
1314
|
+
for (const lit of prologues.keys())
|
|
1315
|
+
if (!before.has(lit))
|
|
1316
|
+
owners.set(lit, fn);
|
|
1317
|
+
}
|
|
1318
|
+
/** Where a literal evaluated its spread of `source`: the declaration the
|
|
1319
|
+
* spread segment names, in the literal's own prologue. */
|
|
1320
|
+
const spreadBinding = (lit, source) => {
|
|
1321
|
+
const stmts = prologues.get(lit);
|
|
1322
|
+
if (stmts === undefined)
|
|
1323
|
+
return null;
|
|
1324
|
+
for (const segment of notes.literalOf(lit) ?? []) {
|
|
1325
|
+
if (segment.kind !== "spread" || segment.shapeId !== source || !segment.value)
|
|
1326
|
+
continue;
|
|
1327
|
+
const localId = segment.value.localId;
|
|
1328
|
+
const at = stmts.findIndex((st) => st.kind === "varDecl" && st.localId === localId);
|
|
1329
|
+
const decl = stmts[at];
|
|
1330
|
+
if (decl?.kind !== "varDecl" || decl.init === null)
|
|
1331
|
+
return null;
|
|
1332
|
+
return { stmts, at, value: { kind: "varRef", localId, type: decl.init.type, loc: lit.loc } };
|
|
1333
|
+
}
|
|
1334
|
+
return null;
|
|
1335
|
+
};
|
|
1336
|
+
/** The binding a copy or spread reads its fields from. A literal's spread
|
|
1337
|
+
* names it; every field of a copy reads it. */
|
|
1338
|
+
const copySource = (lit, source) => {
|
|
1339
|
+
if (notes.literalOf(lit) !== undefined)
|
|
1340
|
+
return spreadBinding(lit, source)?.value ?? null;
|
|
1341
|
+
for (const field of lit.fields) {
|
|
1342
|
+
const value = field.value;
|
|
1343
|
+
if (value.kind === "recordGet" && value.shapeId === source && value.obj.kind === "varRef")
|
|
1344
|
+
return value.obj;
|
|
1345
|
+
}
|
|
1346
|
+
for (const st of prologues.get(lit) ?? []) {
|
|
1347
|
+
if (st.kind !== "varDecl" || st.init === null)
|
|
1348
|
+
continue;
|
|
1349
|
+
const t = st.init.type;
|
|
1350
|
+
if (t.kind === "record" && t.shapeId === source)
|
|
1351
|
+
return { kind: "varRef", localId: st.localId, type: t, loc: lit.loc };
|
|
1352
|
+
}
|
|
1353
|
+
return null;
|
|
1354
|
+
};
|
|
1355
|
+
const orderIndex = (id, lit) => {
|
|
1356
|
+
const orders = variants.get(id);
|
|
1357
|
+
const segments = notes.literalOf(lit);
|
|
1358
|
+
if (segments !== undefined && selfSpread(segments, id)) {
|
|
1359
|
+
const obj = copySource(lit, id);
|
|
1360
|
+
if (obj === null)
|
|
1361
|
+
return null;
|
|
1362
|
+
return {
|
|
1363
|
+
kind: "recordGet",
|
|
1364
|
+
obj,
|
|
1365
|
+
shapeId: id,
|
|
1366
|
+
field: KEY_ORDER_FIELD,
|
|
1367
|
+
type: F64,
|
|
1368
|
+
loc: lit.loc,
|
|
1369
|
+
};
|
|
1370
|
+
}
|
|
1371
|
+
const mirror = mirrors.get(id);
|
|
1372
|
+
if (segments !== undefined && mirror !== undefined) {
|
|
1373
|
+
const obj = copySource(lit, mirror.source);
|
|
1374
|
+
if (obj === null)
|
|
1375
|
+
return null;
|
|
1376
|
+
const sourceIndex = {
|
|
1377
|
+
kind: "recordGet",
|
|
1378
|
+
obj,
|
|
1379
|
+
shapeId: mirror.source,
|
|
1380
|
+
field: KEY_ORDER_FIELD,
|
|
1381
|
+
type: F64,
|
|
1382
|
+
loc: lit.loc,
|
|
1383
|
+
};
|
|
1384
|
+
const select = mirror.select;
|
|
1385
|
+
if (select === undefined)
|
|
1386
|
+
return sourceIndex;
|
|
1387
|
+
// Tests the source for each key in turn, then picks by its index.
|
|
1388
|
+
const pick = (j, present) => {
|
|
1389
|
+
if (j === select.keys.length)
|
|
1390
|
+
return indexChain(sourceIndex, select.index[present], lit.loc);
|
|
1391
|
+
return {
|
|
1392
|
+
kind: "ternary",
|
|
1393
|
+
cond: lowerer.recordFieldPresent(obj, mirror.source, select.keys[j], lit.loc),
|
|
1394
|
+
then: pick(j + 1, present | (1 << j)),
|
|
1395
|
+
else_: pick(j + 1, present),
|
|
1396
|
+
type: F64,
|
|
1397
|
+
loc: lit.loc,
|
|
1398
|
+
};
|
|
1399
|
+
};
|
|
1400
|
+
return pick(0, 0);
|
|
1401
|
+
}
|
|
1402
|
+
if (segments !== undefined) {
|
|
1403
|
+
const order = literalOrder(segments);
|
|
1404
|
+
return order === null ? null : indexOfOrder(orders, complete(order, orders[0]));
|
|
1405
|
+
}
|
|
1406
|
+
const source = notes.copyOf(lit);
|
|
1407
|
+
if (source === undefined)
|
|
1408
|
+
return 0;
|
|
1409
|
+
if (variants.has(source) && (source === id || mirrors.get(id)?.source === source)) {
|
|
1410
|
+
const obj = copySource(lit, source);
|
|
1411
|
+
if (obj === null)
|
|
1412
|
+
return null;
|
|
1413
|
+
return {
|
|
1414
|
+
kind: "recordGet",
|
|
1415
|
+
obj,
|
|
1416
|
+
shapeId: source,
|
|
1417
|
+
field: KEY_ORDER_FIELD,
|
|
1418
|
+
type: F64,
|
|
1419
|
+
loc: lit.loc,
|
|
1420
|
+
};
|
|
1421
|
+
}
|
|
1422
|
+
const resolved = result.get(source);
|
|
1423
|
+
if (resolved === undefined || resolved === "unknown")
|
|
1424
|
+
return null;
|
|
1425
|
+
const keys = new Set(lit.fields.filter((x) => x.value.kind !== "fieldAbsent").map((x) => x.name));
|
|
1426
|
+
return indexOfOrder(orders, complete(resolved.order.filter((k) => keys.has(k)), orders[0]));
|
|
1427
|
+
};
|
|
1428
|
+
const plan = new Map();
|
|
1429
|
+
const dropped = new Set();
|
|
1430
|
+
for (const [id, list] of sites) {
|
|
1431
|
+
for (const lit of list) {
|
|
1432
|
+
const index = orderIndex(id, lit);
|
|
1433
|
+
if (index === null || (typeof index === "number" && index < 0))
|
|
1434
|
+
dropped.add(id);
|
|
1435
|
+
else
|
|
1436
|
+
plan.set(lit, index);
|
|
1437
|
+
}
|
|
1438
|
+
}
|
|
1439
|
+
// Write sites of keys that move: each reads and updates the value's
|
|
1440
|
+
// index before the write.
|
|
1441
|
+
const writeSites = [];
|
|
1442
|
+
let writeFn = null;
|
|
1443
|
+
const writeExpr = (e) => everyExprChild(e, writeExpr, writeOf);
|
|
1444
|
+
const writeOf = (st) => {
|
|
1445
|
+
if (st.kind === "recordSet" &&
|
|
1446
|
+
st.value.kind !== "fieldAbsent" &&
|
|
1447
|
+
moves.get(st.shapeId)?.has(st.field))
|
|
1448
|
+
writeSites.push({ st, fn: writeFn });
|
|
1449
|
+
return everyStmtChild(st, writeExpr, writeOf);
|
|
1450
|
+
};
|
|
1451
|
+
for (const fn of fns) {
|
|
1452
|
+
writeFn = fn;
|
|
1453
|
+
for (const st of fn.body)
|
|
1454
|
+
writeOf(st);
|
|
1455
|
+
}
|
|
1456
|
+
// A shape whose copies cannot read their source keeps today's table, and
|
|
1457
|
+
// so do the shapes that mirror it.
|
|
1458
|
+
for (const [id, mirror] of mirrors)
|
|
1459
|
+
if (dropped.has(mirror.source))
|
|
1460
|
+
dropped.add(id);
|
|
1461
|
+
let temporaries = 0;
|
|
1462
|
+
for (const [lit, index] of plan) {
|
|
1463
|
+
const id = lit.type.shapeId;
|
|
1464
|
+
if (dropped.has(id))
|
|
1465
|
+
continue;
|
|
1466
|
+
let value = typeof index === "number" ? { kind: "numLit", value: index, type: F64, loc: lit.loc } : index;
|
|
1467
|
+
// A spread's order is the source's order at the spread: a later
|
|
1468
|
+
// property may move the source's keys. Read it right after the literal
|
|
1469
|
+
// evaluates the source.
|
|
1470
|
+
const source = mirrors.get(id)?.source;
|
|
1471
|
+
const binding = typeof index === "number" || !source ? null : spreadBinding(lit, source);
|
|
1472
|
+
const fn = owners.get(lit);
|
|
1473
|
+
if (binding && fn) {
|
|
1474
|
+
const localId = `%keyOrderSource.${temporaries++}`;
|
|
1475
|
+
fn.locals.push({ id: localId, name: "%keyOrderSource", type: F64, mutable: false });
|
|
1476
|
+
binding.stmts.splice(binding.at + 1, 0, {
|
|
1477
|
+
kind: "varDecl",
|
|
1478
|
+
localId,
|
|
1479
|
+
init: value,
|
|
1480
|
+
loc: lit.loc,
|
|
1481
|
+
});
|
|
1482
|
+
value = { kind: "varRef", localId, type: F64, loc: lit.loc };
|
|
1483
|
+
}
|
|
1484
|
+
lit.fields.push({ name: KEY_ORDER_FIELD, value });
|
|
1485
|
+
}
|
|
1486
|
+
const replacements = new Map();
|
|
1487
|
+
for (const { st, fn } of writeSites) {
|
|
1488
|
+
if (dropped.has(st.shapeId))
|
|
1489
|
+
continue;
|
|
1490
|
+
const transitions = moves.get(st.shapeId).get(st.field);
|
|
1491
|
+
const loc = st.loc;
|
|
1492
|
+
// A receiver other than a binding evaluates once, into a local. So does
|
|
1493
|
+
// a binding when the value evaluates first (below): the value may
|
|
1494
|
+
// assign the binding, and the write still goes to the object the
|
|
1495
|
+
// binding held before.
|
|
1496
|
+
const pure = st.value.kind === "numLit" ||
|
|
1497
|
+
st.value.kind === "strLit" ||
|
|
1498
|
+
st.value.kind === "boolLit" ||
|
|
1499
|
+
st.value.kind === "varRef";
|
|
1500
|
+
let plain = st.obj;
|
|
1501
|
+
while (plain.kind === "unionNarrow" || plain.kind === "downcast")
|
|
1502
|
+
plain = plain.value;
|
|
1503
|
+
const prologue = [];
|
|
1504
|
+
let obj = st.obj;
|
|
1505
|
+
if (plain.kind !== "varRef" || !pure) {
|
|
1506
|
+
const localId = `%keyOrderReceiver.${temporaries++}`;
|
|
1507
|
+
fn.locals.push({ id: localId, name: "%keyOrderReceiver", type: st.obj.type, mutable: false });
|
|
1508
|
+
prologue.push({ kind: "varDecl", localId, init: st.obj, loc });
|
|
1509
|
+
obj = { kind: "varRef", localId, type: st.obj.type, loc };
|
|
1510
|
+
}
|
|
1511
|
+
const current = {
|
|
1512
|
+
kind: "recordGet",
|
|
1513
|
+
obj,
|
|
1514
|
+
shapeId: st.shapeId,
|
|
1515
|
+
field: KEY_ORDER_FIELD,
|
|
1516
|
+
type: F64,
|
|
1517
|
+
loc,
|
|
1518
|
+
};
|
|
1519
|
+
const next = indexChain(current, transitions, loc);
|
|
1520
|
+
// The value evaluates before the key is tested and moved: it may add
|
|
1521
|
+
// other keys to the same value, which then come first.
|
|
1522
|
+
let value = st.value;
|
|
1523
|
+
if (!pure) {
|
|
1524
|
+
const localId = `%keyOrderValue.${temporaries++}`;
|
|
1525
|
+
fn.locals.push({ id: localId, name: "%keyOrderValue", type: value.type, mutable: false });
|
|
1526
|
+
prologue.push({ kind: "varDecl", localId, init: value, loc });
|
|
1527
|
+
value = { kind: "varRef", localId, type: value.type, loc };
|
|
1528
|
+
}
|
|
1529
|
+
const absent = {
|
|
1530
|
+
kind: "unary",
|
|
1531
|
+
op: "!",
|
|
1532
|
+
operand: lowerer.recordFieldPresent(obj, st.shapeId, st.field, loc),
|
|
1533
|
+
type: BOOL,
|
|
1534
|
+
loc,
|
|
1535
|
+
};
|
|
1536
|
+
const update = {
|
|
1537
|
+
kind: "recordSet",
|
|
1538
|
+
obj,
|
|
1539
|
+
shapeId: st.shapeId,
|
|
1540
|
+
field: KEY_ORDER_FIELD,
|
|
1541
|
+
value: next,
|
|
1542
|
+
loc,
|
|
1543
|
+
};
|
|
1544
|
+
// The write becomes a block that moves the key first.
|
|
1545
|
+
const write = {
|
|
1546
|
+
kind: "recordSet",
|
|
1547
|
+
obj,
|
|
1548
|
+
shapeId: st.shapeId,
|
|
1549
|
+
field: st.field,
|
|
1550
|
+
value,
|
|
1551
|
+
loc,
|
|
1552
|
+
};
|
|
1553
|
+
const guard = { kind: "if", cond: absent, then: [update], else_: null, loc };
|
|
1554
|
+
const block = { kind: "block", body: [...prologue, guard, write], loc };
|
|
1555
|
+
let replaced = replacements.get(fn);
|
|
1556
|
+
if (replaced === undefined) {
|
|
1557
|
+
replaced = new Map();
|
|
1558
|
+
replacements.set(fn, replaced);
|
|
1559
|
+
}
|
|
1560
|
+
replaced.set(st, block);
|
|
1561
|
+
}
|
|
1562
|
+
for (const [fn, replaced] of replacements) {
|
|
1563
|
+
fn.body = transformStmtList(fn.body, {
|
|
1564
|
+
expr: (e) => e,
|
|
1565
|
+
stmt: (st) => replaced.get(st) ?? st,
|
|
1566
|
+
});
|
|
1567
|
+
}
|
|
1568
|
+
for (const [id, orders] of variants) {
|
|
1569
|
+
if (dropped.has(id))
|
|
1570
|
+
continue;
|
|
1571
|
+
const shape = shapes.get(id);
|
|
1572
|
+
const indexKeys = (shape.declaredOrder ?? []).filter(isArrayIndex);
|
|
1573
|
+
shapes.addKeyOrderField(id);
|
|
1574
|
+
const tables = [];
|
|
1575
|
+
for (const order of orders) {
|
|
1576
|
+
const table = [...indexKeys];
|
|
1577
|
+
for (const key of order)
|
|
1578
|
+
table.push(key);
|
|
1579
|
+
tables.push(table);
|
|
1580
|
+
}
|
|
1581
|
+
shape.orderVariants = tables;
|
|
1582
|
+
}
|
|
657
1583
|
}
|
|
658
1584
|
//# sourceMappingURL=key-order-witness.js.map
|