@scriptc/compiler 0.1.7 → 0.2.1
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 +98 -39
- package/ambient/scriptc-overrides.d.ts +10 -6
- package/ambient/scriptc.d.ts +15 -0
- package/dist/backend/build-cache.d.ts +1 -3
- package/dist/backend/build-cache.js +3 -22
- package/dist/backend/build-cache.js.map +1 -1
- package/dist/backend/cache-root.d.ts +3 -0
- package/dist/backend/cache-root.js +23 -0
- package/dist/backend/cache-root.js.map +1 -0
- package/dist/backend/cycle-analysis.d.ts +15 -0
- package/dist/backend/cycle-analysis.js +108 -0
- package/dist/backend/cycle-analysis.js.map +1 -0
- package/dist/backend/cycle-analysis.test.js +124 -0
- package/dist/backend/cycle-analysis.test.js.map +1 -0
- package/dist/backend/executable-features.d.ts +4 -0
- package/dist/backend/executable-features.js +42 -0
- package/dist/backend/executable-features.js.map +1 -0
- package/dist/backend/external-c.d.ts +5 -27
- package/dist/backend/external-c.js +5 -40
- package/dist/backend/external-c.js.map +1 -1
- package/dist/backend/ffi-callbacks.d.ts +2 -3
- package/dist/backend/ffi-callbacks.js +2 -3
- package/dist/backend/ffi-callbacks.js.map +1 -1
- package/dist/backend/library-identity-markers.d.ts +4 -9
- package/dist/backend/library-identity-markers.js +11 -49
- package/dist/backend/library-identity-markers.js.map +1 -1
- package/dist/backend/library-pack.d.ts +5 -0
- package/dist/backend/library-pack.js +123 -0
- package/dist/backend/library-pack.js.map +1 -0
- package/dist/backend/link-plan-core.d.ts +20 -0
- package/dist/backend/link-plan-core.js +18 -0
- package/dist/backend/link-plan-core.js.map +1 -0
- package/dist/backend/link-plan.d.ts +1 -1
- package/dist/backend/link-plan.js +16 -17
- package/dist/backend/link-plan.js.map +1 -1
- package/dist/backend/link-trace.d.ts +2 -0
- package/dist/backend/link-trace.js +24 -0
- package/dist/backend/link-trace.js.map +1 -0
- package/dist/backend/linker.js +1 -1
- package/dist/backend/linker.js.map +1 -1
- package/dist/backend/literals.d.ts +9 -0
- package/dist/backend/literals.js +35 -0
- package/dist/backend/literals.js.map +1 -0
- package/dist/backend/literals.test.d.ts +1 -0
- package/dist/backend/literals.test.js +53 -0
- package/dist/backend/literals.test.js.map +1 -0
- package/dist/backend/llvm/blocks.d.ts +2 -0
- package/dist/backend/llvm/blocks.js +9 -4
- package/dist/backend/llvm/blocks.js.map +1 -1
- package/dist/backend/llvm/blocks.test.d.ts +1 -0
- package/dist/backend/llvm/blocks.test.js +91 -0
- package/dist/backend/llvm/blocks.test.js.map +1 -0
- package/dist/backend/llvm/classes.d.ts +14 -8
- package/dist/backend/llvm/classes.js +88 -30
- package/dist/backend/llvm/classes.js.map +1 -1
- package/dist/backend/llvm/common.d.ts +5 -1
- package/dist/backend/llvm/common.js +45 -4
- package/dist/backend/llvm/common.js.map +1 -1
- package/dist/backend/llvm/debug-info.js +2 -7
- package/dist/backend/llvm/debug-info.js.map +1 -1
- package/dist/backend/llvm/debug-info.test.d.ts +1 -0
- package/dist/backend/llvm/debug-info.test.js +110 -0
- package/dist/backend/llvm/debug-info.test.js.map +1 -0
- package/dist/backend/llvm/dyn.d.ts +21 -2
- package/dist/backend/llvm/dyn.js +647 -251
- package/dist/backend/llvm/dyn.js.map +1 -1
- package/dist/backend/llvm/emitter.d.ts +596 -1
- package/dist/backend/llvm/emitter.js +769 -425
- package/dist/backend/llvm/emitter.js.map +1 -1
- package/dist/backend/llvm/emitter.test.d.ts +1 -0
- package/dist/backend/llvm/emitter.test.js +179 -0
- package/dist/backend/llvm/emitter.test.js.map +1 -0
- package/dist/backend/llvm/expr-async.js +23 -14
- package/dist/backend/llvm/expr-async.js.map +1 -1
- package/dist/backend/llvm/expr-bytes.d.ts +2 -2
- package/dist/backend/llvm/expr-bytes.js +60 -31
- package/dist/backend/llvm/expr-bytes.js.map +1 -1
- package/dist/backend/llvm/expr-callbacks.d.ts +1 -1
- package/dist/backend/llvm/expr-callbacks.js +25 -22
- package/dist/backend/llvm/expr-callbacks.js.map +1 -1
- package/dist/backend/llvm/expr-calls.js +136 -35
- package/dist/backend/llvm/expr-calls.js.map +1 -1
- package/dist/backend/llvm/expr-containers.d.ts +1 -1
- package/dist/backend/llvm/expr-containers.js +43 -14
- package/dist/backend/llvm/expr-containers.js.map +1 -1
- package/dist/backend/llvm/expr-context.d.ts +5 -260
- package/dist/backend/llvm/expr-control.js +10 -6
- package/dist/backend/llvm/expr-control.js.map +1 -1
- package/dist/backend/llvm/expr-dispatch.d.ts +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 +78 -81
- package/dist/backend/llvm/expr-dynamic.js.map +1 -1
- package/dist/backend/llvm/expr-island.d.ts +1 -1
- package/dist/backend/llvm/expr-island.js +11 -7
- package/dist/backend/llvm/expr-island.js.map +1 -1
- package/dist/backend/llvm/expr-primitives.d.ts +1 -1
- package/dist/backend/llvm/expr-primitives.js +62 -31
- 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.d.ts +5 -1
- package/dist/backend/llvm/expr-records.js +54 -7
- package/dist/backend/llvm/expr-records.js.map +1 -1
- package/dist/backend/llvm/expr-stream-bridges.d.ts +4 -4
- package/dist/backend/llvm/expr-stream-bridges.js +220 -131
- package/dist/backend/llvm/expr-stream-bridges.js.map +1 -1
- package/dist/backend/llvm/expr-stream-bridges.test.d.ts +1 -0
- package/dist/backend/llvm/expr-stream-bridges.test.js +55 -0
- package/dist/backend/llvm/expr-stream-bridges.test.js.map +1 -0
- package/dist/backend/llvm/expr-stream-callbacks.d.ts +1 -1
- package/dist/backend/llvm/expr-stream-callbacks.js +12 -12
- package/dist/backend/llvm/expr-stream-callbacks.js.map +1 -1
- package/dist/backend/llvm/layouts.d.ts +19 -0
- package/dist/backend/llvm/layouts.js +12 -0
- package/dist/backend/llvm/layouts.js.map +1 -0
- package/dist/backend/llvm/lib-abi.d.ts +19 -0
- package/dist/backend/llvm/lib-abi.js +82 -0
- package/dist/backend/llvm/lib-abi.js.map +1 -0
- package/dist/backend/llvm/lib-connect.d.ts +2 -0
- package/dist/backend/llvm/lib-connect.js +51 -0
- package/dist/backend/llvm/lib-connect.js.map +1 -0
- package/dist/backend/llvm/lib-datagram.d.ts +2 -0
- package/dist/backend/llvm/lib-datagram.js +135 -0
- package/dist/backend/llvm/lib-datagram.js.map +1 -0
- package/dist/backend/llvm/lib-dispatch.js +50 -6
- package/dist/backend/llvm/lib-dispatch.js.map +1 -1
- package/dist/backend/llvm/lib-filesystem.js +30 -18
- package/dist/backend/llvm/lib-filesystem.js.map +1 -1
- package/dist/backend/llvm/lib-http2.d.ts +2 -0
- package/dist/backend/llvm/lib-http2.js +215 -0
- package/dist/backend/llvm/lib-http2.js.map +1 -0
- package/dist/backend/llvm/lib-lookup.d.ts +2 -0
- package/dist/backend/llvm/lib-lookup.js +39 -0
- package/dist/backend/llvm/lib-lookup.js.map +1 -0
- package/dist/backend/llvm/lib-network.js +25 -2
- package/dist/backend/llvm/lib-network.js.map +1 -1
- package/dist/backend/llvm/lib-process.js +44 -19
- package/dist/backend/llvm/lib-process.js.map +1 -1
- package/dist/backend/llvm/lib-shared.js +162 -3
- package/dist/backend/llvm/lib-shared.js.map +1 -1
- package/dist/backend/llvm/lib-stream.js +3 -2
- package/dist/backend/llvm/lib-stream.js.map +1 -1
- package/dist/backend/llvm/lib-test.d.ts +2 -0
- package/dist/backend/llvm/lib-test.js +34 -0
- package/dist/backend/llvm/lib-test.js.map +1 -0
- package/dist/backend/llvm/lib-tls.d.ts +2 -0
- package/dist/backend/llvm/lib-tls.js +82 -0
- package/dist/backend/llvm/lib-tls.js.map +1 -0
- package/dist/backend/llvm/shapes.d.ts +10 -9
- package/dist/backend/llvm/shapes.js +42 -131
- package/dist/backend/llvm/shapes.js.map +1 -1
- package/dist/backend/llvm/unsupported.d.ts +1 -0
- package/dist/backend/llvm/unsupported.js +1 -2
- package/dist/backend/llvm/unsupported.js.map +1 -1
- package/dist/backend/llvm/walkers.js +1 -7
- package/dist/backend/llvm/walkers.js.map +1 -1
- package/dist/backend/mangle.d.ts +2 -2
- package/dist/backend/mangle.js +16 -5
- package/dist/backend/mangle.js.map +1 -1
- package/dist/backend/{c/may-throw.d.ts → may-throw.d.ts} +1 -1
- package/dist/backend/{c/may-throw.js → may-throw.js} +51 -46
- package/dist/backend/may-throw.js.map +1 -0
- package/dist/backend/may-throw.test.d.ts +1 -0
- package/dist/backend/may-throw.test.js +58 -0
- package/dist/backend/may-throw.test.js.map +1 -0
- package/dist/backend/native-codegen-core.d.ts +22 -0
- package/dist/backend/native-codegen-core.js +44 -0
- package/dist/backend/native-codegen-core.js.map +1 -0
- package/dist/backend/native-codegen.d.ts +3 -19
- package/dist/backend/native-codegen.js +5 -44
- package/dist/backend/native-codegen.js.map +1 -1
- package/dist/backend/native-codegen.test.js +2 -2
- package/dist/backend/native-codegen.test.js.map +1 -1
- package/dist/backend/native-link-info-core.d.ts +94 -0
- package/dist/backend/native-link-info-core.js +62 -0
- package/dist/backend/native-link-info-core.js.map +1 -0
- package/dist/backend/native-link-info.d.ts +3 -88
- package/dist/backend/native-link-info.js +12 -243
- package/dist/backend/native-link-info.js.map +1 -1
- package/dist/backend/native-link-info.test.js +41 -146
- package/dist/backend/native-link-info.test.js.map +1 -1
- package/dist/backend/native-toolchain.d.ts +12 -30
- package/dist/backend/native-toolchain.js +83 -233
- package/dist/backend/native-toolchain.js.map +1 -1
- package/dist/backend/native-toolchain.test.js +77 -5
- package/dist/backend/native-toolchain.test.js.map +1 -1
- package/dist/backend/native-tools.d.ts +24 -0
- package/dist/backend/native-tools.js +33 -0
- package/dist/backend/native-tools.js.map +1 -0
- package/dist/backend/object-localize.js +19 -8
- package/dist/backend/object-localize.js.map +1 -1
- package/dist/backend/object-localize.test.js +22 -0
- package/dist/backend/object-localize.test.js.map +1 -1
- 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 +101 -0
- package/dist/backend/runtime-pack-core.js +172 -0
- package/dist/backend/runtime-pack-core.js.map +1 -0
- package/dist/backend/runtime-pack-native.d.ts +21 -0
- package/dist/backend/runtime-pack-native.js +73 -0
- package/dist/backend/runtime-pack-native.js.map +1 -0
- package/dist/backend/runtime-pack-targets.test.js +1 -1
- package/dist/backend/runtime-pack.d.ts +3 -83
- package/dist/backend/runtime-pack.js +8 -151
- package/dist/backend/runtime-pack.js.map +1 -1
- package/dist/backend/runtime-pack.test.js +24 -1
- package/dist/backend/runtime-pack.test.js.map +1 -1
- package/dist/backend/target-diagnostics.d.ts +22 -0
- package/dist/backend/target-diagnostics.js +108 -0
- package/dist/backend/target-diagnostics.js.map +1 -0
- package/dist/backend/target-platform.d.ts +15 -0
- package/dist/backend/target-platform.js +72 -0
- package/dist/backend/target-platform.js.map +1 -0
- package/dist/backend/targets.d.ts +13 -4
- package/dist/backend/targets.js +103 -34
- package/dist/backend/targets.js.map +1 -1
- package/dist/backend/targets.test.js +72 -4
- package/dist/backend/targets.test.js.map +1 -1
- package/dist/backend/toolchain-environment.d.ts +6 -0
- package/dist/backend/toolchain-environment.js +99 -0
- package/dist/backend/toolchain-environment.js.map +1 -0
- package/dist/backend/vendor-archives.d.ts +1 -9
- package/dist/backend/vendor-archives.js +2 -9
- package/dist/backend/vendor-archives.js.map +1 -1
- package/dist/backend/vendor-inputs.d.ts +9 -0
- package/dist/backend/vendor-inputs.js +10 -0
- package/dist/backend/vendor-inputs.js.map +1 -0
- package/dist/backend/warm-cache.d.ts +3 -0
- package/dist/backend/warm-cache.js +41 -0
- package/dist/backend/warm-cache.js.map +1 -0
- package/dist/cli/command.d.ts +3 -0
- package/dist/cli/command.js +328 -0
- package/dist/cli/command.js.map +1 -0
- package/dist/cli/host.d.ts +24 -0
- package/dist/cli/host.js +2 -0
- package/dist/cli/host.js.map +1 -0
- package/dist/cli/output-options.d.ts +26 -0
- package/dist/cli/output-options.js +60 -0
- package/dist/cli/output-options.js.map +1 -0
- package/dist/cli/paths.d.ts +12 -0
- package/dist/cli/paths.js +42 -0
- package/dist/cli/paths.js.map +1 -0
- package/dist/cli/usage.d.ts +74 -0
- package/dist/cli/usage.js +86 -0
- package/dist/cli/usage.js.map +1 -0
- package/dist/cli/wasi-paths.d.ts +8 -0
- package/dist/cli/wasi-paths.js +41 -0
- package/dist/cli/wasi-paths.js.map +1 -0
- package/dist/cli/wasi-runner.d.ts +2 -0
- package/dist/cli/wasi-runner.js +28 -0
- package/dist/cli/wasi-runner.js.map +1 -0
- package/dist/compat/fetch-profile.js +37 -7
- package/dist/compat/fetch-profile.js.map +1 -1
- package/dist/compile-types.d.ts +162 -0
- package/dist/compile-types.js +2 -0
- package/dist/compile-types.js.map +1 -0
- package/dist/coverage/report.js +11 -5
- package/dist/coverage/report.js.map +1 -1
- package/dist/coverage/surface-manifest.js +5 -2
- package/dist/coverage/surface-manifest.js.map +1 -1
- package/dist/diagnostics/diagnostic.js +5 -10
- package/dist/diagnostics/diagnostic.js.map +1 -1
- package/dist/executable/executable-cache.d.ts +3 -4
- package/dist/executable/executable-cache.js +5 -6
- package/dist/executable/executable-cache.js.map +1 -1
- package/dist/executable/executable-cache.test.js +16 -17
- package/dist/executable/executable-cache.test.js.map +1 -1
- package/dist/executable/prepare.d.ts +14 -0
- package/dist/executable/prepare.js +66 -0
- package/dist/executable/prepare.js.map +1 -0
- package/dist/ffi/ffi-manifest.d.ts +11 -4
- package/dist/ffi/ffi-manifest.js +170 -58
- package/dist/ffi/ffi-manifest.js.map +1 -1
- package/dist/ffi/ffi-manifest.test.d.ts +1 -0
- package/dist/ffi/ffi-manifest.test.js +111 -0
- package/dist/ffi/ffi-manifest.test.js.map +1 -0
- package/dist/format-integer.d.ts +3 -0
- package/dist/format-integer.js +14 -0
- package/dist/format-integer.js.map +1 -0
- package/dist/frontend/analysis.d.ts +5 -0
- package/dist/frontend/analysis.js +88 -0
- package/dist/frontend/analysis.js.map +1 -0
- package/dist/frontend/arguments-usage.d.ts +1 -3
- package/dist/frontend/arguments-usage.js.map +1 -1
- package/dist/frontend/builtin-modules.d.ts +1 -1
- package/dist/frontend/builtin-modules.js +1 -1
- package/dist/frontend/builtin-modules.js.map +1 -1
- package/dist/frontend/cjs-lexer.d.ts +4 -25
- package/dist/frontend/cjs-lexer.js +6 -806
- package/dist/frontend/cjs-lexer.js.map +1 -1
- package/dist/frontend/cjs-resolve.d.ts +5 -0
- package/dist/frontend/cjs-resolve.js +429 -0
- package/dist/frontend/cjs-resolve.js.map +1 -0
- package/dist/frontend/cjs-syntax.d.ts +26 -0
- package/dist/frontend/cjs-syntax.js +806 -0
- package/dist/frontend/cjs-syntax.js.map +1 -0
- package/dist/frontend/comptime-node.d.ts +4 -0
- package/dist/frontend/comptime-node.js +16 -0
- package/dist/frontend/comptime-node.js.map +1 -0
- package/dist/frontend/comptime-node.test.d.ts +1 -0
- package/dist/frontend/comptime-node.test.js +37 -0
- package/dist/frontend/comptime-node.test.js.map +1 -0
- package/dist/frontend/dts-paths.d.ts +3 -4
- package/dist/frontend/dts-paths.js +15 -8
- package/dist/frontend/dts-paths.js.map +1 -1
- package/dist/frontend/fork-target.js +2 -2
- package/dist/frontend/fork-target.js.map +1 -1
- package/dist/frontend/helper-tokens.d.ts +1 -0
- package/dist/frontend/helper-tokens.js +147 -0
- package/dist/frontend/helper-tokens.js.map +1 -0
- package/dist/frontend/helper-tokens.test.d.ts +1 -0
- package/dist/frontend/helper-tokens.test.js +35 -0
- package/dist/frontend/helper-tokens.test.js.map +1 -0
- package/dist/frontend/inferred-js-diagnostics.d.ts +5 -0
- package/dist/frontend/inferred-js-diagnostics.js +69 -0
- package/dist/frontend/inferred-js-diagnostics.js.map +1 -0
- package/dist/frontend/inferred-js-diagnostics.test.d.ts +1 -0
- package/dist/frontend/inferred-js-diagnostics.test.js +58 -0
- package/dist/frontend/inferred-js-diagnostics.test.js.map +1 -0
- package/dist/frontend/input-tracker.d.ts +5 -2
- package/dist/frontend/input-tracker.js +24 -3
- package/dist/frontend/input-tracker.js.map +1 -1
- package/dist/frontend/input-tracker.test.js +23 -0
- package/dist/frontend/input-tracker.test.js.map +1 -1
- package/dist/frontend/lib-contract.js +32 -24
- package/dist/frontend/lib-contract.js.map +1 -1
- package/dist/frontend/literal-values.d.ts +4 -0
- package/dist/frontend/literal-values.js +21 -0
- package/dist/frontend/literal-values.js.map +1 -0
- package/dist/frontend/literal-values.test.d.ts +1 -0
- package/dist/frontend/literal-values.test.js +91 -0
- package/dist/frontend/literal-values.test.js.map +1 -0
- package/dist/frontend/lowering/abstract-equality.d.ts +1 -1
- package/dist/frontend/lowering/abstract-equality.js +3 -0
- package/dist/frontend/lowering/abstract-equality.js.map +1 -1
- package/dist/frontend/lowering/array-indexed-mutation.js +11 -6
- package/dist/frontend/lowering/array-indexed-mutation.js.map +1 -1
- package/dist/frontend/lowering/array-values.d.ts +4 -1
- package/dist/frontend/lowering/array-values.js +43 -1
- package/dist/frontend/lowering/array-values.js.map +1 -1
- package/dist/frontend/lowering/callback-arg.js +1 -0
- package/dist/frontend/lowering/callback-arg.js.map +1 -1
- package/dist/frontend/lowering/class-callbacks.d.ts +12 -0
- package/dist/frontend/lowering/class-callbacks.js +74 -0
- package/dist/frontend/lowering/class-callbacks.js.map +1 -0
- package/dist/frontend/lowering/class-construction.d.ts +12 -0
- package/dist/frontend/lowering/class-construction.js +156 -0
- package/dist/frontend/lowering/class-construction.js.map +1 -0
- package/dist/frontend/lowering/class-descriptors.d.ts +10 -0
- package/dist/frontend/lowering/class-descriptors.js +114 -0
- package/dist/frontend/lowering/class-descriptors.js.map +1 -0
- package/dist/frontend/lowering/class-dynamic-dispatch.d.ts +51 -0
- package/dist/frontend/lowering/class-dynamic-dispatch.js +1158 -0
- package/dist/frontend/lowering/class-dynamic-dispatch.js.map +1 -0
- package/dist/frontend/lowering/class-dynamic-dispatch.test.d.ts +1 -0
- package/dist/frontend/lowering/class-dynamic-dispatch.test.js +93 -0
- package/dist/frontend/lowering/class-dynamic-dispatch.test.js.map +1 -0
- package/dist/frontend/lowering/class-instance-constructor.d.ts +7 -0
- package/dist/frontend/lowering/class-instance-constructor.js +67 -0
- package/dist/frontend/lowering/class-instance-constructor.js.map +1 -0
- package/dist/frontend/lowering/class-method-values.d.ts +13 -0
- package/dist/frontend/lowering/class-method-values.js +235 -0
- package/dist/frontend/lowering/class-method-values.js.map +1 -0
- package/dist/frontend/lowering/class-prototypes.d.ts +19 -0
- package/dist/frontend/lowering/class-prototypes.js +242 -0
- package/dist/frontend/lowering/class-prototypes.js.map +1 -0
- package/dist/frontend/lowering/class-runtime-statics.d.ts +8 -0
- package/dist/frontend/lowering/class-runtime-statics.js +66 -0
- package/dist/frontend/lowering/class-runtime-statics.js.map +1 -0
- package/dist/frontend/lowering/class-static-data.d.ts +6 -0
- package/dist/frontend/lowering/class-static-data.js +56 -0
- package/dist/frontend/lowering/class-static-data.js.map +1 -0
- package/dist/frontend/lowering/containers/buffer-numeric-methods.d.ts +4 -0
- package/dist/frontend/lowering/containers/buffer-numeric-methods.js +26 -0
- package/dist/frontend/lowering/containers/buffer-numeric-methods.js.map +1 -0
- package/dist/frontend/lowering/containers/bytes.d.ts +11 -7
- package/dist/frontend/lowering/containers/bytes.js +208 -163
- package/dist/frontend/lowering/containers/bytes.js.map +1 -1
- package/dist/frontend/lowering/containers/string-and-regexp.d.ts +2 -2
- package/dist/frontend/lowering/containers/string-and-regexp.js +58 -63
- package/dist/frontend/lowering/containers/string-and-regexp.js.map +1 -1
- package/dist/frontend/lowering/containers/string-replacement.d.ts +7 -0
- package/dist/frontend/lowering/containers/string-replacement.js +217 -0
- package/dist/frontend/lowering/containers/string-replacement.js.map +1 -0
- package/dist/frontend/lowering/error-methods.d.ts +14 -0
- package/dist/frontend/lowering/error-methods.js +177 -0
- package/dist/frontend/lowering/error-methods.js.map +1 -0
- package/dist/frontend/lowering/expressions/global-symbols.d.ts +6 -0
- package/dist/frontend/lowering/expressions/global-symbols.js +11 -0
- package/dist/frontend/lowering/expressions/global-symbols.js.map +1 -0
- package/dist/frontend/lowering/expressions/native-proxy.d.ts +7 -0
- package/dist/frontend/lowering/expressions/native-proxy.js +51 -0
- package/dist/frontend/lowering/expressions/native-proxy.js.map +1 -0
- package/dist/frontend/lowering/expressions/nullish-assignment.d.ts +6 -0
- package/dist/frontend/lowering/expressions/nullish-assignment.js +132 -0
- package/dist/frontend/lowering/expressions/nullish-assignment.js.map +1 -0
- package/dist/frontend/lowering/expressions/object-literals.d.ts +8 -8
- package/dist/frontend/lowering/expressions/object-literals.js +509 -183
- package/dist/frontend/lowering/expressions/object-literals.js.map +1 -1
- package/dist/frontend/lowering/expressions/optional-chains.d.ts +3 -4
- package/dist/frontend/lowering/expressions/optional-chains.js +88 -24
- package/dist/frontend/lowering/expressions/optional-chains.js.map +1 -1
- package/dist/frontend/lowering/expressions/try-lower-expression.js +1 -0
- package/dist/frontend/lowering/expressions/try-lower-expression.js.map +1 -1
- package/dist/frontend/lowering/expressions/union-field-write.d.ts +8 -0
- package/dist/frontend/lowering/expressions/union-field-write.js +71 -0
- package/dist/frontend/lowering/expressions/union-field-write.js.map +1 -0
- package/dist/frontend/lowering/function-context.d.ts +101 -0
- package/dist/frontend/lowering/function-context.js +109 -0
- package/dist/frontend/lowering/function-context.js.map +1 -0
- package/dist/frontend/lowering/generator-delegation.d.ts +7 -0
- package/dist/frontend/lowering/generator-delegation.js +85 -0
- package/dist/frontend/lowering/generator-delegation.js.map +1 -0
- package/dist/frontend/lowering/generator-dynamic-dispatch.d.ts +11 -0
- package/dist/frontend/lowering/generator-dynamic-dispatch.js +143 -0
- package/dist/frontend/lowering/generator-dynamic-dispatch.js.map +1 -0
- package/dist/frontend/lowering/lib-boundary.d.ts +4 -1
- package/dist/frontend/lowering/lib-boundary.js +112 -20
- package/dist/frontend/lowering/lib-boundary.js.map +1 -1
- package/dist/frontend/lowering/lib-boundary.test.d.ts +1 -0
- package/dist/frontend/lowering/lib-boundary.test.js +45 -0
- package/dist/frontend/lowering/lib-boundary.test.js.map +1 -0
- package/dist/frontend/lowering/lower-array-sort.d.ts +1 -1
- package/dist/frontend/lowering/lower-assert.d.ts +1 -1
- package/dist/frontend/lowering/lower-assert.js.map +1 -1
- package/dist/frontend/lowering/lower-async-iteration.d.ts +1 -1
- package/dist/frontend/lowering/lower-async-iteration.js.map +1 -1
- package/dist/frontend/lowering/lower-builtin-values.d.ts +18 -0
- package/dist/frontend/lowering/lower-builtin-values.js +249 -0
- package/dist/frontend/lowering/lower-builtin-values.js.map +1 -0
- package/dist/frontend/lowering/lower-builtins.d.ts +33 -46
- package/dist/frontend/lowering/lower-builtins.js +676 -365
- package/dist/frontend/lowering/lower-builtins.js.map +1 -1
- package/dist/frontend/lowering/lower-calls.d.ts +28 -22
- package/dist/frontend/lowering/lower-calls.js +1660 -412
- package/dist/frontend/lowering/lower-calls.js.map +1 -1
- package/dist/frontend/lowering/lower-classes.d.ts +95 -57
- package/dist/frontend/lowering/lower-classes.js +1491 -404
- package/dist/frontend/lowering/lower-classes.js.map +1 -1
- package/dist/frontend/lowering/lower-comptime.d.ts +1 -1
- package/dist/frontend/lowering/lower-comptime.js +23 -32
- package/dist/frontend/lowering/lower-comptime.js.map +1 -1
- package/dist/frontend/lowering/lower-containers.d.ts +36 -32
- package/dist/frontend/lowering/lower-containers.js +925 -181
- package/dist/frontend/lowering/lower-containers.js.map +1 -1
- package/dist/frontend/lowering/lower-dgram.d.ts +1 -1
- package/dist/frontend/lowering/lower-dgram.js +3 -2
- package/dist/frontend/lowering/lower-dgram.js.map +1 -1
- package/dist/frontend/lowering/lower-enums.d.ts +1 -1
- package/dist/frontend/lowering/lower-enums.js.map +1 -1
- package/dist/frontend/lowering/lower-event-emitter.d.ts +30 -1
- package/dist/frontend/lowering/lower-event-emitter.js +58 -26
- package/dist/frontend/lowering/lower-event-emitter.js.map +1 -1
- package/dist/frontend/lowering/lower-expando.d.ts +7 -1
- package/dist/frontend/lowering/lower-expando.js +14 -6
- package/dist/frontend/lowering/lower-expando.js.map +1 -1
- package/dist/frontend/lowering/lower-exprs.d.ts +37 -13
- package/dist/frontend/lowering/lower-exprs.js +2163 -863
- package/dist/frontend/lowering/lower-exprs.js.map +1 -1
- package/dist/frontend/lowering/lower-generators.d.ts +2 -5
- package/dist/frontend/lowering/lower-generators.js +88 -46
- package/dist/frontend/lowering/lower-generators.js.map +1 -1
- package/dist/frontend/lowering/lower-global-value.d.ts +7 -0
- package/dist/frontend/lowering/lower-global-value.js +17 -0
- package/dist/frontend/lowering/lower-global-value.js.map +1 -0
- package/dist/frontend/lowering/lower-inspect.d.ts +1 -1
- package/dist/frontend/lowering/lower-inspect.js +17 -8
- package/dist/frontend/lowering/lower-inspect.js.map +1 -1
- package/dist/frontend/lowering/lower-island.d.ts +7 -8
- package/dist/frontend/lowering/lower-island.js +66 -33
- package/dist/frontend/lowering/lower-island.js.map +1 -1
- package/dist/frontend/lowering/lower-mixins.d.ts +2 -2
- package/dist/frontend/lowering/lower-mixins.js +5 -3
- package/dist/frontend/lowering/lower-mixins.js.map +1 -1
- package/dist/frontend/lowering/lower-modules.d.ts +1 -1
- package/dist/frontend/lowering/lower-modules.js +445 -39
- package/dist/frontend/lowering/lower-modules.js.map +1 -1
- package/dist/frontend/lowering/lower-modules.test.d.ts +1 -0
- package/dist/frontend/lowering/lower-modules.test.js +39 -0
- package/dist/frontend/lowering/lower-modules.test.js.map +1 -0
- package/dist/frontend/lowering/lower-namespaces.d.ts +1 -1
- package/dist/frontend/lowering/lower-namespaces.js.map +1 -1
- package/dist/frontend/lowering/lower-node-module.d.ts +1 -1
- package/dist/frontend/lowering/lower-node-module.js +13 -10
- package/dist/frontend/lowering/lower-node-module.js.map +1 -1
- package/dist/frontend/lowering/lower-server.d.ts +1 -1
- package/dist/frontend/lowering/lower-server.js +6 -10
- package/dist/frontend/lowering/lower-server.js.map +1 -1
- package/dist/frontend/lowering/lower-stmts.d.ts +17 -17
- package/dist/frontend/lowering/lower-stmts.js +855 -514
- package/dist/frontend/lowering/lower-stmts.js.map +1 -1
- package/dist/frontend/lowering/lower-stream.d.ts +1 -1
- package/dist/frontend/lowering/lower-stream.js +20 -11
- package/dist/frontend/lowering/lower-stream.js.map +1 -1
- package/dist/frontend/lowering/lower-test.d.ts +1 -1
- package/dist/frontend/lowering/lower-test.js.map +1 -1
- package/dist/frontend/lowering/lower-url.d.ts +6 -0
- package/dist/frontend/lowering/lower-url.js +77 -0
- package/dist/frontend/lowering/lower-url.js.map +1 -0
- package/dist/frontend/lowering/lowerer.d.ts +140 -190
- package/dist/frontend/lowering/lowerer.js +1193 -712
- package/dist/frontend/lowering/lowerer.js.map +1 -1
- package/dist/frontend/lowering/lowerer.test.d.ts +1 -0
- package/dist/frontend/lowering/lowerer.test.js +172 -0
- package/dist/frontend/lowering/lowerer.test.js.map +1 -0
- package/dist/frontend/lowering/native-ffi.d.ts +5 -0
- package/dist/frontend/lowering/native-ffi.js +40 -0
- package/dist/frontend/lowering/native-ffi.js.map +1 -0
- package/dist/frontend/lowering/object-enumeration-receiver.d.ts +7 -0
- package/dist/frontend/lowering/object-enumeration-receiver.js +33 -0
- package/dist/frontend/lowering/object-enumeration-receiver.js.map +1 -0
- package/dist/frontend/lowering/object-factory-new.d.ts +8 -0
- package/dist/frontend/lowering/object-factory-new.js +68 -0
- package/dist/frontend/lowering/object-factory-new.js.map +1 -0
- package/dist/frontend/lowering/optional-arguments.js +6 -1
- package/dist/frontend/lowering/optional-arguments.js.map +1 -1
- package/dist/frontend/lowering/pairs-snapshot.js +2 -1
- package/dist/frontend/lowering/pairs-snapshot.js.map +1 -1
- package/dist/frontend/lowering/runtime-optional-locals.d.ts +14 -0
- package/dist/frontend/lowering/runtime-optional-locals.js +41 -0
- package/dist/frontend/lowering/runtime-optional-locals.js.map +1 -0
- package/dist/frontend/lowering/runtime-optional-locals.test.d.ts +1 -0
- package/dist/frontend/lowering/runtime-optional-locals.test.js +85 -0
- package/dist/frontend/lowering/runtime-optional-locals.test.js.map +1 -0
- package/dist/frontend/lowering/sanitize-class-types.d.ts +8 -0
- package/dist/frontend/lowering/sanitize-class-types.js +79 -0
- package/dist/frontend/lowering/sanitize-class-types.js.map +1 -0
- package/dist/frontend/lowering/sanitize-class-types.test.d.ts +1 -0
- package/dist/frontend/lowering/sanitize-class-types.test.js +60 -0
- package/dist/frontend/lowering/sanitize-class-types.test.js.map +1 -0
- package/dist/frontend/lowering/static-this.d.ts +5 -1
- package/dist/frontend/lowering/static-this.js +28 -2
- package/dist/frontend/lowering/static-this.js.map +1 -1
- package/dist/frontend/lowering/string-index.d.ts +7 -0
- package/dist/frontend/lowering/string-index.js +39 -0
- package/dist/frontend/lowering/string-index.js.map +1 -0
- package/dist/frontend/lowering/surfaces.d.ts +10 -3
- package/dist/frontend/lowering/surfaces.js +86 -37
- package/dist/frontend/lowering/surfaces.js.map +1 -1
- package/dist/frontend/lowering/symbol-fields.d.ts +22 -0
- package/dist/frontend/lowering/symbol-fields.js +183 -0
- package/dist/frontend/lowering/symbol-fields.js.map +1 -0
- package/dist/frontend/lowering/symbol-methods.d.ts +7 -0
- package/dist/frontend/lowering/symbol-methods.js +30 -0
- package/dist/frontend/lowering/symbol-methods.js.map +1 -0
- package/dist/frontend/lowering/text-decoder-encoding.d.ts +12 -0
- package/dist/frontend/lowering/text-decoder-encoding.js +82 -0
- package/dist/frontend/lowering/text-decoder-encoding.js.map +1 -0
- package/dist/frontend/lowering/text-decoder-encoding.test.d.ts +1 -0
- package/dist/frontend/lowering/text-decoder-encoding.test.js +38 -0
- package/dist/frontend/lowering/text-decoder-encoding.test.js.map +1 -0
- package/dist/frontend/lowering/union-narrow.d.ts +9 -0
- package/dist/frontend/lowering/union-narrow.js +59 -0
- package/dist/frontend/lowering/union-narrow.js.map +1 -0
- package/dist/frontend/lowering/union-narrow.test.d.ts +1 -0
- package/dist/frontend/lowering/union-narrow.test.js +72 -0
- package/dist/frontend/lowering/union-narrow.test.js.map +1 -0
- package/dist/frontend/lowering/union-retag.d.ts +43 -0
- package/dist/frontend/lowering/union-retag.js +259 -0
- package/dist/frontend/lowering/union-retag.js.map +1 -0
- package/dist/frontend/lowering/union-retag.test.d.ts +1 -0
- package/dist/frontend/lowering/union-retag.test.js +405 -0
- package/dist/frontend/lowering/union-retag.test.js.map +1 -0
- package/dist/frontend/lowering/unregistered-class-types.d.ts +14 -0
- package/dist/frontend/lowering/unregistered-class-types.js +94 -0
- package/dist/frontend/lowering/unregistered-class-types.js.map +1 -0
- package/dist/frontend/lowering/unregistered-class-types.test.d.ts +1 -0
- package/dist/frontend/lowering/unregistered-class-types.test.js +65 -0
- package/dist/frontend/lowering/unregistered-class-types.test.js.map +1 -0
- package/dist/frontend/lowering/width-lift.d.ts +40 -0
- package/dist/frontend/lowering/width-lift.js +2 -0
- package/dist/frontend/lowering/width-lift.js.map +1 -0
- package/dist/frontend/module-syntax.d.ts +58 -0
- package/dist/frontend/module-syntax.js +123 -0
- package/dist/frontend/module-syntax.js.map +1 -0
- package/dist/frontend/module-syntax.test.d.ts +1 -0
- package/dist/frontend/module-syntax.test.js +78 -0
- package/dist/frontend/module-syntax.test.js.map +1 -0
- package/dist/frontend/npm-fetch-analysis.d.ts +17 -0
- package/dist/frontend/npm-fetch-analysis.js +100 -0
- package/dist/frontend/npm-fetch-analysis.js.map +1 -0
- package/dist/frontend/npm-fetch-analysis.test.d.ts +1 -0
- package/dist/frontend/npm-fetch-analysis.test.js +107 -0
- package/dist/frontend/npm-fetch-analysis.test.js.map +1 -0
- package/dist/frontend/npm-fetch-node.d.ts +2 -0
- package/dist/frontend/npm-fetch-node.js +12 -0
- package/dist/frontend/npm-fetch-node.js.map +1 -0
- package/dist/frontend/npm-fetch-syntax.d.ts +6 -0
- package/dist/frontend/npm-fetch-syntax.js +207 -0
- package/dist/frontend/npm-fetch-syntax.js.map +1 -0
- package/dist/frontend/npm-node.d.ts +10 -0
- package/dist/frontend/npm-node.js +14 -0
- package/dist/frontend/npm-node.js.map +1 -0
- package/dist/frontend/npm-static-bundled-cjs.d.ts +8 -0
- package/dist/frontend/npm-static-bundled-cjs.js +236 -0
- package/dist/frontend/npm-static-bundled-cjs.js.map +1 -0
- package/dist/frontend/npm-static-bundled-cjs.test.d.ts +1 -0
- package/dist/frontend/npm-static-bundled-cjs.test.js +69 -0
- package/dist/frontend/npm-static-bundled-cjs.test.js.map +1 -0
- package/dist/frontend/npm-static-declaration-syntax.d.ts +57 -0
- package/dist/frontend/npm-static-declaration-syntax.js +944 -0
- package/dist/frontend/npm-static-declaration-syntax.js.map +1 -0
- package/dist/frontend/npm-static-declarations.d.ts +11 -39
- package/dist/frontend/npm-static-declarations.js +22 -561
- package/dist/frontend/npm-static-declarations.js.map +1 -1
- package/dist/frontend/npm-static-declarations.test.js +245 -6
- package/dist/frontend/npm-static-declarations.test.js.map +1 -1
- package/dist/frontend/npm-static-prune.d.ts +1 -1
- package/dist/frontend/npm-static-prune.js +121 -38
- package/dist/frontend/npm-static-prune.js.map +1 -1
- package/dist/frontend/npm-static-prune.test.js +9 -1
- package/dist/frontend/npm-static-prune.test.js.map +1 -1
- package/dist/frontend/npm-static-rewrite-host.d.ts +4 -0
- package/dist/frontend/npm-static-rewrite-host.js +179 -0
- package/dist/frontend/npm-static-rewrite-host.js.map +1 -0
- package/dist/frontend/npm-static-rewrite-syntax.d.ts +16 -0
- package/dist/frontend/npm-static-rewrite-syntax.js +905 -0
- package/dist/frontend/npm-static-rewrite-syntax.js.map +1 -0
- package/dist/frontend/npm-static-rewrite.d.ts +0 -5
- package/dist/frontend/npm-static-rewrite.js +2 -1079
- package/dist/frontend/npm-static-rewrite.js.map +1 -1
- package/dist/frontend/npm-static-subtyping.d.ts +5 -0
- package/dist/frontend/npm-static-subtyping.js +55 -0
- package/dist/frontend/npm-static-subtyping.js.map +1 -0
- package/dist/frontend/npm-static-subtyping.test.d.ts +1 -0
- package/dist/frontend/npm-static-subtyping.test.js +58 -0
- package/dist/frontend/npm-static-subtyping.test.js.map +1 -0
- package/dist/frontend/npm-static.d.ts +7 -15
- package/dist/frontend/npm-static.js +19 -28
- package/dist/frontend/npm-static.js.map +1 -1
- package/dist/frontend/npm.d.ts +8 -69
- package/dist/frontend/npm.js +21 -361
- package/dist/frontend/npm.js.map +1 -1
- package/dist/frontend/npm.test.js +2 -2
- package/dist/frontend/npm.test.js.map +1 -1
- package/dist/frontend/pipeline-native.d.ts +6 -0
- package/dist/frontend/pipeline-native.js +32 -0
- package/dist/frontend/pipeline-native.js.map +1 -0
- package/dist/frontend/pipeline.d.ts +54 -0
- package/dist/frontend/pipeline.js +382 -0
- package/dist/frontend/pipeline.js.map +1 -0
- package/dist/frontend/pipeline.test.d.ts +1 -0
- package/dist/frontend/pipeline.test.js +77 -0
- package/dist/frontend/pipeline.test.js.map +1 -0
- package/dist/frontend/program-analysis.d.ts +10 -0
- package/dist/frontend/program-analysis.js +14 -0
- package/dist/frontend/program-analysis.js.map +1 -0
- package/dist/frontend/program-node.d.ts +9 -0
- package/dist/frontend/program-node.js +48 -0
- package/dist/frontend/program-node.js.map +1 -0
- package/dist/frontend/program.d.ts +39 -20
- package/dist/frontend/program.js +393 -189
- package/dist/frontend/program.js.map +1 -1
- package/dist/frontend/program.test.js +105 -2
- package/dist/frontend/program.test.js.map +1 -1
- package/dist/frontend/provenance-core.d.ts +9 -0
- package/dist/frontend/provenance-core.js +435 -0
- package/dist/frontend/provenance-core.js.map +1 -0
- package/dist/frontend/provenance.d.ts +0 -4
- package/dist/frontend/provenance.js +4 -459
- package/dist/frontend/provenance.js.map +1 -1
- package/dist/frontend/resolve.d.ts +3 -1
- package/dist/frontend/resolve.js +6 -3
- package/dist/frontend/resolve.js.map +1 -1
- package/dist/frontend/runtime-resolve.d.ts +4 -3
- package/dist/frontend/runtime-resolve.js +22 -18
- package/dist/frontend/runtime-resolve.js.map +1 -1
- package/dist/frontend/runtime-resolve.test.js +53 -0
- package/dist/frontend/runtime-resolve.test.js.map +1 -1
- package/dist/frontend/services-node.d.ts +5 -0
- package/dist/frontend/services-node.js +19 -0
- package/dist/frontend/services-node.js.map +1 -0
- package/dist/frontend/services-node.test.d.ts +1 -0
- package/dist/frontend/services-node.test.js +70 -0
- package/dist/frontend/services-node.test.js.map +1 -0
- package/dist/frontend/services.d.ts +44 -0
- package/dist/frontend/services.js +90 -0
- package/dist/frontend/services.js.map +1 -0
- package/dist/frontend/services.test.d.ts +1 -0
- package/dist/frontend/services.test.js +174 -0
- package/dist/frontend/services.test.js.map +1 -0
- package/dist/frontend/ts7/adapter.d.ts +3 -3
- package/dist/frontend/ts7/adapter.js +14 -31
- package/dist/frontend/ts7/adapter.js.map +1 -1
- package/dist/frontend/ts7/api.d.ts +16 -0
- package/dist/frontend/ts7/api.js +24 -0
- package/dist/frontend/ts7/api.js.map +1 -0
- package/dist/frontend/ts7/ast-bytes.d.ts +31 -0
- package/dist/frontend/ts7/ast-bytes.js +137 -0
- package/dist/frontend/ts7/ast-bytes.js.map +1 -0
- package/dist/frontend/ts7/ast-bytes.test.d.ts +1 -0
- package/dist/frontend/ts7/ast-bytes.test.js +73 -0
- package/dist/frontend/ts7/ast-bytes.test.js.map +1 -0
- package/dist/frontend/ts7/ast-guards.generated.d.ts +353 -0
- package/dist/frontend/ts7/ast-guards.generated.js +1951 -0
- package/dist/frontend/ts7/ast-guards.generated.js.map +1 -0
- package/dist/frontend/ts7/ast-guards.test.d.ts +1 -0
- package/dist/frontend/ts7/ast-guards.test.js +43 -0
- package/dist/frontend/ts7/ast-guards.test.js.map +1 -0
- package/dist/frontend/ts7/ast-node.d.ts +194 -0
- package/dist/frontend/ts7/ast-node.js +448 -0
- package/dist/frontend/ts7/ast-node.js.map +1 -0
- package/dist/frontend/ts7/ast-node.test.d.ts +1 -0
- package/dist/frontend/ts7/ast-node.test.js +266 -0
- package/dist/frontend/ts7/ast-node.test.js.map +1 -0
- package/dist/frontend/ts7/ast-schema.generated.d.ts +503 -0
- package/dist/frontend/ts7/ast-schema.generated.js +1446 -0
- package/dist/frontend/ts7/ast-schema.generated.js.map +1 -0
- package/dist/frontend/ts7/ast-text.d.ts +6 -0
- package/dist/frontend/ts7/ast-text.js +124 -0
- package/dist/frontend/ts7/ast-text.js.map +1 -0
- package/dist/frontend/ts7/ast-text.test.d.ts +1 -0
- package/dist/frontend/ts7/ast-text.test.js +38 -0
- package/dist/frontend/ts7/ast-text.test.js.map +1 -0
- package/dist/frontend/ts7/ast-tokens.generated.d.ts +2 -0
- package/dist/frontend/ts7/ast-tokens.generated.js +155 -0
- package/dist/frontend/ts7/ast-tokens.generated.js.map +1 -0
- package/dist/frontend/ts7/ast-types.d.ts +42 -0
- package/dist/frontend/ts7/ast-types.generated.d.ts +1615 -0
- package/dist/frontend/ts7/ast-types.generated.js +5 -0
- package/dist/frontend/ts7/ast-types.generated.js.map +1 -0
- package/dist/frontend/ts7/ast-types.js +3 -0
- package/dist/frontend/ts7/ast-types.js.map +1 -0
- package/dist/frontend/ts7/ast-wire.d.ts +58 -0
- package/dist/frontend/ts7/ast-wire.js +267 -0
- package/dist/frontend/ts7/ast-wire.js.map +1 -0
- package/dist/frontend/ts7/ast-wire.test.d.ts +1 -0
- package/dist/frontend/ts7/ast-wire.test.js +151 -0
- package/dist/frontend/ts7/ast-wire.test.js.map +1 -0
- package/dist/frontend/ts7/ast.d.ts +14 -14
- package/dist/frontend/ts7/ast.js +25 -18
- package/dist/frontend/ts7/ast.js.map +1 -1
- package/dist/frontend/ts7/census-check.js +1 -0
- package/dist/frontend/ts7/census-check.js.map +1 -1
- package/dist/frontend/ts7/checker-cache.d.ts +48 -0
- package/dist/frontend/ts7/checker-cache.js +92 -0
- package/dist/frontend/ts7/checker-cache.js.map +1 -0
- package/dist/frontend/ts7/checker.d.ts +19 -46
- package/dist/frontend/ts7/checker.js +231 -161
- package/dist/frontend/ts7/checker.js.map +1 -1
- package/dist/frontend/ts7/checker.test.d.ts +1 -0
- package/dist/frontend/ts7/checker.test.js +335 -0
- package/dist/frontend/ts7/checker.test.js.map +1 -0
- package/dist/frontend/ts7/enums.d.ts +4 -27
- package/dist/frontend/ts7/enums.generated.d.ts +878 -0
- package/dist/frontend/ts7/enums.generated.js +1313 -0
- package/dist/frontend/ts7/enums.generated.js.map +1 -0
- package/dist/frontend/ts7/enums.js +4 -45
- package/dist/frontend/ts7/enums.js.map +1 -1
- package/dist/frontend/ts7/enums.test.d.ts +1 -0
- package/dist/frontend/ts7/enums.test.js +48 -0
- package/dist/frontend/ts7/enums.test.js.map +1 -0
- package/dist/frontend/ts7/native-api.d.ts +10 -0
- package/dist/frontend/ts7/native-api.js +10 -0
- package/dist/frontend/ts7/native-api.js.map +1 -0
- package/dist/frontend/ts7/native-host.d.ts +2 -0
- package/dist/frontend/ts7/native-host.js +11 -0
- package/dist/frontend/ts7/native-host.js.map +1 -0
- package/dist/frontend/ts7/native-process.d.ts +14 -0
- package/dist/frontend/ts7/native-process.js +62 -0
- package/dist/frontend/ts7/native-process.js.map +1 -0
- package/dist/frontend/ts7/program-adapter.d.ts +10 -98
- package/dist/frontend/ts7/program-adapter.js +16 -310
- package/dist/frontend/ts7/program-adapter.js.map +1 -1
- package/dist/frontend/ts7/program-host.d.ts +115 -0
- package/dist/frontend/ts7/program-host.js +347 -0
- package/dist/frontend/ts7/program-host.js.map +1 -0
- package/dist/frontend/ts7/program-host.test.d.ts +1 -0
- package/dist/frontend/ts7/program-host.test.js +207 -0
- package/dist/frontend/ts7/program-host.test.js.map +1 -0
- package/dist/frontend/ts7/rpc-api.d.ts +12 -0
- package/dist/frontend/ts7/rpc-api.js +23 -0
- package/dist/frontend/ts7/rpc-api.js.map +1 -0
- package/dist/frontend/ts7/rpc-client.d.ts +27 -0
- package/dist/frontend/ts7/rpc-client.js +102 -0
- package/dist/frontend/ts7/rpc-client.js.map +1 -0
- package/dist/frontend/ts7/rpc-client.test.d.ts +1 -0
- package/dist/frontend/ts7/rpc-client.test.js +133 -0
- package/dist/frontend/ts7/rpc-client.test.js.map +1 -0
- package/dist/frontend/ts7/rpc-filesystem.d.ts +16 -0
- package/dist/frontend/ts7/rpc-filesystem.js +42 -0
- package/dist/frontend/ts7/rpc-filesystem.js.map +1 -0
- package/dist/frontend/ts7/rpc-filesystem.test.d.ts +1 -0
- package/dist/frontend/ts7/rpc-filesystem.test.js +89 -0
- package/dist/frontend/ts7/rpc-filesystem.test.js.map +1 -0
- package/dist/frontend/ts7/rpc-process.d.ts +2 -0
- package/dist/frontend/ts7/rpc-process.js +148 -0
- package/dist/frontend/ts7/rpc-process.js.map +1 -0
- package/dist/frontend/ts7/rpc-process.test.d.ts +1 -0
- package/dist/frontend/ts7/rpc-process.test.js +29 -0
- package/dist/frontend/ts7/rpc-process.test.js.map +1 -0
- package/dist/frontend/ts7/rpc-wire.d.ts +46 -0
- package/dist/frontend/ts7/rpc-wire.js +195 -0
- package/dist/frontend/ts7/rpc-wire.js.map +1 -0
- package/dist/frontend/ts7/rpc-wire.test.d.ts +1 -0
- package/dist/frontend/ts7/rpc-wire.test.js +168 -0
- package/dist/frontend/ts7/rpc-wire.test.js.map +1 -0
- package/dist/frontend/ts7/semantic-checker.d.ts +137 -0
- package/dist/frontend/ts7/semantic-checker.js +221 -0
- package/dist/frontend/ts7/semantic-checker.js.map +1 -0
- package/dist/frontend/ts7/semantic-checker.test.d.ts +1 -0
- package/dist/frontend/ts7/semantic-checker.test.js +119 -0
- package/dist/frontend/ts7/semantic-checker.test.js.map +1 -0
- package/dist/frontend/ts7/semantic-json.d.ts +5 -0
- package/dist/frontend/ts7/semantic-json.js +47 -0
- package/dist/frontend/ts7/semantic-json.js.map +1 -0
- package/dist/frontend/ts7/semantic-json.test.d.ts +1 -0
- package/dist/frontend/ts7/semantic-json.test.js +42 -0
- package/dist/frontend/ts7/semantic-json.test.js.map +1 -0
- package/dist/frontend/ts7/semantic-model.d.ts +222 -0
- package/dist/frontend/ts7/semantic-model.js +423 -0
- package/dist/frontend/ts7/semantic-model.js.map +1 -0
- package/dist/frontend/ts7/semantic-model.test.d.ts +1 -0
- package/dist/frontend/ts7/semantic-model.test.js +322 -0
- package/dist/frontend/ts7/semantic-model.test.js.map +1 -0
- package/dist/frontend/ts7/semantic-schema.generated.d.ts +283 -0
- package/dist/frontend/ts7/semantic-schema.generated.js +222 -0
- package/dist/frontend/ts7/semantic-schema.generated.js.map +1 -0
- package/dist/frontend/ts7/semantic-types.d.ts +5 -0
- package/dist/frontend/ts7/semantic-types.js +2 -0
- package/dist/frontend/ts7/semantic-types.js.map +1 -0
- package/dist/frontend/ts7/session-cache.d.ts +17 -0
- package/dist/frontend/ts7/session-cache.js +97 -0
- package/dist/frontend/ts7/session-cache.js.map +1 -0
- package/dist/frontend/ts7/session-cache.test.d.ts +1 -0
- package/dist/frontend/ts7/session-cache.test.js +87 -0
- package/dist/frontend/ts7/session-cache.test.js.map +1 -0
- package/dist/frontend/ts7/session-path.d.ts +18 -0
- package/dist/frontend/ts7/session-path.js +203 -0
- package/dist/frontend/ts7/session-path.js.map +1 -0
- package/dist/frontend/ts7/session-path.test.d.ts +1 -0
- package/dist/frontend/ts7/session-path.test.js +34 -0
- package/dist/frontend/ts7/session-path.test.js.map +1 -0
- package/dist/frontend/ts7/session-schema.generated.d.ts +167 -0
- package/dist/frontend/ts7/session-schema.generated.js +5 -0
- package/dist/frontend/ts7/session-schema.generated.js.map +1 -0
- package/dist/frontend/ts7/session-timing.d.ts +50 -0
- package/dist/frontend/ts7/session-timing.js +61 -0
- package/dist/frontend/ts7/session-timing.js.map +1 -0
- package/dist/frontend/ts7/session-timing.test.d.ts +1 -0
- package/dist/frontend/ts7/session-timing.test.js +52 -0
- package/dist/frontend/ts7/session-timing.test.js.map +1 -0
- package/dist/frontend/ts7/session.d.ts +105 -0
- package/dist/frontend/ts7/session.js +233 -0
- package/dist/frontend/ts7/session.js.map +1 -0
- package/dist/frontend/ts7/session.test.d.ts +1 -0
- package/dist/frontend/ts7/session.test.js +215 -0
- package/dist/frontend/ts7/session.test.js.map +1 -0
- package/dist/frontend/ts7/source-parser-node.d.ts +6 -0
- package/dist/frontend/ts7/source-parser-node.js +15 -0
- package/dist/frontend/ts7/source-parser-node.js.map +1 -0
- package/dist/frontend/ts7/source-parser.d.ts +25 -0
- package/dist/frontend/ts7/source-parser.js +96 -0
- package/dist/frontend/ts7/source-parser.js.map +1 -0
- package/dist/frontend/ts7/source-parser.test.d.ts +1 -0
- package/dist/frontend/ts7/source-parser.test.js +151 -0
- package/dist/frontend/ts7/source-parser.test.js.map +1 -0
- package/dist/frontend/ts7/syntax.d.ts +3 -0
- package/dist/frontend/ts7/syntax.js +4 -0
- package/dist/frontend/ts7/syntax.js.map +1 -0
- package/dist/frontend/tsc-codes.js +3 -0
- package/dist/frontend/tsc-codes.js.map +1 -1
- package/dist/frontend/type-mapper.d.ts +34 -18
- package/dist/frontend/type-mapper.js +552 -131
- package/dist/frontend/type-mapper.js.map +1 -1
- package/dist/frontend/type-mapper.test.js +146 -2
- package/dist/frontend/type-mapper.test.js.map +1 -1
- package/dist/frontend/union-discriminants.d.ts +16 -0
- package/dist/frontend/union-discriminants.js +98 -0
- package/dist/frontend/union-discriminants.js.map +1 -0
- package/dist/frontend/union-discriminants.test.d.ts +1 -0
- package/dist/frontend/union-discriminants.test.js +182 -0
- package/dist/frontend/union-discriminants.test.js.map +1 -0
- package/dist/index.d.ts +7 -198
- package/dist/index.js +369 -1572
- package/dist/index.js.map +1 -1
- package/dist/ir/analysis.d.ts +16 -4
- package/dist/ir/analysis.js +23 -4
- package/dist/ir/analysis.js.map +1 -1
- package/dist/ir/analysis.test.js +15 -2
- package/dist/ir/analysis.test.js.map +1 -1
- package/dist/ir/constant-tables.js +67 -49
- package/dist/ir/constant-tables.js.map +1 -1
- package/dist/ir/constant-tables.test.js +1 -1
- package/dist/ir/control-flow.d.ts +6 -0
- package/dist/ir/control-flow.js +142 -0
- package/dist/ir/control-flow.js.map +1 -0
- package/dist/ir/control-flow.test.d.ts +1 -0
- package/dist/ir/control-flow.test.js +113 -0
- package/dist/ir/control-flow.test.js.map +1 -0
- package/dist/ir/integer-loops.js +7 -18
- package/dist/ir/integer-loops.js.map +1 -1
- package/dist/ir/integer-ranges.js +53 -27
- package/dist/ir/integer-ranges.js.map +1 -1
- package/dist/ir/ir.d.ts +334 -176
- package/dist/ir/ir.js +710 -903
- package/dist/ir/ir.js.map +1 -1
- package/dist/ir/ir.test.js +162 -1
- package/dist/ir/ir.test.js.map +1 -1
- package/dist/ir/scalar-records.js +165 -134
- package/dist/ir/scalar-records.js.map +1 -1
- package/dist/ir/scalar-records.test.js +1 -1
- package/dist/ir/serialize.d.ts +4 -2
- package/dist/ir/serialize.js +33 -14
- package/dist/ir/serialize.js.map +1 -1
- package/dist/ir/serialize.test.d.ts +1 -0
- package/dist/ir/serialize.test.js +57 -0
- package/dist/ir/serialize.test.js.map +1 -0
- package/dist/ir/traverse.d.ts +41 -0
- package/dist/ir/traverse.js +660 -0
- package/dist/ir/traverse.js.map +1 -0
- package/dist/ir/traverse.test.d.ts +1 -0
- package/dist/ir/traverse.test.js +242 -0
- package/dist/ir/traverse.test.js.map +1 -0
- package/dist/ir/validate.js +2018 -1498
- package/dist/ir/validate.js.map +1 -1
- package/dist/ir/validate.test.js +536 -2
- package/dist/ir/validate.test.js.map +1 -1
- package/dist/library/cache-primitives.d.ts +2 -3
- package/dist/library/cache-primitives.js +4 -6
- package/dist/library/cache-primitives.js.map +1 -1
- package/dist/library/fence-eval.js +2 -2
- package/dist/library/fence-eval.js.map +1 -1
- package/dist/library/int-infer.js +7 -6
- package/dist/library/int-infer.js.map +1 -1
- package/dist/library/int-infer.test.js +4 -4
- package/dist/library/library-cache.d.ts +3 -2
- package/dist/library/library-cache.js +5 -17
- package/dist/library/library-cache.js.map +1 -1
- package/dist/library/library-cache.test.js +54 -41
- package/dist/library/library-cache.test.js.map +1 -1
- package/dist/library/library-profile.d.ts +3 -1
- package/dist/library/library-profile.js +15 -6
- package/dist/library/library-profile.js.map +1 -1
- package/dist/library/prepare.d.ts +15 -0
- package/dist/library/prepare.js +584 -0
- package/dist/library/prepare.js.map +1 -0
- package/dist/library/semantic-source.d.ts +1 -1
- package/dist/library/semantic-source.js +8 -6
- package/dist/library/semantic-source.js.map +1 -1
- package/dist/library/sidecar-validate.js +4 -4
- package/dist/library/sidecar-validate.js.map +1 -1
- package/dist/library/sidecar.d.ts +2 -0
- package/dist/library/sidecar.js +10 -3
- package/dist/library/sidecar.js.map +1 -1
- package/dist/native/cache.d.ts +11 -0
- package/dist/native/cache.js +113 -0
- package/dist/native/cache.js.map +1 -0
- package/dist/native/cache.test.d.ts +1 -0
- package/dist/native/cache.test.js +66 -0
- package/dist/native/cache.test.js.map +1 -0
- package/dist/native/cli.d.ts +1 -0
- package/dist/native/cli.js +112 -0
- package/dist/native/cli.js.map +1 -0
- package/dist/native/compiler.d.ts +15 -0
- package/dist/native/compiler.js +336 -0
- package/dist/native/compiler.js.map +1 -0
- package/dist/native/compiler.test.d.ts +1 -0
- package/dist/native/compiler.test.js +174 -0
- package/dist/native/compiler.test.js.map +1 -0
- package/dist/native/comptime.d.ts +5 -0
- package/dist/native/comptime.js +73 -0
- package/dist/native/comptime.js.map +1 -0
- package/dist/native/comptime.test.d.ts +1 -0
- package/dist/native/comptime.test.js +65 -0
- package/dist/native/comptime.test.js.map +1 -0
- package/dist/native/executable-cache.d.ts +26 -0
- package/dist/native/executable-cache.js +228 -0
- package/dist/native/executable-cache.js.map +1 -0
- package/dist/native/executable-cache.test.d.ts +1 -0
- package/dist/native/executable-cache.test.js +151 -0
- package/dist/native/executable-cache.test.js.map +1 -0
- package/dist/native/file-identity.d.ts +4 -0
- package/dist/native/file-identity.js +14 -0
- package/dist/native/file-identity.js.map +1 -0
- package/dist/native/file-identity.test.d.ts +1 -0
- package/dist/native/file-identity.test.js +43 -0
- package/dist/native/file-identity.test.js.map +1 -0
- package/dist/native/library.d.ts +22 -0
- package/dist/native/library.js +83 -0
- package/dist/native/library.js.map +1 -0
- package/dist/native/prepare.d.ts +21 -0
- package/dist/native/prepare.js +174 -0
- package/dist/native/prepare.js.map +1 -0
- package/dist/native/prepare.test.d.ts +1 -0
- package/dist/native/prepare.test.js +70 -0
- package/dist/native/prepare.test.js.map +1 -0
- package/dist/native/sanitizer.d.ts +11 -0
- package/dist/native/sanitizer.js +137 -0
- package/dist/native/sanitizer.js.map +1 -0
- package/dist/native/sanitizer.test.d.ts +1 -0
- package/dist/native/sanitizer.test.js +58 -0
- package/dist/native/sanitizer.test.js.map +1 -0
- package/dist/native/task.d.ts +4 -0
- package/dist/native/task.js +16 -0
- package/dist/native/task.js.map +1 -0
- package/dist/native/task.test.d.ts +1 -0
- package/dist/native/task.test.js +17 -0
- package/dist/native/task.test.js.map +1 -0
- package/dist/native/toolchain.d.ts +45 -0
- package/dist/native/toolchain.js +94 -0
- package/dist/native/toolchain.js.map +1 -0
- package/dist/native/toolchain.test.d.ts +1 -0
- package/dist/native/toolchain.test.js +85 -0
- package/dist/native/toolchain.test.js.map +1 -0
- package/dist/startup-cache.d.ts +1 -1
- package/dist/startup-cache.js +2 -5
- package/dist/startup-cache.js.map +1 -1
- package/dist/timing.d.ts +4 -0
- package/dist/timing.js +19 -0
- package/dist/timing.js.map +1 -0
- package/dist/wasi-paths.js +10 -7
- package/dist/wasi-paths.js.map +1 -1
- package/package.json +28 -19
- package/surface-manifest.json +107 -98
- package/dist/backend/c/async.d.ts +0 -171
- package/dist/backend/c/async.js +0 -1317
- package/dist/backend/c/async.js.map +0 -1
- package/dist/backend/c/c-emitter.d.ts +0 -536
- package/dist/backend/c/c-emitter.js +0 -1932
- package/dist/backend/c/c-emitter.js.map +0 -1
- package/dist/backend/c/exprs.d.ts +0 -15
- package/dist/backend/c/exprs.js +0 -8847
- package/dist/backend/c/exprs.js.map +0 -1
- package/dist/backend/c/island.d.ts +0 -45
- package/dist/backend/c/island.js +0 -281
- package/dist/backend/c/island.js.map +0 -1
- package/dist/backend/c/may-throw.js.map +0 -1
- package/dist/backend/c/shapes.d.ts +0 -142
- package/dist/backend/c/shapes.js +0 -603
- package/dist/backend/c/shapes.js.map +0 -1
- package/dist/backend/c/stmts.d.ts +0 -76
- package/dist/backend/c/stmts.js +0 -1108
- package/dist/backend/c/stmts.js.map +0 -1
- package/dist/backend/c/types.d.ts +0 -71
- package/dist/backend/c/types.js +0 -459
- package/dist/backend/c/types.js.map +0 -1
- package/dist/backend/c/types.test.js +0 -32
- package/dist/backend/c/types.test.js.map +0 -1
- package/dist/backend/c/walkers.d.ts +0 -134
- package/dist/backend/c/walkers.js +0 -1772
- package/dist/backend/c/walkers.js.map +0 -1
- /package/dist/backend/{c/types.test.d.ts → cycle-analysis.test.d.ts} +0 -0
|
@@ -1,1772 +0,0 @@
|
|
|
1
|
-
import { InternalCompilerError } from "../../errors.js";
|
|
2
|
-
import { DYN_HANDLE_KINDS, isDynTypedRefType, isRefCounted, typeEquals, typeKey } from "../../ir/ir.js";
|
|
3
|
-
import { dynDesc, undefinedArmTag } from "../../ir/analysis.js";
|
|
4
|
-
import { cCommentText, cDecl, cStringLiteral, cType, elemAccess, releaseCallC, retainCallC, vAdapters } from "./types.js";
|
|
5
|
-
import { mangleField, mangleRecordNew, mangleRecordStruct } from "../mangle.js";
|
|
6
|
-
import { jsonObjectKeyLabel } from "../json-literal.js";
|
|
7
|
-
import { OVERFLOW_MEMBER } from "./shapes.js";
|
|
8
|
-
/** The per-union ToBoolean helper (interned per unionId): switch on the
|
|
9
|
-
* runtime tag — unit arms false, f64 arms 0/NaN-falsy, string arms
|
|
10
|
-
* empty-falsy, bool arms by payload, ref arms always true (JS objects),
|
|
11
|
-
* jsval arms answered by the engine. Borrows the operand. */
|
|
12
|
-
export function unionTruthyHelper(emitter, unionId) {
|
|
13
|
-
const existing = emitter.unionTruthyFns.get(unionId);
|
|
14
|
-
if (existing)
|
|
15
|
-
return existing;
|
|
16
|
-
const def = emitter.unionsById.get(unionId);
|
|
17
|
-
if (!def)
|
|
18
|
-
throw new InternalCompilerError(`emitter bug: truthiness of unknown union ${unionId}`);
|
|
19
|
-
const name = `sc_ut_${emitter.unionTruthyFns.size}`;
|
|
20
|
-
emitter.unionTruthyFns.set(unionId, name);
|
|
21
|
-
const sig = `static bool ${name}(ScrUnion *v)`;
|
|
22
|
-
emitter.walkerProtos.push(`${sig}; /* ToBoolean ${unionId} */`);
|
|
23
|
-
const d = [`${sig} { /* ToBoolean ${unionId} */`, ` switch (v->tag) {`];
|
|
24
|
-
def.arms.forEach((arm, i) => {
|
|
25
|
-
switch (arm.kind) {
|
|
26
|
-
case "undefinedT":
|
|
27
|
-
case "nullT":
|
|
28
|
-
d.push(` case ${i}: return false;`);
|
|
29
|
-
break;
|
|
30
|
-
case "f64":
|
|
31
|
-
d.push(` case ${i}: { double x = scr_union_get_f64(v); return x == x && x != 0; }`);
|
|
32
|
-
break;
|
|
33
|
-
case "bool":
|
|
34
|
-
d.push(` case ${i}: return scr_union_get_bool(v);`);
|
|
35
|
-
break;
|
|
36
|
-
case "string":
|
|
37
|
-
d.push(` case ${i}: return ((ScrStr *)scr_union_peek(v))->len != 0;`);
|
|
38
|
-
break;
|
|
39
|
-
case "bigint":
|
|
40
|
-
d.push(` case ${i}: return scr_bigint_truthy((ScrBigInt *)scr_union_peek(v));`);
|
|
41
|
-
break;
|
|
42
|
-
case "jsval":
|
|
43
|
-
d.push(` case ${i}: return scr_jsval_truthy((ScrJsval *)scr_union_peek(v)) != 0;`);
|
|
44
|
-
break;
|
|
45
|
-
default:
|
|
46
|
-
// Arrays, maps, sets, records, objects, functions, promises,
|
|
47
|
-
// regexes, ...: JS objects are always truthy — [] and {} included.
|
|
48
|
-
d.push(` case ${i}: return true; /* ${arm.kind} */`);
|
|
49
|
-
}
|
|
50
|
-
});
|
|
51
|
-
d.push(` default: scr_trap("scriptc: internal error: invalid union tag\\n");`, ` }`, `}`, ``);
|
|
52
|
-
emitter.walkerDefs.push(...d);
|
|
53
|
-
return name;
|
|
54
|
-
}
|
|
55
|
-
/** The per-union strict-equality helper (interned per unionId, with a
|
|
56
|
-
* separate SameValue variant per unionId when Object.is reaches it):
|
|
57
|
-
* different tags are never equal; equal tags compare the arm values —
|
|
58
|
-
* unit arms equal, f64 with C == (NaN !== NaN, +0 === -0) or SameValue
|
|
59
|
-
* (NaN equals NaN, +0 differs from -0) under the sameValue flag,
|
|
60
|
-
* strings by bytes, bools by value, ref arms by POINTER identity (JS
|
|
61
|
-
* object equality). Borrows both operands. */
|
|
62
|
-
export function unionEqHelper(emitter, unionId, sameValue) {
|
|
63
|
-
const key = sameValue ? `sv:${unionId}` : unionId;
|
|
64
|
-
const existing = emitter.unionEqFns.get(key);
|
|
65
|
-
if (existing)
|
|
66
|
-
return existing;
|
|
67
|
-
const def = emitter.unionsById.get(unionId);
|
|
68
|
-
if (!def)
|
|
69
|
-
throw new InternalCompilerError(`emitter bug: equality of unknown union ${unionId}`);
|
|
70
|
-
const name = `sc_ue_${emitter.unionEqFns.size}`;
|
|
71
|
-
emitter.unionEqFns.set(key, name);
|
|
72
|
-
const what = sameValue ? "SameValue" : "strict equality";
|
|
73
|
-
const sig = `static bool ${name}(ScrUnion *a, ScrUnion *b)`;
|
|
74
|
-
emitter.walkerProtos.push(`${sig}; /* ${what} ${unionId} */`);
|
|
75
|
-
const d = [
|
|
76
|
-
`${sig} { /* ${what} ${unionId} */`,
|
|
77
|
-
` if (a->tag != b->tag) return false;`,
|
|
78
|
-
` switch (a->tag) {`,
|
|
79
|
-
];
|
|
80
|
-
def.arms.forEach((arm, i) => {
|
|
81
|
-
switch (arm.kind) {
|
|
82
|
-
case "undefinedT":
|
|
83
|
-
case "nullT":
|
|
84
|
-
d.push(` case ${i}: return true;`);
|
|
85
|
-
break;
|
|
86
|
-
case "f64":
|
|
87
|
-
d.push(sameValue
|
|
88
|
-
? ` case ${i}: return scr_num_same_value(scr_union_get_f64(a), scr_union_get_f64(b));`
|
|
89
|
-
: ` case ${i}: return scr_union_get_f64(a) == scr_union_get_f64(b);`);
|
|
90
|
-
break;
|
|
91
|
-
case "bool":
|
|
92
|
-
d.push(` case ${i}: return scr_union_get_bool(a) == scr_union_get_bool(b);`);
|
|
93
|
-
break;
|
|
94
|
-
case "string":
|
|
95
|
-
d.push(` case ${i}: return scr_str_eq((ScrStr *)scr_union_peek(a), (ScrStr *)scr_union_peek(b));`);
|
|
96
|
-
break;
|
|
97
|
-
case "bigint":
|
|
98
|
-
d.push(` case ${i}: return scr_bigint_eq((ScrBigInt *)scr_union_peek(a), (ScrBigInt *)scr_union_peek(b));`);
|
|
99
|
-
break;
|
|
100
|
-
default:
|
|
101
|
-
// Ref arms: pointer identity, exactly JS object equality.
|
|
102
|
-
d.push(` case ${i}: return scr_union_peek(a) == scr_union_peek(b); /* ${arm.kind} */`);
|
|
103
|
-
}
|
|
104
|
-
});
|
|
105
|
-
d.push(` default: scr_trap("scriptc: internal error: invalid union tag\\n");`, ` }`, `}`, ``);
|
|
106
|
-
emitter.walkerDefs.push(...d);
|
|
107
|
-
return name;
|
|
108
|
-
}
|
|
109
|
-
/** The per-union ToString helper (interned per unionId): switch on the
|
|
110
|
-
* runtime tag — unit arms return the interned "undefined"/"null" texts,
|
|
111
|
-
* string arms retain the payload, f64/bool arms go through the JS-exact
|
|
112
|
-
* formatters (String(x) semantics). Ref arms never arrive (the frontend
|
|
113
|
-
* fences unions with object arms from string conversion — JS would print
|
|
114
|
-
* "[object Object]"). Borrows the operand; the result is owned (+1). */
|
|
115
|
-
export function unionToStrHelper(emitter, unionId) {
|
|
116
|
-
const existing = emitter.unionToStrFns.get(unionId);
|
|
117
|
-
if (existing)
|
|
118
|
-
return existing;
|
|
119
|
-
const def = emitter.unionsById.get(unionId);
|
|
120
|
-
if (!def)
|
|
121
|
-
throw new InternalCompilerError(`emitter bug: ToString of unknown union ${unionId}`);
|
|
122
|
-
const name = `sc_us_${emitter.unionToStrFns.size}`;
|
|
123
|
-
emitter.unionToStrFns.set(unionId, name);
|
|
124
|
-
const sig = `static ScrStr *${name}(ScrUnion *v)`;
|
|
125
|
-
emitter.walkerProtos.push(`${sig}; /* ToString ${unionId} */`);
|
|
126
|
-
const d = [`${sig} { /* ToString ${unionId} */`, ` switch (v->tag) {`];
|
|
127
|
-
def.arms.forEach((arm, i) => {
|
|
128
|
-
switch (arm.kind) {
|
|
129
|
-
case "undefinedT":
|
|
130
|
-
case "nullT": {
|
|
131
|
-
const lit = emitter.internLiteral(arm.kind === "undefinedT" ? "undefined" : "null");
|
|
132
|
-
d.push(` case ${i}: return scr_str_retain((ScrStr *)&${lit});`);
|
|
133
|
-
break;
|
|
134
|
-
}
|
|
135
|
-
case "string":
|
|
136
|
-
d.push(` case ${i}: return scr_str_retain((ScrStr *)scr_union_peek(v));`);
|
|
137
|
-
break;
|
|
138
|
-
case "f64":
|
|
139
|
-
d.push(` case ${i}: return scr_f64_to_scrstr(scr_union_get_f64(v));`);
|
|
140
|
-
break;
|
|
141
|
-
case "bool":
|
|
142
|
-
d.push(` case ${i}: return scr_bool_to_scrstr(scr_union_get_bool(v));`);
|
|
143
|
-
break;
|
|
144
|
-
case "bigint":
|
|
145
|
-
d.push(` case ${i}: return scr_bigint_to_string((ScrBigInt *)scr_union_peek(v), 10);`);
|
|
146
|
-
break;
|
|
147
|
-
case "bytes": {
|
|
148
|
-
// Buffer.toString() IS the utf8 decode (Node's default
|
|
149
|
-
// encoding) — the `Buffer | string` chunk idiom.
|
|
150
|
-
const enc = emitter.internLiteral("utf8");
|
|
151
|
-
d.push(` case ${i}: return scr_bytes_to_str((ScrBytes *)scr_union_peek(v), (ScrStr *)&${enc});`);
|
|
152
|
-
break;
|
|
153
|
-
}
|
|
154
|
-
default:
|
|
155
|
-
throw new InternalCompilerError(`emitter bug: ToString of union with a ${arm.kind} arm (frontend fences these)`);
|
|
156
|
-
}
|
|
157
|
-
});
|
|
158
|
-
d.push(` default: scr_trap("scriptc: internal error: invalid union tag\\n");`, ` }`, `}`, ``);
|
|
159
|
-
emitter.walkerDefs.push(...d);
|
|
160
|
-
return name;
|
|
161
|
-
}
|
|
162
|
-
/** The per-union array-join helper (interned per unionId): Array.prototype
|
|
163
|
-
* .join over union elements — undefined/null arms print EMPTY (exactly
|
|
164
|
-
* JS's join, which silences only the nullish elements), every other arm
|
|
165
|
-
* goes through the per-union ToString walker (string arms verbatim,
|
|
166
|
-
* f64/bool via the JS-exact formatters). The frontend admits only unions
|
|
167
|
-
* of f64/string/bool/unit arms here. Borrows the array and separator;
|
|
168
|
-
* the result is owned (+1). */
|
|
169
|
-
export function unionJoinHelper(emitter, unionId) {
|
|
170
|
-
const existing = emitter.unionJoinFns.get(unionId);
|
|
171
|
-
if (existing)
|
|
172
|
-
return existing;
|
|
173
|
-
const def = emitter.unionsById.get(unionId);
|
|
174
|
-
if (!def)
|
|
175
|
-
throw new InternalCompilerError(`emitter bug: join of unknown union ${unionId}`);
|
|
176
|
-
const name = `sc_uj_${emitter.unionJoinFns.size}`;
|
|
177
|
-
emitter.unionJoinFns.set(unionId, name);
|
|
178
|
-
const toStr = unionToStrHelper(emitter, unionId);
|
|
179
|
-
const unitTags = def.arms.flatMap((a, i) => a.kind === "undefinedT" || a.kind === "nullT" ? [i] : []);
|
|
180
|
-
const sig = `static ScrStr *${name}(ScrArr *a, ScrStr *sep)`;
|
|
181
|
-
emitter.walkerProtos.push(`${sig}; /* join ${unionId} */`);
|
|
182
|
-
emitter.walkerDefs.push(`${sig} { /* Array#join over ${unionId}: nullish arms print empty */`, ` ScrJsonBuf b;`, ` scr_jb_init(&b);`, ` size_t n = (size_t)scr_arr_len(a);`, ` for (size_t i = 0; i < n; i++) {`, ` if (i) for (size_t j = 0; j < sep->len; j++) scr_jb_putc(&b, sep->data[j]);`, ` /* Holes and payload-free present undefined both stringify empty. */`, ` if (scr_arr_state(a, (double)i) != SCR_ARR_VALUE) continue;`, ` ScrUnion *u = (ScrUnion *)scr_arr_get_ref(a, (double)i);`, ...(unitTags.length > 0
|
|
183
|
-
? [` if (${unitTags.map((t) => `u->tag == ${t}`).join(" || ")}) { scr_union_release(u); continue; }`]
|
|
184
|
-
: []), ` ScrStr *s = ${toStr}(u);`, ` for (size_t j = 0; j < s->len; j++) scr_jb_putc(&b, s->data[j]);`, ` scr_str_release(s);`, ` scr_union_release(u);`, ` }`, ` return scr_jb_finish(&b);`, `}`, ``);
|
|
185
|
-
return name;
|
|
186
|
-
}
|
|
187
|
-
/** The dyn ToString helper pair (interned once, type-independent):
|
|
188
|
-
* Node's String() over a dyn value — "undefined"/"null" texts, bools,
|
|
189
|
-
* JS-exact number formatting (NaN/Infinity spelled out — NOT the JSON
|
|
190
|
-
* null), strings verbatim, arrays via Array.prototype.toString (join
|
|
191
|
-
* with ","; null/undefined ELEMENTS print empty, nested arrays flatten
|
|
192
|
-
* through the recursion — JS-exact), plain objects as
|
|
193
|
-
* "[object Object]". The operand is borrowed; the result is owned (+1). */
|
|
194
|
-
export function dynToStrHelper(emitter) {
|
|
195
|
-
if (emitter.dynToStrFn)
|
|
196
|
-
return emitter.dynToStrFn;
|
|
197
|
-
const name = "sc_ds";
|
|
198
|
-
emitter.dynToStrFn = name;
|
|
199
|
-
emitter.walkerProtos.push(`static void ${name}_buf(ScrJsonBuf *b, const ScrDyn *d); /* String(unknown) walker */`, `static ScrStr *${name}(const ScrDyn *d); /* String(unknown) */`);
|
|
200
|
-
emitter.walkerDefs.push(`static void ${name}_buf(ScrJsonBuf *b, const ScrDyn *d) { /* String(unknown), recursive */`, ` switch (d->kind) {`, ` case SCR_DYN_UNDEF: scr_jb_puts(b, "undefined"); break;`, ` case SCR_DYN_NULL: scr_jb_puts(b, "null"); break;`, ` case SCR_DYN_BOOL: scr_jb_puts(b, d->v.b ? "true" : "false"); break;`, ` case SCR_DYN_NUM: {`, ` ScrStr *s = scr_f64_to_scrstr(d->v.num); /* String(n): NaN/Infinity spelled out, not JSON null */`, ` for (size_t i = 0; i < s->len; i++) scr_jb_putc(b, s->data[i]);`, ` scr_str_release(s);`, ` break;`, ` }`, ` case SCR_DYN_STR:`, ` for (size_t i = 0; i < d->v.str->len; i++) scr_jb_putc(b, d->v.str->data[i]);`, ` break;`, ` case SCR_DYN_ARR:`, ` /* Array.prototype.toString: join(",") — null/undefined ELEMENTS`, ` * print empty (unlike top level), nested arrays flatten. */`, ` for (size_t i = 0; i < d->v.arr.len; i++) {`, ` if (i > 0) scr_jb_putc(b, ',');`, ` const ScrDyn *e = d->v.arr.items[i];`, ` if (e->kind == SCR_DYN_UNDEF || e->kind == SCR_DYN_NULL) continue;`, ` ${name}_buf(b, e);`, ` }`, ` break;`, ` case SCR_DYN_OBJ:`, ` if (scr_dyn_obj_get(d, "%error", 6)) {`, ` /* The checked-dynamic tree's error encoding (caughtToDyn): Error.prototype`, ` * .toString over the encoded name/message — Node's String(err),`, ` * which carries no stack either. */`, ` const ScrDyn *en = scr_dyn_obj_get(d, "name", 4);`, ` const ScrDyn *em = scr_dyn_obj_get(d, "message", 7);`, ` const ScrStr *ens = (en && en->kind == SCR_DYN_STR) ? en->v.str : NULL;`, ` const ScrStr *ems = (em && em->kind == SCR_DYN_STR) ? em->v.str : NULL;`, ` if (ens) for (size_t i = 0; i < ens->len; i++) scr_jb_putc(b, ens->data[i]);`, ` if (ens && ens->len && ems && ems->len) scr_jb_puts(b, ": ");`, ` if (ems) for (size_t i = 0; i < ems->len; i++) scr_jb_putc(b, ems->data[i]);`, ` break;`, ` }`, ` scr_jb_puts(b, "[object Object]");`, ` break;`, ` case SCR_DYN_BYTES: {`, ` /* Buffer-flavored values (stream chunks) coerce utf8 (Node's`, ` * Buffer.toString); plain Uint8Array joins its elements. */`, ` if (d->buffer) {`, ` ScrStr *enc = scr_str_new("utf8", 4);`, ` ScrStr *txt = scr_bytes_to_str(d->v.bytes, enc);`, ` scr_str_release(enc);`, ` for (size_t i = 0; i < txt->len; i++) scr_jb_putc(b, txt->data[i]);`, ` scr_str_release(txt);`, ` break;`, ` }`, ` for (size_t i = 0; i < d->v.bytes->len; i++) {`, ` if (i > 0) scr_jb_putc(b, ',');`, ` char n[16];`, ` snprintf(n, sizeof n, "%u", (unsigned)d->v.bytes->data[i]);`, ` scr_jb_puts(b, n);`, ` }`, ` break;`, ` }`, ` case SCR_DYN_FUNC:`, ` /* Function.prototype.toString: the SOURCE is gone in a compiled`, ` * program, so the native-code form — exactly what JS engines`, ` * print for their own non-JS functions. */`, ` scr_jb_puts(b, "function ");`, ` if (d->v.fn.name) scr_jb_puts(b, d->v.fn.name);`, ` scr_jb_puts(b, "() { [native code] }");`, ` break;`, ` case SCR_DYN_HANDLE:`, ` /* Object.prototype.toString — Node's String() over these`, ` * classes (IncomingMessage/ServerResponse/Socket). */`, ` scr_jb_puts(b, "[object Object]");`, ` break;`, ` case SCR_DYN_PROMISE:`, ` /* Object.prototype.toString with the Promise @@toStringTag. */`, ` scr_jb_puts(b, "[object Promise]");`, ` break;`, ` case SCR_DYN_JSVAL:`, ` /* Island-held: the engine's own ToString (a bridged failure`, ` * leaves the exception pending and appends nothing). */`, ` scr_dyn_isl_tostr_buf(b, d);`, ` break;`, ` case SCR_DYN_TYPED_REF: {`, ` ScrDyn *sc_materialized = scr_dyn_typed_ref_materialize(d);`, ` ${name}_buf(b, sc_materialized);`, ` scr_dyn_release(sc_materialized);`, ` break;`, ` }`, ` }`, `}`, `static ScrStr *${name}(const ScrDyn *d) { /* String(unknown) -> owned (+1) */`, ` if (d->kind == SCR_DYN_STR) return scr_str_retain(d->v.str);`, ` ScrJsonBuf b;`, ` scr_jb_init(&b);`, ` ${name}_buf(&b, d);`, ` return scr_jb_finish(&b);`, `}`, ``);
|
|
201
|
-
return name;
|
|
202
|
-
}
|
|
203
|
-
/** The caught→dyn converter (interned once, type-independent): a catch
|
|
204
|
-
* binding flowing into an `unknown` slot — the typed→unknown deep-copy
|
|
205
|
-
* stance over the exception snapshot's runtime kind. Scalar payloads
|
|
206
|
-
* convert exactly; an Error-family OBJ payload becomes the checked-dynamic tree's error
|
|
207
|
-
* encoding — the reserved "%error" marker plus name/message (and code
|
|
208
|
-
* when stamped), so `instanceof Error`, the %Error extraction, and
|
|
209
|
-
* String() answer like Node; every other payload (REF — records, arrays,
|
|
210
|
-
* closures, unions — and non-Error hierarchy objects, type-erased at
|
|
211
|
-
* runtime) becomes an EMPTY dyn object (SEMANTICS.md 67). Borrows the
|
|
212
|
-
* snapshot; the result is a fresh tree (+1). Never throws. */
|
|
213
|
-
export function caughtToDynHelper(emitter) {
|
|
214
|
-
if (emitter.caughtToDynFn)
|
|
215
|
-
return emitter.caughtToDynFn;
|
|
216
|
-
const name = "sc_cd";
|
|
217
|
-
emitter.caughtToDynFn = name;
|
|
218
|
-
const sig = `static ScrDyn *${name}(const ScrCaught *c)`;
|
|
219
|
-
emitter.walkerProtos.push(`${sig}; /* caught -> unknown */`);
|
|
220
|
-
emitter.walkerDefs.push(`${sig} { /* caught -> unknown (+1, fresh tree) */`, ` switch (c->kind) {`, ` case SCR_EXC_F64: return scr_dyn_new_num(c->f64);`, ` case SCR_EXC_BOOL: return scr_dyn_new_bool(c->b);`, ` case SCR_EXC_STR: return scr_dyn_new_str((ScrStr *)c->payload); /* _new_str retains */`, ` case SCR_EXC_OBJ:`, ` if (scr_error_is(c->payload)) {`, ` /* The identity-cached crossing (scr_json.c): the SAME error`, ` * instance boxes to ONE dyn node however it crosses, so a`, ` * caught dyn compares reference-equal to the thrown error's`, ` * other boxings, like Node. */`, ` return scr_dyn_from_error((const ScrError *)c->payload);`, ` }`, ` /* FALLTHROUGH: a non-Error hierarchy object is type-erased */`, ` case SCR_EXC_REF:`, ` case SCR_EXC_PRIMITIVE_REF:`, ` /* A thrown dyn value passes back BY REFERENCE (identity with`, ` * every other holder of the node — the traced-throw shape). */`, ` if (c->retain_fn == scr_dyn_retain_v) return scr_dyn_retain((ScrDyn *)c->payload);`, ` /* FALLTHROUGH */`, ` default:`, ` /* non-dyn REF and non-Error objects: the "[object Object]"`, ` * approximation — truthy, typeof "object", fields unreadable. */`, ` return scr_dyn_new_obj();`, ` }`, `}`, ``);
|
|
221
|
-
return name;
|
|
222
|
-
}
|
|
223
|
-
/** The pretty-print re-indenter (interned once, type-independent):
|
|
224
|
-
* `JSON.stringify(v, null, space)` output as a REWRITE of the compact
|
|
225
|
-
* serializer text — Node's gap algorithm exactly. Structural '{'/'[' open
|
|
226
|
-
* a newline + one-deeper indent (unless immediately closed: `{}` and `[]`
|
|
227
|
-
* stay inline, like Node), '}'/']' close onto their own line at the outer
|
|
228
|
-
* depth, ',' breaks the line at the current depth, and the key ':' gains
|
|
229
|
-
* one space. String state (with escape skipping) keeps literal braces,
|
|
230
|
-
* commas, and colons inside JSON strings untouched. Compact input is
|
|
231
|
-
* BORROWED; the result is a fresh string (+1). An empty indent (space 0,
|
|
232
|
-
* "", null) never reaches here — the frontend drops the property. */
|
|
233
|
-
export function jsonIndentHelper(emitter) {
|
|
234
|
-
if (emitter.jsonIndentFn)
|
|
235
|
-
return emitter.jsonIndentFn;
|
|
236
|
-
const name = "sc_ji";
|
|
237
|
-
emitter.jsonIndentFn = name;
|
|
238
|
-
const sig = `static ScrStr *${name}(ScrStr *compact, const char *indent, size_t ilen)`;
|
|
239
|
-
emitter.walkerProtos.push(`${sig}; /* stringify space re-indent */`);
|
|
240
|
-
emitter.walkerDefs.push(`${sig} { /* stringify space re-indent (Node's gap algorithm) */`, ` ScrJsonBuf b;`, ` scr_jb_init(&b);`, ` const char *s = compact->data;`, ` size_t n = compact->len;`, ` size_t depth = 0;`, ` bool instr = false;`, `#define SCR_JI_INDENT() do { \\`, ` scr_jb_putc(&b, '\\n'); \\`, ` for (size_t td = 0; td < depth; td++) \\`, ` for (size_t tk = 0; tk < ilen; tk++) scr_jb_putc(&b, indent[tk]); \\`, ` } while (0)`, ` for (size_t i = 0; i < n; i++) {`, ` char c = s[i];`, ` if (instr) {`, ` scr_jb_putc(&b, c);`, ` if (c == '\\\\' && i + 1 < n) { scr_jb_putc(&b, s[++i]); }`, ` else if (c == '"') instr = false;`, ` continue;`, ` }`, ` switch (c) {`, ` case '"': instr = true; scr_jb_putc(&b, c); break;`, ` case '{': case '[':`, ` scr_jb_putc(&b, c);`, ` if (i + 1 < n && s[i + 1] == (c == '{' ? '}' : ']')) {`, ` scr_jb_putc(&b, s[++i]); /* empty {} / [] stay inline, like Node */`, ` break;`, ` }`, ` depth++;`, ` SCR_JI_INDENT();`, ` break;`, ` case '}': case ']':`, ` depth--;`, ` SCR_JI_INDENT();`, ` scr_jb_putc(&b, c);`, ` break;`, ` case ',':`, ` scr_jb_putc(&b, ',');`, ` SCR_JI_INDENT();`, ` break;`, ` case ':':`, ` scr_jb_putc(&b, ':');`, ` scr_jb_putc(&b, ' ');`, ` break;`, ` default:`, ` scr_jb_putc(&b, c);`, ` }`, ` }`, `#undef SCR_JI_INDENT`, ` return scr_jb_finish(&b);`, `}`, ``);
|
|
241
|
-
return name;
|
|
242
|
-
}
|
|
243
|
-
export function jsonWriteHelper(emitter, t) {
|
|
244
|
-
const key = typeKey(t);
|
|
245
|
-
const existing = emitter.jsonWriters.get(key);
|
|
246
|
-
if (existing)
|
|
247
|
-
return existing;
|
|
248
|
-
const name = `sc_jw_${emitter.jsonWriters.size}`;
|
|
249
|
-
emitter.jsonWriters.set(key, name);
|
|
250
|
-
const sig = `static void ${name}(ScrJsonBuf *b, ${cDecl(t, "v")})`;
|
|
251
|
-
emitter.walkerProtos.push(`${sig}; /* stringify ${key} */`);
|
|
252
|
-
const d = [`${sig} { /* stringify ${key} */`];
|
|
253
|
-
switch (t.kind) {
|
|
254
|
-
case "f64":
|
|
255
|
-
d.push(` scr_jb_put_f64(b, v); /* NaN/Infinity -> null, -0 -> 0, like JS */`);
|
|
256
|
-
break;
|
|
257
|
-
case "bool":
|
|
258
|
-
d.push(` scr_jb_puts(b, v ? "true" : "false");`);
|
|
259
|
-
break;
|
|
260
|
-
case "string":
|
|
261
|
-
d.push(` scr_jb_put_json_str(b, v);`);
|
|
262
|
-
break;
|
|
263
|
-
case "record": {
|
|
264
|
-
const shape = emitter.recordsById.get(t.shapeId);
|
|
265
|
-
if (!shape)
|
|
266
|
-
throw new InternalCompilerError(`emitter bug: jsonStringify of unknown shape ${t.shapeId}`);
|
|
267
|
-
// CYCLE-CAPABLE shapes (recursive record types — the collector-
|
|
268
|
-
// fixpoint set) bracket the walk with the circular-detection
|
|
269
|
-
// stack: a value already being serialized above throws V8's exact
|
|
270
|
-
// circular-structure TypeError (scr_jb_enter). Edge labels stamp
|
|
271
|
-
// only before members whose walk can re-enter (cycle-capable
|
|
272
|
-
// types); acyclic shapes pay nothing.
|
|
273
|
-
const cyclic = emitter.traceAdapterC(t) !== null;
|
|
274
|
-
const edgeable = (ft) => cyclic && emitter.traceAdapterC(ft) !== null;
|
|
275
|
-
if (cyclic)
|
|
276
|
-
d.push(` if (!scr_jb_enter(b, v, ${shape.tuple ? "true" : "false"})) return; /* circular: pending TypeError */`);
|
|
277
|
-
// A tuple serializes as a JSON ARRAY in index order — JS-exact
|
|
278
|
-
// (JSON.stringify(["a", 1]) is `["a",1]`). Every position is
|
|
279
|
-
// required, so labels/commas are static like all-required records.
|
|
280
|
-
if (shape.tuple) {
|
|
281
|
-
const byIndex = [...shape.fields].sort((a, b) => Number(a.name) - Number(b.name));
|
|
282
|
-
d.push(` scr_jb_putc(b, '[');`);
|
|
283
|
-
byIndex.forEach((f, i) => {
|
|
284
|
-
if (i > 0)
|
|
285
|
-
d.push(` scr_jb_putc(b, ',');`);
|
|
286
|
-
if (edgeable(f.type))
|
|
287
|
-
d.push(` scr_jb_edge_idx(b, ${i});`);
|
|
288
|
-
d.push(` ${emitter.jsonWriteHelper(f.type)}(b, v->${mangleField(f.name)});`);
|
|
289
|
-
});
|
|
290
|
-
d.push(` scr_jb_putc(b, ']');`);
|
|
291
|
-
if (cyclic)
|
|
292
|
-
d.push(` scr_jb_leave(b);`);
|
|
293
|
-
break;
|
|
294
|
-
}
|
|
295
|
-
// Fields serialize in DECLARED order — JS insertion order, exactly
|
|
296
|
-
// Node for objects constructed in declaration order (SEMANTICS.md
|
|
297
|
-
// 36 documents the divergence when they are not) — never the
|
|
298
|
-
// canonical (sorted) struct order. declaredOrder may omit internal
|
|
299
|
-
// '%'-fields (Dirent's %dtype): those are hidden from JSON exactly
|
|
300
|
-
// like every other key-order surface. Shapes interned WITHOUT an
|
|
301
|
-
// order (the CJS export-table literal, accessor-narrowed JS
|
|
302
|
-
// shapes) keep the canonical order — their construction paths
|
|
303
|
-
// document the divergence.
|
|
304
|
-
const order = shape.declaredOrder ?? shape.fields.map((f) => f.name);
|
|
305
|
-
const inOrder = new Set(order);
|
|
306
|
-
if (shape.fields.some((f) => !inOrder.has(f.name) && !f.name.startsWith("%"))) {
|
|
307
|
-
throw new InternalCompilerError(`emitter bug: declaredOrder of shape ${t.shapeId} omits a non-internal field`);
|
|
308
|
-
}
|
|
309
|
-
const byName = new Map(shape.fields.map((f) => [f.name, f]));
|
|
310
|
-
const emitFields = order.map((n) => byName.get(n)).filter((f) => f !== undefined);
|
|
311
|
-
// Optional-flavored fields (undefined-armed unions) DROP from the
|
|
312
|
-
// output while they hold the undefined arm — exactly Node — so as
|
|
313
|
-
// soon as one exists, comma placement turns dynamic (a `first`
|
|
314
|
-
// flag); all-required shapes keep the static prefix labels. An
|
|
315
|
-
// overflow portion forces the dynamic path too (entry count is
|
|
316
|
-
// runtime state).
|
|
317
|
-
const droppable = emitFields.some((f) => undefinedArmTag(f.type, emitter.unionsById) >= 0) || !!shape.indexValue;
|
|
318
|
-
d.push(` scr_jb_putc(b, '{');`);
|
|
319
|
-
if (!droppable) {
|
|
320
|
-
emitFields.forEach((f, i) => {
|
|
321
|
-
const label = cStringLiteral(Buffer.from(`${i > 0 ? "," : ""}${jsonObjectKeyLabel(f.name)}`, "utf8"));
|
|
322
|
-
d.push(` scr_jb_puts(b, ${label});`);
|
|
323
|
-
if (edgeable(f.type))
|
|
324
|
-
d.push(` scr_jb_edge_prop(b, ${cStringLiteral(Buffer.from(f.name, "utf8"))});`);
|
|
325
|
-
// Refcounted fields are BORROWED straight off the struct (the
|
|
326
|
-
// record itself is borrowed for the whole call).
|
|
327
|
-
d.push(` ${emitter.jsonWriteHelper(f.type)}(b, v->${mangleField(f.name)});`);
|
|
328
|
-
});
|
|
329
|
-
}
|
|
330
|
-
else {
|
|
331
|
-
d.push(` bool first = true;`);
|
|
332
|
-
for (const f of emitFields) {
|
|
333
|
-
const label = cStringLiteral(Buffer.from(jsonObjectKeyLabel(f.name), "utf8"));
|
|
334
|
-
const utag = undefinedArmTag(f.type, emitter.unionsById);
|
|
335
|
-
const pad = utag >= 0 ? " " : " ";
|
|
336
|
-
if (utag >= 0) {
|
|
337
|
-
d.push(` if (v->${mangleField(f.name)}->tag != ${utag}) { /* undefined-valued field: dropped, like Node */`);
|
|
338
|
-
}
|
|
339
|
-
d.push(`${pad}if (!first) scr_jb_putc(b, ',');`);
|
|
340
|
-
d.push(`${pad}first = false;`);
|
|
341
|
-
d.push(`${pad}scr_jb_puts(b, ${label});`);
|
|
342
|
-
if (edgeable(f.type))
|
|
343
|
-
d.push(`${pad}scr_jb_edge_prop(b, ${cStringLiteral(Buffer.from(f.name, "utf8"))});`);
|
|
344
|
-
d.push(`${pad}${emitter.jsonWriteHelper(f.type)}(b, v->${mangleField(f.name)});`);
|
|
345
|
-
if (utag >= 0)
|
|
346
|
-
d.push(` }`);
|
|
347
|
-
}
|
|
348
|
-
// Overflow entries follow the declared fields, themselves in JS
|
|
349
|
-
// OWN-KEY order — integer-like keys ascending first, then the
|
|
350
|
-
// rest in insertion order (scr_map_keys_js_order, the same
|
|
351
|
-
// enumeration Object.keys answers; number-keyed signatures make
|
|
352
|
-
// integer-like overflow keys ordinary). SEMANTICS.md documents
|
|
353
|
-
// the declared-canonical-then-overflow divergence from JS's one
|
|
354
|
-
// interleaved key order. Keys escape like any JSON string;
|
|
355
|
-
// undefined-valued entries drop, exactly the optional-field rule.
|
|
356
|
-
if (shape.indexValue) {
|
|
357
|
-
const iv = shape.indexValue;
|
|
358
|
-
const m = `v->${OVERFLOW_MEMBER}`;
|
|
359
|
-
d.push(` {`);
|
|
360
|
-
d.push(` ScrArr *ks = scr_map_keys_js_order(${m});`);
|
|
361
|
-
d.push(` for (size_t i = 0; i < ks->len; i++) {`);
|
|
362
|
-
d.push(` ScrStr *k = (ScrStr *)scr_arr_get_ref(ks, (double)i);`);
|
|
363
|
-
if (iv.kind === "f64" || iv.kind === "bool") {
|
|
364
|
-
d.push(` ${cDecl(iv, "e")} = 0;`);
|
|
365
|
-
d.push(` scr_map_get_str_${iv.kind === "f64" ? "f64" : "bool"}(${m}, k, &e);`);
|
|
366
|
-
}
|
|
367
|
-
else {
|
|
368
|
-
d.push(` ${cDecl(iv, "e")} = (${cType(iv).trim()})scr_map_get_str_ref(${m}, k);`);
|
|
369
|
-
}
|
|
370
|
-
const skipUndef = iv.kind === "dyn"
|
|
371
|
-
? `e->kind == SCR_DYN_UNDEF`
|
|
372
|
-
: undefinedArmTag(iv, emitter.unionsById) >= 0
|
|
373
|
-
? `e->tag == ${undefinedArmTag(iv, emitter.unionsById)}`
|
|
374
|
-
: null;
|
|
375
|
-
if (skipUndef) {
|
|
376
|
-
d.push(` if (${skipUndef}) { /* undefined-valued entry: dropped, like Node */`);
|
|
377
|
-
d.push(` ${releaseCallC(iv, "e")};`);
|
|
378
|
-
d.push(` scr_str_release(k);`);
|
|
379
|
-
d.push(` continue;`);
|
|
380
|
-
d.push(` }`);
|
|
381
|
-
}
|
|
382
|
-
d.push(` if (!first) scr_jb_putc(b, ',');`);
|
|
383
|
-
d.push(` first = false;`);
|
|
384
|
-
d.push(` scr_jb_put_json_str(b, k);`);
|
|
385
|
-
d.push(` scr_jb_putc(b, ':');`);
|
|
386
|
-
if (edgeable(iv))
|
|
387
|
-
d.push(` scr_jb_edge_key(b, k);`);
|
|
388
|
-
d.push(` ${emitter.jsonWriteHelper(iv)}(b, e);`);
|
|
389
|
-
d.push(` scr_str_release(k);`);
|
|
390
|
-
if (isRefCounted(iv))
|
|
391
|
-
d.push(` ${releaseCallC(iv, "e")};`);
|
|
392
|
-
d.push(` }`);
|
|
393
|
-
d.push(` scr_arr_release(ks);`);
|
|
394
|
-
d.push(` }`);
|
|
395
|
-
}
|
|
396
|
-
}
|
|
397
|
-
d.push(` scr_jb_putc(b, '}');`);
|
|
398
|
-
if (cyclic)
|
|
399
|
-
d.push(` scr_jb_leave(b);`);
|
|
400
|
-
break;
|
|
401
|
-
}
|
|
402
|
-
case "dyn":
|
|
403
|
-
// Overflow values under an `unknown` index signature: the checked-dynamic tree
|
|
404
|
-
// serializes itself (runtime walker) — object members holding
|
|
405
|
-
// undefined drop, array slots holding undefined print null,
|
|
406
|
-
// exactly Node. Bare JSON.stringify of dyn stays frontend-fenced;
|
|
407
|
-
// this writer is reachable only through overflow entries.
|
|
408
|
-
d.push(` scr_jb_put_dyn(b, v);`);
|
|
409
|
-
break;
|
|
410
|
-
case "array": {
|
|
411
|
-
const elem = t.elem;
|
|
412
|
-
const w = emitter.jsonWriteHelper(elem);
|
|
413
|
-
// A cycle-capable array (elements can point back at it) joins the
|
|
414
|
-
// circular-detection stack exactly like a cycle-capable record.
|
|
415
|
-
const cyclic = emitter.traceAdapterC(t) !== null;
|
|
416
|
-
if (cyclic)
|
|
417
|
-
d.push(` if (!scr_jb_enter(b, v, true)) return; /* circular: pending TypeError */`);
|
|
418
|
-
d.push(` scr_jb_putc(b, '[');`);
|
|
419
|
-
d.push(` for (size_t i = 0; i < v->len; i++) {`);
|
|
420
|
-
d.push(` if (i > 0) scr_jb_putc(b, ',');`);
|
|
421
|
-
d.push(` if (scr_arr_state(v, (double)i) != SCR_ARR_VALUE) { scr_jb_puts(b, "null"); continue; }`);
|
|
422
|
-
if (cyclic)
|
|
423
|
-
d.push(` scr_jb_edge_idx(b, i);`);
|
|
424
|
-
if (elem.kind === "f64") {
|
|
425
|
-
d.push(` ${w}(b, scr_arr_get_f64(v, (double)i));`);
|
|
426
|
-
}
|
|
427
|
-
else if (elem.kind === "bool") {
|
|
428
|
-
d.push(` ${w}(b, scr_arr_get_bool(v, (double)i));`);
|
|
429
|
-
}
|
|
430
|
-
else {
|
|
431
|
-
// _get_ref returns +1; release after writing.
|
|
432
|
-
d.push(` ${cDecl(elem, "e")} = (${cType(elem).trim()})scr_arr_get_ref(v, (double)i);`);
|
|
433
|
-
d.push(` ${w}(b, e);`);
|
|
434
|
-
d.push(` ${releaseCallC(elem, "e")};`);
|
|
435
|
-
}
|
|
436
|
-
d.push(` }`);
|
|
437
|
-
d.push(` scr_jb_putc(b, ']');`);
|
|
438
|
-
if (cyclic)
|
|
439
|
-
d.push(` scr_jb_leave(b);`);
|
|
440
|
-
break;
|
|
441
|
-
}
|
|
442
|
-
case "union": {
|
|
443
|
-
const def = emitter.unionsById.get(t.unionId);
|
|
444
|
-
if (!def)
|
|
445
|
-
throw new InternalCompilerError(`emitter bug: jsonStringify of unknown union ${t.unionId}`);
|
|
446
|
-
d.push(` switch (v->tag) {`);
|
|
447
|
-
def.arms.forEach((arm, i) => {
|
|
448
|
-
if (arm.kind === "nullT") {
|
|
449
|
-
// Payload-less arm: JSON.stringify(null) is the text `null`,
|
|
450
|
-
// exactly like Node.
|
|
451
|
-
d.push(` case ${i}: scr_jb_puts(b, "null"); break;`);
|
|
452
|
-
return;
|
|
453
|
-
}
|
|
454
|
-
if (arm.kind === "undefinedT") {
|
|
455
|
-
// Array and tuple slots stringify undefined as null. Ordinary
|
|
456
|
-
// record fields drop the key before invoking this writer.
|
|
457
|
-
d.push(` case ${i}: scr_jb_puts(b, "null"); break;`);
|
|
458
|
-
return;
|
|
459
|
-
}
|
|
460
|
-
const w = emitter.jsonWriteHelper(arm);
|
|
461
|
-
if (arm.kind === "f64") {
|
|
462
|
-
d.push(` case ${i}: ${w}(b, scr_union_get_f64(v)); break;`);
|
|
463
|
-
}
|
|
464
|
-
else if (arm.kind === "bool") {
|
|
465
|
-
d.push(` case ${i}: ${w}(b, scr_union_get_bool(v)); break;`);
|
|
466
|
-
}
|
|
467
|
-
else {
|
|
468
|
-
// Payload is BORROWED out of the box for the write.
|
|
469
|
-
d.push(` case ${i}: ${w}(b, (${cType(arm).trim()})scr_union_peek(v)); break;`);
|
|
470
|
-
}
|
|
471
|
-
});
|
|
472
|
-
d.push(` default: scr_trap("scriptc: internal error: invalid union tag\\n");`);
|
|
473
|
-
d.push(` }`);
|
|
474
|
-
break;
|
|
475
|
-
}
|
|
476
|
-
default:
|
|
477
|
-
throw new InternalCompilerError(`emitter bug: jsonStringify of non-JSON type ${t.kind}`);
|
|
478
|
-
}
|
|
479
|
-
d.push(`}`, ``);
|
|
480
|
-
emitter.walkerDefs.push(...d);
|
|
481
|
-
return name;
|
|
482
|
-
}
|
|
483
|
-
/** The emitted match predicate for one dynCheck target type:
|
|
484
|
-
* `static bool sc_dm_<n>(const ScrDyn *d)` — does this dyn fit T?
|
|
485
|
-
* Never throws, builds nothing; union builders use it to try arms in
|
|
486
|
-
* canonical order (first FULL match wins). Records are width-tolerant
|
|
487
|
-
* here too: extra keys are ignored, only declared fields are examined. */
|
|
488
|
-
export function dynMatchHelper(emitter, t) {
|
|
489
|
-
const key = typeKey(t);
|
|
490
|
-
const existing = emitter.dynMatchers.get(key);
|
|
491
|
-
if (existing)
|
|
492
|
-
return existing;
|
|
493
|
-
const name = `sc_dm_${emitter.dynMatchers.size}`;
|
|
494
|
-
emitter.dynMatchers.set(key, name);
|
|
495
|
-
const sig = `static bool ${name}(const ScrDyn *d)`;
|
|
496
|
-
emitter.walkerProtos.push(`${sig}; /* matches ${key} */`);
|
|
497
|
-
const d = [`${sig} { /* matches ${key} */`];
|
|
498
|
-
if (isRefCounted(t) && t.kind !== "dyn") {
|
|
499
|
-
const keyLit = cStringLiteral(Buffer.from(key, "utf8"));
|
|
500
|
-
d.push(` if (scr_dyn_typed_ref_is(d, ${keyLit}, ${Buffer.byteLength(key, "utf8")})) return true;`);
|
|
501
|
-
}
|
|
502
|
-
if (t.kind !== "dyn") {
|
|
503
|
-
d.push(` if (d && d->kind == SCR_DYN_TYPED_REF) {`, ` ScrDyn *sc_materialized = scr_dyn_typed_ref_materialize(d);`, ` bool sc_out = ${name}(sc_materialized);`, ` scr_dyn_release(sc_materialized);`, ` return sc_out;`, ` }`);
|
|
504
|
-
}
|
|
505
|
-
switch (t.kind) {
|
|
506
|
-
case "f64":
|
|
507
|
-
d.push(` return d->kind == SCR_DYN_NUM;`);
|
|
508
|
-
break;
|
|
509
|
-
case "string":
|
|
510
|
-
d.push(` return d->kind == SCR_DYN_STR;`);
|
|
511
|
-
break;
|
|
512
|
-
case "bool":
|
|
513
|
-
d.push(` return d->kind == SCR_DYN_BOOL;`);
|
|
514
|
-
break;
|
|
515
|
-
case "nullT":
|
|
516
|
-
// JSON null matches exactly the nullT arm (reachable only as a
|
|
517
|
-
// union-arm matcher — bare null is not a valid dynCheck target).
|
|
518
|
-
d.push(` return d->kind == SCR_DYN_NULL;`);
|
|
519
|
-
break;
|
|
520
|
-
case "undefinedT":
|
|
521
|
-
// JSON text never parses to undefined, but the checked-dynamic tree can HOLD it now
|
|
522
|
-
// (overflow reads/conversions under `unknown` index signatures):
|
|
523
|
-
// the undefined dyn value matches exactly the undefined arm.
|
|
524
|
-
d.push(` return d->kind == SCR_DYN_UNDEF;`);
|
|
525
|
-
break;
|
|
526
|
-
case "dyn":
|
|
527
|
-
// An `unknown` target: every dyn value fits, undefined included.
|
|
528
|
-
d.push(` (void)d;`);
|
|
529
|
-
d.push(` return true;`);
|
|
530
|
-
break;
|
|
531
|
-
case "bytes":
|
|
532
|
-
// A Uint8Array target (the checked-dynamic tree carries u8 payloads only).
|
|
533
|
-
if (t.elem !== "u8")
|
|
534
|
-
throw new InternalCompilerError(`emitter bug: dynMatch of bytes<${t.elem}>`);
|
|
535
|
-
d.push(` return d->kind == SCR_DYN_BYTES;`);
|
|
536
|
-
break;
|
|
537
|
-
case "func":
|
|
538
|
-
d.push(` return d->kind == SCR_DYN_FUNC;`);
|
|
539
|
-
break;
|
|
540
|
-
case "object":
|
|
541
|
-
if (t.className === "%Error") {
|
|
542
|
-
d.push(` return d->kind == SCR_DYN_OBJ && scr_dyn_obj_get(d, "%error", 6) != NULL;`);
|
|
543
|
-
}
|
|
544
|
-
else {
|
|
545
|
-
// Non-error classes match only the exact typed-reference fast
|
|
546
|
-
// path above. A plain object (including JSON input) must never
|
|
547
|
-
// acquire a class identity structurally.
|
|
548
|
-
d.push(` (void)d; return false;`);
|
|
549
|
-
}
|
|
550
|
-
break;
|
|
551
|
-
case "record": {
|
|
552
|
-
const shape = emitter.recordsById.get(t.shapeId);
|
|
553
|
-
if (!shape)
|
|
554
|
-
throw new InternalCompilerError(`emitter bug: dynCheck of unknown shape ${t.shapeId}`);
|
|
555
|
-
// A tuple matches a JSON ARRAY of EXACTLY its arity whose elements
|
|
556
|
-
// match positionally (arity is part of the type — width tolerance
|
|
557
|
-
// is an object-key concept and does not apply).
|
|
558
|
-
if (shape.tuple) {
|
|
559
|
-
const byIndex = [...shape.fields].sort((a, b) => Number(a.name) - Number(b.name));
|
|
560
|
-
d.push(` if (d->kind != SCR_DYN_ARR || d->v.arr.len != ${byIndex.length}) return false;`);
|
|
561
|
-
byIndex.forEach((f, i) => {
|
|
562
|
-
d.push(` if (!${emitter.dynMatchHelper(f.type)}(d->v.arr.items[${i}])) return false;`);
|
|
563
|
-
});
|
|
564
|
-
d.push(` return true;`);
|
|
565
|
-
break;
|
|
566
|
-
}
|
|
567
|
-
d.push(` if (d->kind != SCR_DYN_OBJ) return false;`);
|
|
568
|
-
// dyn ('unknown') fields match ANY value, present or missing (a
|
|
569
|
-
// missing key builds the undefined dyn value) — no test to emit.
|
|
570
|
-
if (shape.fields.some((f) => f.type.kind !== "dyn"))
|
|
571
|
-
d.push(` const ScrDyn *m;`);
|
|
572
|
-
for (const f of shape.fields) {
|
|
573
|
-
if (f.type.kind === "dyn")
|
|
574
|
-
continue;
|
|
575
|
-
const keyLit = cStringLiteral(Buffer.from(f.name, "utf8"));
|
|
576
|
-
const keyLen = Buffer.byteLength(f.name, "utf8");
|
|
577
|
-
d.push(` m = scr_dyn_obj_get(d, ${keyLit}, ${keyLen});`);
|
|
578
|
-
if (undefinedArmTag(f.type, emitter.unionsById) >= 0) {
|
|
579
|
-
// Optional-flavored field: a MISSING key is the undefined arm
|
|
580
|
-
// (a match); a PRESENT key must fit the union as usual.
|
|
581
|
-
d.push(` if (m && !${emitter.dynMatchHelper(f.type)}(m)) return false;`);
|
|
582
|
-
}
|
|
583
|
-
else {
|
|
584
|
-
d.push(` if (!m || !${emitter.dynMatchHelper(f.type)}(m)) return false;`);
|
|
585
|
-
}
|
|
586
|
-
}
|
|
587
|
-
// Index-signature shapes: UNDECLARED keys must fit the overflow
|
|
588
|
-
// value type (the builder CAPTURES them — width tolerance became
|
|
589
|
-
// width capture). A dyn value type accepts anything; concrete
|
|
590
|
-
// types check every extra entry.
|
|
591
|
-
if (shape.indexValue && shape.indexValue.kind !== "dyn") {
|
|
592
|
-
const skip = shape.fields
|
|
593
|
-
.map((f) => {
|
|
594
|
-
const keyLit = cStringLiteral(Buffer.from(f.name, "utf8"));
|
|
595
|
-
const keyLen = Buffer.byteLength(f.name, "utf8");
|
|
596
|
-
return `(e->key_len == ${keyLen} && memcmp(e->key, ${keyLit}, ${keyLen}) == 0)`;
|
|
597
|
-
})
|
|
598
|
-
.join(" || ");
|
|
599
|
-
d.push(` for (size_t i = 0; i < d->v.obj.len; i++) {`);
|
|
600
|
-
d.push(` const ScrDynEntry *e = &d->v.obj.entries[i];`);
|
|
601
|
-
if (shape.fields.length > 0)
|
|
602
|
-
d.push(` if (${skip}) continue;`);
|
|
603
|
-
d.push(` if (!${emitter.dynMatchHelper(shape.indexValue)}(e->value)) return false;`);
|
|
604
|
-
d.push(` }`);
|
|
605
|
-
}
|
|
606
|
-
d.push(` return true;`);
|
|
607
|
-
break;
|
|
608
|
-
}
|
|
609
|
-
case "array": {
|
|
610
|
-
const m = emitter.dynMatchHelper(t.elem);
|
|
611
|
-
d.push(` if (d->kind != SCR_DYN_ARR) return false;`);
|
|
612
|
-
d.push(` for (size_t i = 0; i < d->v.arr.len; i++) {`);
|
|
613
|
-
d.push(` if (!${m}(d->v.arr.items[i])) return false;`);
|
|
614
|
-
d.push(` }`);
|
|
615
|
-
d.push(` return true;`);
|
|
616
|
-
break;
|
|
617
|
-
}
|
|
618
|
-
case "union": {
|
|
619
|
-
const def = emitter.unionsById.get(t.unionId);
|
|
620
|
-
if (!def)
|
|
621
|
-
throw new InternalCompilerError(`emitter bug: dynCheck of unknown union ${t.unionId}`);
|
|
622
|
-
// The undefined arm participates: parsed JSON never contains
|
|
623
|
-
// undefined (a MISSING record key was the arm's only source), but
|
|
624
|
-
// the checked-dynamic tree can hold the undefined value now — overflow entries
|
|
625
|
-
// under `unknown` index signatures — and it matches exactly the
|
|
626
|
-
// undefined arm.
|
|
627
|
-
const arms = def.arms.map((a) => `${emitter.dynMatchHelper(a)}(d)`);
|
|
628
|
-
d.push(` return ${arms.join(" || ")};`);
|
|
629
|
-
break;
|
|
630
|
-
}
|
|
631
|
-
default: {
|
|
632
|
-
const h = DYN_HANDLE_KINDS.get(t.kind);
|
|
633
|
-
if (h) {
|
|
634
|
-
d.push(` return d->kind == SCR_DYN_HANDLE && d->v.handle.tag == ${h.tag};`);
|
|
635
|
-
break;
|
|
636
|
-
}
|
|
637
|
-
throw new InternalCompilerError(`emitter bug: dynMatch of non-JSON type ${t.kind}`);
|
|
638
|
-
}
|
|
639
|
-
}
|
|
640
|
-
d.push(`}`, ``);
|
|
641
|
-
emitter.walkerDefs.push(...d);
|
|
642
|
-
return name;
|
|
643
|
-
}
|
|
644
|
-
/** The emitted keyed read on a dyn value:
|
|
645
|
-
* `static ScrDyn *sc_dyn_key_get(ScrDyn *d, ScrStr *k, bool opt)` —
|
|
646
|
-
* OBJ answers the member (+1) or the undefined singleton (own-property
|
|
647
|
-
* answer); ARR answers `length` and canonical in-range indices, STR
|
|
648
|
-
* answers `length` (UTF-16-exact via scr_str_utf16_len), both
|
|
649
|
-
* undefined otherwise; NUM/BOOL/BYTES answer undefined. undefined/null
|
|
650
|
-
* receivers THROW the catchable Node-shaped TypeError, or answer the
|
|
651
|
-
* undefined singleton when `opt` is set (a `?.` step). Borrows d and k;
|
|
652
|
-
* the result is +1. Interned once (the memo key can never collide with
|
|
653
|
-
* a typeKey — no IR type spells "%"). */
|
|
654
|
-
/** RequireObjectCoercible with V8's destructuring TypeError (the
|
|
655
|
-
* dynDestrCheck node): nullish throws "Cannot destructure 'SPELL' as it
|
|
656
|
-
* is undefined." (or "…null."), the property form "Cannot destructure
|
|
657
|
-
* property 'PROP' of 'SPELL' …" when firstProp is non-NULL — V8's exact
|
|
658
|
-
* strings, source spelling included. Non-nullish values pass silently. */
|
|
659
|
-
export function dynDestrCheckHelper(emitter) {
|
|
660
|
-
const memoKey = "%dynDestrCheck";
|
|
661
|
-
const existing = emitter.dynBuilders.get(memoKey);
|
|
662
|
-
if (existing)
|
|
663
|
-
return existing;
|
|
664
|
-
const name = "sc_dyn_destr_check";
|
|
665
|
-
emitter.dynBuilders.set(memoKey, name);
|
|
666
|
-
const sig = `static void ${name}(const ScrDyn *d, const char *spell, const char *firstProp)`;
|
|
667
|
-
emitter.walkerProtos.push(`${sig}; /* destructuring RequireObjectCoercible */`);
|
|
668
|
-
emitter.walkerDefs.push(`${sig} { /* destructuring RequireObjectCoercible */`, ` if (d->kind != SCR_DYN_UNDEF && d->kind != SCR_DYN_NULL) return;`, ` ScrJsonBuf b;`, ` scr_jb_init(&b);`, ` if (firstProp) {`, ` scr_jb_puts(&b, "Cannot destructure property '");`, ` scr_jb_puts(&b, firstProp);`, ` scr_jb_puts(&b, "' of '");`, ` scr_jb_puts(&b, spell);`, ` scr_jb_puts(&b, "' as it is ");`, ` } else {`, ` scr_jb_puts(&b, "Cannot destructure '");`, ` scr_jb_puts(&b, spell);`, ` scr_jb_puts(&b, "' as it is ");`, ` }`, ` scr_jb_puts(&b, d->kind == SCR_DYN_UNDEF ? "undefined." : "null.");`, ` scr_throw_error(SCR_ERR_TYPE, scr_jb_finish(&b));`, `}`, ``);
|
|
669
|
-
return name;
|
|
670
|
-
}
|
|
671
|
-
/** GetIterator + first-N steps over a dyn value (the dynIterN node), as
|
|
672
|
-
* array destructuring sees it: arrays step by index, strings by CODE
|
|
673
|
-
* POINT (the string iterator — astral chars arrive unsplit), Buffers by
|
|
674
|
-
* byte; everything else throws V8's exact not-iterable TypeError
|
|
675
|
-
* ("undefined is not iterable …", "object null is not iterable …",
|
|
676
|
-
* "number 1 is not iterable …", "boolean true …", "object …",
|
|
677
|
-
* "function …" — each with the "(cannot read property
|
|
678
|
-
* Symbol(Symbol.iterator))" tail). Returns a fresh +1 dyn array of
|
|
679
|
-
* exactly n elements, undefined-padded past the end. */
|
|
680
|
-
export function dynIterNHelper(emitter) {
|
|
681
|
-
const memoKey = "%dynIterN";
|
|
682
|
-
const existing = emitter.dynBuilders.get(memoKey);
|
|
683
|
-
if (existing)
|
|
684
|
-
return existing;
|
|
685
|
-
const name = "sc_dyn_iter_n";
|
|
686
|
-
emitter.dynBuilders.set(memoKey, name);
|
|
687
|
-
const sig = `static ScrDyn *${name}(const ScrDyn *d, size_t n)`;
|
|
688
|
-
emitter.walkerProtos.push(`${sig}; /* destructuring GetIterator + N steps */`);
|
|
689
|
-
emitter.walkerDefs.push(`${sig} { /* destructuring GetIterator + N steps */`, ` if (d->kind == SCR_DYN_TYPED_REF) {`, ` ScrDyn *sc_materialized = scr_dyn_typed_ref_materialize(d);`, ` ScrDyn *sc_out = ${name}(sc_materialized, n);`, ` scr_dyn_release(sc_materialized);`, ` return sc_out;`, ` }`, ` if (d->kind == SCR_DYN_JSVAL) {`, ` /* An engine array IS iterable — the not-iterable TypeError below`, ` * would be a wrong claim. Loud fence (lane dyn-routing-ops). */`, ` scr_dyn_isl_fence(d, "iteration");`, ` return NULL;`, ` }`, ` if (d->kind != SCR_DYN_ARR && d->kind != SCR_DYN_STR && d->kind != SCR_DYN_BYTES) {`, ` ScrJsonBuf b;`, ` scr_jb_init(&b);`, ` switch (d->kind) {`, ` case SCR_DYN_UNDEF: scr_jb_puts(&b, "undefined"); break;`, ` case SCR_DYN_NULL: scr_jb_puts(&b, "object null"); break;`, ` case SCR_DYN_BOOL: scr_jb_puts(&b, d->v.b ? "boolean true" : "boolean false"); break;`, ` case SCR_DYN_NUM: {`, ` scr_jb_puts(&b, "number ");`, ` ScrStr *s = scr_f64_to_scrstr(d->v.num);`, ` for (size_t i = 0; i < s->len; i++) scr_jb_putc(&b, s->data[i]);`, ` scr_str_release(s);`, ` break;`, ` }`, ` case SCR_DYN_FUNC: scr_jb_puts(&b, "function"); break;`, ` default: scr_jb_puts(&b, "object"); break;`, ` }`, ` scr_jb_puts(&b, " is not iterable (cannot read property Symbol(Symbol.iterator))");`, ` scr_throw_error(SCR_ERR_TYPE, scr_jb_finish(&b));`, ` return NULL;`, ` }`, ` ScrDyn *out = scr_dyn_new_arr();`, ` for (size_t i = 0; i < n; i++) {`, ` ScrDyn *item = NULL;`, ` if (d->kind == SCR_DYN_ARR) {`, ` item = i < d->v.arr.len ? scr_dyn_retain(d->v.arr.items[i]) : scr_dyn_retain(scr_dyn_undefined());`, ` } else if (d->kind == SCR_DYN_BYTES) {`, ` item = i < d->v.bytes->len ? scr_dyn_new_num((double)d->v.bytes->data[i]) : scr_dyn_retain(scr_dyn_undefined());`, ` } else {`, ` /* String iteration: whole code POINTS (astral chars arrive`, ` * unsplit — the string iterator, not charAt). */`, ` double len = scr_str_utf16_len(d->v.str);`, ` double at = 0;`, ` for (size_t step = 0; step < i && at < len; step++) {`, ` ScrStr *cp = scr_str_cp_at(d->v.str, at);`, ` at += scr_str_utf16_len(cp);`, ` scr_str_release(cp);`, ` }`, ` if (at < len) {`, ` ScrStr *cp = scr_str_cp_at(d->v.str, at);`, ` item = scr_dyn_new_str(cp);`, ` scr_str_release(cp);`, ` } else {`, ` item = scr_dyn_retain(scr_dyn_undefined());`, ` }`, ` }`, ` scr_dyn_arr_push(out, item); /* push takes ownership */`, ` }`, ` return out;`, `}`, ``);
|
|
690
|
-
return name;
|
|
691
|
-
}
|
|
692
|
-
export function dynKeyGetHelper(emitter) {
|
|
693
|
-
const memoKey = "%dynKeyGet";
|
|
694
|
-
const existing = emitter.dynBuilders.get(memoKey);
|
|
695
|
-
if (existing)
|
|
696
|
-
return existing;
|
|
697
|
-
const name = "sc_dyn_key_get";
|
|
698
|
-
emitter.dynBuilders.set(memoKey, name);
|
|
699
|
-
const sig = `static ScrDyn *${name}(ScrDyn *d, ScrStr *k, bool opt)`;
|
|
700
|
-
emitter.walkerProtos.push(`${sig}; /* d[k] on dyn */`);
|
|
701
|
-
const d = [`${sig} { /* d[k] on dyn */`];
|
|
702
|
-
d.push(` if (d->kind == SCR_DYN_UNDEF || d->kind == SCR_DYN_NULL) {`);
|
|
703
|
-
d.push(` if (opt) return scr_dyn_retain(scr_dyn_undefined());`);
|
|
704
|
-
d.push(` const char *base = d->kind == SCR_DYN_UNDEF`);
|
|
705
|
-
d.push(` ? "Cannot read properties of undefined (reading '"`);
|
|
706
|
-
d.push(` : "Cannot read properties of null (reading '";`);
|
|
707
|
-
d.push(` ScrStr *head = scr_str_new(base, strlen(base));`);
|
|
708
|
-
d.push(` ScrStr *withKey = scr_str_concat(head, k);`);
|
|
709
|
-
d.push(` scr_str_release(head);`);
|
|
710
|
-
d.push(` ScrStr *tail = scr_str_new("')", 2);`);
|
|
711
|
-
d.push(` ScrStr *msg = scr_str_concat(withKey, tail);`);
|
|
712
|
-
d.push(` scr_str_release(withKey);`);
|
|
713
|
-
d.push(` scr_str_release(tail);`);
|
|
714
|
-
d.push(` scr_throw_error(SCR_ERR_TYPE, msg); /* takes ownership */`);
|
|
715
|
-
d.push(` return NULL;`);
|
|
716
|
-
d.push(` }`);
|
|
717
|
-
d.push(` if (d->kind == SCR_DYN_TYPED_REF) {`);
|
|
718
|
-
d.push(` ScrDyn *sc_materialized = scr_dyn_typed_ref_materialize(d);`);
|
|
719
|
-
d.push(` ScrDyn *sc_out = ${name}(sc_materialized, k, opt);`);
|
|
720
|
-
d.push(` scr_dyn_release(sc_materialized);`);
|
|
721
|
-
d.push(` return sc_out;`);
|
|
722
|
-
d.push(` }`);
|
|
723
|
-
d.push(` if (d->kind == SCR_DYN_OBJ) {`);
|
|
724
|
-
d.push(` return scr_dyn_obj_read(d, k->data, k->len);`);
|
|
725
|
-
d.push(` }`);
|
|
726
|
-
d.push(` if (d->kind == SCR_DYN_JSVAL) {`);
|
|
727
|
-
d.push(` /* Island-held: o[k] reads the REAL engine property (getters`);
|
|
728
|
-
d.push(` * included, throws bridged catchably) and the result wraps`);
|
|
729
|
-
d.push(` * back scalar-normalized — the routed keyed read that retired`);
|
|
730
|
-
d.push(` * the fence (and before it, the fence box's .length -> 0). */`);
|
|
731
|
-
d.push(` return scr_dyn_isl_key_get(d, k);`);
|
|
732
|
-
d.push(` }`);
|
|
733
|
-
d.push(` if (d->kind == SCR_DYN_HANDLE) {`);
|
|
734
|
-
d.push(` /* Native handles: the tag's modeled properties (req.url,`);
|
|
735
|
-
d.push(` * res.statusCode, ...) answer boxed values through the`);
|
|
736
|
-
d.push(` * installed ops; the rest is the undefined singleton or the`);
|
|
737
|
-
d.push(` * loud not-supported ladder (scr_json.c). */`);
|
|
738
|
-
d.push(` return scr_dyn_handle_key_get(d, k);`);
|
|
739
|
-
d.push(` }`);
|
|
740
|
-
d.push(` if (d->kind == SCR_DYN_BYTES) {`);
|
|
741
|
-
d.push(` /* Buffer-shaped dyn (a stream's 'data' chunk in the JS lane):`);
|
|
742
|
-
d.push(` * .length and canonical-index byte reads answer like Node. */`);
|
|
743
|
-
d.push(` if (k->len == 6 && memcmp(k->data, "length", 6) == 0) {`);
|
|
744
|
-
d.push(` return scr_dyn_new_num((double)d->v.bytes->len);`);
|
|
745
|
-
d.push(` }`);
|
|
746
|
-
d.push(` if (k->len > 0 && !(k->len > 1 && k->data[0] == '0')) {`);
|
|
747
|
-
d.push(` size_t idx = 0; bool digits = true;`);
|
|
748
|
-
d.push(` for (size_t i = 0; i < k->len; i++) {`);
|
|
749
|
-
d.push(` if (k->data[i] < '0' || k->data[i] > '9' || idx > (SIZE_MAX - 9) / 10) { digits = false; break; }`);
|
|
750
|
-
d.push(` idx = idx * 10 + (size_t)(k->data[i] - '0');`);
|
|
751
|
-
d.push(` }`);
|
|
752
|
-
d.push(` if (digits && idx < d->v.bytes->len) return scr_dyn_new_num((double)d->v.bytes->data[idx]);`);
|
|
753
|
-
d.push(` }`);
|
|
754
|
-
d.push(` }`);
|
|
755
|
-
d.push(` if (d->kind == SCR_DYN_FUNC) {`);
|
|
756
|
-
d.push(` /* own props (defineProperties writes), then name/length —`);
|
|
757
|
-
d.push(` * the function-instance members test/common copies. */`);
|
|
758
|
-
d.push(` ScrDyn *m = scr_dyn_fn_get(d, k->data, k->len);`);
|
|
759
|
-
d.push(` if (m) return m;`);
|
|
760
|
-
d.push(` }`);
|
|
761
|
-
d.push(` if (d->kind == SCR_DYN_ARR || d->kind == SCR_DYN_STR) {`);
|
|
762
|
-
d.push(` if (k->len == 6 && memcmp(k->data, "length", 6) == 0) {`);
|
|
763
|
-
d.push(` return scr_dyn_new_num(d->kind == SCR_DYN_ARR ? (double)d->v.arr.len : scr_str_utf16_len(d->v.str));`);
|
|
764
|
-
d.push(` }`);
|
|
765
|
-
d.push(` if (k->len > 0 && !(k->len > 1 && k->data[0] == '0')) {`);
|
|
766
|
-
d.push(` /* canonical index: digits only, no leading zero — array`);
|
|
767
|
-
d.push(` * elements, and the string's 1-code-unit char ("abc"[1] is`);
|
|
768
|
-
d.push(` * "b" in JS; out of range reads as an absent key). */`);
|
|
769
|
-
d.push(` size_t idx = 0; bool digits = true;`);
|
|
770
|
-
d.push(` for (size_t i = 0; i < k->len; i++) {`);
|
|
771
|
-
d.push(` if (k->data[i] < '0' || k->data[i] > '9' || idx > (SIZE_MAX - 9) / 10) { digits = false; break; }`);
|
|
772
|
-
d.push(` idx = idx * 10 + (size_t)(k->data[i] - '0');`);
|
|
773
|
-
d.push(` }`);
|
|
774
|
-
d.push(` if (digits && d->kind == SCR_DYN_ARR && idx < d->v.arr.len) return scr_dyn_retain(d->v.arr.items[idx]);`);
|
|
775
|
-
d.push(` if (digits && d->kind == SCR_DYN_STR && (double)idx < scr_str_utf16_len(d->v.str)) {`);
|
|
776
|
-
d.push(` ScrStr *c = scr_str_char_at(d->v.str, (double)idx);`);
|
|
777
|
-
d.push(` ScrDyn *r = scr_dyn_new_str(c);`);
|
|
778
|
-
d.push(` scr_str_release(c);`);
|
|
779
|
-
d.push(` return r;`);
|
|
780
|
-
d.push(` }`);
|
|
781
|
-
d.push(` }`);
|
|
782
|
-
d.push(` }`);
|
|
783
|
-
d.push(` return scr_dyn_retain(scr_dyn_undefined());`);
|
|
784
|
-
d.push(`}`, ``);
|
|
785
|
-
emitter.walkerDefs.push(...d);
|
|
786
|
-
return name;
|
|
787
|
-
}
|
|
788
|
-
/** The emitted checked builder for one dynCheck target type:
|
|
789
|
-
* `static T sc_dc_<n>(const ScrDyn *d, const ScrDynPath *path)` —
|
|
790
|
-
* validate the checked-dynamic tree against T and BUILD the typed value (+1), or throw a
|
|
791
|
-
* catchable, path-annotated TypeError-shaped string through the exception
|
|
792
|
-
* cell and return a dummy (0/false/NULL) with the pending flag set.
|
|
793
|
-
* Recursive calls propagate a pending exception by releasing the
|
|
794
|
-
* partially-built value and returning — the same pending-check discipline
|
|
795
|
-
* emitted function bodies follow. */
|
|
796
|
-
export function dynCheckHelper(emitter, t) {
|
|
797
|
-
const key = typeKey(t);
|
|
798
|
-
const existing = emitter.dynBuilders.get(key);
|
|
799
|
-
if (existing)
|
|
800
|
-
return existing;
|
|
801
|
-
const name = `sc_dc_${emitter.dynBuilders.size}`;
|
|
802
|
-
emitter.dynBuilders.set(key, name);
|
|
803
|
-
const sig = `static ${cType(t)}${cType(t).endsWith("*") ? "" : " "}${name}(const ScrDyn *d, const ScrDynPath *path)`;
|
|
804
|
-
emitter.walkerProtos.push(`${sig}; /* check ${key} */`);
|
|
805
|
-
const want = cStringLiteral(Buffer.from(dynDesc(t, emitter.recordsById, emitter.unionsById), "utf8"));
|
|
806
|
-
const d = [`${sig} { /* check ${key} */`];
|
|
807
|
-
if (isRefCounted(t) && t.kind !== "dyn") {
|
|
808
|
-
const keyLit = cStringLiteral(Buffer.from(key, "utf8"));
|
|
809
|
-
const keyLen = Buffer.byteLength(key, "utf8");
|
|
810
|
-
d.push(` if (scr_dyn_typed_ref_is(d, ${keyLit}, ${keyLen})) {`, ` return (${cType(t).trim()})scr_dyn_typed_ref_unbox(d);`, ` }`);
|
|
811
|
-
if (t.kind !== "union") {
|
|
812
|
-
const rc = vAdapters(t);
|
|
813
|
-
d.push(` if (d && d->kind == SCR_DYN_TYPED_REF) {`, ` ${cDecl(t, "sc_cached")} = (${cType(t).trim()})scr_dyn_typed_ref_cached_cast(d, ${keyLit}, ${keyLen});`);
|
|
814
|
-
if (t.kind !== "record" && t.kind !== "array") {
|
|
815
|
-
d.push(` if (sc_cached) return sc_cached;`);
|
|
816
|
-
}
|
|
817
|
-
d.push(` ScrDyn *sc_materialized = scr_dyn_typed_ref_materialize(d);`, ` ${cDecl(t, "sc_out")} = ${name}(sc_materialized, path);`, ` scr_dyn_release(sc_materialized);`);
|
|
818
|
-
if (t.kind === "record") {
|
|
819
|
-
const shape = emitter.recordsById.get(t.shapeId);
|
|
820
|
-
if (!shape) {
|
|
821
|
-
throw new InternalCompilerError(`emitter bug: cached typed-ref cast of unknown shape ${t.shapeId}`);
|
|
822
|
-
}
|
|
823
|
-
d.push(` if (sc_out && sc_cached) {`);
|
|
824
|
-
for (const field of shape.fields) {
|
|
825
|
-
const member = mangleField(field.name);
|
|
826
|
-
d.push(` {`, ` ${cDecl(field.type, "sc_old")} = sc_cached->${member};`, ` sc_cached->${member} = sc_out->${member};`, ` sc_out->${member} = sc_old;`, ` }`);
|
|
827
|
-
}
|
|
828
|
-
if (shape.indexValue) {
|
|
829
|
-
d.push(` ScrMap *sc_old = sc_cached->${OVERFLOW_MEMBER};`, ` sc_cached->${OVERFLOW_MEMBER} = sc_out->${OVERFLOW_MEMBER};`, ` sc_out->${OVERFLOW_MEMBER} = sc_old;`);
|
|
830
|
-
}
|
|
831
|
-
d.push(` ${releaseCallC(t, "sc_out")};`, ` return sc_cached;`, ` }`, ` if (sc_cached) ${releaseCallC(t, "sc_cached")};`);
|
|
832
|
-
}
|
|
833
|
-
else if (t.kind === "array") {
|
|
834
|
-
d.push(` if (sc_out && sc_cached) {`, ` size_t sc_old_len = sc_cached->len;`, ` size_t sc_old_cap = sc_cached->cap;`, ` uint64_t *sc_old_data = sc_cached->data;`, ` sc_cached->len = sc_out->len;`, ` sc_cached->cap = sc_out->cap;`, ` sc_cached->data = sc_out->data;`, ` sc_out->len = sc_old_len;`, ` sc_out->cap = sc_old_cap;`, ` sc_out->data = sc_old_data;`, ` scr_arr_release(sc_out);`, ` return sc_cached;`, ` }`, ` if (sc_cached) scr_arr_release(sc_cached);`);
|
|
835
|
-
}
|
|
836
|
-
d.push(` if (sc_out) {`, ` scr_dyn_typed_ref_cache_cast((ScrDyn *)d, ${keyLit}, ${keyLen}, sc_out, &${rc.retain}, &${rc.release});`, ` }`, ` return sc_out;`, ` }`);
|
|
837
|
-
}
|
|
838
|
-
}
|
|
839
|
-
switch (t.kind) {
|
|
840
|
-
case "f64":
|
|
841
|
-
d.push(` if (d->kind != SCR_DYN_NUM) { scr_dyn_check_fail(path, ${want}, d); return 0; }`);
|
|
842
|
-
d.push(` return d->v.num;`);
|
|
843
|
-
break;
|
|
844
|
-
case "bool":
|
|
845
|
-
d.push(` if (d->kind != SCR_DYN_BOOL) { scr_dyn_check_fail(path, ${want}, d); return false; }`);
|
|
846
|
-
d.push(` return d->v.b;`);
|
|
847
|
-
break;
|
|
848
|
-
case "string":
|
|
849
|
-
d.push(` if (d->kind != SCR_DYN_STR) { scr_dyn_check_fail(path, ${want}, d); return NULL; }`);
|
|
850
|
-
d.push(` return scr_str_retain(d->v.str);`);
|
|
851
|
-
break;
|
|
852
|
-
case "dyn":
|
|
853
|
-
// An `unknown` slot passes through as-is. Typed Web-stream transit
|
|
854
|
-
// capsules stay wrapped so repeated references keep identity;
|
|
855
|
-
// generic operations materialize their one cached detached view.
|
|
856
|
-
d.push(` (void)path;`);
|
|
857
|
-
d.push(` return scr_dyn_retain((ScrDyn *)d);`);
|
|
858
|
-
break;
|
|
859
|
-
case "bytes":
|
|
860
|
-
// `u as Uint8Array`: kind check, then a fresh COPY out (the
|
|
861
|
-
// boundary's aliasing stance in both directions).
|
|
862
|
-
if (t.elem !== "u8")
|
|
863
|
-
throw new InternalCompilerError(`emitter bug: dynCheck of bytes<${t.elem}>`);
|
|
864
|
-
d.push(` if (d->kind != SCR_DYN_BYTES) { scr_dyn_check_fail(path, ${want}, d); return NULL; }`);
|
|
865
|
-
d.push(` return scr_dyn_bytes_copy_out(d);`);
|
|
866
|
-
break;
|
|
867
|
-
case "object":
|
|
868
|
-
// The %Error extraction (an instanceof-Error narrow on unknown):
|
|
869
|
-
// validate the checked-dynamic tree's error encoding — the reserved "%error" marker
|
|
870
|
-
// caughtToDyn builds — and extract through the runtime's IDENTITY
|
|
871
|
-
// CACHE (scr_error_from_dyn): a dyn error that came from a runtime
|
|
872
|
-
// ScrError answers that very instance, so out-and-back crossings
|
|
873
|
-
// compare reference-equal (the tracing suite's shape); alien
|
|
874
|
-
// %error objects rebuild once and cache the pair.
|
|
875
|
-
if (t.className === "%Error") {
|
|
876
|
-
d.push(` if (d->kind != SCR_DYN_OBJ || !scr_dyn_obj_get(d, "%error", 6)) { scr_dyn_check_fail(path, ${want}, d); return NULL; }`);
|
|
877
|
-
d.push(` return scr_error_from_dyn(d);`);
|
|
878
|
-
}
|
|
879
|
-
else {
|
|
880
|
-
// Exact typed references returned before this switch. Plain dyn
|
|
881
|
-
// objects do not carry a class brand, so fail instead of
|
|
882
|
-
// manufacturing an instance from matching fields.
|
|
883
|
-
d.push(` scr_dyn_check_fail(path, ${want}, d);`);
|
|
884
|
-
d.push(` return NULL;`);
|
|
885
|
-
}
|
|
886
|
-
break;
|
|
887
|
-
case "record": {
|
|
888
|
-
const shape = emitter.recordsById.get(t.shapeId);
|
|
889
|
-
if (!shape)
|
|
890
|
-
throw new InternalCompilerError(`emitter bug: dynCheck of unknown shape ${t.shapeId}`);
|
|
891
|
-
const rel = (v) => releaseCallC(t, v);
|
|
892
|
-
// Tuple targets: a JSON ARRAY of exactly the arity, validated and
|
|
893
|
-
// extracted positionally with index paths ("$.pairs[3][1]").
|
|
894
|
-
if (shape.tuple) {
|
|
895
|
-
const byIndex = [...shape.fields].sort((a, b) => Number(a.name) - Number(b.name));
|
|
896
|
-
const arityWant = cStringLiteral(Buffer.from(`array of length ${byIndex.length}`, "utf8"));
|
|
897
|
-
d.push(` if (d->kind != SCR_DYN_ARR) { scr_dyn_check_fail(path, ${want}, d); return NULL; }`);
|
|
898
|
-
d.push(` if (d->v.arr.len != ${byIndex.length}) { scr_dyn_check_fail(path, ${arityWant}, d); return NULL; }`);
|
|
899
|
-
d.push(` ${cDecl(t, "r")} = ${mangleRecordNew(t.shapeId)}();`);
|
|
900
|
-
byIndex.forEach((f, i) => {
|
|
901
|
-
d.push(` {`);
|
|
902
|
-
d.push(` ScrDynPath p = { path, NULL, ${i} };`);
|
|
903
|
-
d.push(` r->${mangleField(f.name)} = ${emitter.dynCheckHelper(f.type)}(d->v.arr.items[${i}], &p);`);
|
|
904
|
-
d.push(` if (scr_exc_pending()) { ${rel("r")}; return NULL; }`);
|
|
905
|
-
d.push(` }`);
|
|
906
|
-
});
|
|
907
|
-
d.push(` return r;`);
|
|
908
|
-
break;
|
|
909
|
-
}
|
|
910
|
-
d.push(` if (d->kind != SCR_DYN_OBJ) { scr_dyn_check_fail(path, ${want}, d); return NULL; }`);
|
|
911
|
-
d.push(` ${cDecl(t, "r")} = ${mangleRecordNew(t.shapeId)}();`);
|
|
912
|
-
for (const f of shape.fields) {
|
|
913
|
-
const keyLit = cStringLiteral(Buffer.from(f.name, "utf8"));
|
|
914
|
-
const keyLen = Buffer.byteLength(f.name, "utf8");
|
|
915
|
-
const fieldWant = cStringLiteral(Buffer.from(dynDesc(f.type, emitter.recordsById, emitter.unionsById), "utf8"));
|
|
916
|
-
// Width tolerance: only declared fields are looked up — extra JSON
|
|
917
|
-
// keys are simply never examined (check-and-extract, not shape
|
|
918
|
-
// equality). A missing field fails as "got undefined" — except
|
|
919
|
-
// optional-flavored fields (undefined-armed unions), where the
|
|
920
|
-
// missing key IS the undefined arm: the interned immortal
|
|
921
|
-
// instance, no retain owed (rc == SIZE_MAX).
|
|
922
|
-
const utag = f.type.kind === "union" ? undefinedArmTag(f.type, emitter.unionsById) : -1;
|
|
923
|
-
d.push(` {`);
|
|
924
|
-
d.push(` ScrDynPath p = { path, ${keyLit}, 0 };`);
|
|
925
|
-
d.push(` const ScrDyn *m = scr_dyn_obj_get(d, ${keyLit}, ${keyLen});`);
|
|
926
|
-
if (f.type.kind === "dyn") {
|
|
927
|
-
// An `unknown` field: a present key passes through, a missing
|
|
928
|
-
// one IS the undefined dyn value (JS's missing-property read).
|
|
929
|
-
// Go through the dyn builder so a Web-stream typed-ref capsule
|
|
930
|
-
// cannot escape inside a checked record field.
|
|
931
|
-
d.push(` r->${mangleField(f.name)} = ${emitter.dynCheckHelper(f.type)}(m ? m : scr_dyn_undefined(), &p);`);
|
|
932
|
-
}
|
|
933
|
-
else if (utag >= 0 && f.type.kind === "union") {
|
|
934
|
-
const unit = emitter.unitInstanceRef(f.type.unionId, utag);
|
|
935
|
-
d.push(` if (!m) {`);
|
|
936
|
-
d.push(` r->${mangleField(f.name)} = ${unit}; /* absent key -> the undefined arm */`);
|
|
937
|
-
d.push(` } else {`);
|
|
938
|
-
d.push(` r->${mangleField(f.name)} = ${emitter.dynCheckHelper(f.type)}(m, &p);`);
|
|
939
|
-
d.push(` if (scr_exc_pending()) { ${rel("r")}; return NULL; }`);
|
|
940
|
-
d.push(` }`);
|
|
941
|
-
}
|
|
942
|
-
else {
|
|
943
|
-
d.push(` if (!m) { scr_dyn_check_fail(&p, ${fieldWant}, NULL); ${rel("r")}; return NULL; }`);
|
|
944
|
-
d.push(` r->${mangleField(f.name)} = ${emitter.dynCheckHelper(f.type)}(m, &p);`);
|
|
945
|
-
d.push(` if (scr_exc_pending()) { ${rel("r")}; return NULL; }`);
|
|
946
|
-
}
|
|
947
|
-
d.push(` }`);
|
|
948
|
-
}
|
|
949
|
-
// Index-signature shapes CAPTURE undeclared keys into the overflow
|
|
950
|
-
// map (width tolerance became width capture — plain shapes above
|
|
951
|
-
// keep ignoring extras). dyn value types retain the checked-dynamic tree subtree
|
|
952
|
-
// as-is; concrete types validate each entry with its key path.
|
|
953
|
-
if (shape.indexValue) {
|
|
954
|
-
const iv = shape.indexValue;
|
|
955
|
-
const skip = shape.fields
|
|
956
|
-
.map((f) => {
|
|
957
|
-
const keyLit = cStringLiteral(Buffer.from(f.name, "utf8"));
|
|
958
|
-
const keyLen = Buffer.byteLength(f.name, "utf8");
|
|
959
|
-
return `(e->key_len == ${keyLen} && memcmp(e->key, ${keyLit}, ${keyLen}) == 0)`;
|
|
960
|
-
})
|
|
961
|
-
.join(" || ");
|
|
962
|
-
d.push(` for (size_t i = 0; i < d->v.obj.len; i++) {`);
|
|
963
|
-
d.push(` const ScrDynEntry *e = &d->v.obj.entries[i];`);
|
|
964
|
-
if (shape.fields.length > 0)
|
|
965
|
-
d.push(` if (${skip}) continue;`);
|
|
966
|
-
if (iv.kind === "dyn") {
|
|
967
|
-
d.push(` ${cDecl(iv, "ev")} = scr_dyn_retain(e->value);`);
|
|
968
|
-
}
|
|
969
|
-
else {
|
|
970
|
-
d.push(` ScrDynPath p = { path, e->key, 0 };`);
|
|
971
|
-
d.push(` ${cDecl(iv, "ev")} = ${emitter.dynCheckHelper(iv)}(e->value, &p);`);
|
|
972
|
-
d.push(` if (scr_exc_pending()) { ${rel("r")}; return NULL; }`);
|
|
973
|
-
}
|
|
974
|
-
d.push(` ScrStr *ek = scr_str_new(e->key, e->key_len);`);
|
|
975
|
-
if (iv.kind === "f64" || iv.kind === "bool") {
|
|
976
|
-
d.push(` scr_map_set_str_${iv.kind === "f64" ? "f64" : "bool"}(r->${OVERFLOW_MEMBER}, ek, ev);`);
|
|
977
|
-
}
|
|
978
|
-
else {
|
|
979
|
-
d.push(` scr_map_set_str_ref(r->${OVERFLOW_MEMBER}, ek, ev);`);
|
|
980
|
-
}
|
|
981
|
-
d.push(` scr_str_release(ek);`);
|
|
982
|
-
d.push(` }`);
|
|
983
|
-
}
|
|
984
|
-
d.push(` return r;`);
|
|
985
|
-
break;
|
|
986
|
-
}
|
|
987
|
-
case "array": {
|
|
988
|
-
const elem = t.elem;
|
|
989
|
-
const c = emitter.dynCheckHelper(elem);
|
|
990
|
-
d.push(` if (d->kind != SCR_DYN_ARR) { scr_dyn_check_fail(path, ${want}, d); return NULL; }`);
|
|
991
|
-
d.push(` ScrArr *a = ${emitter.arrNewC(elem, "d->v.arr.len")};`);
|
|
992
|
-
d.push(` for (size_t i = 0; i < d->v.arr.len; i++) {`);
|
|
993
|
-
d.push(` ScrDynPath p = { path, NULL, i };`);
|
|
994
|
-
d.push(` ${cDecl(elem, "e")} = ${c}(d->v.arr.items[i], &p);`);
|
|
995
|
-
d.push(` if (scr_exc_pending()) { scr_arr_release(a); return NULL; }`);
|
|
996
|
-
d.push(` scr_arr_push_${elemAccess(elem)}(a, e);`);
|
|
997
|
-
d.push(` }`);
|
|
998
|
-
d.push(` return a;`);
|
|
999
|
-
break;
|
|
1000
|
-
}
|
|
1001
|
-
case "union": {
|
|
1002
|
-
const def = emitter.unionsById.get(t.unionId);
|
|
1003
|
-
if (!def)
|
|
1004
|
-
throw new InternalCompilerError(`emitter bug: dynCheck of unknown union ${t.unionId}`);
|
|
1005
|
-
// Arms in CANONICAL order, first FULL match wins (discriminated
|
|
1006
|
-
// unions disambiguate naturally: the arm whose declared fields all
|
|
1007
|
-
// fit). The matched arm's builder can no longer fail.
|
|
1008
|
-
def.arms.forEach((arm, i) => {
|
|
1009
|
-
const m = emitter.dynMatchHelper(arm);
|
|
1010
|
-
if (arm.kind === "undefinedT") {
|
|
1011
|
-
// Parsed JSON never matches here (no undefined in JSON text —
|
|
1012
|
-
// a MISSING record key builds this arm in the record builder
|
|
1013
|
-
// above), but the undefined dyn value can arrive from
|
|
1014
|
-
// `unknown` index-signature overflows and builds the interned
|
|
1015
|
-
// unit instance exactly like null.
|
|
1016
|
-
d.push(` if (${m}(d)) {`);
|
|
1017
|
-
d.push(` return ${emitter.unitInstanceRef(t.unionId, i)};`);
|
|
1018
|
-
d.push(` }`);
|
|
1019
|
-
return;
|
|
1020
|
-
}
|
|
1021
|
-
if (arm.kind === "nullT") {
|
|
1022
|
-
// A matched unit arm builds nothing: the result is THE interned
|
|
1023
|
-
// immortal instance (rc == SIZE_MAX — RC entry points and the
|
|
1024
|
-
// collector both skip it, so no retain is owed).
|
|
1025
|
-
d.push(` if (${m}(d)) {`);
|
|
1026
|
-
d.push(` return ${emitter.unitInstanceRef(t.unionId, i)};`);
|
|
1027
|
-
d.push(` }`);
|
|
1028
|
-
return;
|
|
1029
|
-
}
|
|
1030
|
-
const c = emitter.dynCheckHelper(arm);
|
|
1031
|
-
d.push(` if (${m}(d)) {`);
|
|
1032
|
-
if (arm.kind === "f64") {
|
|
1033
|
-
d.push(` return scr_union_new_f64(${i}, ${c}(d, path));`);
|
|
1034
|
-
}
|
|
1035
|
-
else if (arm.kind === "bool") {
|
|
1036
|
-
d.push(` return scr_union_new_bool(${i}, ${c}(d, path));`);
|
|
1037
|
-
}
|
|
1038
|
-
else {
|
|
1039
|
-
const rc = vAdapters(arm);
|
|
1040
|
-
d.push(` return scr_union_new_ref(${i}, ${c}(d, path), &${rc.retain}, &${rc.release}, ${emitter.traceArgC(arm)});`);
|
|
1041
|
-
}
|
|
1042
|
-
d.push(` }`);
|
|
1043
|
-
});
|
|
1044
|
-
// A typed stream capsule may fit one arm EXACTLY; those probes run
|
|
1045
|
-
// first so the matching arm can preserve object identity. Only when
|
|
1046
|
-
// no arm matches the producer tag do we snapshot and retry the
|
|
1047
|
-
// ordinary copy-based structural union check (the compiler's width
|
|
1048
|
-
// coercion stance, rather than a live narrowed alias).
|
|
1049
|
-
d.push(` if (d && d->kind == SCR_DYN_TYPED_REF) {`);
|
|
1050
|
-
{
|
|
1051
|
-
const keyLit = cStringLiteral(Buffer.from(key, "utf8"));
|
|
1052
|
-
const keyLen = Buffer.byteLength(key, "utf8");
|
|
1053
|
-
const rc = vAdapters(t);
|
|
1054
|
-
d.push(` ${cDecl(t, "sc_cached")} = (${cType(t).trim()})scr_dyn_typed_ref_cached_cast(d, ${keyLit}, ${keyLen});`);
|
|
1055
|
-
d.push(` ScrDyn *sc_materialized = scr_dyn_typed_ref_materialize(d);`);
|
|
1056
|
-
d.push(` ${cDecl(t, "sc_out")} = ${name}(sc_materialized, path);`);
|
|
1057
|
-
d.push(` scr_dyn_release(sc_materialized);`);
|
|
1058
|
-
d.push(` if (sc_out && sc_cached) {`);
|
|
1059
|
-
d.push(` size_t sc_cached_rc = sc_cached->rc;`);
|
|
1060
|
-
d.push(` size_t sc_out_rc = sc_out->rc;`);
|
|
1061
|
-
d.push(` ScrUnion sc_old = *sc_cached;`);
|
|
1062
|
-
d.push(` *sc_cached = *sc_out;`);
|
|
1063
|
-
d.push(` sc_cached->rc = sc_cached_rc;`);
|
|
1064
|
-
d.push(` *sc_out = sc_old;`);
|
|
1065
|
-
d.push(` sc_out->rc = sc_out_rc;`);
|
|
1066
|
-
d.push(` scr_union_release(sc_out);`);
|
|
1067
|
-
d.push(` return sc_cached;`);
|
|
1068
|
-
d.push(` }`);
|
|
1069
|
-
d.push(` if (sc_cached) scr_union_release(sc_cached);`);
|
|
1070
|
-
d.push(` if (sc_out) {`);
|
|
1071
|
-
d.push(` scr_dyn_typed_ref_cache_cast((ScrDyn *)d, ${keyLit}, ${keyLen}, sc_out, &${rc.retain}, &${rc.release});`);
|
|
1072
|
-
d.push(` }`);
|
|
1073
|
-
d.push(` return sc_out;`);
|
|
1074
|
-
}
|
|
1075
|
-
d.push(` }`);
|
|
1076
|
-
d.push(` scr_dyn_check_fail(path, ${want}, d);`);
|
|
1077
|
-
d.push(` return NULL;`);
|
|
1078
|
-
break;
|
|
1079
|
-
}
|
|
1080
|
-
case "func": {
|
|
1081
|
-
// The checked-dynamic function boundary, OUT direction: a
|
|
1082
|
-
// non-function kind fails like any dynCheck; an IDENTICAL boxed
|
|
1083
|
-
// signature (the interned typeKey — same key ⇔ same IR type ⇔
|
|
1084
|
-
// same ABI) unwraps the closure directly (identity preserved:
|
|
1085
|
-
// `mustCall(fn)` handed back to a slot of fn's own type IS fn's
|
|
1086
|
-
// wrapper, retained); anything else wraps in the per-target
|
|
1087
|
-
// adapter closure, whose caps[0] obj-box owns the dyn value
|
|
1088
|
-
// (untraced — cycles through dyn never collect, SEMANTICS.md).
|
|
1089
|
-
const adapter = dynFuncAdapterHelper(emitter, t);
|
|
1090
|
-
const sigLit = cStringLiteral(Buffer.from(key, "utf8"));
|
|
1091
|
-
d.push(` if (d->kind != SCR_DYN_FUNC) { scr_dyn_check_fail(path, ${want}, d); return NULL; }`);
|
|
1092
|
-
d.push(` if (strcmp(d->v.fn.sig, ${sigLit}) == 0) return scr_closure_retain(d->v.fn.clo);`);
|
|
1093
|
-
d.push(` {`);
|
|
1094
|
-
d.push(` ScrClosure *a = scr_closure_new((void *)&${adapter}, 1);`);
|
|
1095
|
-
d.push(` a->caps[0] = scr_box_new_obj(&scr_dyn_retain_v, &scr_dyn_release_v, NULL);`);
|
|
1096
|
-
d.push(` scr_box_set_ref(a->caps[0], scr_dyn_retain((ScrDyn *)d));`);
|
|
1097
|
-
d.push(` return a;`);
|
|
1098
|
-
d.push(` }`);
|
|
1099
|
-
break;
|
|
1100
|
-
}
|
|
1101
|
-
default: {
|
|
1102
|
-
// Runtime HANDLE targets: a tag-checked reference unwrap (+1 —
|
|
1103
|
-
// identity, no copy; the runtime throws the path-annotated
|
|
1104
|
-
// TypeError on any other kind or tag).
|
|
1105
|
-
const h = DYN_HANDLE_KINDS.get(t.kind);
|
|
1106
|
-
if (h) {
|
|
1107
|
-
d.push(` return (${cType(t).trim()})scr_dyn_handle_unbox(d, ${h.tag}, path, ${want});`);
|
|
1108
|
-
break;
|
|
1109
|
-
}
|
|
1110
|
-
throw new InternalCompilerError(`emitter bug: dynCheck of non-JSON type ${t.kind}`);
|
|
1111
|
-
}
|
|
1112
|
-
}
|
|
1113
|
-
d.push(`}`, ``);
|
|
1114
|
-
emitter.walkerDefs.push(...d);
|
|
1115
|
-
return name;
|
|
1116
|
-
}
|
|
1117
|
-
/** The emitted static→dyn converter for one type:
|
|
1118
|
-
* `static ScrDyn *sc_td_<n>(<T> v)` — build a fresh dyn value from a
|
|
1119
|
-
* static one (+1), DEEP-COPYING composites (a dyn value never aliases
|
|
1120
|
-
* static storage — the jsMarshal stance). Domain: the JSON-safe kinds
|
|
1121
|
-
* plus undefined-armed unions (the undefined arm becomes the undefined
|
|
1122
|
-
* dyn singleton) and index-signature records (whose overflow entries
|
|
1123
|
-
* copy over). The operand is borrowed. Never throws. */
|
|
1124
|
-
export function toDynHelper(emitter, t) {
|
|
1125
|
-
const key = typeKey(t);
|
|
1126
|
-
const existing = emitter.toDynFns.get(key);
|
|
1127
|
-
if (existing)
|
|
1128
|
-
return existing;
|
|
1129
|
-
const name = `sc_td_${emitter.toDynFns.size}`;
|
|
1130
|
-
emitter.toDynFns.set(key, name);
|
|
1131
|
-
const sig = `static ScrDyn *${name}(${cDecl(t, "v")})`;
|
|
1132
|
-
emitter.walkerProtos.push(`${sig}; /* to-dyn ${key} */`);
|
|
1133
|
-
const d = [`${sig} { /* to-dyn ${key} */`];
|
|
1134
|
-
let sourceAccessor = null;
|
|
1135
|
-
switch (t.kind) {
|
|
1136
|
-
case "f64":
|
|
1137
|
-
d.push(` return scr_dyn_new_num(v);`);
|
|
1138
|
-
break;
|
|
1139
|
-
case "bool":
|
|
1140
|
-
d.push(` return scr_dyn_new_bool(v);`);
|
|
1141
|
-
break;
|
|
1142
|
-
case "string":
|
|
1143
|
-
d.push(` return scr_dyn_new_str(v); /* retains v */`);
|
|
1144
|
-
break;
|
|
1145
|
-
case "undefinedT":
|
|
1146
|
-
// A bare unit field (`x: undefined` in a record — the tls
|
|
1147
|
-
// options-record's explicit-absent member): the dyn unit value.
|
|
1148
|
-
d.push(` (void)v; return scr_dyn_retain(scr_dyn_undefined());`);
|
|
1149
|
-
break;
|
|
1150
|
-
case "nullT":
|
|
1151
|
-
d.push(` (void)v; return scr_dyn_new_null();`);
|
|
1152
|
-
break;
|
|
1153
|
-
case "object": {
|
|
1154
|
-
const className = t.className;
|
|
1155
|
-
if (className === "%Error") {
|
|
1156
|
-
d.push(` return scr_dyn_from_error(v);`);
|
|
1157
|
-
break;
|
|
1158
|
-
}
|
|
1159
|
-
if (!isDynTypedRefType(t)) {
|
|
1160
|
-
throw new InternalCompilerError(`emitter bug: to-dyn of runtime class ${className}`);
|
|
1161
|
-
}
|
|
1162
|
-
{
|
|
1163
|
-
const adapter = emitter.liveDynRefAdapter(t);
|
|
1164
|
-
const rc = vAdapters(t);
|
|
1165
|
-
const key = typeKey(t);
|
|
1166
|
-
const keyLit = cStringLiteral(Buffer.from(key, "utf8"));
|
|
1167
|
-
d.push(` return scr_dyn_new_typed_ref(v, &${rc.retain}, &${rc.release}, ${keyLit}, ${Buffer.byteLength(key, "utf8")}, &${adapter.snapshot}, ${adapter.commit});`);
|
|
1168
|
-
}
|
|
1169
|
-
break;
|
|
1170
|
-
}
|
|
1171
|
-
case "dyn":
|
|
1172
|
-
// A dyn member of a converting composite (a dyn record field): the
|
|
1173
|
-
// dyn value passes through by reference — already a dyn, already
|
|
1174
|
-
// immutable-through-copies.
|
|
1175
|
-
d.push(` return scr_dyn_retain(v);`);
|
|
1176
|
-
break;
|
|
1177
|
-
case "func":
|
|
1178
|
-
// Function-valued record/array fields (EventListenerObject's
|
|
1179
|
-
// handleEvent method) box through the same identity-preserving
|
|
1180
|
-
// closure bridge as a bare dynFrom function.
|
|
1181
|
-
d.push(` return ${dynFuncBoxHelper(emitter, t)}(v, NULL);`);
|
|
1182
|
-
break;
|
|
1183
|
-
case "bytes":
|
|
1184
|
-
// bytes<u8> → the checked-dynamic tree's bytes kind, payload COPIED (the boundary
|
|
1185
|
-
// stance; stdin chunks into unknown-typed helpers).
|
|
1186
|
-
if (t.elem !== "u8")
|
|
1187
|
-
throw new InternalCompilerError(`emitter bug: to-dyn of bytes<${t.elem}>`);
|
|
1188
|
-
d.push(` return scr_dyn_new_bytes_copy(v);`);
|
|
1189
|
-
break;
|
|
1190
|
-
case "record": {
|
|
1191
|
-
const shape = emitter.recordsById.get(t.shapeId);
|
|
1192
|
-
if (!shape)
|
|
1193
|
-
throw new InternalCompilerError(`emitter bug: to-dyn of unknown shape ${t.shapeId}`);
|
|
1194
|
-
// CYCLE-CAPABLE shapes guard the deep copy: a cyclic value has no
|
|
1195
|
-
// finite dyn copy, so enter TRAPS on re-entry (SEMANTICS.md — Node
|
|
1196
|
-
// shares the reference instead of copying).
|
|
1197
|
-
const cyclicRec = emitter.traceAdapterC(t) !== null;
|
|
1198
|
-
if (cyclicRec)
|
|
1199
|
-
d.push(` scr_dyn_from_enter(v);`);
|
|
1200
|
-
if (shape.tuple) {
|
|
1201
|
-
// A tuple converts as the JSON ARRAY it is everywhere else.
|
|
1202
|
-
const byIndex = [...shape.fields].sort((a, b) => Number(a.name) - Number(b.name));
|
|
1203
|
-
d.push(` ScrDyn *d = scr_dyn_new_arr();`);
|
|
1204
|
-
for (const f of byIndex) {
|
|
1205
|
-
d.push(` scr_dyn_arr_push(d, ${emitter.toDynHelper(f.type)}(v->${mangleField(f.name)}));`);
|
|
1206
|
-
}
|
|
1207
|
-
if (cyclicRec)
|
|
1208
|
-
d.push(` scr_dyn_from_leave();`);
|
|
1209
|
-
d.push(` return d;`);
|
|
1210
|
-
break;
|
|
1211
|
-
}
|
|
1212
|
-
const carriesListenerIdentity = shape.fields.some((f) => f.name === "handleEvent" && f.type.kind === "func");
|
|
1213
|
-
if (carriesListenerIdentity) {
|
|
1214
|
-
const rc = vAdapters(t);
|
|
1215
|
-
sourceAccessor = {
|
|
1216
|
-
name: `${name}_source_access`,
|
|
1217
|
-
release: rc.release,
|
|
1218
|
-
};
|
|
1219
|
-
emitter.walkerProtos.push(`static ScrDyn *${sourceAccessor.name}(void *v, bool materialize); /* live listener source ${key} */`);
|
|
1220
|
-
d.push(` ScrDyn *d = scr_dyn_new_obj_with_identity(v, &${rc.retain}, &${sourceAccessor.name});`);
|
|
1221
|
-
}
|
|
1222
|
-
else {
|
|
1223
|
-
d.push(` ScrDyn *d = scr_dyn_new_obj();`);
|
|
1224
|
-
}
|
|
1225
|
-
// Keys insert in DECLARED order — the dyn object's insertion order
|
|
1226
|
-
// is observable (Object.keys/for-in over checked-dynamic values,
|
|
1227
|
-
// dyn JSON), so it must be JS's (SEMANTICS.md 36's stance, same as
|
|
1228
|
-
// the JSON writer above). Internal '%'-fields declaredOrder omits
|
|
1229
|
-
// still enter the checked-dynamic tree (after the visible keys) so a
|
|
1230
|
-
// record→dyn→record round trip keeps their data.
|
|
1231
|
-
{
|
|
1232
|
-
const byName = new Map(shape.fields.map((f) => [f.name, f]));
|
|
1233
|
-
const order = shape.declaredOrder ?? shape.fields.map((f) => f.name);
|
|
1234
|
-
const inOrder = new Set(order);
|
|
1235
|
-
const dynFields = [
|
|
1236
|
-
...order.map((n) => byName.get(n)).filter((f) => f !== undefined),
|
|
1237
|
-
...shape.fields.filter((f) => !inOrder.has(f.name)),
|
|
1238
|
-
];
|
|
1239
|
-
for (const f of dynFields) {
|
|
1240
|
-
const keyLit = cStringLiteral(Buffer.from(f.name, "utf8"));
|
|
1241
|
-
const keyLen = Buffer.byteLength(f.name, "utf8");
|
|
1242
|
-
d.push(` scr_dyn_obj_set(d, ${keyLit}, ${keyLen}, ${emitter.toDynHelper(f.type)}(v->${mangleField(f.name)}));`);
|
|
1243
|
-
}
|
|
1244
|
-
}
|
|
1245
|
-
if (shape.indexValue) {
|
|
1246
|
-
const iv = shape.indexValue;
|
|
1247
|
-
const m = `v->${OVERFLOW_MEMBER}`;
|
|
1248
|
-
// JS OWN-KEY order (integer-like keys ascending first) — the same
|
|
1249
|
-
// enumeration Object.keys and the JSON writer answer.
|
|
1250
|
-
d.push(` {`);
|
|
1251
|
-
d.push(` ScrArr *ks = scr_map_keys_js_order(${m});`);
|
|
1252
|
-
d.push(` for (size_t i = 0; i < ks->len; i++) {`);
|
|
1253
|
-
d.push(` ScrStr *k = (ScrStr *)scr_arr_get_ref(ks, (double)i);`);
|
|
1254
|
-
if (iv.kind === "f64" || iv.kind === "bool") {
|
|
1255
|
-
d.push(` ${cDecl(iv, "sv")} = 0;`);
|
|
1256
|
-
d.push(` scr_map_get_str_${iv.kind === "f64" ? "f64" : "bool"}(${m}, k, &sv);`);
|
|
1257
|
-
d.push(` scr_dyn_obj_set(d, k->data, k->len, scr_dyn_new_${iv.kind === "f64" ? "num" : "bool"}(sv));`);
|
|
1258
|
-
}
|
|
1259
|
-
else if (iv.kind === "dyn") {
|
|
1260
|
-
// get_str_ref returns +1 — exactly the ownership obj_set takes.
|
|
1261
|
-
d.push(` scr_dyn_obj_set(d, k->data, k->len, (ScrDyn *)scr_map_get_str_ref(${m}, k));`);
|
|
1262
|
-
}
|
|
1263
|
-
else {
|
|
1264
|
-
d.push(` ${cDecl(iv, "e")} = (${cType(iv).trim()})scr_map_get_str_ref(${m}, k);`);
|
|
1265
|
-
d.push(` scr_dyn_obj_set(d, k->data, k->len, ${emitter.toDynHelper(iv)}(e));`);
|
|
1266
|
-
d.push(` ${releaseCallC(iv, "e")};`);
|
|
1267
|
-
}
|
|
1268
|
-
d.push(` scr_str_release(k);`);
|
|
1269
|
-
d.push(` }`);
|
|
1270
|
-
d.push(` scr_arr_release(ks);`);
|
|
1271
|
-
d.push(` }`);
|
|
1272
|
-
}
|
|
1273
|
-
if (cyclicRec)
|
|
1274
|
-
d.push(` scr_dyn_from_leave();`);
|
|
1275
|
-
d.push(` return d;`);
|
|
1276
|
-
break;
|
|
1277
|
-
}
|
|
1278
|
-
case "array": {
|
|
1279
|
-
const elem = t.elem;
|
|
1280
|
-
// Cycle-capable arrays guard the deep copy like records above.
|
|
1281
|
-
const cyclicArr = emitter.traceAdapterC(t) !== null;
|
|
1282
|
-
if (cyclicArr)
|
|
1283
|
-
d.push(` scr_dyn_from_enter(v);`);
|
|
1284
|
-
d.push(` ScrDyn *d = scr_dyn_new_arr();`);
|
|
1285
|
-
d.push(` for (size_t i = 0; i < v->len; i++) {`);
|
|
1286
|
-
if (elem.kind === "f64") {
|
|
1287
|
-
d.push(` scr_dyn_arr_push(d, scr_dyn_new_num(scr_arr_get_f64(v, (double)i)));`);
|
|
1288
|
-
}
|
|
1289
|
-
else if (elem.kind === "bool") {
|
|
1290
|
-
d.push(` scr_dyn_arr_push(d, scr_dyn_new_bool(scr_arr_get_bool(v, (double)i)));`);
|
|
1291
|
-
}
|
|
1292
|
-
else {
|
|
1293
|
-
d.push(` ${cDecl(elem, "e")} = (${cType(elem).trim()})scr_arr_get_ref(v, (double)i);`);
|
|
1294
|
-
d.push(` scr_dyn_arr_push(d, ${emitter.toDynHelper(elem)}(e));`);
|
|
1295
|
-
d.push(` ${releaseCallC(elem, "e")};`);
|
|
1296
|
-
}
|
|
1297
|
-
d.push(` }`);
|
|
1298
|
-
if (cyclicArr)
|
|
1299
|
-
d.push(` scr_dyn_from_leave();`);
|
|
1300
|
-
d.push(` return d;`);
|
|
1301
|
-
break;
|
|
1302
|
-
}
|
|
1303
|
-
case "union": {
|
|
1304
|
-
const def = emitter.unionsById.get(t.unionId);
|
|
1305
|
-
if (!def)
|
|
1306
|
-
throw new InternalCompilerError(`emitter bug: to-dyn of unknown union ${t.unionId}`);
|
|
1307
|
-
d.push(` switch (v->tag) {`);
|
|
1308
|
-
def.arms.forEach((arm, i) => {
|
|
1309
|
-
if (arm.kind === "undefinedT") {
|
|
1310
|
-
d.push(` case ${i}: return scr_dyn_retain(scr_dyn_undefined());`);
|
|
1311
|
-
}
|
|
1312
|
-
else if (arm.kind === "nullT") {
|
|
1313
|
-
d.push(` case ${i}: return scr_dyn_new_null();`);
|
|
1314
|
-
}
|
|
1315
|
-
else if (arm.kind === "f64") {
|
|
1316
|
-
d.push(` case ${i}: return scr_dyn_new_num(scr_union_get_f64(v));`);
|
|
1317
|
-
}
|
|
1318
|
-
else if (arm.kind === "bool") {
|
|
1319
|
-
d.push(` case ${i}: return scr_dyn_new_bool(scr_union_get_bool(v));`);
|
|
1320
|
-
}
|
|
1321
|
-
else if (arm.kind === "func") {
|
|
1322
|
-
// A boxable function arm crosses through the checked-dynamic
|
|
1323
|
-
// function boundary (the dynFrom func special case, sans name).
|
|
1324
|
-
d.push(` case ${i}: return ${dynFuncBoxHelper(emitter, arm)}((ScrClosure *)scr_union_peek(v), NULL);`);
|
|
1325
|
-
}
|
|
1326
|
-
else {
|
|
1327
|
-
d.push(` case ${i}: return ${emitter.toDynHelper(arm)}((${cType(arm).trim()})scr_union_peek(v));`);
|
|
1328
|
-
}
|
|
1329
|
-
});
|
|
1330
|
-
d.push(` default: scr_trap("scriptc: internal error: invalid union tag\\n");`);
|
|
1331
|
-
d.push(` }`);
|
|
1332
|
-
break;
|
|
1333
|
-
}
|
|
1334
|
-
case "promise": {
|
|
1335
|
-
// Promises box by REFERENCE (SCR_DYN_PROMISE — identity is the
|
|
1336
|
-
// promise): promise<dyn> carries its ScrPromise directly (the
|
|
1337
|
-
// payload is already a dyn value); any other inner boxes an
|
|
1338
|
-
// ADAPTER promise whose settle callback converts the payload
|
|
1339
|
-
// (rejections copy raw inside the runtime's cb-waiter machinery).
|
|
1340
|
-
if (t.inner.kind === "dyn") {
|
|
1341
|
-
d.push(` return scr_dyn_new_promise(v);`);
|
|
1342
|
-
break;
|
|
1343
|
-
}
|
|
1344
|
-
d.push(` return scr_dyn_new_promise_adapting(v, &${promiseDynAdapterHelper(emitter, t.inner)});`);
|
|
1345
|
-
break;
|
|
1346
|
-
}
|
|
1347
|
-
default: {
|
|
1348
|
-
// Runtime HANDLE kinds box by REFERENCE (identity — no copy):
|
|
1349
|
-
// scr_dyn_new_handle retains the borrowed operand through the
|
|
1350
|
-
// tag's installed ops.
|
|
1351
|
-
const h = DYN_HANDLE_KINDS.get(t.kind);
|
|
1352
|
-
if (h) {
|
|
1353
|
-
d.push(` return scr_dyn_new_handle(v, ${h.tag});`);
|
|
1354
|
-
break;
|
|
1355
|
-
}
|
|
1356
|
-
throw new InternalCompilerError(`emitter bug: to-dyn of unsupported type ${t.kind}`);
|
|
1357
|
-
}
|
|
1358
|
-
}
|
|
1359
|
-
d.push(`}`, ``);
|
|
1360
|
-
emitter.walkerDefs.push(...d);
|
|
1361
|
-
if (sourceAccessor) {
|
|
1362
|
-
emitter.walkerDefs.push(`static ScrDyn *${sourceAccessor.name}(void *v, bool materialize) {`, ` if (materialize) return ${name}((${cType(t).trim()})v);`, ` ${sourceAccessor.release}(v);`, ` return NULL;`, `}`, ``);
|
|
1363
|
-
}
|
|
1364
|
-
return name;
|
|
1365
|
-
}
|
|
1366
|
-
/** The checked-dynamic tree-promise settle adapter for one fulfillment payload type:
|
|
1367
|
-
* `static void sc_pda_<n>(ScrPromise *dst, ScrPromise *src)` — read
|
|
1368
|
-
* src's fulfilled payload by its compile-time kind, convert it to a dyn
|
|
1369
|
-
* value, and fulfill dst with it (scr_dyn_new_promise_adapting's
|
|
1370
|
-
* callback; rejections never reach an adapter — the runtime copies them
|
|
1371
|
-
* raw). Interned per inner typeKey. */
|
|
1372
|
-
function promiseDynAdapterHelper(emitter, inner) {
|
|
1373
|
-
const key = typeKey(inner);
|
|
1374
|
-
const existing = emitter.promiseDynAdapters.get(key);
|
|
1375
|
-
if (existing)
|
|
1376
|
-
return existing;
|
|
1377
|
-
const name = `sc_pda_${emitter.promiseDynAdapters.size}`;
|
|
1378
|
-
emitter.promiseDynAdapters.set(key, name);
|
|
1379
|
-
const sig = `static void ${name}(ScrPromise *dst, ScrPromise *src)`;
|
|
1380
|
-
emitter.walkerProtos.push(`${sig}; /* dyn-box settle adapter for promise<${key}> */`);
|
|
1381
|
-
const d = [`${sig} { /* dyn-box settle adapter for promise<${key}> */`];
|
|
1382
|
-
const fulfill = (expr) => ` scr_promise_fulfill_ref(dst, ${expr}, scr_dyn_retain_v, scr_dyn_release_v, NULL);`;
|
|
1383
|
-
switch (inner.kind) {
|
|
1384
|
-
case "void":
|
|
1385
|
-
case "undefinedT":
|
|
1386
|
-
d.push(` (void)src;`);
|
|
1387
|
-
d.push(fulfill(`scr_dyn_retain(scr_dyn_undefined())`));
|
|
1388
|
-
break;
|
|
1389
|
-
case "nullT":
|
|
1390
|
-
d.push(` (void)src;`);
|
|
1391
|
-
d.push(fulfill(`scr_dyn_new_null()`));
|
|
1392
|
-
break;
|
|
1393
|
-
case "f64":
|
|
1394
|
-
d.push(fulfill(`scr_dyn_new_num(scr_promise_payload_f64(src))`));
|
|
1395
|
-
break;
|
|
1396
|
-
case "bool":
|
|
1397
|
-
d.push(fulfill(`scr_dyn_new_bool(scr_promise_payload_bool(src))`));
|
|
1398
|
-
break;
|
|
1399
|
-
case "string":
|
|
1400
|
-
d.push(` ScrStr *s = scr_promise_payload_str(src);`);
|
|
1401
|
-
d.push(` ScrDyn *dv = scr_dyn_new_str(s); /* retains s */`);
|
|
1402
|
-
d.push(` scr_str_release(s);`);
|
|
1403
|
-
d.push(fulfill(`dv`));
|
|
1404
|
-
break;
|
|
1405
|
-
default: {
|
|
1406
|
-
// Ref-payload inners (records, arrays, bytes, %Error, unions,
|
|
1407
|
-
// nested promises, handles): extract (+1 via the stored retain),
|
|
1408
|
-
// convert through the shared to-dyn spelling, release the extract.
|
|
1409
|
-
d.push(` ${cDecl(inner, "pv")} = (${cType(inner).trim()})scr_promise_payload_ref(src);`);
|
|
1410
|
-
d.push(` ScrDyn *dv = ${toDynExprC(emitter, inner, "pv")};`);
|
|
1411
|
-
if (isRefCounted(inner))
|
|
1412
|
-
d.push(` ${releaseCallC(inner, "pv")};`);
|
|
1413
|
-
d.push(fulfill(`dv`));
|
|
1414
|
-
break;
|
|
1415
|
-
}
|
|
1416
|
-
}
|
|
1417
|
-
d.push(`}`, ``);
|
|
1418
|
-
emitter.walkerDefs.push(...d);
|
|
1419
|
-
return name;
|
|
1420
|
-
}
|
|
1421
|
-
/* ── the checked-dynamic function boundary (ir.ts) ─────────────────
|
|
1422
|
-
* Three interned per-signature helpers:
|
|
1423
|
-
*
|
|
1424
|
-
* sc_dfk_<n> — the CALL THUNK a dyn-boxed closure carries: validate
|
|
1425
|
-
* each dyn argument into the declared param type (JS arity: extras
|
|
1426
|
-
* ignored, missing args are the undefined dyn value — a param type
|
|
1427
|
-
* the undefined value fails checks throws the path-annotated
|
|
1428
|
-
* TypeError), call through the closure, convert the result back to a
|
|
1429
|
-
* dyn value (+1).
|
|
1430
|
-
*
|
|
1431
|
-
* sc_dfb_<n> — the BOX builder dynFrom emits: a fresh SCR_DYN_FUNC
|
|
1432
|
-
* node carrying the retained closure, the thunk, the arity, the
|
|
1433
|
-
* interned signature key (typeKey — dynCheck's exact-unwrap fast
|
|
1434
|
-
* path), and the best-effort name.
|
|
1435
|
-
*
|
|
1436
|
-
* sc_dfa_<n> — the ADAPTER a func-targeted dynCheck wraps a
|
|
1437
|
-
* NON-identical boxed signature in: a closure of the TARGET type
|
|
1438
|
-
* whose body converts each typed argument INTO dyn, calls the boxed
|
|
1439
|
-
* thunk, and validates the dyn result into the target's return type.
|
|
1440
|
-
*/
|
|
1441
|
-
/** The dyn argument spelling of one static value (thunk results, adapter
|
|
1442
|
-
* arguments): dyn passes through (+1 via retain — callers own the
|
|
1443
|
-
* result uniformly), funcs box (anonymous — the static name is gone by
|
|
1444
|
-
* the time a value flows through an adapter; SEMANTICS.md), everything
|
|
1445
|
-
* else rides the toDyn converter. `expr` is BORROWED in every arm. */
|
|
1446
|
-
function toDynExprC(emitter, t, expr) {
|
|
1447
|
-
if (t.kind === "dyn")
|
|
1448
|
-
return `scr_dyn_retain(${expr})`;
|
|
1449
|
-
if (t.kind === "func")
|
|
1450
|
-
return `${emitter.dynFuncBoxHelper(t)}(${expr}, NULL)`;
|
|
1451
|
-
// An island value wraps by reference (scalar-normalizing) — the
|
|
1452
|
-
// jsval-returning callback shape of the routed-dispatch lane.
|
|
1453
|
-
if (t.kind === "jsval")
|
|
1454
|
-
return `scr_dyn_from_jsval(${expr})`;
|
|
1455
|
-
return `${emitter.toDynHelper(t)}(${expr})`;
|
|
1456
|
-
}
|
|
1457
|
-
/** The call thunk for one closure signature (see the block comment). */
|
|
1458
|
-
function dynFuncThunkHelper(emitter, t) {
|
|
1459
|
-
const key = typeKey(t);
|
|
1460
|
-
const existing = emitter.dynFuncThunks.get(key);
|
|
1461
|
-
if (existing)
|
|
1462
|
-
return existing;
|
|
1463
|
-
const name = `sc_dfk_${emitter.dynFuncThunks.size}`;
|
|
1464
|
-
emitter.dynFuncThunks.set(key, name);
|
|
1465
|
-
const sig = `static ScrDyn *${name}(ScrClosure *c, ScrDyn *const *args, size_t argc)`;
|
|
1466
|
-
emitter.walkerProtos.push(`${sig}; /* dyn call thunk for ${key} */`);
|
|
1467
|
-
const d = [`${sig} { /* dyn call thunk for ${key} */`];
|
|
1468
|
-
if (t.params.length === 0)
|
|
1469
|
-
d.push(` (void)args;`);
|
|
1470
|
-
d.push(` (void)argc;`);
|
|
1471
|
-
t.params.forEach((p, i) => {
|
|
1472
|
-
// JS arity: a missing argument IS the undefined dyn value; the
|
|
1473
|
-
// param's own check decides whether that flies (dyn params take
|
|
1474
|
-
// anything; a number param throws the catchable TypeError).
|
|
1475
|
-
d.push(` ${cDecl(p, `a${i}`)};`);
|
|
1476
|
-
d.push(` {`);
|
|
1477
|
-
d.push(` const ScrDyn *ad = ${i} < argc ? args[${i}] : scr_dyn_undefined();`);
|
|
1478
|
-
if (p.kind === "dyn") {
|
|
1479
|
-
d.push(` a${i} = scr_dyn_retain((ScrDyn *)ad);`);
|
|
1480
|
-
}
|
|
1481
|
-
else if (p.kind === "jsval") {
|
|
1482
|
-
// A checker-'any' param: the dyn argument enters the island —
|
|
1483
|
-
// wrapped cells unwrap by reference, data deep-copies, boxed
|
|
1484
|
-
// functions cross through the host shim; a kind with no crossing
|
|
1485
|
-
// throws the catchable TypeError (NULL + pending).
|
|
1486
|
-
d.push(` a${i} = scr_jsval_from_dyn(ad);`);
|
|
1487
|
-
const undo = t.params
|
|
1488
|
-
.slice(0, i)
|
|
1489
|
-
.flatMap((q, j) => (isRefCounted(q) ? [`${releaseCallC(q, `a${j}`)};`] : []));
|
|
1490
|
-
d.push(` if (!a${i}) { ${undo.join(" ")}${undo.length > 0 ? " " : ""}return NULL; }`);
|
|
1491
|
-
}
|
|
1492
|
-
else {
|
|
1493
|
-
d.push(` ScrDynPath pp = { NULL, NULL, ${i} };`);
|
|
1494
|
-
d.push(` a${i} = ${emitter.dynCheckHelper(p)}(ad, &pp);`);
|
|
1495
|
-
const undo = t.params
|
|
1496
|
-
.slice(0, i)
|
|
1497
|
-
.flatMap((q, j) => (isRefCounted(q) ? [`${releaseCallC(q, `a${j}`)};`] : []));
|
|
1498
|
-
d.push(` if (scr_exc_pending()) { ${undo.join(" ")}${undo.length > 0 ? " " : ""}return NULL; }`);
|
|
1499
|
-
}
|
|
1500
|
-
d.push(` }`);
|
|
1501
|
-
});
|
|
1502
|
-
// VARIADIC (rest-marked) signatures: one extra trailing dyn-array
|
|
1503
|
-
// param carries the call's arguments from index params.length on —
|
|
1504
|
-
// the mustCall wrapper's `arguments`, a JS `...args`. Built fresh per
|
|
1505
|
-
// call (+1, moved into the callee like every param).
|
|
1506
|
-
if (t.rest) {
|
|
1507
|
-
d.push(` ScrDyn *rest = scr_dyn_new_arr();`);
|
|
1508
|
-
d.push(` for (size_t ri = ${t.argumentsAll ? 0 : t.params.length}; ri < argc; ri++) {`);
|
|
1509
|
-
d.push(` scr_dyn_arr_push(rest, scr_dyn_retain((ScrDyn *)args[ri]));`);
|
|
1510
|
-
d.push(` }`);
|
|
1511
|
-
}
|
|
1512
|
-
// The closure CONSUMES its params (+1 each moved in — exactly what the
|
|
1513
|
-
// builders above returned).
|
|
1514
|
-
const castParams = ["ScrClosure *", ...t.params.map((p) => cType(p).trim()), ...(t.rest ? ["ScrDyn *"] : [])].join(", ");
|
|
1515
|
-
const call = `((${cType(t.ret).trim()} (*)(${castParams}))c->fn)(${["c", ...t.params.map((_, i) => `a${i}`), ...(t.rest ? ["rest"] : [])].join(", ")})`;
|
|
1516
|
-
if (t.ret.kind === "void") {
|
|
1517
|
-
d.push(` ${call};`);
|
|
1518
|
-
d.push(` if (scr_exc_pending()) return NULL;`);
|
|
1519
|
-
d.push(` return scr_dyn_retain(scr_dyn_undefined());`);
|
|
1520
|
-
}
|
|
1521
|
-
else if (t.ret.kind === "dyn") {
|
|
1522
|
-
d.push(` ScrDyn *r = ${call};`);
|
|
1523
|
-
d.push(` if (scr_exc_pending()) return NULL;`);
|
|
1524
|
-
d.push(` return r;`);
|
|
1525
|
-
}
|
|
1526
|
-
else {
|
|
1527
|
-
d.push(` ${cDecl(t.ret, "r")} = ${call};`);
|
|
1528
|
-
d.push(` if (scr_exc_pending()) return NULL;`);
|
|
1529
|
-
d.push(` ScrDyn *out = ${toDynExprC(emitter, t.ret, "r")};`);
|
|
1530
|
-
if (isRefCounted(t.ret))
|
|
1531
|
-
d.push(` ${releaseCallC(t.ret, "r")};`);
|
|
1532
|
-
d.push(` return out;`);
|
|
1533
|
-
}
|
|
1534
|
-
d.push(`}`, ``);
|
|
1535
|
-
emitter.walkerDefs.push(...d);
|
|
1536
|
-
return name;
|
|
1537
|
-
}
|
|
1538
|
-
/** The box builder dynFrom emits for one closure signature. */
|
|
1539
|
-
export function dynFuncBoxHelper(emitter, t) {
|
|
1540
|
-
const key = typeKey(t);
|
|
1541
|
-
const existing = emitter.dynFuncBoxes.get(key);
|
|
1542
|
-
if (existing)
|
|
1543
|
-
return existing;
|
|
1544
|
-
const name = `sc_dfb_${emitter.dynFuncBoxes.size}`;
|
|
1545
|
-
emitter.dynFuncBoxes.set(key, name);
|
|
1546
|
-
const sig = `static ScrDyn *${name}(ScrClosure *v, const char *fname)`;
|
|
1547
|
-
emitter.walkerProtos.push(`${sig}; /* box ${key} into dyn */`);
|
|
1548
|
-
const thunk = dynFuncThunkHelper(emitter, t);
|
|
1549
|
-
const sigLit = cStringLiteral(Buffer.from(key, "utf8"));
|
|
1550
|
-
emitter.walkerDefs.push(`${sig} { /* box ${key} into dyn */`, ` return scr_dyn_new_func(scr_closure_retain(v), &${thunk}, ${t.params.length}, ${sigLit}, fname);`, `}`, ``);
|
|
1551
|
-
return name;
|
|
1552
|
-
}
|
|
1553
|
-
/** The adapter closure body for one TARGET signature: the emitted C
|
|
1554
|
-
* function a func-targeted dynCheck wraps a non-identical boxed
|
|
1555
|
-
* signature in. caps[0] is an untraced obj-box owning the dyn function
|
|
1556
|
-
* value. */
|
|
1557
|
-
function dynFuncAdapterHelper(emitter, t) {
|
|
1558
|
-
const key = typeKey(t);
|
|
1559
|
-
const existing = emitter.dynFuncAdapters.get(key);
|
|
1560
|
-
if (existing)
|
|
1561
|
-
return existing;
|
|
1562
|
-
const name = `sc_dfa_${emitter.dynFuncAdapters.size}`;
|
|
1563
|
-
emitter.dynFuncAdapters.set(key, name);
|
|
1564
|
-
const params = ["ScrClosure *sc_env", ...t.params.map((p, i) => cDecl(p, `a${i}`))].join(", ");
|
|
1565
|
-
const sig = `static ${cType(t.ret)}${cType(t.ret).endsWith("*") ? "" : " "}${name}(${params})`;
|
|
1566
|
-
emitter.walkerProtos.push(`${sig}; /* dyn fn adapter to ${key} */`);
|
|
1567
|
-
const dummy = t.ret.kind === "void" ? "" : t.ret.kind === "f64" ? "0" : t.ret.kind === "bool" ? "false" : "NULL";
|
|
1568
|
-
const d = [`${sig} { /* dyn fn adapter to ${key} */`];
|
|
1569
|
-
d.push(` ScrDyn *sc_fn = (ScrDyn *)scr_box_get_ref(sc_env->caps[0]); /* +1 */`);
|
|
1570
|
-
// The adapter OWNS its params (closure ABI); each converts to a dyn
|
|
1571
|
-
// argument (toDynExprC borrows) and releases.
|
|
1572
|
-
if (t.params.length > 0) {
|
|
1573
|
-
d.push(` ScrDyn *sc_args[${t.params.length}];`);
|
|
1574
|
-
t.params.forEach((p, i) => {
|
|
1575
|
-
d.push(` sc_args[${i}] = ${toDynExprC(emitter, p, `a${i}`)};`);
|
|
1576
|
-
if (isRefCounted(p))
|
|
1577
|
-
d.push(` ${releaseCallC(p, `a${i}`)};`);
|
|
1578
|
-
});
|
|
1579
|
-
}
|
|
1580
|
-
// The kind is FUNC by construction (the dynCheck that built this
|
|
1581
|
-
// adapter tested it), so `what` is unreachable — spelled anyway.
|
|
1582
|
-
d.push(` ScrDyn *sc_r = scr_dyn_call(sc_fn, ${t.params.length > 0 ? "sc_args" : "NULL"}, ${t.params.length}, "value");`);
|
|
1583
|
-
d.push(` scr_dyn_release(sc_fn);`);
|
|
1584
|
-
t.params.forEach((_, i) => d.push(` scr_dyn_release(sc_args[${i}]);`));
|
|
1585
|
-
d.push(` if (scr_exc_pending()) return ${dummy};`.replace("return ;", "return;"));
|
|
1586
|
-
if (t.ret.kind === "void") {
|
|
1587
|
-
d.push(` scr_dyn_release(sc_r);`);
|
|
1588
|
-
d.push(` return;`);
|
|
1589
|
-
}
|
|
1590
|
-
else if (t.ret.kind === "dyn") {
|
|
1591
|
-
d.push(` return sc_r;`);
|
|
1592
|
-
}
|
|
1593
|
-
else {
|
|
1594
|
-
// Validate the dyn result into the target's return type — a lying
|
|
1595
|
-
// wrapper throws the catchable TypeError here (path "$"), exactly
|
|
1596
|
-
// the dynCheck stance; the dummy result rides the pending unwind.
|
|
1597
|
-
d.push(` ${cDecl(t.ret, "out")} = ${emitter.dynCheckHelper(t.ret)}(sc_r, NULL);`);
|
|
1598
|
-
d.push(` scr_dyn_release(sc_r);`);
|
|
1599
|
-
d.push(` return out;`);
|
|
1600
|
-
}
|
|
1601
|
-
d.push(`}`, ``);
|
|
1602
|
-
emitter.walkerDefs.push(...d);
|
|
1603
|
-
return name;
|
|
1604
|
-
}
|
|
1605
|
-
/** The emitted dynamic-keyed READ helper for one (shape, result type):
|
|
1606
|
-
* `static <T> sc_rkg_<n>(<struct> *r, ScrStr *k)` — declared fields
|
|
1607
|
-
* answer first (string comparisons in canonical order; the frontend
|
|
1608
|
-
* proved each surfaces as T: identity, a to-dyn conversion, or an
|
|
1609
|
-
* arm-into-union wrap), then the overflow map on index-signature shapes.
|
|
1610
|
-
* A MISSING key yields the undefined dyn value (T dyn), the undefined
|
|
1611
|
-
* arm (T undefined-armed union), or TRAPS with the key text (the array
|
|
1612
|
-
* OOB policy — the checker claimed T and no undefined is representable).
|
|
1613
|
-
* Borrows both; refcounted results are owned (+1). */
|
|
1614
|
-
export function recordKeyGetHelper(emitter, shapeId, t, overflowOnly = false) {
|
|
1615
|
-
const key = `${shapeId}|${typeKey(t)}${overflowOnly ? "|ovf" : ""}`;
|
|
1616
|
-
const existing = emitter.recordKeyGetFns.get(key);
|
|
1617
|
-
if (existing)
|
|
1618
|
-
return existing;
|
|
1619
|
-
const shape = emitter.recordsById.get(shapeId);
|
|
1620
|
-
if (!shape)
|
|
1621
|
-
throw new InternalCompilerError(`emitter bug: keyed read of unknown shape ${shapeId}`);
|
|
1622
|
-
const name = `sc_rkg_${emitter.recordKeyGetFns.size}`;
|
|
1623
|
-
emitter.recordKeyGetFns.set(key, name);
|
|
1624
|
-
const struct = mangleRecordStruct(shapeId);
|
|
1625
|
-
const sig = `static ${cType(t)}${cType(t).endsWith("*") ? "" : " "}${name}(${struct} *r, ScrStr *k)`;
|
|
1626
|
-
emitter.walkerProtos.push(`${sig}; /* r[k] on ${shapeId} as ${typeKey(t)} */`);
|
|
1627
|
-
const d = [`${sig} { /* r[k] on ${shapeId} as ${typeKey(t)} */`];
|
|
1628
|
-
// How a value of type `vt` (a field, or the overflow hit) surfaces as T.
|
|
1629
|
-
const surface = (vt, expr, owned) => {
|
|
1630
|
-
if (typeEquals(vt, t)) {
|
|
1631
|
-
return owned || !isRefCounted(vt) ? expr : retainCallC(vt, expr);
|
|
1632
|
-
}
|
|
1633
|
-
if (t.kind === "dyn") {
|
|
1634
|
-
// toDyn borrows — an owned operand would leak; callers pass borrowed.
|
|
1635
|
-
return `${emitter.toDynHelper(vt)}(${expr})`;
|
|
1636
|
-
}
|
|
1637
|
-
if (t.kind === "union") {
|
|
1638
|
-
const def = emitter.unionsById.get(t.unionId);
|
|
1639
|
-
const tag = def?.arms.findIndex((a) => typeEquals(a, vt)) ?? -1;
|
|
1640
|
-
if (tag < 0)
|
|
1641
|
-
throw new InternalCompilerError(`emitter bug: keyed read arm for ${typeKey(vt)} in ${typeKey(t)}`);
|
|
1642
|
-
if (vt.kind === "f64")
|
|
1643
|
-
return `scr_union_new_f64(${tag}, ${expr})`;
|
|
1644
|
-
if (vt.kind === "bool")
|
|
1645
|
-
return `scr_union_new_bool(${tag}, ${expr})`;
|
|
1646
|
-
const rc = vAdapters(vt);
|
|
1647
|
-
const payload = owned ? expr : retainCallC(vt, expr);
|
|
1648
|
-
return `scr_union_new_ref(${tag}, ${payload}, &${rc.retain}, &${rc.release}, ${emitter.traceArgC(vt)})`;
|
|
1649
|
-
}
|
|
1650
|
-
throw new InternalCompilerError(`emitter bug: keyed read cannot surface ${typeKey(vt)} as ${typeKey(t)}`);
|
|
1651
|
-
};
|
|
1652
|
-
// overflowOnly (a literal key naming no declared field): the declared
|
|
1653
|
-
// switch can never hit — only the overflow answers.
|
|
1654
|
-
for (const f of overflowOnly ? [] : shape.fields) {
|
|
1655
|
-
const lit = emitter.internLiteral(f.name);
|
|
1656
|
-
d.push(` if (scr_str_eq(k, (ScrStr *)&${lit})) { /* ${cCommentText(f.name)} */`);
|
|
1657
|
-
d.push(` return ${surface(f.type, `r->${mangleField(f.name)}`, false)};`);
|
|
1658
|
-
d.push(` }`);
|
|
1659
|
-
}
|
|
1660
|
-
const iv = shape.indexValue;
|
|
1661
|
-
if (iv) {
|
|
1662
|
-
const m = `r->${OVERFLOW_MEMBER}`;
|
|
1663
|
-
if (iv.kind === "f64" || iv.kind === "bool") {
|
|
1664
|
-
const acc = iv.kind === "f64" ? "f64" : "bool";
|
|
1665
|
-
d.push(` ${cDecl(iv, "hit")};`);
|
|
1666
|
-
d.push(` if (scr_map_get_str_${acc}(${m}, k, &hit)) {`);
|
|
1667
|
-
d.push(` return ${surface(iv, "hit", true)};`);
|
|
1668
|
-
d.push(` }`);
|
|
1669
|
-
}
|
|
1670
|
-
else {
|
|
1671
|
-
d.push(` ${cDecl(iv, "hit")} = (${cType(iv).trim()})scr_map_get_str_ref(${m}, k);`);
|
|
1672
|
-
d.push(` if (hit) {`);
|
|
1673
|
-
if (typeEquals(iv, t)) {
|
|
1674
|
-
d.push(` return hit; /* get returned +1 */`);
|
|
1675
|
-
}
|
|
1676
|
-
else if (t.kind === "union") {
|
|
1677
|
-
d.push(` return ${surface(iv, "hit", true)};`);
|
|
1678
|
-
}
|
|
1679
|
-
else {
|
|
1680
|
-
throw new InternalCompilerError(`emitter bug: keyed read overflow ${typeKey(iv)} as ${typeKey(t)}`);
|
|
1681
|
-
}
|
|
1682
|
-
d.push(` }`);
|
|
1683
|
-
}
|
|
1684
|
-
}
|
|
1685
|
-
// The miss path.
|
|
1686
|
-
if (t.kind === "dyn") {
|
|
1687
|
-
d.push(` return scr_dyn_retain(scr_dyn_undefined());`);
|
|
1688
|
-
}
|
|
1689
|
-
else if (t.kind === "union" && undefinedArmTag(t, emitter.unionsById) >= 0) {
|
|
1690
|
-
d.push(` return ${emitter.unitInstanceRef(t.unionId, undefinedArmTag(t, emitter.unionsById))};`);
|
|
1691
|
-
}
|
|
1692
|
-
else {
|
|
1693
|
-
// JS would answer undefined; T has no way to say it (the checker
|
|
1694
|
-
// claimed T without noUncheckedIndexedAccess) — trap like an array
|
|
1695
|
-
// OOB read instead of corrupting a typed slot (SEMANTICS.md).
|
|
1696
|
-
d.push(` scr_trap_fmt("scriptc: TypeError: record has no key '%.*s' (typed '${dynDesc(t, emitter.recordsById, emitter.unionsById)}' — no undefined is representable)\\n", (int)k->len, k->data);`);
|
|
1697
|
-
}
|
|
1698
|
-
d.push(`}`, ``);
|
|
1699
|
-
emitter.walkerDefs.push(...d);
|
|
1700
|
-
return name;
|
|
1701
|
-
}
|
|
1702
|
-
/** The emitted dynamic-keyed WRITE helper for one index-signature shape:
|
|
1703
|
-
* `static void sc_rks_<n>(<struct> *r, ScrStr *k, <V> v)` — a declared
|
|
1704
|
-
* key writes THROUGH to the struct slot (dyn values validate against the
|
|
1705
|
-
* field's type first via the dynCheck walker: a mismatch throws the
|
|
1706
|
-
* catchable TypeError and leaves the field untouched — JS would store
|
|
1707
|
-
* anything, the documented divergence; typed values store directly),
|
|
1708
|
-
* an undeclared key inserts/replaces in the overflow map. Borrows r and
|
|
1709
|
-
* k; OWNS v (+1 moves in — released on the validation-failure path). */
|
|
1710
|
-
export function recordKeySetHelper(emitter, shapeId) {
|
|
1711
|
-
const existing = emitter.recordKeySetFns.get(shapeId);
|
|
1712
|
-
if (existing)
|
|
1713
|
-
return existing;
|
|
1714
|
-
const shape = emitter.recordsById.get(shapeId);
|
|
1715
|
-
// Signature-free shapes dispatch over their (one-typed) declared
|
|
1716
|
-
// fields and TRAP on a miss (scr_record_key_miss — JS would add the
|
|
1717
|
-
// property, which a monomorphic struct cannot); overflow shapes keep
|
|
1718
|
-
// the map insert tail.
|
|
1719
|
-
const iv = shape?.indexValue ?? shape?.fields[0]?.type;
|
|
1720
|
-
if (!shape || !iv)
|
|
1721
|
-
throw new InternalCompilerError(`emitter bug: keyed write on field-free non-overflow shape ${shapeId}`);
|
|
1722
|
-
const name = `sc_rks_${emitter.recordKeySetFns.size}`;
|
|
1723
|
-
emitter.recordKeySetFns.set(shapeId, name);
|
|
1724
|
-
const struct = mangleRecordStruct(shapeId);
|
|
1725
|
-
const sig = `static void ${name}(${struct} *r, ScrStr *k, ${cDecl(iv, "v")})`;
|
|
1726
|
-
emitter.walkerProtos.push(`${sig}; /* r[k] = v on ${shapeId} */`);
|
|
1727
|
-
const d = [`${sig} { /* r[k] = v on ${shapeId} */`];
|
|
1728
|
-
for (const f of shape.fields) {
|
|
1729
|
-
const lit = emitter.internLiteral(f.name);
|
|
1730
|
-
const member = `r->${mangleField(f.name)}`;
|
|
1731
|
-
d.push(` if (scr_str_eq(k, (ScrStr *)&${lit})) { /* ${cCommentText(f.name)} */`);
|
|
1732
|
-
if (iv.kind === "dyn" && shape.indexValue) {
|
|
1733
|
-
const keyLit = cStringLiteral(Buffer.from(f.name, "utf8"));
|
|
1734
|
-
d.push(` ScrDynPath p = { NULL, ${keyLit}, 0 };`);
|
|
1735
|
-
d.push(` ${cDecl(f.type, "nv")} = ${emitter.dynCheckHelper(f.type)}(v, &p);`);
|
|
1736
|
-
d.push(` scr_dyn_release(v);`);
|
|
1737
|
-
d.push(` if (scr_exc_pending()) return; /* mismatched write: TypeError, field untouched */`);
|
|
1738
|
-
d.push(` ${isRefCounted(f.type) ? `if (${member}) ${releaseCallC(f.type, member)};` : `(void)0;`}`);
|
|
1739
|
-
d.push(` ${member} = nv;`);
|
|
1740
|
-
}
|
|
1741
|
-
else {
|
|
1742
|
-
// typeEquals(f.type, iv) — the frontend fences everything else.
|
|
1743
|
-
if (isRefCounted(f.type)) {
|
|
1744
|
-
d.push(` if (${member}) ${releaseCallC(f.type, member)};`);
|
|
1745
|
-
}
|
|
1746
|
-
d.push(` ${member} = v;`);
|
|
1747
|
-
}
|
|
1748
|
-
d.push(` return;`);
|
|
1749
|
-
d.push(` }`);
|
|
1750
|
-
}
|
|
1751
|
-
if (!shape.indexValue) {
|
|
1752
|
-
// The MISS on a fixed shape: release the moved-in value, throw the
|
|
1753
|
-
// catchable TypeError naming the key (JS would add the property —
|
|
1754
|
-
// the documented monomorphic-struct divergence).
|
|
1755
|
-
if (isRefCounted(iv))
|
|
1756
|
-
d.push(` if (v) ${releaseCallC(iv, "v")};`);
|
|
1757
|
-
d.push(` scr_record_key_miss(k);`);
|
|
1758
|
-
}
|
|
1759
|
-
else {
|
|
1760
|
-
const m = `r->${OVERFLOW_MEMBER}`;
|
|
1761
|
-
if (iv.kind === "f64" || iv.kind === "bool") {
|
|
1762
|
-
d.push(` scr_map_set_str_${iv.kind === "f64" ? "f64" : "bool"}(${m}, k, v);`);
|
|
1763
|
-
}
|
|
1764
|
-
else {
|
|
1765
|
-
d.push(` scr_map_set_str_ref(${m}, k, v); /* v moves in */`);
|
|
1766
|
-
}
|
|
1767
|
-
}
|
|
1768
|
-
d.push(`}`, ``);
|
|
1769
|
-
emitter.walkerDefs.push(...d);
|
|
1770
|
-
return name;
|
|
1771
|
-
}
|
|
1772
|
-
//# sourceMappingURL=walkers.js.map
|