@scriptc/compiler 0.2.5 → 0.2.7
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 +62 -48
- package/dist/backend/cycle-analysis.d.ts +21 -9
- package/dist/backend/cycle-analysis.js +139 -67
- package/dist/backend/cycle-analysis.js.map +1 -1
- package/dist/backend/cycle-analysis.test.js +283 -3
- package/dist/backend/cycle-analysis.test.js.map +1 -1
- package/dist/backend/cycle-mutability.d.ts +39 -0
- package/dist/backend/cycle-mutability.js +205 -0
- package/dist/backend/cycle-mutability.js.map +1 -0
- package/dist/backend/executable-features.js +1 -0
- package/dist/backend/executable-features.js.map +1 -1
- package/dist/backend/link-plan-core.d.ts +4 -1
- package/dist/backend/link-plan-core.js +16 -3
- package/dist/backend/link-plan-core.js.map +1 -1
- package/dist/backend/link-plan.d.ts +3 -1
- package/dist/backend/link-plan.js +3 -0
- package/dist/backend/link-plan.js.map +1 -1
- package/dist/backend/llvm/alloc.d.ts +40 -0
- package/dist/backend/llvm/alloc.js +205 -0
- package/dist/backend/llvm/alloc.js.map +1 -0
- package/dist/backend/llvm/alloc.test.d.ts +1 -0
- package/dist/backend/llvm/alloc.test.js +102 -0
- package/dist/backend/llvm/alloc.test.js.map +1 -0
- package/dist/backend/llvm/byte-numbers.js +32 -4
- package/dist/backend/llvm/byte-numbers.js.map +1 -1
- package/dist/backend/llvm/byte-windows.d.ts +31 -0
- package/dist/backend/llvm/byte-windows.js +334 -0
- package/dist/backend/llvm/byte-windows.js.map +1 -0
- package/dist/backend/llvm/byte-windows.test.d.ts +1 -0
- package/dist/backend/llvm/byte-windows.test.js +244 -0
- package/dist/backend/llvm/byte-windows.test.js.map +1 -0
- package/dist/backend/llvm/call-lifetimes.d.ts +17 -5
- package/dist/backend/llvm/call-lifetimes.js +58 -24
- package/dist/backend/llvm/call-lifetimes.js.map +1 -1
- package/dist/backend/llvm/call-lifetimes.test.js +170 -0
- package/dist/backend/llvm/call-lifetimes.test.js.map +1 -1
- package/dist/backend/llvm/classes.d.ts +18 -2
- package/dist/backend/llvm/classes.js +115 -41
- package/dist/backend/llvm/classes.js.map +1 -1
- package/dist/backend/llvm/classes.test.d.ts +1 -0
- package/dist/backend/llvm/classes.test.js +132 -0
- package/dist/backend/llvm/classes.test.js.map +1 -0
- package/dist/backend/llvm/common.d.ts +13 -0
- package/dist/backend/llvm/common.js +30 -0
- package/dist/backend/llvm/common.js.map +1 -1
- package/dist/backend/llvm/constant-callbacks.d.ts +27 -0
- package/dist/backend/llvm/constant-callbacks.js +450 -0
- package/dist/backend/llvm/constant-callbacks.js.map +1 -0
- package/dist/backend/llvm/constant-callbacks.test.d.ts +1 -0
- package/dist/backend/llvm/constant-callbacks.test.js +261 -0
- package/dist/backend/llvm/constant-callbacks.test.js.map +1 -0
- package/dist/backend/llvm/dense-array-access.d.ts +29 -0
- package/dist/backend/llvm/dense-array-access.js +335 -0
- package/dist/backend/llvm/dense-array-access.js.map +1 -0
- package/dist/backend/llvm/dense-array-access.test.d.ts +1 -0
- package/dist/backend/llvm/dense-array-access.test.js +149 -0
- package/dist/backend/llvm/dense-array-access.test.js.map +1 -0
- package/dist/backend/llvm/dyn.d.ts +35 -1
- package/dist/backend/llvm/dyn.js +196 -35
- package/dist/backend/llvm/dyn.js.map +1 -1
- package/dist/backend/llvm/emitter.d.ts +143 -4
- package/dist/backend/llvm/emitter.js +882 -136
- package/dist/backend/llvm/emitter.js.map +1 -1
- package/dist/backend/llvm/emitter.test.js +82 -14
- package/dist/backend/llvm/emitter.test.js.map +1 -1
- package/dist/backend/llvm/expr-async.js +58 -4
- package/dist/backend/llvm/expr-async.js.map +1 -1
- package/dist/backend/llvm/expr-async.test.d.ts +1 -0
- package/dist/backend/llvm/expr-async.test.js +62 -0
- package/dist/backend/llvm/expr-async.test.js.map +1 -0
- package/dist/backend/llvm/expr-bytes.js +11 -0
- package/dist/backend/llvm/expr-bytes.js.map +1 -1
- package/dist/backend/llvm/expr-calls.js +151 -25
- package/dist/backend/llvm/expr-calls.js.map +1 -1
- package/dist/backend/llvm/expr-containers.js +37 -14
- package/dist/backend/llvm/expr-containers.js.map +1 -1
- package/dist/backend/llvm/expr-control.js +92 -2
- package/dist/backend/llvm/expr-control.js.map +1 -1
- package/dist/backend/llvm/expr-dispatch.js +2 -0
- package/dist/backend/llvm/expr-dispatch.js.map +1 -1
- package/dist/backend/llvm/expr-dynamic.js +210 -28
- package/dist/backend/llvm/expr-dynamic.js.map +1 -1
- package/dist/backend/llvm/expr-primitives.d.ts +1 -1
- package/dist/backend/llvm/expr-primitives.js +58 -23
- package/dist/backend/llvm/expr-primitives.js.map +1 -1
- package/dist/backend/llvm/expr-primitives.test.js +1 -1
- package/dist/backend/llvm/expr-records.js +3 -3
- package/dist/backend/llvm/expr-records.js.map +1 -1
- package/dist/backend/llvm/expr-stream-bridges.js +59 -2
- 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/integer-remainder.d.ts +18 -0
- package/dist/backend/llvm/integer-remainder.js +117 -0
- package/dist/backend/llvm/integer-remainder.js.map +1 -0
- package/dist/backend/llvm/layouts.d.ts +2 -1
- package/dist/backend/llvm/layouts.js +4 -3
- package/dist/backend/llvm/layouts.js.map +1 -1
- package/dist/backend/llvm/lazy-captures.d.ts +16 -0
- package/dist/backend/llvm/lazy-captures.js +96 -0
- package/dist/backend/llvm/lazy-captures.js.map +1 -0
- package/dist/backend/llvm/lazy-captures.test.d.ts +1 -0
- package/dist/backend/llvm/lazy-captures.test.js +78 -0
- package/dist/backend/llvm/lazy-captures.test.js.map +1 -0
- package/dist/backend/llvm/lib-abi.js +7 -0
- package/dist/backend/llvm/lib-abi.js.map +1 -1
- package/dist/backend/llvm/lib-dispatch.js +7 -22
- package/dist/backend/llvm/lib-dispatch.js.map +1 -1
- package/dist/backend/llvm/lib-filesystem.js +3 -4
- package/dist/backend/llvm/lib-filesystem.js.map +1 -1
- package/dist/backend/llvm/lib-shared.js +15 -0
- package/dist/backend/llvm/lib-shared.js.map +1 -1
- package/dist/backend/llvm/local-array-reads.d.ts +13 -3
- package/dist/backend/llvm/local-array-reads.js +159 -77
- package/dist/backend/llvm/local-array-reads.js.map +1 -1
- package/dist/backend/llvm/local-array-reads.test.js +105 -4
- package/dist/backend/llvm/local-array-reads.test.js.map +1 -1
- package/dist/backend/llvm/local-union-storage.d.ts +5 -1
- package/dist/backend/llvm/local-union-storage.js +48 -6
- package/dist/backend/llvm/local-union-storage.js.map +1 -1
- package/dist/backend/llvm/local-union-storage.test.js +91 -4
- package/dist/backend/llvm/local-union-storage.test.js.map +1 -1
- package/dist/backend/llvm/loop-array-borrows.d.ts +11 -0
- package/dist/backend/llvm/loop-array-borrows.js +70 -0
- package/dist/backend/llvm/loop-array-borrows.js.map +1 -0
- package/dist/backend/llvm/loop-array-borrows.test.d.ts +1 -0
- package/dist/backend/llvm/loop-array-borrows.test.js +145 -0
- package/dist/backend/llvm/loop-array-borrows.test.js.map +1 -0
- package/dist/backend/llvm/map-read-lifetimes.d.ts +5 -0
- package/dist/backend/llvm/map-read-lifetimes.js +20 -5
- package/dist/backend/llvm/map-read-lifetimes.js.map +1 -1
- package/dist/backend/llvm/map-read-lifetimes.test.js +1 -1
- package/dist/backend/llvm/nullable-fields.d.ts +28 -0
- package/dist/backend/llvm/nullable-fields.js +45 -0
- package/dist/backend/llvm/nullable-fields.js.map +1 -0
- package/dist/backend/llvm/nullable-fields.test.d.ts +1 -0
- package/dist/backend/llvm/nullable-fields.test.js +48 -0
- package/dist/backend/llvm/nullable-fields.test.js.map +1 -0
- package/dist/backend/llvm/reference-effects.d.ts +2 -1
- package/dist/backend/llvm/reference-effects.js +7 -0
- package/dist/backend/llvm/reference-effects.js.map +1 -1
- package/dist/backend/llvm/serialized-ir-emission.test.d.ts +1 -0
- package/dist/backend/llvm/serialized-ir-emission.test.js +52 -0
- package/dist/backend/llvm/serialized-ir-emission.test.js.map +1 -0
- package/dist/backend/llvm/shapes.d.ts +73 -3
- package/dist/backend/llvm/shapes.js +281 -34
- package/dist/backend/llvm/shapes.js.map +1 -1
- package/dist/backend/llvm/shapes.test.js +114 -5
- package/dist/backend/llvm/shapes.test.js.map +1 -1
- package/dist/backend/llvm/split-loops.d.ts +48 -0
- package/dist/backend/llvm/split-loops.js +183 -0
- package/dist/backend/llvm/split-loops.js.map +1 -0
- package/dist/backend/llvm/split.js +0 -7
- package/dist/backend/llvm/split.js.map +1 -1
- package/dist/backend/llvm/split.test.js +66 -2
- package/dist/backend/llvm/split.test.js.map +1 -1
- package/dist/backend/llvm/stack-callbacks.d.ts +14 -0
- package/dist/backend/llvm/stack-callbacks.js +72 -0
- package/dist/backend/llvm/stack-callbacks.js.map +1 -0
- package/dist/backend/llvm/stack-captures.d.ts +27 -0
- package/dist/backend/llvm/stack-captures.js +152 -0
- package/dist/backend/llvm/stack-captures.js.map +1 -0
- package/dist/backend/llvm/stack-unions.test.js +38 -1
- package/dist/backend/llvm/stack-unions.test.js.map +1 -1
- package/dist/backend/llvm/string-construction.test.js +1 -1
- package/dist/backend/llvm/string-key-hash.d.ts +8 -0
- package/dist/backend/llvm/string-key-hash.js +59 -0
- package/dist/backend/llvm/string-key-hash.js.map +1 -0
- package/dist/backend/llvm/string-key-hash.test.d.ts +1 -0
- package/dist/backend/llvm/string-key-hash.test.js +34 -0
- package/dist/backend/llvm/string-key-hash.test.js.map +1 -0
- package/dist/backend/llvm/string-lifetimes.test.js +48 -7
- package/dist/backend/llvm/string-lifetimes.test.js.map +1 -1
- package/dist/backend/llvm/string-slices.d.ts +20 -0
- package/dist/backend/llvm/string-slices.js +87 -0
- package/dist/backend/llvm/string-slices.js.map +1 -0
- package/dist/backend/llvm/string-slices.test.d.ts +1 -0
- package/dist/backend/llvm/string-slices.test.js +98 -0
- package/dist/backend/llvm/string-slices.test.js.map +1 -0
- package/dist/backend/llvm/switch-dispatch.js +1 -1
- package/dist/backend/llvm/switch-dispatch.js.map +1 -1
- package/dist/backend/llvm/switch-dispatch.test.js +2 -2
- package/dist/backend/llvm/switch-dispatch.test.js.map +1 -1
- package/dist/backend/llvm/walkers.d.ts +4 -14
- package/dist/backend/llvm/walkers.js +53 -311
- package/dist/backend/llvm/walkers.js.map +1 -1
- package/dist/backend/may-throw.js +4 -1
- package/dist/backend/may-throw.js.map +1 -1
- package/dist/backend/may-throw.test.js +1 -1
- package/dist/backend/native/cache-warm.d.ts +2 -1
- package/dist/backend/native/cache-warm.js.map +1 -1
- package/dist/backend/native/contracts.d.ts +5 -2
- package/dist/backend/native/contracts.js.map +1 -1
- package/dist/backend/native/executable.js +12 -4
- 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 +3 -0
- package/dist/backend/native/runtime-inputs.js.map +1 -1
- package/dist/backend/native-codegen-core.d.ts +7 -0
- package/dist/backend/native-codegen-core.js +21 -0
- package/dist/backend/native-codegen-core.js.map +1 -1
- package/dist/backend/native-codegen.d.ts +9 -0
- package/dist/backend/native-codegen.js +38 -18
- package/dist/backend/native-codegen.js.map +1 -1
- package/dist/backend/native-codegen.test.js +70 -2
- package/dist/backend/native-codegen.test.js.map +1 -1
- package/dist/backend/native-link-info-core.d.ts +4 -2
- package/dist/backend/native-link-info-core.js.map +1 -1
- package/dist/backend/native-link-info.d.ts +2 -1
- package/dist/backend/native-link-info.js.map +1 -1
- package/dist/backend/native-link-info.test.js +2 -2
- package/dist/backend/native-link-info.test.js.map +1 -1
- package/dist/backend/native-tools.d.ts +6 -2
- package/dist/backend/native-tools.js +6 -5
- package/dist/backend/native-tools.js.map +1 -1
- package/dist/backend/optimization.d.ts +25 -0
- package/dist/backend/optimization.js +21 -0
- package/dist/backend/optimization.js.map +1 -0
- package/dist/backend/optimization.test.d.ts +1 -0
- package/dist/backend/optimization.test.js +24 -0
- package/dist/backend/optimization.test.js.map +1 -0
- package/dist/backend/runtime-abi.d.ts +2 -2
- package/dist/backend/runtime-abi.js +2 -2
- package/dist/backend/runtime-pack-core.d.ts +16 -4
- package/dist/backend/runtime-pack-core.js +31 -13
- package/dist/backend/runtime-pack-core.js.map +1 -1
- package/dist/backend/runtime-pack-native.d.ts +7 -3
- package/dist/backend/runtime-pack-native.js +0 -3
- package/dist/backend/runtime-pack-native.js.map +1 -1
- package/dist/backend/runtime-pack-targets.test.js +41 -4
- package/dist/backend/runtime-pack-targets.test.js.map +1 -1
- package/dist/backend/runtime-pack.d.ts +20 -2
- package/dist/backend/runtime-pack.js +23 -0
- package/dist/backend/runtime-pack.js.map +1 -1
- package/dist/backend/runtime-pack.test.js +125 -2
- package/dist/backend/runtime-pack.test.js.map +1 -1
- package/dist/backend/target-diagnostics.test.js +1 -1
- package/dist/backend/targets.d.ts +2 -1
- package/dist/backend/targets.js +1 -1
- package/dist/backend/targets.js.map +1 -1
- package/dist/cli/command.js +5 -4
- package/dist/cli/command.js.map +1 -1
- package/dist/cli/host.d.ts +2 -1
- package/dist/cli/usage.d.ts +1 -1
- package/dist/cli/usage.js +5 -2
- package/dist/cli/usage.js.map +1 -1
- package/dist/compile-types.d.ts +5 -2
- package/dist/diagnostics/diagnostic.js +10 -8
- package/dist/diagnostics/diagnostic.js.map +1 -1
- package/dist/executable/executable-cache.d.ts +3 -2
- package/dist/executable/executable-cache.js +8 -4
- package/dist/executable/executable-cache.js.map +1 -1
- package/dist/executable/executable-cache.test.js +35 -0
- package/dist/executable/executable-cache.test.js.map +1 -1
- package/dist/frontend/fork-target.d.ts +5 -0
- package/dist/frontend/fork-target.js +40 -8
- package/dist/frontend/fork-target.js.map +1 -1
- package/dist/frontend/fork-target.test.d.ts +1 -0
- package/dist/frontend/fork-target.test.js +59 -0
- package/dist/frontend/fork-target.test.js.map +1 -0
- package/dist/frontend/lowering/abstract-equality.js +5 -49
- package/dist/frontend/lowering/abstract-equality.js.map +1 -1
- package/dist/frontend/lowering/array-values.d.ts +23 -0
- package/dist/frontend/lowering/array-values.js +129 -0
- package/dist/frontend/lowering/array-values.js.map +1 -1
- package/dist/frontend/lowering/binding-analysis.js +2 -2
- package/dist/frontend/lowering/binding-analysis.js.map +1 -1
- package/dist/frontend/lowering/builtins/atomics.d.ts +2 -11
- package/dist/frontend/lowering/builtins/atomics.js +64 -28
- package/dist/frontend/lowering/builtins/atomics.js.map +1 -1
- package/dist/frontend/lowering/builtins/errors.js +17 -2
- package/dist/frontend/lowering/builtins/errors.js.map +1 -1
- package/dist/frontend/lowering/builtins/filesystem-calls.d.ts +3 -0
- package/dist/frontend/lowering/builtins/filesystem-calls.js +51 -4
- package/dist/frontend/lowering/builtins/filesystem-calls.js.map +1 -1
- package/dist/frontend/lowering/builtins/module-calls.js +6 -1
- package/dist/frontend/lowering/builtins/module-calls.js.map +1 -1
- package/dist/frontend/lowering/builtins/process.d.ts +6 -17
- package/dist/frontend/lowering/builtins/process.js +56 -29
- package/dist/frontend/lowering/builtins/process.js.map +1 -1
- package/dist/frontend/lowering/builtins/workers.d.ts +5 -0
- package/dist/frontend/lowering/builtins/workers.js +65 -0
- package/dist/frontend/lowering/builtins/workers.js.map +1 -0
- package/dist/frontend/lowering/caught-value-dispatch.d.ts +11 -0
- package/dist/frontend/lowering/caught-value-dispatch.js +87 -0
- package/dist/frontend/lowering/caught-value-dispatch.js.map +1 -0
- package/dist/frontend/lowering/class-assertions.d.ts +11 -0
- package/dist/frontend/lowering/class-assertions.js +104 -0
- package/dist/frontend/lowering/class-assertions.js.map +1 -0
- package/dist/frontend/lowering/class-callbacks.d.ts +3 -3
- package/dist/frontend/lowering/class-callbacks.js +18 -5
- package/dist/frontend/lowering/class-callbacks.js.map +1 -1
- package/dist/frontend/lowering/class-dynamic-dispatch.d.ts +1 -0
- package/dist/frontend/lowering/class-dynamic-dispatch.js +4 -1
- package/dist/frontend/lowering/class-dynamic-dispatch.js.map +1 -1
- package/dist/frontend/lowering/class-method-mutations.d.ts +5 -0
- package/dist/frontend/lowering/class-method-mutations.js +472 -0
- package/dist/frontend/lowering/class-method-mutations.js.map +1 -0
- package/dist/frontend/lowering/class-method-values.js +25 -5
- package/dist/frontend/lowering/class-method-values.js.map +1 -1
- package/dist/frontend/lowering/class-protocols.d.ts +17 -0
- package/dist/frontend/lowering/class-protocols.js +126 -0
- package/dist/frontend/lowering/class-protocols.js.map +1 -0
- package/dist/frontend/lowering/class-prototypes.js +8 -2
- package/dist/frontend/lowering/class-prototypes.js.map +1 -1
- package/dist/frontend/lowering/class-unions.d.ts +16 -0
- package/dist/frontend/lowering/class-unions.js +127 -0
- package/dist/frontend/lowering/class-unions.js.map +1 -0
- package/dist/frontend/lowering/coercions/builders.js +8 -1
- package/dist/frontend/lowering/coercions/builders.js.map +1 -1
- package/dist/frontend/lowering/coercions/function-adapters.js +2 -0
- package/dist/frontend/lowering/coercions/function-adapters.js.map +1 -1
- package/dist/frontend/lowering/coercions/identity.d.ts +7 -0
- package/dist/frontend/lowering/coercions/identity.js +26 -0
- package/dist/frontend/lowering/coercions/identity.js.map +1 -0
- package/dist/frontend/lowering/coercions/structural.js +9 -6
- package/dist/frontend/lowering/coercions/structural.js.map +1 -1
- package/dist/frontend/lowering/collection-narrowing.d.ts +6 -0
- package/dist/frontend/lowering/collection-narrowing.js +31 -0
- package/dist/frontend/lowering/collection-narrowing.js.map +1 -0
- package/dist/frontend/lowering/containers/array-callback-call.d.ts +7 -0
- package/dist/frontend/lowering/containers/array-callback-call.js +52 -0
- package/dist/frontend/lowering/containers/array-callback-call.js.map +1 -0
- package/dist/frontend/lowering/containers/array-callbacks.d.ts +8 -12
- package/dist/frontend/lowering/containers/array-callbacks.js +415 -136
- package/dist/frontend/lowering/containers/array-callbacks.js.map +1 -1
- package/dist/frontend/lowering/containers/array-concat.d.ts +7 -0
- package/dist/frontend/lowering/containers/array-concat.js +130 -0
- package/dist/frontend/lowering/containers/array-concat.js.map +1 -0
- package/dist/frontend/lowering/containers/array-construction.d.ts +2 -0
- package/dist/frontend/lowering/containers/array-construction.js +95 -3
- package/dist/frontend/lowering/containers/array-construction.js.map +1 -1
- package/dist/frontend/lowering/containers/array-methods.d.ts +1 -11
- package/dist/frontend/lowering/containers/array-methods.js +43 -132
- package/dist/frontend/lowering/containers/array-methods.js.map +1 -1
- package/dist/frontend/lowering/containers/bytes.js +12 -34
- package/dist/frontend/lowering/containers/bytes.js.map +1 -1
- package/dist/frontend/lowering/containers/collection-methods.js +10 -1
- package/dist/frontend/lowering/containers/collection-methods.js.map +1 -1
- package/dist/frontend/lowering/containers/indexed-objects.js +56 -70
- package/dist/frontend/lowering/containers/indexed-objects.js.map +1 -1
- package/dist/frontend/lowering/containers/string-and-regexp.js +22 -3
- package/dist/frontend/lowering/containers/string-and-regexp.js.map +1 -1
- package/dist/frontend/lowering/cycle-initialization.d.ts +41 -0
- package/dist/frontend/lowering/cycle-initialization.js +277 -0
- package/dist/frontend/lowering/cycle-initialization.js.map +1 -0
- package/dist/frontend/lowering/expressions/evaluation-safety.js +4 -0
- package/dist/frontend/lowering/expressions/evaluation-safety.js.map +1 -1
- package/dist/frontend/lowering/expressions/object-literals.js +140 -38
- package/dist/frontend/lowering/expressions/object-literals.js.map +1 -1
- package/dist/frontend/lowering/expressions/union-field-write.d.ts +4 -4
- package/dist/frontend/lowering/expressions/union-field-write.js +54 -44
- package/dist/frontend/lowering/expressions/union-field-write.js.map +1 -1
- package/dist/frontend/lowering/generic-functions.d.ts +2 -5
- package/dist/frontend/lowering/generic-functions.js +13 -10
- package/dist/frontend/lowering/generic-functions.js.map +1 -1
- package/dist/frontend/lowering/instantiation-path.d.ts +8 -0
- package/dist/frontend/lowering/instantiation-path.js +10 -0
- package/dist/frontend/lowering/instantiation-path.js.map +1 -0
- package/dist/frontend/lowering/instantiation-path.test.d.ts +1 -0
- package/dist/frontend/lowering/instantiation-path.test.js +23 -0
- package/dist/frontend/lowering/instantiation-path.test.js.map +1 -0
- package/dist/frontend/lowering/iterator-adapters.d.ts +20 -0
- package/dist/frontend/lowering/iterator-adapters.js +605 -0
- package/dist/frontend/lowering/iterator-adapters.js.map +1 -0
- package/dist/frontend/lowering/lower-array-sort.d.ts +1 -1
- package/dist/frontend/lowering/lower-array-sort.js +44 -5
- package/dist/frontend/lowering/lower-array-sort.js.map +1 -1
- package/dist/frontend/lowering/lower-array-sort.test.d.ts +1 -0
- package/dist/frontend/lowering/lower-array-sort.test.js +31 -0
- package/dist/frontend/lowering/lower-array-sort.test.js.map +1 -0
- package/dist/frontend/lowering/lower-assert.js +7 -0
- package/dist/frontend/lowering/lower-assert.js.map +1 -1
- package/dist/frontend/lowering/lower-builtin-values.js +12 -7
- package/dist/frontend/lowering/lower-builtin-values.js.map +1 -1
- package/dist/frontend/lowering/lower-calls.d.ts +3 -3
- package/dist/frontend/lowering/lower-calls.js +198 -124
- package/dist/frontend/lowering/lower-calls.js.map +1 -1
- package/dist/frontend/lowering/lower-classes.d.ts +7 -0
- package/dist/frontend/lowering/lower-classes.js +166 -96
- package/dist/frontend/lowering/lower-classes.js.map +1 -1
- package/dist/frontend/lowering/lower-event-emitter.js +1 -1
- package/dist/frontend/lowering/lower-event-emitter.js.map +1 -1
- package/dist/frontend/lowering/lower-exprs.d.ts +9 -2
- package/dist/frontend/lowering/lower-exprs.js +421 -167
- package/dist/frontend/lowering/lower-exprs.js.map +1 -1
- package/dist/frontend/lowering/lower-functions.d.ts +1 -1
- package/dist/frontend/lowering/lower-functions.js +33 -20
- package/dist/frontend/lowering/lower-functions.js.map +1 -1
- package/dist/frontend/lowering/lower-inspect.js +26 -2
- package/dist/frontend/lowering/lower-inspect.js.map +1 -1
- package/dist/frontend/lowering/lower-island.js +1 -1
- package/dist/frontend/lowering/lower-island.js.map +1 -1
- package/dist/frontend/lowering/lower-modules.d.ts +1 -0
- package/dist/frontend/lowering/lower-modules.js +54 -11
- package/dist/frontend/lowering/lower-modules.js.map +1 -1
- package/dist/frontend/lowering/lower-stmts.js +59 -69
- package/dist/frontend/lowering/lower-stmts.js.map +1 -1
- package/dist/frontend/lowering/lower-stream.js +1 -1
- package/dist/frontend/lowering/lower-stream.js.map +1 -1
- package/dist/frontend/lowering/lowerer.d.ts +50 -1
- package/dist/frontend/lowering/lowerer.js +333 -26
- package/dist/frontend/lowering/lowerer.js.map +1 -1
- package/dist/frontend/lowering/native-ffi.js +3 -1
- package/dist/frontend/lowering/native-ffi.js.map +1 -1
- package/dist/frontend/lowering/runtime-optional-provenance.d.ts +15 -0
- package/dist/frontend/lowering/runtime-optional-provenance.js +40 -0
- package/dist/frontend/lowering/runtime-optional-provenance.js.map +1 -0
- package/dist/frontend/lowering/sanitize-class-types.test.js +2 -2
- package/dist/frontend/lowering/split-consumers.d.ts +7 -0
- package/dist/frontend/lowering/split-consumers.js +64 -0
- package/dist/frontend/lowering/split-consumers.js.map +1 -0
- package/dist/frontend/lowering/strict-equality.d.ts +9 -0
- package/dist/frontend/lowering/strict-equality.js +116 -0
- package/dist/frontend/lowering/strict-equality.js.map +1 -0
- package/dist/frontend/lowering/surfaces.d.ts +3 -4
- package/dist/frontend/lowering/surfaces.js +38 -7
- package/dist/frontend/lowering/surfaces.js.map +1 -1
- package/dist/frontend/lowering/union-comparison.d.ts +5 -0
- package/dist/frontend/lowering/union-comparison.js +47 -0
- package/dist/frontend/lowering/union-comparison.js.map +1 -0
- package/dist/frontend/module-source-candidates.d.ts +10 -0
- package/dist/frontend/module-source-candidates.js +40 -0
- package/dist/frontend/module-source-candidates.js.map +1 -0
- package/dist/frontend/module-source-candidates.test.d.ts +1 -0
- package/dist/frontend/module-source-candidates.test.js +53 -0
- package/dist/frontend/module-source-candidates.test.js.map +1 -0
- package/dist/frontend/pipeline.js +2 -2
- package/dist/frontend/pipeline.js.map +1 -1
- package/dist/frontend/program-analysis.d.ts +2 -0
- package/dist/frontend/program-analysis.js +2 -0
- package/dist/frontend/program-analysis.js.map +1 -1
- package/dist/frontend/program.d.ts +38 -2
- package/dist/frontend/program.js +457 -88
- package/dist/frontend/program.js.map +1 -1
- package/dist/frontend/program.test.js +59 -6
- package/dist/frontend/program.test.js.map +1 -1
- package/dist/frontend/ts7/ast-node.js +6 -8
- package/dist/frontend/ts7/ast-node.js.map +1 -1
- package/dist/frontend/ts7/ast-node.test.js +42 -1
- package/dist/frontend/ts7/ast-node.test.js.map +1 -1
- package/dist/frontend/ts7/ast-wire.d.ts +4 -0
- package/dist/frontend/ts7/ast-wire.js +28 -0
- package/dist/frontend/ts7/ast-wire.js.map +1 -1
- package/dist/frontend/ts7/ast.d.ts +2 -1
- package/dist/frontend/ts7/ast.js +8 -4
- package/dist/frontend/ts7/ast.js.map +1 -1
- package/dist/frontend/ts7/checker.d.ts +8 -2
- package/dist/frontend/ts7/checker.js +41 -5
- package/dist/frontend/ts7/checker.js.map +1 -1
- package/dist/frontend/ts7/checker.test.js +42 -0
- package/dist/frontend/ts7/checker.test.js.map +1 -1
- package/dist/frontend/ts7/program-host.d.ts +7 -0
- package/dist/frontend/ts7/program-host.js +26 -2
- package/dist/frontend/ts7/program-host.js.map +1 -1
- package/dist/frontend/ts7/program-host.test.js +29 -0
- package/dist/frontend/ts7/program-host.test.js.map +1 -1
- package/dist/frontend/type-mapper.d.ts +4 -1
- package/dist/frontend/type-mapper.js +133 -16
- package/dist/frontend/type-mapper.js.map +1 -1
- package/dist/frontend/type-mapper.test.js +15 -3
- package/dist/frontend/type-mapper.test.js.map +1 -1
- package/dist/frontend/worker-target.d.ts +6 -0
- package/dist/frontend/worker-target.js +108 -0
- package/dist/frontend/worker-target.js.map +1 -0
- package/dist/frontend/worker-target.test.d.ts +1 -0
- package/dist/frontend/worker-target.test.js +71 -0
- package/dist/frontend/worker-target.test.js.map +1 -0
- package/dist/index.js +47 -14
- package/dist/index.js.map +1 -1
- package/dist/ir/analysis.d.ts +3 -1
- package/dist/ir/analysis.js +4 -0
- package/dist/ir/analysis.js.map +1 -1
- package/dist/ir/builtin-effects.js +12 -0
- package/dist/ir/builtin-effects.js.map +1 -1
- package/dist/ir/builtin-signatures.d.ts +1 -1
- package/dist/ir/builtin-signatures.js +15 -15
- package/dist/ir/builtin-signatures.js.map +1 -1
- package/dist/ir/constant-tables.test.js +1 -1
- package/dist/ir/initializer-bindings.test.js +1 -1
- package/dist/ir/ir.d.ts +85 -23
- package/dist/ir/ir.js +20 -6
- package/dist/ir/ir.js.map +1 -1
- package/dist/ir/numeric-call-specialization.d.ts +8 -0
- package/dist/ir/numeric-call-specialization.js +198 -0
- package/dist/ir/numeric-call-specialization.js.map +1 -0
- package/dist/ir/runtime-features.js +4 -3
- package/dist/ir/runtime-features.js.map +1 -1
- package/dist/ir/scalar-records.test.js +1 -1
- package/dist/ir/serialize.d.ts +1 -1
- package/dist/ir/serialize.js +3 -3
- package/dist/ir/serialize.js.map +1 -1
- package/dist/ir/traverse.js +8 -0
- package/dist/ir/traverse.js.map +1 -1
- package/dist/ir/validate.js +207 -43
- package/dist/ir/validate.js.map +1 -1
- package/dist/ir/validate.test.js +356 -8
- package/dist/ir/validate.test.js.map +1 -1
- package/dist/library/fence-eval.test.js +1 -1
- package/dist/library/int-infer.test.js +4 -4
- package/dist/library/ir-policy.js +2 -0
- package/dist/library/ir-policy.js.map +1 -1
- package/dist/library/library-cache.test.js +5 -5
- package/dist/library/library-profile.d.ts +2 -1
- package/dist/library/library-profile.js +4 -3
- package/dist/library/library-profile.js.map +1 -1
- package/dist/native/compiler.js +24 -11
- package/dist/native/compiler.js.map +1 -1
- package/dist/native/compiler.test.js +7 -3
- package/dist/native/compiler.test.js.map +1 -1
- package/dist/native/library.d.ts +2 -1
- package/dist/native/library.js.map +1 -1
- package/dist/native/prepare.js +29 -3
- package/dist/native/prepare.js.map +1 -1
- package/dist/native/sanitizer.d.ts +3 -2
- package/dist/native/sanitizer.js +3 -13
- package/dist/native/sanitizer.js.map +1 -1
- package/dist/native/sanitizer.test.js +1 -0
- package/dist/native/sanitizer.test.js.map +1 -1
- package/package.json +20 -20
- package/surface-manifest.json +37 -3
|
@@ -1,4 +1,8 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { generatorDrain } from "./iterator-adapters.js";
|
|
2
|
+
import { lowerUnionEquality, tagEqualityMayMissAlias } from "./strict-equality.js";
|
|
3
|
+
import { isOptionalProcessStreamProperty } from "./builtins/process.js";
|
|
4
|
+
import { lowerWorkerMetadata } from "./builtins/workers.js";
|
|
5
|
+
import { dynUndefinedExpr, nodeThrowExpr, numLit, strLit, varRef } from "../../ir/build.js";
|
|
2
6
|
import { InternalCompilerError } from "../../errors.js";
|
|
3
7
|
import { SYMBOL_T } from "../../ir/ir.js";
|
|
4
8
|
import { literalValues } from "../literal-values.js";
|
|
@@ -10,8 +14,12 @@ import { literalUnionArm } from "../union-discriminants.js";
|
|
|
10
14
|
* ToBoolean/ToString coercion helpers, and field/element reads and writes
|
|
11
15
|
* (FieldTarget). */
|
|
12
16
|
import * as ts from "../ts7/adapter.js";
|
|
17
|
+
import { constituentTypes } from "../ts7/checker.js";
|
|
13
18
|
import { dirname } from "node:path";
|
|
14
19
|
import * as posix from "node:path/posix";
|
|
20
|
+
import { checkedClassAssertion } from "./class-assertions.js";
|
|
21
|
+
import { narrowClassUnion, narrowStoredClassValue } from "./class-unions.js";
|
|
22
|
+
import { lowerUnionFieldWrite } from "./expressions/union-field-write.js";
|
|
15
23
|
import { captureContextArguments } from "./function-context.js";
|
|
16
24
|
import { OBJECT_CALLABLE_VALUES } from "./surfaces.js";
|
|
17
25
|
import { wasiGuestPath } from "../../wasi-paths.js";
|
|
@@ -21,9 +29,8 @@ import { ARRAY_METHODS, builtinConstLit, builtinFenceHintOf, builtinModuleConstO
|
|
|
21
29
|
import { UNSUPPORTED, blockedBindingUseDiag, requiresDynamicPackageDiag, unsupportedDiag, } from "../../diagnostics/diagnostic.js";
|
|
22
30
|
import { PoisonError, dynFallbackType, jsFuncNameOf, neverTaintedJsType, own } from "./lowerer.js";
|
|
23
31
|
import { lowerCollectionSpread } from "./containers/collection-methods.js";
|
|
24
|
-
import {
|
|
32
|
+
import { arrayValueRead, arrayValueStore, arrayValueType, lowerSafeIndexRead, tryLowerIndexTruthiness, tryLowerNumericIndexRead, } from "./array-values.js";
|
|
25
33
|
import { strCharsCall } from "./containers/array-construction.js";
|
|
26
|
-
import { arrayValueRead, arrayValueStore, arrayValueType } from "./array-values.js";
|
|
27
34
|
import { lowerOptionalStringIndex } from "./string-index.js";
|
|
28
35
|
import { tryLowerIndexedComparison } from "./indexed-comparison.js";
|
|
29
36
|
import { npmStaticPackageOfPath } from "../npm-static.js";
|
|
@@ -96,8 +103,8 @@ export function templateRawTextOf(node) {
|
|
|
96
103
|
const LOWER_EXPR_MAX_DEPTH = 200;
|
|
97
104
|
let lowerExprDepth = 0;
|
|
98
105
|
/** True when a property access names an ABSTRACT property declaration
|
|
99
|
-
* (`abstract p: number` — a PropertyDeclaration, not an accessor)
|
|
100
|
-
*
|
|
106
|
+
* (`abstract p: number` — a PropertyDeclaration, not an accessor).
|
|
107
|
+
* These uses need concrete property dispatch because the base has no slot. */
|
|
101
108
|
export function abstractPropertyDeclOf(lowerer, expr) {
|
|
102
109
|
const sym = lowerer.checker.getSymbolAtLocation(expr.name);
|
|
103
110
|
if (!sym)
|
|
@@ -159,7 +166,10 @@ export function lowerExpr(lowerer, expr) {
|
|
|
159
166
|
}
|
|
160
167
|
lowerExprDepth++;
|
|
161
168
|
try {
|
|
162
|
-
|
|
169
|
+
const lowered = lowerExprInner(lowerer, expr);
|
|
170
|
+
if (lowered.type.kind === "void" && (lowerer.typeOf(expr).flags & ts.TypeFlags.Never) !== 0)
|
|
171
|
+
lowerer.neverValued.add(lowered);
|
|
172
|
+
return lowered;
|
|
163
173
|
}
|
|
164
174
|
finally {
|
|
165
175
|
lowerExprDepth--;
|
|
@@ -286,6 +296,11 @@ function lowerExprInner(lowerer, expr) {
|
|
|
286
296
|
if (ts.isNonNullExpression(expr)) {
|
|
287
297
|
const inner = lowerer.lowerExpr(expr.expression);
|
|
288
298
|
if (inner.type.kind === "union") {
|
|
299
|
+
// `!` performs no runtime check: a missing array element stays
|
|
300
|
+
// undefined where its destination can hold it.
|
|
301
|
+
if (ts.isElementAccessExpression(expr.expression) &&
|
|
302
|
+
assertedElementKeepsUndefined(lowerer, expr))
|
|
303
|
+
return inner;
|
|
289
304
|
const use = runtimeOptionalUseOf(expr);
|
|
290
305
|
if (runtimeOptionalAssertionErases(lowerer, expr, inner, use))
|
|
291
306
|
return inner;
|
|
@@ -1112,6 +1127,11 @@ function lowerExprInner(lowerer, expr) {
|
|
|
1112
1127
|
{
|
|
1113
1128
|
const bi = lowerer.builtinImportOf(expr);
|
|
1114
1129
|
if (bi) {
|
|
1130
|
+
if (bi.module === "worker_threads") {
|
|
1131
|
+
const value = lowerWorkerMetadata(bi.member, loc);
|
|
1132
|
+
if (value)
|
|
1133
|
+
return value;
|
|
1134
|
+
}
|
|
1115
1135
|
const c = builtinModuleConstOf(lowerer, bi.module, bi.member);
|
|
1116
1136
|
if (c !== undefined)
|
|
1117
1137
|
return builtinConstLit(c, loc);
|
|
@@ -1323,7 +1343,7 @@ function lowerExprInner(lowerer, expr) {
|
|
|
1323
1343
|
Proxy: "Proxy constructor values have no native lowering; use a direct new Proxy with checked-native plain objects",
|
|
1324
1344
|
Reflect: "reflective property access has no static lowering — read and call members directly",
|
|
1325
1345
|
Intl: 'native Intl supports default Unicode grapheme segmentation and the composed new Intl.NumberFormat("en-US").format(x); locale negotiation and other ICU-backed operations remain unsupported',
|
|
1326
|
-
SharedArrayBuffer: "
|
|
1346
|
+
SharedArrayBuffer: "use direct new SharedArrayBuffer(length) for fixed shared storage",
|
|
1327
1347
|
ArrayBuffer: "ArrayBuffer constructor values have no native lowering; use new ArrayBuffer(length) for fixed-length shared storage",
|
|
1328
1348
|
WeakRef: "deref()-after-collect exposes GC timing — genuinely dynamic; hold a strong reference instead",
|
|
1329
1349
|
FinalizationRegistry: "finalization callbacks expose GC timing — genuinely dynamic; release resources explicitly instead",
|
|
@@ -3068,6 +3088,11 @@ export function maybeNarrow(lowerer, expr, node) {
|
|
|
3068
3088
|
// same trust-the-checker contract as the union bridge below.
|
|
3069
3089
|
if (expr.type.kind === "object") {
|
|
3070
3090
|
const narrowed = lowerer.mapTypeOf(lowerer.typeOf(node));
|
|
3091
|
+
if (narrowed?.kind === "union") {
|
|
3092
|
+
const union = narrowClassUnion(lowerer, expr, narrowed);
|
|
3093
|
+
if (union)
|
|
3094
|
+
return union;
|
|
3095
|
+
}
|
|
3071
3096
|
if (narrowed?.kind === "object" &&
|
|
3072
3097
|
narrowed.className !== expr.type.className &&
|
|
3073
3098
|
lowerer.isSubclassOf(narrowed.className, expr.type.className)) {
|
|
@@ -3077,6 +3102,8 @@ export function maybeNarrow(lowerer, expr, node) {
|
|
|
3077
3102
|
}
|
|
3078
3103
|
if (expr.type.kind !== "union")
|
|
3079
3104
|
return expr;
|
|
3105
|
+
if (ts.isPropertyAccessExpression(node) && isOptionalProcessStreamProperty(lowerer, node))
|
|
3106
|
+
return expr;
|
|
3080
3107
|
// Represented fields and index values can include undefined even when
|
|
3081
3108
|
// checker inference or lib.d.ts declares strings (RegExp captures).
|
|
3082
3109
|
// Only a declaration that represents the optional arm can provide a
|
|
@@ -3221,6 +3248,9 @@ function runtimeOptionalReceiverRead(lowerer, expr, local, property, loc) {
|
|
|
3221
3248
|
lowerer.unsupported("SC1090", expr, "a runtime-optional capture whose narrowed value type is not representable");
|
|
3222
3249
|
}
|
|
3223
3250
|
if (narrowed.kind === "union") {
|
|
3251
|
+
const classView = narrowStoredClassValue(lowerer, varRef(local.id, local.type, loc), narrowed);
|
|
3252
|
+
if (classView)
|
|
3253
|
+
return classView;
|
|
3224
3254
|
// The checker may keep the receiver at the storage union unchanged
|
|
3225
3255
|
// (`string | undefined` on a JS `.match()` call). There is no
|
|
3226
3256
|
// sub-union to re-tag: preserve the value for the downstream
|
|
@@ -3235,7 +3265,7 @@ function runtimeOptionalReceiverRead(lowerer, expr, local, property, loc) {
|
|
|
3235
3265
|
// undefined arm; re-tag it to the checker-narrowed value union with a
|
|
3236
3266
|
// checked trap for that arm, then let union property lowering inspect
|
|
3237
3267
|
// the surviving record arms.
|
|
3238
|
-
const helper = lowerer.narrowedRetagHelper(
|
|
3268
|
+
const helper = lowerer.narrowedRetagHelper(narrowedNode, local.type.unionId, narrowed.unionId, loc);
|
|
3239
3269
|
if (!helper) {
|
|
3240
3270
|
lowerer.unsupported("SC1090", expr, "a runtime-optional capture whose narrowed union is not representable");
|
|
3241
3271
|
}
|
|
@@ -3247,6 +3277,13 @@ function runtimeOptionalReceiverRead(lowerer, expr, local, property, loc) {
|
|
|
3247
3277
|
loc,
|
|
3248
3278
|
};
|
|
3249
3279
|
}
|
|
3280
|
+
if (narrowed.kind === "object") {
|
|
3281
|
+
const view = checkedClassAssertion(lowerer, varRef(local.id, local.type, loc), narrowed, loc);
|
|
3282
|
+
// Preserve the member-specific missing-value error on the two-arm
|
|
3283
|
+
// path below; mixed storage also needs to validate its concrete class.
|
|
3284
|
+
if (view && (lowerer.unions.get(local.type.unionId)?.arms.length ?? 0) > 2)
|
|
3285
|
+
return view;
|
|
3286
|
+
}
|
|
3250
3287
|
const undefTag = lowerer.armTag(local.type.unionId, UNDEFINED_T);
|
|
3251
3288
|
const def = lowerer.unions.get(local.type.unionId);
|
|
3252
3289
|
if (!def || undefTag < 0)
|
|
@@ -3401,6 +3438,45 @@ function runtimeOptionalElementKey(expr) {
|
|
|
3401
3438
|
return expr.text;
|
|
3402
3439
|
return null;
|
|
3403
3440
|
}
|
|
3441
|
+
/** Whether `xs[i]!` lands where an absent element's undefined is
|
|
3442
|
+
* representable: array storage (a literal element, a push/unshift
|
|
3443
|
+
* argument, an element assignment — arrays record the undefined state),
|
|
3444
|
+
* an equality operand, or a slot whose contextual type admits undefined.
|
|
3445
|
+
* TypeScript's `!` has no runtime effect, so such reads stay optional. */
|
|
3446
|
+
function assertedElementKeepsUndefined(lowerer, node) {
|
|
3447
|
+
let outer = node;
|
|
3448
|
+
while (ts.isParenthesizedExpression(outer.parent))
|
|
3449
|
+
outer = outer.parent;
|
|
3450
|
+
const parent = outer.parent;
|
|
3451
|
+
if (ts.isArrayLiteralExpression(parent))
|
|
3452
|
+
return true;
|
|
3453
|
+
// An equality test observes the missing element itself.
|
|
3454
|
+
if (ts.isBinaryExpression(parent) &&
|
|
3455
|
+
(parent.operatorToken.kind === ts.SyntaxKind.EqualsEqualsEqualsToken ||
|
|
3456
|
+
parent.operatorToken.kind === ts.SyntaxKind.ExclamationEqualsEqualsToken ||
|
|
3457
|
+
parent.operatorToken.kind === ts.SyntaxKind.EqualsEqualsToken ||
|
|
3458
|
+
parent.operatorToken.kind === ts.SyntaxKind.ExclamationEqualsToken))
|
|
3459
|
+
return true;
|
|
3460
|
+
const isArray = (receiver) => lowerer.checker.isArrayType(lowerer.typeOf(receiver));
|
|
3461
|
+
if (ts.isCallExpression(parent) &&
|
|
3462
|
+
parent.arguments.includes(outer) &&
|
|
3463
|
+
ts.isPropertyAccessExpression(parent.expression) &&
|
|
3464
|
+
(parent.expression.name.text === "push" || parent.expression.name.text === "unshift") &&
|
|
3465
|
+
isArray(parent.expression.expression))
|
|
3466
|
+
return true;
|
|
3467
|
+
if (ts.isBinaryExpression(parent) &&
|
|
3468
|
+
parent.operatorToken.kind === ts.SyntaxKind.EqualsToken &&
|
|
3469
|
+
parent.right === outer &&
|
|
3470
|
+
ts.isElementAccessExpression(parent.left) &&
|
|
3471
|
+
isArray(parent.left.expression))
|
|
3472
|
+
return true;
|
|
3473
|
+
const contextual = lowerer.checker.getContextualType(outer);
|
|
3474
|
+
if (!contextual)
|
|
3475
|
+
return false;
|
|
3476
|
+
const admits = (type) => (type.flags & (ts.TypeFlags.Any | ts.TypeFlags.Unknown | ts.TypeFlags.Undefined)) !== 0;
|
|
3477
|
+
return (admits(contextual) ||
|
|
3478
|
+
((contextual.flags & ts.TypeFlags.Union) !== 0 && constituentTypes(contextual).some(admits)));
|
|
3479
|
+
}
|
|
3404
3480
|
function runtimeOptionalAssertionErases(lowerer, expr, inner, use) {
|
|
3405
3481
|
if (inner.type.kind !== "union" ||
|
|
3406
3482
|
!use?.optional ||
|
|
@@ -3648,6 +3724,32 @@ export function lowerNullishCoalesce(lowerer, expr, loc) {
|
|
|
3648
3724
|
}
|
|
3649
3725
|
return result;
|
|
3650
3726
|
}
|
|
3727
|
+
/** A plain value read that may be runtime-optional: an unchecked element
|
|
3728
|
+
* read, or a binding, member or call that carries one. Lowering these
|
|
3729
|
+
* without a destination type is the same as lowering them into one. */
|
|
3730
|
+
function isPlainValueRead(node) {
|
|
3731
|
+
while (ts.isParenthesizedExpression(node))
|
|
3732
|
+
node = node.expression;
|
|
3733
|
+
return (ts.isElementAccessExpression(node) ||
|
|
3734
|
+
ts.isIdentifier(node) ||
|
|
3735
|
+
ts.isPropertyAccessExpression(node) ||
|
|
3736
|
+
ts.isCallExpression(node));
|
|
3737
|
+
}
|
|
3738
|
+
/** A member access or call receiver needs the present value itself (JS
|
|
3739
|
+
* throws a TypeError reading a member of undefined). */
|
|
3740
|
+
function isMemberReceiver(node) {
|
|
3741
|
+
let child = node;
|
|
3742
|
+
let parent = node.parent;
|
|
3743
|
+
while (ts.isParenthesizedExpression(parent)) {
|
|
3744
|
+
child = parent;
|
|
3745
|
+
parent = parent.parent;
|
|
3746
|
+
}
|
|
3747
|
+
return (((ts.isPropertyAccessExpression(parent) ||
|
|
3748
|
+
ts.isElementAccessExpression(parent) ||
|
|
3749
|
+
ts.isCallExpression(parent)) &&
|
|
3750
|
+
parent.expression === child) ||
|
|
3751
|
+
(ts.isTaggedTemplateExpression(parent) && parent.tag === child));
|
|
3752
|
+
}
|
|
3651
3753
|
function lowerNullishPair(lowerer, expr, loc, left) {
|
|
3652
3754
|
if (left.type.kind === "dyn") {
|
|
3653
3755
|
// `a ?? b` on a CHECKED-DYNAMIC left: the deciding test is the
|
|
@@ -3684,7 +3786,24 @@ function lowerNullishPair(lowerer, expr, loc, left) {
|
|
|
3684
3786
|
const fresh = rest.length === 1 ? lowerer.emptyCollectionFor(expr.right, rest[0]) : null;
|
|
3685
3787
|
if (fresh)
|
|
3686
3788
|
return { kind: "nullish", left, right: fresh, type: fresh.type, loc };
|
|
3687
|
-
|
|
3789
|
+
let type = lowerer.irTypeOf(expr);
|
|
3790
|
+
// A runtime-optional read can reach the default even when declarations
|
|
3791
|
+
// call the left side present. Preserve a differently typed primitive
|
|
3792
|
+
// fallback rather than checking it against that incomplete result type.
|
|
3793
|
+
const rightType = lowerer.mapTypeOf(lowerer.typeOf(expr.right));
|
|
3794
|
+
const primitive = (t) => t.kind === "f64" || t.kind === "string" || t.kind === "bool";
|
|
3795
|
+
if (rightType &&
|
|
3796
|
+
primitive(type) &&
|
|
3797
|
+
primitive(rightType) &&
|
|
3798
|
+
!typeEquals(type, rightType) &&
|
|
3799
|
+
rest.every(primitive)) {
|
|
3800
|
+
const arms = [...rest];
|
|
3801
|
+
if (!arms.some((arm) => typeEquals(arm, rightType)))
|
|
3802
|
+
arms.push(rightType);
|
|
3803
|
+
arms.sort((a, b) => (typeKey(a) < typeKey(b) ? -1 : 1));
|
|
3804
|
+
type = { kind: "union", unionId: lowerer.unions.intern(arms) };
|
|
3805
|
+
lowerer.runtimeOptionalArithmeticTypes.set(expr, type);
|
|
3806
|
+
}
|
|
3688
3807
|
if (type.kind === "dyn" && lowerer.dynConvertible(left.type)) {
|
|
3689
3808
|
return {
|
|
3690
3809
|
kind: "nullish",
|
|
@@ -3694,6 +3813,27 @@ function lowerNullishPair(lowerer, expr, loc, left) {
|
|
|
3694
3813
|
loc,
|
|
3695
3814
|
};
|
|
3696
3815
|
}
|
|
3816
|
+
// A runtime-optional default (`name ?? names[0]`): the checker types an
|
|
3817
|
+
// unchecked element read as the bare element type, but an out-of-range
|
|
3818
|
+
// read is undefined at runtime. When the default shares the left's
|
|
3819
|
+
// optional union, that union is the result, so the undefined state
|
|
3820
|
+
// reaches the consumer (an optional return or parameter takes it as its
|
|
3821
|
+
// undefined arm; a plain slot still extracts the element with its
|
|
3822
|
+
// checked narrow).
|
|
3823
|
+
if (rest.length === 1 &&
|
|
3824
|
+
typeEquals(type, rest[0]) &&
|
|
3825
|
+
isPlainValueRead(expr.right) &&
|
|
3826
|
+
!isMemberReceiver(expr)) {
|
|
3827
|
+
const raw = lowerer.lowerExpr(expr.right);
|
|
3828
|
+
if (typeEquals(raw.type, left.type))
|
|
3829
|
+
return { kind: "nullish", left, right: raw, type: left.type, loc };
|
|
3830
|
+
// `names[0] ?? undefined`: an explicit unit default stays the left's arm.
|
|
3831
|
+
if (isUnitType(raw.type) && lowerer.armTag(left.type.unionId, raw.type) >= 0) {
|
|
3832
|
+
const right = lowerer.coerceInto(expr.right, raw, left.type);
|
|
3833
|
+
return { kind: "nullish", left, right, type: left.type, loc };
|
|
3834
|
+
}
|
|
3835
|
+
return { kind: "nullish", left, right: lowerer.coerceInto(expr.right, raw, type), type, loc };
|
|
3836
|
+
}
|
|
3697
3837
|
if (typeEquals(type, left.type) || (rest.length === 1 && typeEquals(type, rest[0]))) {
|
|
3698
3838
|
const right = lowerer.lowerExprExpecting(expr.right, type);
|
|
3699
3839
|
return { kind: "nullish", left, right, type, loc };
|
|
@@ -3817,7 +3957,8 @@ export function lowerCondition(lowerer, expr) {
|
|
|
3817
3957
|
};
|
|
3818
3958
|
}
|
|
3819
3959
|
}
|
|
3820
|
-
|
|
3960
|
+
const value = lowerAbsenceProbe(lowerer, expr) ?? lowerer.lowerExpr(expr);
|
|
3961
|
+
return (tryLowerIndexTruthiness(lowerer, value, expr, locOf(expr)) ?? lowerer.ensureBool(value, expr));
|
|
3821
3962
|
}
|
|
3822
3963
|
function lowerPromiseThenPresence(lowerer, access, result) {
|
|
3823
3964
|
if (access.name.text !== "then")
|
|
@@ -5024,6 +5165,13 @@ export function lowerArrayLiteral(lowerer, expr, expected) {
|
|
|
5024
5165
|
loc: locOf(el),
|
|
5025
5166
|
};
|
|
5026
5167
|
}
|
|
5168
|
+
// `[...it]` over a generator (or an iterator adapted into one):
|
|
5169
|
+
// drain it once, in order, into a fresh element array.
|
|
5170
|
+
if (src.type.kind === "generator") {
|
|
5171
|
+
const drained = generatorDrain(lowerer, src, type.elem, locOf(el));
|
|
5172
|
+
if (drained)
|
|
5173
|
+
src = drained;
|
|
5174
|
+
}
|
|
5027
5175
|
// A native checked iterable can supply scalar elements even when
|
|
5028
5176
|
// the checker inferred a typed array from its producer. Drain once
|
|
5029
5177
|
// and validate the elements before the ordinary spread copy.
|
|
@@ -5547,7 +5695,7 @@ export function lowerElementAccess(lowerer, expr) {
|
|
|
5547
5695
|
// declared number type.
|
|
5548
5696
|
if (recv.type.kind === "jsval")
|
|
5549
5697
|
return islandElementRead(lowerer, expr, recv);
|
|
5550
|
-
const index = lowerer.lowerExpr(expr.argumentExpression);
|
|
5698
|
+
const index = lowerOptionalNumber(lowerer, lowerer.lowerExpr(expr.argumentExpression), locOf(expr.argumentExpression), expr.argumentExpression);
|
|
5551
5699
|
if (isJsSourceFile(expr.getSourceFile()) && recv.type.kind === "bytes") {
|
|
5552
5700
|
return {
|
|
5553
5701
|
kind: "dynKeyGet",
|
|
@@ -5804,36 +5952,12 @@ export function lowerElementAccess(lowerer, expr) {
|
|
|
5804
5952
|
}
|
|
5805
5953
|
}
|
|
5806
5954
|
if (receiverIr?.kind === "string") {
|
|
5807
|
-
//
|
|
5808
|
-
//
|
|
5809
|
-
// noUncheckedIndexedAccess the checker types the read `string`,
|
|
5810
|
-
// and charAt's "" is the only string-typed answer for an
|
|
5811
|
-
// out-of-range or fractional index where JS reads `undefined` —
|
|
5812
|
-
// SEMANTICS.md documents the divergence; in-range integer reads
|
|
5813
|
-
// (the loop pattern) are JS-exact. Optional results instead retain
|
|
5814
|
-
// undefined for missing string properties.
|
|
5955
|
+
// An indexed string property is absent for non-integer and missing
|
|
5956
|
+
// indexes. charAt has different coercion and out-of-range semantics.
|
|
5815
5957
|
const recv = lowerer.lowerExpr(expr.expression);
|
|
5816
|
-
const index = lowerer.lowerExpr(expr.argumentExpression);
|
|
5817
|
-
const resultType = lowerer.mapTypeOf(lowerer.typeOf(expr));
|
|
5958
|
+
const index = lowerOptionalNumber(lowerer, lowerer.lowerExpr(expr.argumentExpression), locOf(expr.argumentExpression), expr.argumentExpression);
|
|
5818
5959
|
if (index.type.kind === "f64" && recv.type.kind === "string") {
|
|
5819
|
-
|
|
5820
|
-
return {
|
|
5821
|
-
kind: "strIntrinsic",
|
|
5822
|
-
method: "charAt",
|
|
5823
|
-
receiver: recv,
|
|
5824
|
-
args: [index],
|
|
5825
|
-
type: STRING,
|
|
5826
|
-
loc: locOf(expr),
|
|
5827
|
-
};
|
|
5828
|
-
}
|
|
5829
|
-
if (resultType?.kind === "union") {
|
|
5830
|
-
const arms = lowerer.unions.get(resultType.unionId)?.arms;
|
|
5831
|
-
if (arms?.length === 2 &&
|
|
5832
|
-
lowerer.armTag(resultType.unionId, STRING) >= 0 &&
|
|
5833
|
-
lowerer.armTag(resultType.unionId, UNDEFINED_T) >= 0) {
|
|
5834
|
-
return lowerOptionalStringIndex(lowerer, recv, index, resultType, locOf(expr));
|
|
5835
|
-
}
|
|
5836
|
-
}
|
|
5960
|
+
return lowerOptionalStringIndex(lowerer, recv, index, lowerer.withUndefinedArm(STRING), locOf(expr));
|
|
5837
5961
|
}
|
|
5838
5962
|
lowerer.unsupported("SC1090", expr, "string indexing with this index/result shape (expected a number index and a string or string | undefined result)");
|
|
5839
5963
|
}
|
|
@@ -5955,10 +6079,13 @@ export function lowerElementAccess(lowerer, expr) {
|
|
|
5955
6079
|
// change the storage representation or the low-level getter itself.
|
|
5956
6080
|
if (arr.type.kind === "array") {
|
|
5957
6081
|
// A non-null assertion is the explicit proven-present form. Preserve
|
|
5958
|
-
// the dense getter's established bounds trap
|
|
5959
|
-
//
|
|
5960
|
-
//
|
|
5961
|
-
|
|
6082
|
+
// the dense getter's established bounds trap where the asserted value
|
|
6083
|
+
// must be the element type (library ABI checks and the catchable
|
|
6084
|
+
// RangeError contract for an out-of-bounds assert). Where undefined is
|
|
6085
|
+
// representable, the assertion keeps JavaScript's unchecked read.
|
|
6086
|
+
const provenPresent = ts.isNonNullExpression(expr.parent) &&
|
|
6087
|
+
expr.parent.expression === expr &&
|
|
6088
|
+
!assertedElementKeepsUndefined(lowerer, expr.parent);
|
|
5962
6089
|
if (provenPresent) {
|
|
5963
6090
|
return lowerer.maybeNarrow({ kind: "arrayGet", arr, index, type: elemT, loc: locOf(expr) }, expr);
|
|
5964
6091
|
}
|
|
@@ -5972,7 +6099,7 @@ export function lowerElementAccess(lowerer, expr) {
|
|
|
5972
6099
|
arr.kind === "arrIntrinsic" &&
|
|
5973
6100
|
arr.method === "slice" &&
|
|
5974
6101
|
npmStaticPackageOfPath(expr.getSourceFile().fileName) !== null) {
|
|
5975
|
-
const safe =
|
|
6102
|
+
const safe = lowerSafeIndexRead(lowerer, arr, index, locOf(expr));
|
|
5976
6103
|
if (safe)
|
|
5977
6104
|
return safe;
|
|
5978
6105
|
}
|
|
@@ -6218,6 +6345,10 @@ export function lowerAbsenceProbe(lowerer, node) {
|
|
|
6218
6345
|
expr = expr.expression;
|
|
6219
6346
|
}
|
|
6220
6347
|
if (ts.isPropertyAccessExpression(expr)) {
|
|
6348
|
+
// Namespace members are bindings, not fields of a runtime namespace
|
|
6349
|
+
// object. Their ordinary read already preserves optional storage.
|
|
6350
|
+
if (!expr.questionDotToken && nsMemberIdentOf(lowerer, expr))
|
|
6351
|
+
return null;
|
|
6221
6352
|
const target = lowerer.fieldTarget(expr);
|
|
6222
6353
|
if (target?.container === "class" &&
|
|
6223
6354
|
target.fieldType.kind === "union" &&
|
|
@@ -7180,6 +7311,19 @@ export function ensureString(lowerer, e, node) {
|
|
|
7180
7311
|
return ensureString(lowerer, { kind: "call", callee: helper, args: [e], type: narrowed, loc: e.loc }, node);
|
|
7181
7312
|
}
|
|
7182
7313
|
}
|
|
7314
|
+
if (narrowed?.kind === "union" &&
|
|
7315
|
+
!typeEquals(narrowed, e.type) &&
|
|
7316
|
+
lowerer.unions
|
|
7317
|
+
.get(narrowed.unionId)
|
|
7318
|
+
?.arms.every((arm) => isUnitType(arm) ||
|
|
7319
|
+
arm.kind === "string" ||
|
|
7320
|
+
arm.kind === "f64" ||
|
|
7321
|
+
arm.kind === "bool" ||
|
|
7322
|
+
arm.kind === "bigint")) {
|
|
7323
|
+
const helper = lowerer.narrowedRetagHelper(node, e.type.unionId, narrowed.unionId, e.loc);
|
|
7324
|
+
if (helper)
|
|
7325
|
+
return ensureString(lowerer, { kind: "call", callee: helper, args: [e], type: narrowed, loc: e.loc }, node);
|
|
7326
|
+
}
|
|
7183
7327
|
lowerer.unsupported("SC1090", node, `string conversions of unions with object arms (${NARROW_FIRST})`);
|
|
7184
7328
|
}
|
|
7185
7329
|
if (e.type.kind === "symbol") {
|
|
@@ -7353,20 +7497,16 @@ export function lowerAsExpression(lowerer, expr) {
|
|
|
7353
7497
|
};
|
|
7354
7498
|
}
|
|
7355
7499
|
}
|
|
7356
|
-
//
|
|
7357
|
-
//
|
|
7358
|
-
//
|
|
7359
|
-
// (`/** @type {T} */ (e)` — JS has no `as`); 5.9.3 parsed that as a
|
|
7360
|
-
// plain parenthesized read, which lowered caught→dyn and met the
|
|
7361
|
-
// target through the ordinary checked-cast coercion — so the dyn
|
|
7362
|
-
// bridge stays open here exactly for that shape.
|
|
7500
|
+
// Structural assertions use the ordinary checked dynamic bridge. It
|
|
7501
|
+
// retains primitive values and native class identity before validating
|
|
7502
|
+
// the requested shape; an assertion does not bypass runtime checks.
|
|
7363
7503
|
const narrowed = lowerer.mapTypeOf(lowerer.typeOf(expr.expression));
|
|
7364
7504
|
const bridged = narrowed &&
|
|
7365
7505
|
(narrowed.kind === "f64" ||
|
|
7366
7506
|
narrowed.kind === "bool" ||
|
|
7367
7507
|
narrowed.kind === "string" ||
|
|
7368
7508
|
narrowed.kind === "object" ||
|
|
7369
|
-
|
|
7509
|
+
narrowed.kind === "dyn");
|
|
7370
7510
|
if (!bridged)
|
|
7371
7511
|
lowerer.unsupported("SC1063", expr);
|
|
7372
7512
|
}
|
|
@@ -7381,6 +7521,11 @@ export function lowerAsExpression(lowerer, expr) {
|
|
|
7381
7521
|
return lowerer.jsvalIn(inner, expr.expression);
|
|
7382
7522
|
}
|
|
7383
7523
|
const target = lowerer.mapTypeOf(targetTs0);
|
|
7524
|
+
if (target?.kind === "object") {
|
|
7525
|
+
const asserted = checkedClassAssertion(lowerer, inner, target, locOf(expr));
|
|
7526
|
+
if (asserted)
|
|
7527
|
+
return asserted;
|
|
7528
|
+
}
|
|
7384
7529
|
// Unknown-only record views use the checked-dynamic representation.
|
|
7385
7530
|
// A native record asserted to such a view still denotes the original
|
|
7386
7531
|
// object. Box a live reference instead of erasing the assertion and
|
|
@@ -7613,11 +7758,11 @@ export function lowerIncDec(lowerer, expr, prefix) {
|
|
|
7613
7758
|
}
|
|
7614
7759
|
fenceNodeModuleMutation(lowerer, access, "assignment");
|
|
7615
7760
|
if (ts.isPropertyAccessExpression(access)) {
|
|
7616
|
-
const target = staticFieldWriteTarget(lowerer, access)
|
|
7761
|
+
const target = staticFieldWriteTarget(lowerer, access) ??
|
|
7762
|
+
expandoWritableTarget(lowerer, access) ??
|
|
7763
|
+
nsWritableTarget(lowerer, access);
|
|
7617
7764
|
if (target) {
|
|
7618
|
-
|
|
7619
|
-
lowerer.unsupported("SC1043", expr);
|
|
7620
|
-
return { kind: "incDec", op, prefix, localId: target.id, type: F64, loc };
|
|
7765
|
+
return lowerIncDecTarget(lowerer, expr, target, prefix);
|
|
7621
7766
|
}
|
|
7622
7767
|
}
|
|
7623
7768
|
const stmts = [];
|
|
@@ -7729,10 +7874,18 @@ export function lowerIncDec(lowerer, expr, prefix) {
|
|
|
7729
7874
|
if (!target) {
|
|
7730
7875
|
lowerer.rejectUnresolved(expr.operand, `increment/decrement of '${expr.operand.text}' (not a writable local or module global)`);
|
|
7731
7876
|
}
|
|
7877
|
+
return lowerIncDecTarget(lowerer, expr, target, prefix);
|
|
7878
|
+
}
|
|
7879
|
+
/** Numeric updates read the represented slot once and write the computed
|
|
7880
|
+
* value back in that same representation. In particular, an unchecked
|
|
7881
|
+
* indexed initializer can leave undefined in an otherwise numeric binding. */
|
|
7882
|
+
export function lowerIncDecTarget(lowerer, expr, target, prefix) {
|
|
7883
|
+
const loc = locOf(expr);
|
|
7884
|
+
const op = expr.operator === ts.SyntaxKind.PlusPlusToken ? "+" : "-";
|
|
7732
7885
|
if (target.type.kind === "dyn") {
|
|
7733
7886
|
const old = lowerer.declareHiddenLocal("%numericOld", DYN);
|
|
7734
7887
|
const next = lowerer.declareHiddenLocal("%numericNext", DYN);
|
|
7735
|
-
const read =
|
|
7888
|
+
const read = varRef(target.id, target.type, loc);
|
|
7736
7889
|
return {
|
|
7737
7890
|
kind: "seqExpr",
|
|
7738
7891
|
stmts: [
|
|
@@ -7764,6 +7917,42 @@ export function lowerIncDec(lowerer, expr, prefix) {
|
|
|
7764
7917
|
loc,
|
|
7765
7918
|
};
|
|
7766
7919
|
}
|
|
7920
|
+
if (target.type.kind === "union") {
|
|
7921
|
+
const read = lowerOptionalNumber(lowerer, varRef(target.id, target.type, loc), loc, expr.operand);
|
|
7922
|
+
if (read.type.kind === "f64") {
|
|
7923
|
+
const old = lowerer.declareHiddenLocal("%numericOld", F64);
|
|
7924
|
+
const next = lowerer.declareHiddenLocal("%numericNext", F64);
|
|
7925
|
+
const result = varRef(prefix ? next.id : old.id, F64, loc);
|
|
7926
|
+
return {
|
|
7927
|
+
kind: "seqExpr",
|
|
7928
|
+
stmts: [
|
|
7929
|
+
{ kind: "varDecl", localId: old.id, init: read, loc },
|
|
7930
|
+
{
|
|
7931
|
+
kind: "varDecl",
|
|
7932
|
+
localId: next.id,
|
|
7933
|
+
init: {
|
|
7934
|
+
kind: "bin",
|
|
7935
|
+
op,
|
|
7936
|
+
left: varRef(old.id, F64, loc),
|
|
7937
|
+
right: numLit(1, loc),
|
|
7938
|
+
type: F64,
|
|
7939
|
+
loc,
|
|
7940
|
+
},
|
|
7941
|
+
loc,
|
|
7942
|
+
},
|
|
7943
|
+
{
|
|
7944
|
+
kind: "assign",
|
|
7945
|
+
localId: target.id,
|
|
7946
|
+
value: lowerer.coerceInto(expr.operand, varRef(next.id, F64, loc), target.type),
|
|
7947
|
+
loc,
|
|
7948
|
+
},
|
|
7949
|
+
],
|
|
7950
|
+
result,
|
|
7951
|
+
type: F64,
|
|
7952
|
+
loc,
|
|
7953
|
+
};
|
|
7954
|
+
}
|
|
7955
|
+
}
|
|
7767
7956
|
if (target.type.kind !== "f64")
|
|
7768
7957
|
lowerer.unsupported("SC1043", expr);
|
|
7769
7958
|
return { kind: "incDec", op, prefix, localId: target.id, type: F64, loc };
|
|
@@ -7858,14 +8047,18 @@ export function lowerCompoundValueToTarget(lowerer, expr, compound, target) {
|
|
|
7858
8047
|
};
|
|
7859
8048
|
return lowerer.coerceInto(expr, wrapped, target.type);
|
|
7860
8049
|
}
|
|
7861
|
-
if (compound === "+" &&
|
|
7862
|
-
|
|
8050
|
+
if (compound === "+" &&
|
|
8051
|
+
(target.type.kind === "string" ||
|
|
8052
|
+
(target.type.kind === "union" &&
|
|
8053
|
+
lowerer.stripUndefinedArm(target.type).kind === "string" &&
|
|
8054
|
+
rhs.type.kind === "string"))) {
|
|
8055
|
+
return lowerer.coerceInto(expr, {
|
|
7863
8056
|
kind: "strConcat",
|
|
7864
|
-
left: read,
|
|
8057
|
+
left: lowerer.ensureString(read, expr.left),
|
|
7865
8058
|
right: lowerer.ensureString(rhs, expr.right),
|
|
7866
8059
|
type: STRING,
|
|
7867
8060
|
loc,
|
|
7868
|
-
};
|
|
8061
|
+
}, target.type);
|
|
7869
8062
|
}
|
|
7870
8063
|
if (numericRead.type.kind === "f64" && numericRhs.type.kind === "f64") {
|
|
7871
8064
|
return lowerer.coerceInto(expr, { kind: "bin", op: compound, left: numericRead, right: numericRhs, type: F64, loc }, target.type);
|
|
@@ -8120,6 +8313,9 @@ export function lowerBinary(lowerer, expr) {
|
|
|
8120
8313
|
const recv = tryLowerExpression(lowerer, expr.left.expression);
|
|
8121
8314
|
if (recv && recv.type.kind === "dyn")
|
|
8122
8315
|
return lowerDynMemberAssignment(lowerer, expr, recv);
|
|
8316
|
+
const unionWrite = lowerUnionFieldWrite(lowerer, expr.left, expr.right);
|
|
8317
|
+
if (unionWrite)
|
|
8318
|
+
return unionWrite;
|
|
8123
8319
|
const field = lowerer.fieldTarget(expr.left);
|
|
8124
8320
|
if (field) {
|
|
8125
8321
|
const recvTmp = lowerer.declareHiddenLocal("%setReceiver", field.obj.type);
|
|
@@ -8705,7 +8901,7 @@ export function lowerBinary(lowerer, expr) {
|
|
|
8705
8901
|
const optionalStringPlus = lowerOptionalStringPlus();
|
|
8706
8902
|
if (optionalStringPlus)
|
|
8707
8903
|
return optionalStringPlus;
|
|
8708
|
-
|
|
8904
|
+
{
|
|
8709
8905
|
const primitive = (type) => type.kind === "f64" ||
|
|
8710
8906
|
type.kind === "string" ||
|
|
8711
8907
|
type.kind === "bool" ||
|
|
@@ -8811,6 +9007,13 @@ export function lowerBinary(lowerer, expr) {
|
|
|
8811
9007
|
if (unitTest)
|
|
8812
9008
|
return unitTest;
|
|
8813
9009
|
if (left.type.kind === "union" || right.type.kind === "union") {
|
|
9010
|
+
const compared = lowerUnionEquality(lowerer, left, right, negated, false, loc);
|
|
9011
|
+
if (compared)
|
|
9012
|
+
return compared;
|
|
9013
|
+
const aliasRefusal = (type) => {
|
|
9014
|
+
if (tagEqualityMayMissAlias(lowerer, type))
|
|
9015
|
+
lowerer.unsupported("SC1090", expr, `comparisons of related class values beside structural union members (${NARROW_FIRST})`);
|
|
9016
|
+
};
|
|
8814
9017
|
// JS strict equality of the ARM values, per union tag (a
|
|
8815
9018
|
// per-union helper): equal tags compare payloads (f64 ==, string
|
|
8816
9019
|
// bytes, bool ==, ref-arm POINTER identity), different tags are
|
|
@@ -8846,6 +9049,7 @@ export function lowerBinary(lowerer, expr) {
|
|
|
8846
9049
|
};
|
|
8847
9050
|
}
|
|
8848
9051
|
if ((sameUnion || !bothUnion) && lowerer.eqComparableUnion(ut.unionId)) {
|
|
9052
|
+
aliasRefusal(ut);
|
|
8849
9053
|
return {
|
|
8850
9054
|
kind: "unionEq",
|
|
8851
9055
|
unionId: ut.unionId,
|
|
@@ -8876,6 +9080,7 @@ export function lowerBinary(lowerer, expr) {
|
|
|
8876
9080
|
kind: "union",
|
|
8877
9081
|
unionId: lowerer.unions.intern(arms),
|
|
8878
9082
|
};
|
|
9083
|
+
aliasRefusal(common);
|
|
8879
9084
|
return {
|
|
8880
9085
|
kind: "unionEq",
|
|
8881
9086
|
unionId: common.unionId,
|
|
@@ -10021,17 +10226,30 @@ export function caughtRead(lowerer, node, local, loc) {
|
|
|
10021
10226
|
}
|
|
10022
10227
|
if (narrowed?.kind === "object") {
|
|
10023
10228
|
const info = lowerer.classes.get(narrowed.className);
|
|
10024
|
-
if (info
|
|
10025
|
-
|
|
10229
|
+
if (info) {
|
|
10230
|
+
const value = { kind: "caughtNarrow", value: ref, type: narrowed, loc };
|
|
10231
|
+
if (lowerer.inHierarchy(info))
|
|
10232
|
+
return value;
|
|
10233
|
+
return {
|
|
10234
|
+
kind: "ternary",
|
|
10235
|
+
cond: {
|
|
10236
|
+
kind: "caughtTest",
|
|
10237
|
+
value: ref,
|
|
10238
|
+
test: "instanceof",
|
|
10239
|
+
className: info.def.name,
|
|
10240
|
+
type: BOOL,
|
|
10241
|
+
loc,
|
|
10242
|
+
},
|
|
10243
|
+
then: value,
|
|
10244
|
+
else_: lowerer.coerceInto(node, { kind: "caughtToDyn", value: ref, type: DYN, loc }, narrowed),
|
|
10245
|
+
type: narrowed,
|
|
10246
|
+
loc,
|
|
10247
|
+
};
|
|
10026
10248
|
}
|
|
10027
10249
|
}
|
|
10028
|
-
//
|
|
10029
|
-
//
|
|
10030
|
-
//
|
|
10031
|
-
// extended to exception payloads. Error payloads keep their
|
|
10032
|
-
// observability (instanceof Error / .message / String() — the checked-dynamic tree's
|
|
10033
|
-
// error encoding); other object payloads are type-erased at runtime and
|
|
10034
|
-
// convert to the "[object Object]" approximation — SEMANTICS.md 67.
|
|
10250
|
+
// Unnarrowed reads cross into unknown. The caught-value dispatch pass
|
|
10251
|
+
// retains known native class payloads through live identity capsules;
|
|
10252
|
+
// other payload kinds use the runtime's ordinary conversion.
|
|
10035
10253
|
if (narrowed?.kind === "dyn") {
|
|
10036
10254
|
return { kind: "caughtToDyn", value: ref, type: DYN, loc };
|
|
10037
10255
|
}
|
|
@@ -10097,6 +10315,38 @@ export function lowerInstanceOf(lowerer, expr, loc) {
|
|
|
10097
10315
|
(lowerer.isStdlibGlobal(expr.right, "Set") || lowerer.isStdlibGlobal(expr.right, "Map"))) {
|
|
10098
10316
|
const collection = lowerer.isStdlibGlobal(expr.right, "Map") ? "map" : "set";
|
|
10099
10317
|
const value = lowerer.lowerExpr(expr.left);
|
|
10318
|
+
if (value.type.kind === "union") {
|
|
10319
|
+
const union = lowerer.unions.get(value.type.unionId);
|
|
10320
|
+
if (union) {
|
|
10321
|
+
const local = lowerer.declareHiddenLocal("%collectionTest", value.type);
|
|
10322
|
+
const reference = varRef(local.id, value.type, loc);
|
|
10323
|
+
let result = { kind: "boolLit", value: false, type: BOOL, loc };
|
|
10324
|
+
union.arms.forEach((arm, tag) => {
|
|
10325
|
+
if (arm.kind !== collection)
|
|
10326
|
+
return;
|
|
10327
|
+
const test = {
|
|
10328
|
+
kind: "unionIsTag",
|
|
10329
|
+
unionId: union.id,
|
|
10330
|
+
value: reference,
|
|
10331
|
+
tag,
|
|
10332
|
+
negated: false,
|
|
10333
|
+
type: BOOL,
|
|
10334
|
+
loc,
|
|
10335
|
+
};
|
|
10336
|
+
result =
|
|
10337
|
+
result.kind === "boolLit"
|
|
10338
|
+
? test
|
|
10339
|
+
: { kind: "logical", op: "||", left: result, right: test, type: BOOL, loc };
|
|
10340
|
+
});
|
|
10341
|
+
return {
|
|
10342
|
+
kind: "seqExpr",
|
|
10343
|
+
stmts: [{ kind: "varDecl", localId: local.id, init: value, loc }],
|
|
10344
|
+
result,
|
|
10345
|
+
type: BOOL,
|
|
10346
|
+
loc,
|
|
10347
|
+
};
|
|
10348
|
+
}
|
|
10349
|
+
}
|
|
10100
10350
|
if (value.type.kind === "dyn")
|
|
10101
10351
|
return {
|
|
10102
10352
|
kind: "libCall",
|
|
@@ -10158,6 +10408,10 @@ export function lowerInstanceOf(lowerer, expr, loc) {
|
|
|
10158
10408
|
const value = lowerer.coerceInto(expr.left, lowerer.lowerExpr(expr.left), DYN);
|
|
10159
10409
|
return { kind: "libCall", fn: "dyn.dataViewIs", args: [value], type: BOOL, loc };
|
|
10160
10410
|
}
|
|
10411
|
+
if (lowerer.isStdlibGlobal(expr.right, "SharedArrayBuffer")) {
|
|
10412
|
+
const value = lowerer.coerceInto(expr.left, lowerer.lowerExpr(expr.left), DYN);
|
|
10413
|
+
return { kind: "libCall", fn: "sharedArrayBuffer.is", args: [value], type: BOOL, loc };
|
|
10414
|
+
}
|
|
10161
10415
|
if (lowerer.isStdlibGlobal(expr.right, "ArrayBuffer")) {
|
|
10162
10416
|
const value = lowerer.coerceInto(expr.left, lowerer.lowerExpr(expr.left), DYN);
|
|
10163
10417
|
return { kind: "libCall", fn: "arrayBuffer.is", args: [value], type: BOOL, loc };
|
|
@@ -10370,8 +10624,22 @@ export function lowerInstanceOf(lowerer, expr, loc) {
|
|
|
10370
10624
|
const caughtLocal = lowerer.caughtLocalOf(expr.left);
|
|
10371
10625
|
if (caughtLocal) {
|
|
10372
10626
|
if (!lowerer.inHierarchy(target)) {
|
|
10373
|
-
|
|
10374
|
-
|
|
10627
|
+
const value = varRef(caughtLocal.id, CAUGHT, loc);
|
|
10628
|
+
return {
|
|
10629
|
+
kind: "ternary",
|
|
10630
|
+
cond: {
|
|
10631
|
+
kind: "caughtTest",
|
|
10632
|
+
value,
|
|
10633
|
+
test: "instanceof",
|
|
10634
|
+
className: target.def.name,
|
|
10635
|
+
type: BOOL,
|
|
10636
|
+
loc,
|
|
10637
|
+
},
|
|
10638
|
+
then: { kind: "boolLit", value: true, type: BOOL, loc },
|
|
10639
|
+
else_: classInstanceOf(lowerer, { kind: "caughtToDyn", value, type: DYN, loc }, target, loc),
|
|
10640
|
+
type: BOOL,
|
|
10641
|
+
loc,
|
|
10642
|
+
};
|
|
10375
10643
|
}
|
|
10376
10644
|
return {
|
|
10377
10645
|
kind: "caughtTest",
|
|
@@ -10669,11 +10937,10 @@ function lowerPrivateIn(lowerer, expr, priv, loc) {
|
|
|
10669
10937
|
* type-directed: a declared non-optional field is a compile-time `true`,
|
|
10670
10938
|
* a missing field (no index signature) a compile-time `false` — both
|
|
10671
10939
|
* folds limited to side-effect-free receivers, the lowerInstanceOf rule —
|
|
10672
|
-
* and an OPTIONAL field (undefined-armed union) is a runtime
|
|
10673
|
-
* the slot:
|
|
10674
|
-
*
|
|
10675
|
-
*
|
|
10676
|
-
* false here; SEMANTICS.md 55). Union receivers (the `in`-narrowing
|
|
10940
|
+
* and an OPTIONAL field (undefined-armed union) is a runtime presence
|
|
10941
|
+
* test on the slot: an omitted or deleted property is absent, while a
|
|
10942
|
+
* property explicitly holding `undefined` is present, as in JS
|
|
10943
|
+
* (`"a" in {a: undefined}` is true). Union receivers (the `in`-narrowing
|
|
10677
10944
|
* idiom over multiple shapes), index-signature keys, class instances,
|
|
10678
10945
|
* and dyn/unknown stay fenced. Keys are literal strings — a computed key
|
|
10679
10946
|
* over a shape would need the runtime key table. */
|
|
@@ -10717,13 +10984,42 @@ function lowerInExpression(lowerer, expr, loc) {
|
|
|
10717
10984
|
}
|
|
10718
10985
|
}
|
|
10719
10986
|
}
|
|
10987
|
+
// A RUNTIME numeric key over an ARRAY receiver (`if (i in arr)` in a
|
|
10988
|
+
// loop) asks the same slot/property presence query as the literal fold
|
|
10989
|
+
// above and `Object.hasOwn`. The checked-dynamic fallback below would
|
|
10990
|
+
// box the receiver and materialize every element on each evaluation,
|
|
10991
|
+
// which makes such loops quadratic. A Number key never names an
|
|
10992
|
+
// inherited property: neither Array.prototype nor Object.prototype has
|
|
10993
|
+
// index-like or numeric-string keys. JS evaluates the key before the
|
|
10994
|
+
// receiver, so the key is stabilized in a hidden local first.
|
|
10995
|
+
if (lowerer.mapTypeOf(lowerer.typeOf(expr.left))?.kind === "f64" &&
|
|
10996
|
+
lowerer.mapTypeOf(lowerer.typeOf(expr.right))?.kind === "array") {
|
|
10997
|
+
const k = lowerer.lowerExpr(expr.left);
|
|
10998
|
+
const recvArr = lowerer.lowerExpr(expr.right);
|
|
10999
|
+
if (k.type.kind === "f64" && recvArr.type.kind === "array") {
|
|
11000
|
+
const keyLocal = lowerer.declareHiddenLocal("%inIndex", F64);
|
|
11001
|
+
return {
|
|
11002
|
+
kind: "seqExpr",
|
|
11003
|
+
stmts: [{ kind: "varDecl", localId: keyLocal.id, init: k, loc }],
|
|
11004
|
+
result: {
|
|
11005
|
+
kind: "arrayHas",
|
|
11006
|
+
arr: recvArr,
|
|
11007
|
+
index: varRef(keyLocal.id, F64, loc),
|
|
11008
|
+
type: BOOL,
|
|
11009
|
+
loc,
|
|
11010
|
+
},
|
|
11011
|
+
type: BOOL,
|
|
11012
|
+
loc,
|
|
11013
|
+
};
|
|
11014
|
+
}
|
|
11015
|
+
}
|
|
10720
11016
|
const key = foldedStringKeyOf(lowerer, expr.left);
|
|
10721
11017
|
if (key === null) {
|
|
10722
11018
|
// A RUNTIME string key over an INDEX-SIGNATURE record receiver (the
|
|
10723
11019
|
// `names.filter((k) => k in config)` idiom): the interned key-
|
|
10724
11020
|
// presence helper — declared fields answer statically per name
|
|
10725
|
-
// (optional slots
|
|
10726
|
-
//
|
|
11021
|
+
// (optional slots by their runtime presence), then the overflow
|
|
11022
|
+
// map's live keys. Other receivers keep the
|
|
10727
11023
|
// fence: fixed shapes want the literal folds above, and there is no
|
|
10728
11024
|
// runtime key table to ask.
|
|
10729
11025
|
const rIn = lowerRuntimeKeyIn(lowerer, expr, loc);
|
|
@@ -10966,24 +11262,9 @@ function lowerInExpression(lowerer, expr, loc) {
|
|
|
10966
11262
|
const field = shape.fields.find((f) => f.name === key);
|
|
10967
11263
|
if (field) {
|
|
10968
11264
|
if (field.type.kind === "union" && lowerer.armTag(field.type.unionId, UNDEFINED_T) >= 0) {
|
|
10969
|
-
// Optional slot: the key is present
|
|
10970
|
-
|
|
10971
|
-
|
|
10972
|
-
obj: recv,
|
|
10973
|
-
shapeId: recv.type.shapeId,
|
|
10974
|
-
field: key,
|
|
10975
|
-
type: field.type,
|
|
10976
|
-
loc,
|
|
10977
|
-
};
|
|
10978
|
-
return {
|
|
10979
|
-
kind: "unionIsTag",
|
|
10980
|
-
unionId: field.type.unionId,
|
|
10981
|
-
tag: lowerer.armTag(field.type.unionId, UNDEFINED_T),
|
|
10982
|
-
negated: true,
|
|
10983
|
-
value: read,
|
|
10984
|
-
type: BOOL,
|
|
10985
|
-
loc,
|
|
10986
|
-
};
|
|
11265
|
+
// Optional slot: the key is present unless the field is absent
|
|
11266
|
+
// (omitted or deleted); an explicit undefined is present.
|
|
11267
|
+
return lowerer.recordFieldPresent(recv, recv.type.shapeId, key, loc);
|
|
10987
11268
|
}
|
|
10988
11269
|
// A declared non-optional field always exists on every value of the
|
|
10989
11270
|
// shape — statically true, but folding may only drop a
|
|
@@ -11023,9 +11304,9 @@ function lowerInExpression(lowerer, expr, loc) {
|
|
|
11023
11304
|
* runtime string and r an index-signature record — an interned
|
|
11024
11305
|
* `%rec.haskey.<n>(k, r)` walks the declared names (a string-equality
|
|
11025
11306
|
* chain: non-optional fields and accessor slots answer true, optional
|
|
11026
|
-
* slots answer their per-value tag test) and then the overflow
|
|
11027
|
-
*
|
|
11028
|
-
* its fence). */
|
|
11307
|
+
* slots answer their per-value tag test) and then probes the overflow
|
|
11308
|
+
* map's hashed key set. Null when the pair is outside that shape (the
|
|
11309
|
+
* caller keeps its fence). */
|
|
11029
11310
|
function lowerRuntimeKeyIn(lowerer, expr, loc) {
|
|
11030
11311
|
if (lowerer.mapTypeOf(lowerer.typeOf(expr.left))?.kind !== "string")
|
|
11031
11312
|
return null;
|
|
@@ -11060,62 +11341,15 @@ function lowerRuntimeKeyIn(lowerer, expr, loc) {
|
|
|
11060
11341
|
type: BOOL,
|
|
11061
11342
|
loc,
|
|
11062
11343
|
};
|
|
11063
|
-
const
|
|
11064
|
-
|
|
11065
|
-
|
|
11066
|
-
kind: "unionIsTag",
|
|
11067
|
-
unionId: f.type.unionId,
|
|
11068
|
-
tag: utag,
|
|
11069
|
-
negated: true,
|
|
11070
|
-
value: {
|
|
11071
|
-
kind: "recordGet",
|
|
11072
|
-
obj: r,
|
|
11073
|
-
shapeId: recvT.shapeId,
|
|
11074
|
-
field: f.name,
|
|
11075
|
-
type: f.type,
|
|
11076
|
-
loc,
|
|
11077
|
-
},
|
|
11078
|
-
type: BOOL,
|
|
11079
|
-
loc,
|
|
11080
|
-
}
|
|
11081
|
-
: { kind: "boolLit", value: true, type: BOOL, loc };
|
|
11344
|
+
const answer = accessor
|
|
11345
|
+
? { kind: "boolLit", value: true, type: BOOL, loc }
|
|
11346
|
+
: lowerer.recordFieldPresent(r, recvT.shapeId, f.name, loc);
|
|
11082
11347
|
body.push({ kind: "if", cond: eq, then: [ret(answer)], else_: null, loc });
|
|
11083
11348
|
}
|
|
11084
|
-
|
|
11085
|
-
|
|
11086
|
-
|
|
11087
|
-
|
|
11088
|
-
init: { kind: "recordOvfKeys", obj: r, shapeId: recvT.shapeId, type: ksT, loc },
|
|
11089
|
-
loc,
|
|
11090
|
-
}, countedFor(loc, {
|
|
11091
|
-
kind: "arrIntrinsic",
|
|
11092
|
-
method: "length",
|
|
11093
|
-
receiver: varRef("ks.0", ksT, loc),
|
|
11094
|
-
args: [],
|
|
11095
|
-
type: F64,
|
|
11096
|
-
loc,
|
|
11097
|
-
}, () => [
|
|
11098
|
-
{
|
|
11099
|
-
kind: "if",
|
|
11100
|
-
cond: {
|
|
11101
|
-
kind: "strEq",
|
|
11102
|
-
negated: false,
|
|
11103
|
-
left: k,
|
|
11104
|
-
right: {
|
|
11105
|
-
kind: "arrayGet",
|
|
11106
|
-
arr: varRef("ks.0", ksT, loc),
|
|
11107
|
-
index: varRef("i.0", F64, loc),
|
|
11108
|
-
type: STRING,
|
|
11109
|
-
loc,
|
|
11110
|
-
},
|
|
11111
|
-
type: BOOL,
|
|
11112
|
-
loc,
|
|
11113
|
-
},
|
|
11114
|
-
then: [ret({ kind: "boolLit", value: true, type: BOOL, loc })],
|
|
11115
|
-
else_: null,
|
|
11116
|
-
loc,
|
|
11117
|
-
},
|
|
11118
|
-
]), ret({ kind: "boolLit", value: false, type: BOOL, loc }));
|
|
11349
|
+
// Overflow keys answer through the map's hashed presence probe (a
|
|
11350
|
+
// stored undefined value is still present), not a scan over a fresh
|
|
11351
|
+
// key snapshot, which made `k in dict` loops quadratic.
|
|
11352
|
+
body.push(ret({ kind: "recordOvfHas", obj: r, shapeId: recvT.shapeId, key: k, type: BOOL, loc }));
|
|
11119
11353
|
lowerer.liftedFns.push({
|
|
11120
11354
|
name: helper,
|
|
11121
11355
|
params: [
|
|
@@ -11126,8 +11360,6 @@ function lowerRuntimeKeyIn(lowerer, expr, loc) {
|
|
|
11126
11360
|
locals: [
|
|
11127
11361
|
{ id: "k.0", name: "k", type: STRING, mutable: true },
|
|
11128
11362
|
{ id: "r.0", name: "r", type: recT, mutable: true },
|
|
11129
|
-
{ id: "ks.0", name: "ks", type: ksT, mutable: false },
|
|
11130
|
-
{ id: "i.0", name: "i", type: F64, mutable: true },
|
|
11131
11363
|
],
|
|
11132
11364
|
body,
|
|
11133
11365
|
loc,
|
|
@@ -11815,7 +12047,7 @@ export function lowerUnionProperty(lowerer, expr) {
|
|
|
11815
12047
|
return null;
|
|
11816
12048
|
}
|
|
11817
12049
|
if (value.type.kind !== "union") {
|
|
11818
|
-
|
|
12050
|
+
lowerer.unsupported("SC1090", expr, "shared property access without a represented union receiver");
|
|
11819
12051
|
}
|
|
11820
12052
|
const def = lowerer.unions.get(value.type.unionId);
|
|
11821
12053
|
if (!def)
|
|
@@ -12192,11 +12424,32 @@ export function fieldTarget(lowerer, access) {
|
|
|
12192
12424
|
const stored = ts.isIdentifier(access.expression)
|
|
12193
12425
|
? (lowerer.peekLocal(access.expression)?.type ?? lowerer.globalOf(access.expression)?.type)
|
|
12194
12426
|
: undefined;
|
|
12195
|
-
const
|
|
12427
|
+
const narrowed = lowerer.mapTypeOf(lowerer.typeOf(access.expression));
|
|
12428
|
+
// Structural record views retain their storage layout, while a nominal
|
|
12429
|
+
// subclass guard proves a more specific layout of the same object.
|
|
12430
|
+
const receiverIr = stored?.kind === "record"
|
|
12196
12431
|
? stored
|
|
12197
|
-
:
|
|
12432
|
+
: stored?.kind === "object" &&
|
|
12433
|
+
!(narrowed?.kind === "object" &&
|
|
12434
|
+
lowerer.isSubclassOf(narrowed.className, stored.className))
|
|
12435
|
+
? stored
|
|
12436
|
+
: narrowed;
|
|
12198
12437
|
if (receiverIr?.kind === "object") {
|
|
12199
|
-
|
|
12438
|
+
const target = classFieldTarget(lowerer, access.expression, receiverIr, access.name.text);
|
|
12439
|
+
if (target)
|
|
12440
|
+
return target;
|
|
12441
|
+
// Abstract properties declare no base storage. Resolve the concrete
|
|
12442
|
+
// instance's live field or accessor through the existing class bridge;
|
|
12443
|
+
// inventing a shared field offset would misread subclass layouts.
|
|
12444
|
+
if (abstractPropertyDeclOf(lowerer, access)) {
|
|
12445
|
+
return {
|
|
12446
|
+
container: "dynamic",
|
|
12447
|
+
obj: lowerer.coerceInto(access.expression, lowerer.lowerExpr(access.expression), DYN),
|
|
12448
|
+
field: access.name.text,
|
|
12449
|
+
fieldType: lowerer.irTypeOf(access),
|
|
12450
|
+
};
|
|
12451
|
+
}
|
|
12452
|
+
return null;
|
|
12200
12453
|
}
|
|
12201
12454
|
if (receiverIr?.kind === "union" && hasClassPayload(lowerer, receiverIr)) {
|
|
12202
12455
|
return representedClassFieldTarget(lowerer, access.expression, access.name.text, lowerer.lowerExpr(access.expression));
|
|
@@ -12437,13 +12690,13 @@ function symbolFieldTarget(lowerer, expr) {
|
|
|
12437
12690
|
* undefined, which these property types cannot represent. */
|
|
12438
12691
|
export function fieldGetExpr(lowerer, target, loc, blame) {
|
|
12439
12692
|
if (target.container === "dynamic")
|
|
12440
|
-
return {
|
|
12693
|
+
return lowerer.coerceInto(blame, {
|
|
12441
12694
|
kind: "dynKeyGet",
|
|
12442
12695
|
value: target.obj,
|
|
12443
12696
|
key: { kind: "strLit", value: target.field, type: STRING, loc },
|
|
12444
12697
|
type: DYN,
|
|
12445
12698
|
loc,
|
|
12446
|
-
};
|
|
12699
|
+
}, target.fieldType);
|
|
12447
12700
|
if (target.container === "class" &&
|
|
12448
12701
|
(target.field === "message" || target.field === "name") &&
|
|
12449
12702
|
(target.className === "%Error" || lowerer.isSubclassOf(target.className, "%Error")))
|
|
@@ -12904,7 +13157,8 @@ function lowerFieldCompoundValue(lowerer, access, op, rhsNode, loc) {
|
|
|
12904
13157
|
? { kind: "dynCheck", value: rhs, type: F64, loc: rhs.loc }
|
|
12905
13158
|
: lowerOptionalNumber(lowerer, rhs, loc);
|
|
12906
13159
|
let value;
|
|
12907
|
-
|
|
13160
|
+
const numericRead = lowerOptionalNumber(lowerer, read, loc, access);
|
|
13161
|
+
if (op === "+" && read.type.kind === "string") {
|
|
12908
13162
|
value = {
|
|
12909
13163
|
kind: "strConcat",
|
|
12910
13164
|
left: read,
|
|
@@ -12913,8 +13167,8 @@ function lowerFieldCompoundValue(lowerer, access, op, rhsNode, loc) {
|
|
|
12913
13167
|
loc,
|
|
12914
13168
|
};
|
|
12915
13169
|
}
|
|
12916
|
-
else if (
|
|
12917
|
-
value = { kind: "bin", op, left:
|
|
13170
|
+
else if (numericRead.type.kind === "f64" && numericRhs.type.kind === "f64") {
|
|
13171
|
+
value = { kind: "bin", op, left: numericRead, right: numericRhs, type: F64, loc };
|
|
12918
13172
|
}
|
|
12919
13173
|
else if (target.fieldType.kind === "dyn" && isJsSourceFile(access.getSourceFile())) {
|
|
12920
13174
|
const numeric = ["-", "*", "/", "%", "**"].includes(op);
|
|
@@ -12934,7 +13188,7 @@ function lowerFieldCompoundValue(lowerer, access, op, rhsNode, loc) {
|
|
|
12934
13188
|
lowerer.unsupported("SC1043", access);
|
|
12935
13189
|
}
|
|
12936
13190
|
const result = save(value, "%compoundResult");
|
|
12937
|
-
body.push(lowerer.fieldSetStmt(target, result, loc, access));
|
|
13191
|
+
body.push(lowerer.fieldSetStmt(target, lowerer.coerceInto(access, result, target.fieldType), loc, access));
|
|
12938
13192
|
return { kind: "seqExpr", stmts: body, result, type: result.type, loc };
|
|
12939
13193
|
}
|
|
12940
13194
|
/** Stream-rooted receivers' property surface (readableEnded, destroyed,
|