@scriptc/compiler 0.0.34 → 0.0.36
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/ambient/scriptc-node-fallback.d.ts +7 -6
- package/dist/backend/build-cache.d.ts +44 -0
- package/dist/backend/build-cache.js +241 -0
- package/dist/backend/build-cache.js.map +1 -0
- package/dist/backend/{emission/emit-async.d.ts → c/async.d.ts} +21 -30
- package/dist/backend/{emission/emit-async.js → c/async.js} +270 -286
- package/dist/backend/c/async.js.map +1 -0
- package/dist/backend/{emission/emitter.d.ts → c/c-emitter.d.ts} +6 -23
- package/dist/backend/{emission/emitter.js → c/c-emitter.js} +53 -107
- package/dist/backend/c/c-emitter.js.map +1 -0
- package/dist/backend/c/exprs.d.ts +8 -0
- package/dist/backend/c/exprs.js +7913 -0
- package/dist/backend/c/exprs.js.map +1 -0
- package/dist/backend/{emission/emit-island.d.ts → c/island.d.ts} +5 -5
- package/dist/backend/{emission/emit-island.js → c/island.js} +24 -22
- package/dist/backend/c/island.js.map +1 -0
- package/dist/backend/{emission → c}/may-throw.d.ts +1 -1
- package/dist/backend/{emission → c}/may-throw.js +1 -1
- package/dist/backend/c/may-throw.js.map +1 -0
- package/dist/backend/{emission/emit-shapes.d.ts → c/shapes.d.ts} +19 -19
- package/dist/backend/{emission/emit-shapes.js → c/shapes.js} +78 -87
- package/dist/backend/c/shapes.js.map +1 -0
- package/dist/backend/{emission/emit-stmts.d.ts → c/stmts.d.ts} +12 -12
- package/dist/backend/{emission/emit-stmts.js → c/stmts.js} +377 -343
- package/dist/backend/c/stmts.js.map +1 -0
- package/dist/backend/{emission/emit-types.d.ts → c/types.d.ts} +1 -1
- package/dist/backend/{emission/emit-types.js → c/types.js} +42 -286
- package/dist/backend/c/types.js.map +1 -0
- package/dist/backend/c/types.test.js +25 -0
- package/dist/backend/c/types.test.js.map +1 -0
- package/dist/backend/{emission/emit-walkers.d.ts → c/walkers.d.ts} +19 -41
- package/dist/backend/{emission/emit-walkers.js → c/walkers.js} +238 -298
- package/dist/backend/c/walkers.js.map +1 -0
- package/dist/backend/ffi-callbacks.d.ts +1 -1
- package/dist/backend/ffi-callbacks.js +4 -3
- package/dist/backend/ffi-callbacks.js.map +1 -1
- package/dist/backend/{library-identity.d.ts → library-identity-markers.d.ts} +0 -4
- package/dist/backend/{library-identity.js → library-identity-markers.js} +10 -9
- package/dist/backend/library-identity-markers.js.map +1 -0
- package/dist/backend/llvm/blocks.d.ts +4 -0
- package/dist/backend/llvm/blocks.js +29 -0
- package/dist/backend/llvm/blocks.js.map +1 -1
- package/dist/backend/llvm/classes.d.ts +2 -19
- package/dist/backend/llvm/classes.js +20 -52
- package/dist/backend/llvm/classes.js.map +1 -1
- package/dist/backend/llvm/common.d.ts +4 -0
- package/dist/backend/llvm/common.js +27 -0
- package/dist/backend/llvm/common.js.map +1 -0
- package/dist/backend/llvm/dyn.d.ts +3 -8
- package/dist/backend/llvm/dyn.js +152 -224
- package/dist/backend/llvm/dyn.js.map +1 -1
- package/dist/backend/llvm/emitter.d.ts +4 -1
- package/dist/backend/llvm/emitter.js +514 -9981
- package/dist/backend/llvm/emitter.js.map +1 -1
- package/dist/backend/llvm/expr-async.d.ts +4 -0
- package/dist/backend/llvm/expr-async.js +726 -0
- package/dist/backend/llvm/expr-async.js.map +1 -0
- package/dist/backend/llvm/expr-bytes.d.ts +13 -0
- package/dist/backend/llvm/expr-bytes.js +456 -0
- package/dist/backend/llvm/expr-bytes.js.map +1 -0
- package/dist/backend/llvm/expr-callbacks.d.ts +22 -0
- package/dist/backend/llvm/expr-callbacks.js +520 -0
- package/dist/backend/llvm/expr-callbacks.js.map +1 -0
- package/dist/backend/llvm/expr-calls.d.ts +2 -0
- package/dist/backend/llvm/expr-calls.js +618 -0
- package/dist/backend/llvm/expr-calls.js.map +1 -0
- package/dist/backend/llvm/expr-containers.d.ts +25 -0
- package/dist/backend/llvm/expr-containers.js +623 -0
- package/dist/backend/llvm/expr-containers.js.map +1 -0
- package/dist/backend/llvm/expr-context.d.ts +255 -0
- package/dist/backend/llvm/expr-context.js +2 -0
- package/dist/backend/llvm/expr-context.js.map +1 -0
- package/dist/backend/llvm/expr-control.d.ts +2 -0
- package/dist/backend/llvm/expr-control.js +473 -0
- package/dist/backend/llvm/expr-control.js.map +1 -0
- package/dist/backend/llvm/expr-dispatch.d.ts +4 -0
- package/dist/backend/llvm/expr-dispatch.js +151 -0
- package/dist/backend/llvm/expr-dispatch.js.map +1 -0
- package/dist/backend/llvm/expr-dynamic.d.ts +2 -0
- package/dist/backend/llvm/expr-dynamic.js +810 -0
- package/dist/backend/llvm/expr-dynamic.js.map +1 -0
- package/dist/backend/llvm/expr-island.d.ts +15 -0
- package/dist/backend/llvm/expr-island.js +690 -0
- package/dist/backend/llvm/expr-island.js.map +1 -0
- package/dist/backend/llvm/expr-primitives.d.ts +6 -0
- package/dist/backend/llvm/expr-primitives.js +622 -0
- package/dist/backend/llvm/expr-primitives.js.map +1 -0
- package/dist/backend/llvm/expr-records.d.ts +9 -0
- package/dist/backend/llvm/expr-records.js +299 -0
- package/dist/backend/llvm/expr-records.js.map +1 -0
- package/dist/backend/llvm/expr-stream-bridges.d.ts +13 -0
- package/dist/backend/llvm/expr-stream-bridges.js +396 -0
- package/dist/backend/llvm/expr-stream-bridges.js.map +1 -0
- package/dist/backend/llvm/expr-stream-callbacks.d.ts +12 -0
- package/dist/backend/llvm/expr-stream-callbacks.js +360 -0
- package/dist/backend/llvm/expr-stream-callbacks.js.map +1 -0
- package/dist/backend/llvm/lib-dispatch.d.ts +5 -0
- package/dist/backend/llvm/lib-dispatch.js +267 -0
- package/dist/backend/llvm/lib-dispatch.js.map +1 -0
- package/dist/backend/llvm/lib-filesystem.d.ts +6 -0
- package/dist/backend/llvm/lib-filesystem.js +594 -0
- package/dist/backend/llvm/lib-filesystem.js.map +1 -0
- package/dist/backend/llvm/lib-network.d.ts +2 -0
- package/dist/backend/llvm/lib-network.js +429 -0
- package/dist/backend/llvm/lib-network.js.map +1 -0
- package/dist/backend/llvm/lib-process.d.ts +5 -0
- package/dist/backend/llvm/lib-process.js +585 -0
- package/dist/backend/llvm/lib-process.js.map +1 -0
- package/dist/backend/llvm/lib-shared.d.ts +6 -0
- package/dist/backend/llvm/lib-shared.js +687 -0
- package/dist/backend/llvm/lib-shared.js.map +1 -0
- package/dist/backend/llvm/lib-stream.d.ts +2 -0
- package/dist/backend/llvm/lib-stream.js +470 -0
- package/dist/backend/llvm/lib-stream.js.map +1 -0
- package/dist/backend/llvm/shapes.d.ts +12 -2
- package/dist/backend/llvm/shapes.js +66 -307
- package/dist/backend/llvm/shapes.js.map +1 -1
- package/dist/backend/llvm/shapes.test.js +52 -0
- package/dist/backend/llvm/shapes.test.js.map +1 -0
- package/dist/backend/llvm/split.d.ts +43 -0
- package/dist/backend/llvm/split.js +227 -0
- package/dist/backend/llvm/split.js.map +1 -0
- package/dist/backend/llvm/split.test.d.ts +1 -0
- package/dist/backend/llvm/split.test.js +102 -0
- package/dist/backend/llvm/split.test.js.map +1 -0
- package/dist/backend/llvm/unsupported.d.ts +1 -1
- package/dist/backend/llvm/walkers.d.ts +2 -3
- package/dist/backend/llvm/walkers.js +164 -218
- package/dist/backend/llvm/walkers.js.map +1 -1
- package/dist/backend/native-codegen.d.ts +38 -0
- package/dist/backend/native-codegen.js +261 -0
- package/dist/backend/native-codegen.js.map +1 -0
- package/dist/backend/native-codegen.test.d.ts +1 -0
- package/dist/backend/native-codegen.test.js +188 -0
- package/dist/backend/native-codegen.test.js.map +1 -0
- package/dist/backend/native-link-info.d.ts +96 -0
- package/dist/backend/native-link-info.js +219 -0
- package/dist/backend/native-link-info.js.map +1 -0
- package/dist/backend/native-link-info.test.d.ts +1 -0
- package/dist/backend/native-link-info.test.js +134 -0
- package/dist/backend/native-link-info.test.js.map +1 -0
- package/dist/backend/{cc.d.ts → native-toolchain.d.ts} +139 -47
- package/dist/backend/{cc.js → native-toolchain.js} +1008 -910
- package/dist/backend/native-toolchain.js.map +1 -0
- package/dist/backend/native-toolchain.test.d.ts +1 -0
- package/dist/backend/{cc-cache.test.js → native-toolchain.test.js} +1297 -127
- package/dist/backend/native-toolchain.test.js.map +1 -0
- package/dist/backend/object-localize.js +1 -1
- package/dist/backend/object-localize.test.js +20 -0
- package/dist/backend/object-localize.test.js.map +1 -1
- package/dist/backend/runtime-abi.d.ts +10 -0
- package/dist/backend/runtime-abi.js +11 -0
- package/dist/backend/runtime-abi.js.map +1 -0
- package/dist/backend/runtime-pack.d.ts +137 -0
- package/dist/backend/runtime-pack.js +400 -0
- package/dist/backend/runtime-pack.js.map +1 -0
- package/dist/backend/runtime-pack.test.d.ts +1 -0
- package/dist/backend/runtime-pack.test.js +438 -0
- package/dist/backend/runtime-pack.test.js.map +1 -0
- package/dist/backend/targets.d.ts +30 -0
- package/dist/backend/targets.js +46 -0
- package/dist/backend/targets.js.map +1 -0
- package/dist/backend/targets.test.d.ts +1 -0
- package/dist/backend/targets.test.js +19 -0
- package/dist/backend/targets.test.js.map +1 -0
- package/dist/backend/vendor-archives.d.ts +41 -0
- package/dist/backend/vendor-archives.js +462 -0
- package/dist/backend/vendor-archives.js.map +1 -0
- package/dist/compat/fetch-profile.d.ts +0 -1
- package/dist/compat/fetch-profile.js +0 -1
- package/dist/compat/fetch-profile.js.map +1 -1
- package/dist/coverage/report.js +3 -3
- package/dist/coverage/report.js.map +1 -1
- package/dist/coverage/surface-manifest.js +25 -32
- package/dist/coverage/surface-manifest.js.map +1 -1
- package/dist/diagnostics/diagnostic.d.ts +11 -12
- package/dist/diagnostics/diagnostic.js +19 -17
- package/dist/diagnostics/diagnostic.js.map +1 -1
- package/dist/diagnostics/render.d.ts +1 -1
- package/dist/diagnostics/render.js +1 -1
- package/dist/diagnostics/render.js.map +1 -1
- package/dist/errors.d.ts +5 -0
- package/dist/errors.js +9 -0
- package/dist/errors.js.map +1 -0
- package/dist/executable/executable-cache.d.ts +86 -0
- package/dist/executable/executable-cache.js +398 -0
- package/dist/executable/executable-cache.js.map +1 -0
- package/dist/executable/executable-cache.test.d.ts +1 -0
- package/dist/executable/executable-cache.test.js +300 -0
- package/dist/executable/executable-cache.test.js.map +1 -0
- package/dist/ffi/{profile.d.ts → ffi-manifest.d.ts} +7 -2
- package/dist/ffi/{profile.js → ffi-manifest.js} +2 -1
- package/dist/ffi/ffi-manifest.js.map +1 -0
- package/dist/frontend/builtin-modules.d.ts +21 -0
- package/dist/frontend/builtin-modules.js +82 -0
- package/dist/frontend/builtin-modules.js.map +1 -0
- package/dist/frontend/cjs-lexer.d.ts +7 -0
- package/dist/frontend/cjs-lexer.js +15 -17
- package/dist/frontend/cjs-lexer.js.map +1 -1
- package/dist/frontend/dts-paths.d.ts +26 -0
- package/dist/frontend/dts-paths.js +41 -0
- package/dist/frontend/dts-paths.js.map +1 -0
- package/dist/frontend/input-tracker.d.ts +0 -2
- package/dist/frontend/input-tracker.js +1 -4
- package/dist/frontend/input-tracker.js.map +1 -1
- package/dist/frontend/lib-contract.d.ts +1 -5
- package/dist/frontend/lib-contract.js +1 -1
- package/dist/frontend/lib-contract.js.map +1 -1
- package/dist/frontend/lib-exports.d.ts +1 -1
- package/dist/frontend/lowering/call-position.d.ts +4 -0
- package/dist/frontend/lowering/call-position.js +7 -0
- package/dist/frontend/lowering/call-position.js.map +1 -0
- package/dist/frontend/lowering/callback-arg.d.ts +20 -0
- package/dist/frontend/lowering/callback-arg.js +44 -0
- package/dist/frontend/lowering/callback-arg.js.map +1 -0
- package/dist/frontend/lowering/lib-boundary.d.ts +1 -1
- package/dist/frontend/lowering/lib-boundary.js +34 -34
- package/dist/frontend/lowering/lib-boundary.js.map +1 -1
- package/dist/frontend/lowering/lower-assert.d.ts +3 -3
- package/dist/frontend/lowering/lower-assert.js +214 -241
- package/dist/frontend/lowering/lower-assert.js.map +1 -1
- package/dist/frontend/lowering/lower-builtins.d.ts +74 -146
- package/dist/frontend/lowering/lower-builtins.js +1126 -1234
- package/dist/frontend/lowering/lower-builtins.js.map +1 -1
- package/dist/frontend/lowering/lower-calls.d.ts +56 -188
- package/dist/frontend/lowering/lower-calls.js +1409 -1494
- package/dist/frontend/lowering/lower-calls.js.map +1 -1
- package/dist/frontend/lowering/lower-classes.d.ts +62 -125
- package/dist/frontend/lowering/lower-classes.js +832 -866
- package/dist/frontend/lowering/lower-classes.js.map +1 -1
- package/dist/frontend/lowering/lower-comptime.d.ts +5 -12
- package/dist/frontend/lowering/lower-comptime.js +32 -31
- package/dist/frontend/lowering/lower-comptime.js.map +1 -1
- package/dist/frontend/lowering/lower-containers.d.ts +35 -135
- package/dist/frontend/lowering/lower-containers.js +1394 -1715
- package/dist/frontend/lowering/lower-containers.js.map +1 -1
- package/dist/frontend/lowering/lower-dgram.d.ts +3 -7
- package/dist/frontend/lowering/lower-dgram.js +97 -111
- package/dist/frontend/lowering/lower-dgram.js.map +1 -1
- package/dist/frontend/lowering/lower-enums.d.ts +4 -4
- package/dist/frontend/lowering/lower-enums.js +30 -30
- package/dist/frontend/lowering/lower-enums.js.map +1 -1
- package/dist/frontend/lowering/{lower-emitter.d.ts → lower-event-emitter.d.ts} +7 -18
- package/dist/frontend/lowering/{lower-emitter.js → lower-event-emitter.js} +172 -174
- package/dist/frontend/lowering/lower-event-emitter.js.map +1 -0
- package/dist/frontend/lowering/lower-expando.d.ts +5 -5
- package/dist/frontend/lowering/lower-expando.js +40 -40
- package/dist/frontend/lowering/lower-expando.js.map +1 -1
- package/dist/frontend/lowering/lower-exprs.d.ts +56 -264
- package/dist/frontend/lowering/lower-exprs.js +1644 -1704
- package/dist/frontend/lowering/lower-exprs.js.map +1 -1
- package/dist/frontend/lowering/lower-generators.d.ts +6 -6
- package/dist/frontend/lowering/lower-generators.js +73 -72
- package/dist/frontend/lowering/lower-generators.js.map +1 -1
- package/dist/frontend/lowering/lower-inspect.d.ts +5 -17
- package/dist/frontend/lowering/lower-inspect.js +236 -238
- package/dist/frontend/lowering/lower-inspect.js.map +1 -1
- package/dist/frontend/lowering/lower-island.d.ts +34 -45
- package/dist/frontend/lowering/lower-island.js +440 -511
- package/dist/frontend/lowering/lower-island.js.map +1 -1
- package/dist/frontend/lowering/lower-mixins.d.ts +7 -10
- package/dist/frontend/lowering/lower-mixins.js +86 -86
- package/dist/frontend/lowering/lower-mixins.js.map +1 -1
- package/dist/frontend/lowering/lower-modules.d.ts +12 -18
- package/dist/frontend/lowering/lower-modules.js +284 -283
- package/dist/frontend/lowering/lower-modules.js.map +1 -1
- package/dist/frontend/lowering/lower-namespaces.d.ts +23 -49
- package/dist/frontend/lowering/lower-namespaces.js +123 -115
- package/dist/frontend/lowering/lower-namespaces.js.map +1 -1
- package/dist/frontend/lowering/lower-server.d.ts +18 -25
- package/dist/frontend/lowering/lower-server.js +899 -899
- package/dist/frontend/lowering/lower-server.js.map +1 -1
- package/dist/frontend/lowering/lower-stmts.d.ts +30 -149
- package/dist/frontend/lowering/lower-stmts.js +1176 -1229
- package/dist/frontend/lowering/lower-stmts.js.map +1 -1
- package/dist/frontend/lowering/lower-stream.d.ts +12 -12
- package/dist/frontend/lowering/lower-stream.js +300 -301
- package/dist/frontend/lowering/lower-stream.js.map +1 -1
- package/dist/frontend/lowering/lower-test.d.ts +5 -5
- package/dist/frontend/lowering/lower-test.js +82 -82
- package/dist/frontend/lowering/lower-test.js.map +1 -1
- package/dist/frontend/lowering/lowerer.d.ts +66 -20
- package/dist/frontend/lowering/lowerer.js +421 -198
- package/dist/frontend/lowering/lowerer.js.map +1 -1
- package/dist/frontend/lowering/pairs-snapshot.d.ts +11 -0
- package/dist/frontend/lowering/pairs-snapshot.js +85 -0
- package/dist/frontend/lowering/pairs-snapshot.js.map +1 -0
- package/dist/frontend/lowering/static-this.d.ts +6 -0
- package/dist/frontend/lowering/static-this.js +24 -0
- package/dist/frontend/lowering/static-this.js.map +1 -0
- package/dist/frontend/lowering/surfaces.d.ts +14 -33
- package/dist/frontend/lowering/surfaces.js +64 -64
- package/dist/frontend/lowering/surfaces.js.map +1 -1
- package/dist/frontend/npm-static-rewrite.js +6 -28
- package/dist/frontend/npm-static-rewrite.js.map +1 -1
- package/dist/frontend/npm-static.d.ts +0 -10
- package/dist/frontend/npm-static.js +4 -7
- package/dist/frontend/npm-static.js.map +1 -1
- package/dist/frontend/npm.d.ts +0 -24
- package/dist/frontend/npm.js +11 -85
- package/dist/frontend/npm.js.map +1 -1
- package/dist/frontend/program.d.ts +3 -1
- package/dist/frontend/program.js +51 -17
- package/dist/frontend/program.js.map +1 -1
- package/dist/frontend/provenance-registry.d.ts +0 -2
- package/dist/frontend/provenance-registry.js +0 -10
- package/dist/frontend/provenance-registry.js.map +1 -1
- package/dist/frontend/provenance.js +4 -7
- package/dist/frontend/provenance.js.map +1 -1
- package/dist/frontend/resolve.d.ts +7 -2
- package/dist/frontend/resolve.js +12 -17
- package/dist/frontend/resolve.js.map +1 -1
- package/dist/frontend/resolve.test.d.ts +1 -0
- package/dist/frontend/resolve.test.js +29 -0
- package/dist/frontend/resolve.test.js.map +1 -0
- package/dist/frontend/ts7/adapter.d.ts +2 -2
- package/dist/frontend/ts7/adapter.js +1 -1
- package/dist/frontend/ts7/adapter.js.map +1 -1
- package/dist/frontend/ts7/checker.d.ts +40 -2
- package/dist/frontend/ts7/checker.js +182 -54
- package/dist/frontend/ts7/checker.js.map +1 -1
- package/dist/frontend/ts7/enums.js +2 -1
- package/dist/frontend/ts7/enums.js.map +1 -1
- package/dist/frontend/ts7/{program.js → program-adapter.js} +7 -6
- package/dist/frontend/ts7/program-adapter.js.map +1 -0
- package/dist/frontend/ts7/world-check.d.ts +1 -3
- package/dist/frontend/ts7/world-check.js +3 -1
- package/dist/frontend/ts7/world-check.js.map +1 -1
- package/dist/frontend/tsc-codes.d.ts +8 -0
- package/dist/frontend/tsc-codes.js +109 -0
- package/dist/frontend/tsc-codes.js.map +1 -0
- package/dist/frontend/{types.d.ts → type-mapper.d.ts} +2 -25
- package/dist/frontend/{types.js → type-mapper.js} +31 -52
- package/dist/frontend/type-mapper.js.map +1 -0
- package/dist/frontend/workspace-registry.d.ts +26 -0
- package/dist/frontend/workspace-registry.js +71 -0
- package/dist/frontend/workspace-registry.js.map +1 -0
- package/dist/index.d.ts +115 -30
- package/dist/index.js +650 -146
- package/dist/index.js.map +1 -1
- package/dist/ir/analysis.d.ts +37 -0
- package/dist/ir/analysis.js +118 -0
- package/dist/ir/analysis.js.map +1 -0
- package/dist/ir/analysis.test.d.ts +1 -0
- package/dist/ir/analysis.test.js +21 -0
- package/dist/ir/analysis.test.js.map +1 -0
- package/dist/ir/build.d.ts +9 -0
- package/dist/ir/build.js +33 -0
- package/dist/ir/build.js.map +1 -0
- package/dist/ir/integer-loops.d.ts +1 -1
- package/dist/ir/{nodes.d.ts → ir.d.ts} +60 -26
- package/dist/ir/{nodes.js → ir.js} +173 -141
- package/dist/ir/ir.js.map +1 -0
- package/dist/ir/ir.test.d.ts +1 -0
- package/dist/ir/ir.test.js +17 -0
- package/dist/ir/ir.test.js.map +1 -0
- package/dist/ir/serialize.d.ts +1 -1
- package/dist/ir/serialize.js +2 -1
- package/dist/ir/serialize.js.map +1 -1
- package/dist/ir/validate.d.ts +1 -1
- package/dist/ir/validate.js +16 -5
- package/dist/ir/validate.js.map +1 -1
- package/dist/library/cache-primitives.d.ts +24 -0
- package/dist/library/cache-primitives.js +83 -0
- package/dist/library/cache-primitives.js.map +1 -0
- package/dist/library/cache-reset.test.d.ts +1 -0
- package/dist/library/cache-reset.test.js +47 -0
- package/dist/library/cache-reset.test.js.map +1 -0
- package/dist/library/compiler-self-identity.d.ts +23 -0
- package/dist/library/compiler-self-identity.js +84 -0
- package/dist/library/compiler-self-identity.js.map +1 -0
- package/dist/library/fence-eval.d.ts +3 -1
- package/dist/library/fence-eval.js +5 -1
- package/dist/library/fence-eval.js.map +1 -1
- package/dist/library/int-infer.d.ts +1 -36
- package/dist/library/int-infer.js +17 -17
- package/dist/library/int-infer.js.map +1 -1
- package/dist/library/{early-cache.d.ts → library-cache.d.ts} +1 -1
- package/dist/library/{early-cache.js → library-cache.js} +37 -111
- package/dist/library/library-cache.js.map +1 -0
- package/dist/library/library-cache.test.d.ts +1 -0
- package/dist/library/{early-cache.test.js → library-cache.test.js} +2 -2
- package/dist/library/library-cache.test.js.map +1 -0
- package/dist/library/{profile.d.ts → library-profile.d.ts} +4 -7
- package/dist/library/{profile.js → library-profile.js} +18 -11
- package/dist/library/library-profile.js.map +1 -0
- package/dist/library/semantic-source.js +2 -1
- package/dist/library/semantic-source.js.map +1 -1
- package/dist/library/sidecar.d.ts +5 -2
- package/dist/library/sidecar.js +11 -5
- package/dist/library/sidecar.js.map +1 -1
- package/dist/startup-cache.d.ts +6 -0
- package/dist/startup-cache.js +6 -0
- package/dist/startup-cache.js.map +1 -0
- package/package.json +7 -2
- package/surface-manifest.json +1 -1
- package/dist/backend/cc-cache.test.js.map +0 -1
- package/dist/backend/cc.js.map +0 -1
- package/dist/backend/emission/emit-async.js.map +0 -1
- package/dist/backend/emission/emit-exprs.d.ts +0 -13
- package/dist/backend/emission/emit-exprs.js +0 -7407
- package/dist/backend/emission/emit-exprs.js.map +0 -1
- package/dist/backend/emission/emit-island.js.map +0 -1
- package/dist/backend/emission/emit-shapes.js.map +0 -1
- package/dist/backend/emission/emit-stmts.js.map +0 -1
- package/dist/backend/emission/emit-types.js.map +0 -1
- package/dist/backend/emission/emit-walkers.js.map +0 -1
- package/dist/backend/emission/emitter.js.map +0 -1
- package/dist/backend/emission/may-throw.js.map +0 -1
- package/dist/backend/library-identity.js.map +0 -1
- package/dist/ffi/profile.js.map +0 -1
- package/dist/frontend/lowering/lower-emitter.js.map +0 -1
- package/dist/frontend/shared.d.ts +0 -82
- package/dist/frontend/shared.js +0 -308
- package/dist/frontend/shared.js.map +0 -1
- package/dist/frontend/ts7/program.js.map +0 -1
- package/dist/frontend/types.js.map +0 -1
- package/dist/ir/nodes.js.map +0 -1
- package/dist/library/early-cache.js.map +0 -1
- package/dist/library/early-cache.test.js.map +0 -1
- package/dist/library/profile.js.map +0 -1
- /package/dist/backend/{cc-cache.test.d.ts → c/types.test.d.ts} +0 -0
- /package/dist/{library/early-cache.test.d.ts → backend/llvm/shapes.test.d.ts} +0 -0
- /package/dist/frontend/ts7/{program.d.ts → program-adapter.d.ts} +0 -0
|
@@ -1,84 +1,24 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import { InternalCompilerError } from "../../errors.js";
|
|
2
|
+
import { DYN_HANDLE_KINDS, isRefCounted, typeEquals, typeKey } from "../../ir/ir.js";
|
|
3
|
+
import { dynDesc, undefinedArmTag } from "../../ir/analysis.js";
|
|
4
|
+
import { cDecl, cStringLiteral, cType, elemAccess, releaseCallC, retainCallC, vAdapters } from "./types.js";
|
|
3
5
|
import { mangleField, mangleRecordNew, mangleRecordStruct } from "../mangle.js";
|
|
4
|
-
import { OVERFLOW_MEMBER } from "./
|
|
5
|
-
/** Short human description of a dynCheck target for error messages
|
|
6
|
-
* ("expected number | string at $.items[2]"). Records read as "object" —
|
|
7
|
-
* the path already says where; the full shape would bloat messages. */
|
|
8
|
-
export function dynDesc(E, t) {
|
|
9
|
-
switch (t.kind) {
|
|
10
|
-
case "f64":
|
|
11
|
-
return "number";
|
|
12
|
-
case "string":
|
|
13
|
-
return "string";
|
|
14
|
-
case "bool":
|
|
15
|
-
return "boolean";
|
|
16
|
-
case "record":
|
|
17
|
-
// Tuples read as "array": that IS the JSON representation the
|
|
18
|
-
// caller must supply (arity failures carry their own message).
|
|
19
|
-
return E.recordsById.get(t.shapeId)?.tuple ? "array" : "object";
|
|
20
|
-
case "array":
|
|
21
|
-
return "array";
|
|
22
|
-
case "nullT":
|
|
23
|
-
return "null";
|
|
24
|
-
// Reachable through optional-flavored record fields ("expected
|
|
25
|
-
// string | undefined at $.a" — honest: the fix is a string value OR
|
|
26
|
-
// omitting the key).
|
|
27
|
-
case "undefinedT":
|
|
28
|
-
return "undefined";
|
|
29
|
-
// dyn fields accept any dyn value — only reachable in messages as a
|
|
30
|
-
// sibling of a failing field, never as the failure itself.
|
|
31
|
-
case "dyn":
|
|
32
|
-
return "unknown";
|
|
33
|
-
case "bytes":
|
|
34
|
-
return "Uint8Array";
|
|
35
|
-
// The %Error extraction (an instanceof-Error narrow / cast on an
|
|
36
|
-
// unknown value): the failure names the class, like caughtCheck's.
|
|
37
|
-
case "object":
|
|
38
|
-
return t.className.replace(/^%/, "");
|
|
39
|
-
case "union": {
|
|
40
|
-
const def = E.unionsById.get(t.unionId);
|
|
41
|
-
if (!def)
|
|
42
|
-
throw new Error(`emitter bug: dynDesc of unknown union ${t.unionId}`);
|
|
43
|
-
return def.arms.map((a) => E.dynDesc(a)).join(" | ");
|
|
44
|
-
}
|
|
45
|
-
// Function targets (the checked-dynamic function boundary): the
|
|
46
|
-
// failure names the expected callability, not the full signature —
|
|
47
|
-
// the path already says where.
|
|
48
|
-
case "func":
|
|
49
|
-
return "function";
|
|
50
|
-
// Map/Set-valued index signatures (Record<string, Map<K, V>>): only
|
|
51
|
-
// reachable through the keyed-read miss trap's message — no dynCheck
|
|
52
|
-
// ever expects one.
|
|
53
|
-
case "map":
|
|
54
|
-
return "Map";
|
|
55
|
-
case "set":
|
|
56
|
-
return "Set";
|
|
57
|
-
default: {
|
|
58
|
-
// Runtime HANDLE targets name the class ("expected
|
|
59
|
-
// IncomingMessage at $, got string").
|
|
60
|
-
const h = DYN_HANDLE_KINDS.get(t.kind);
|
|
61
|
-
if (h)
|
|
62
|
-
return h.cls;
|
|
63
|
-
throw new Error(`emitter bug: dynDesc of non-JSON type ${t.kind}`);
|
|
64
|
-
}
|
|
65
|
-
}
|
|
66
|
-
}
|
|
6
|
+
import { OVERFLOW_MEMBER } from "./shapes.js";
|
|
67
7
|
/** The per-union ToBoolean helper (interned per unionId): switch on the
|
|
68
8
|
* runtime tag — unit arms false, f64 arms 0/NaN-falsy, string arms
|
|
69
9
|
* empty-falsy, bool arms by payload, ref arms always true (JS objects),
|
|
70
10
|
* jsval arms answered by the engine. Borrows the operand. */
|
|
71
|
-
export function unionTruthyHelper(
|
|
72
|
-
const existing =
|
|
11
|
+
export function unionTruthyHelper(emitter, unionId) {
|
|
12
|
+
const existing = emitter.unionTruthyFns.get(unionId);
|
|
73
13
|
if (existing)
|
|
74
14
|
return existing;
|
|
75
|
-
const def =
|
|
15
|
+
const def = emitter.unionsById.get(unionId);
|
|
76
16
|
if (!def)
|
|
77
|
-
throw new
|
|
78
|
-
const name = `sc_ut_${
|
|
79
|
-
|
|
17
|
+
throw new InternalCompilerError(`emitter bug: truthiness of unknown union ${unionId}`);
|
|
18
|
+
const name = `sc_ut_${emitter.unionTruthyFns.size}`;
|
|
19
|
+
emitter.unionTruthyFns.set(unionId, name);
|
|
80
20
|
const sig = `static bool ${name}(ScrUnion *v)`;
|
|
81
|
-
|
|
21
|
+
emitter.walkerProtos.push(`${sig}; /* ToBoolean ${unionId} */`);
|
|
82
22
|
const d = [`${sig} { /* ToBoolean ${unionId} */`, ` switch (v->tag) {`];
|
|
83
23
|
def.arms.forEach((arm, i) => {
|
|
84
24
|
switch (arm.kind) {
|
|
@@ -105,7 +45,7 @@ export function unionTruthyHelper(E, unionId) {
|
|
|
105
45
|
}
|
|
106
46
|
});
|
|
107
47
|
d.push(` default: scr_trap("scriptc: internal error: invalid union tag\\n");`, ` }`, `}`, ``);
|
|
108
|
-
|
|
48
|
+
emitter.walkerDefs.push(...d);
|
|
109
49
|
return name;
|
|
110
50
|
}
|
|
111
51
|
/** The per-union strict-equality helper (interned per unionId, with a
|
|
@@ -115,19 +55,19 @@ export function unionTruthyHelper(E, unionId) {
|
|
|
115
55
|
* (NaN equals NaN, +0 differs from -0) under the sameValue flag,
|
|
116
56
|
* strings by bytes, bools by value, ref arms by POINTER identity (JS
|
|
117
57
|
* object equality). Borrows both operands. */
|
|
118
|
-
export function unionEqHelper(
|
|
58
|
+
export function unionEqHelper(emitter, unionId, sameValue) {
|
|
119
59
|
const key = sameValue ? `sv:${unionId}` : unionId;
|
|
120
|
-
const existing =
|
|
60
|
+
const existing = emitter.unionEqFns.get(key);
|
|
121
61
|
if (existing)
|
|
122
62
|
return existing;
|
|
123
|
-
const def =
|
|
63
|
+
const def = emitter.unionsById.get(unionId);
|
|
124
64
|
if (!def)
|
|
125
|
-
throw new
|
|
126
|
-
const name = `sc_ue_${
|
|
127
|
-
|
|
65
|
+
throw new InternalCompilerError(`emitter bug: equality of unknown union ${unionId}`);
|
|
66
|
+
const name = `sc_ue_${emitter.unionEqFns.size}`;
|
|
67
|
+
emitter.unionEqFns.set(key, name);
|
|
128
68
|
const what = sameValue ? "SameValue" : "strict equality";
|
|
129
69
|
const sig = `static bool ${name}(ScrUnion *a, ScrUnion *b)`;
|
|
130
|
-
|
|
70
|
+
emitter.walkerProtos.push(`${sig}; /* ${what} ${unionId} */`);
|
|
131
71
|
const d = [
|
|
132
72
|
`${sig} { /* ${what} ${unionId} */`,
|
|
133
73
|
` if (a->tag != b->tag) return false;`,
|
|
@@ -156,7 +96,7 @@ export function unionEqHelper(E, unionId, sameValue) {
|
|
|
156
96
|
}
|
|
157
97
|
});
|
|
158
98
|
d.push(` default: scr_trap("scriptc: internal error: invalid union tag\\n");`, ` }`, `}`, ``);
|
|
159
|
-
|
|
99
|
+
emitter.walkerDefs.push(...d);
|
|
160
100
|
return name;
|
|
161
101
|
}
|
|
162
102
|
/** The per-union ToString helper (interned per unionId): switch on the
|
|
@@ -165,23 +105,23 @@ export function unionEqHelper(E, unionId, sameValue) {
|
|
|
165
105
|
* formatters (String(x) semantics). Ref arms never arrive (the frontend
|
|
166
106
|
* fences unions with object arms from string conversion — JS would print
|
|
167
107
|
* "[object Object]"). Borrows the operand; the result is owned (+1). */
|
|
168
|
-
export function unionToStrHelper(
|
|
169
|
-
const existing =
|
|
108
|
+
export function unionToStrHelper(emitter, unionId) {
|
|
109
|
+
const existing = emitter.unionToStrFns.get(unionId);
|
|
170
110
|
if (existing)
|
|
171
111
|
return existing;
|
|
172
|
-
const def =
|
|
112
|
+
const def = emitter.unionsById.get(unionId);
|
|
173
113
|
if (!def)
|
|
174
|
-
throw new
|
|
175
|
-
const name = `sc_us_${
|
|
176
|
-
|
|
114
|
+
throw new InternalCompilerError(`emitter bug: ToString of unknown union ${unionId}`);
|
|
115
|
+
const name = `sc_us_${emitter.unionToStrFns.size}`;
|
|
116
|
+
emitter.unionToStrFns.set(unionId, name);
|
|
177
117
|
const sig = `static ScrStr *${name}(ScrUnion *v)`;
|
|
178
|
-
|
|
118
|
+
emitter.walkerProtos.push(`${sig}; /* ToString ${unionId} */`);
|
|
179
119
|
const d = [`${sig} { /* ToString ${unionId} */`, ` switch (v->tag) {`];
|
|
180
120
|
def.arms.forEach((arm, i) => {
|
|
181
121
|
switch (arm.kind) {
|
|
182
122
|
case "undefinedT":
|
|
183
123
|
case "nullT": {
|
|
184
|
-
const lit =
|
|
124
|
+
const lit = emitter.internLiteral(arm.kind === "undefinedT" ? "undefined" : "null");
|
|
185
125
|
d.push(` case ${i}: return scr_str_retain((ScrStr *)&${lit});`);
|
|
186
126
|
break;
|
|
187
127
|
}
|
|
@@ -197,16 +137,16 @@ export function unionToStrHelper(E, unionId) {
|
|
|
197
137
|
case "bytes": {
|
|
198
138
|
// Buffer.toString() IS the utf8 decode (Node's default
|
|
199
139
|
// encoding) — the `Buffer | string` chunk idiom.
|
|
200
|
-
const enc =
|
|
140
|
+
const enc = emitter.internLiteral("utf8");
|
|
201
141
|
d.push(` case ${i}: return scr_bytes_to_str((ScrBytes *)scr_union_peek(v), (ScrStr *)&${enc});`);
|
|
202
142
|
break;
|
|
203
143
|
}
|
|
204
144
|
default:
|
|
205
|
-
throw new
|
|
145
|
+
throw new InternalCompilerError(`emitter bug: ToString of union with a ${arm.kind} arm (frontend fences these)`);
|
|
206
146
|
}
|
|
207
147
|
});
|
|
208
148
|
d.push(` default: scr_trap("scriptc: internal error: invalid union tag\\n");`, ` }`, `}`, ``);
|
|
209
|
-
|
|
149
|
+
emitter.walkerDefs.push(...d);
|
|
210
150
|
return name;
|
|
211
151
|
}
|
|
212
152
|
/** The per-union array-join helper (interned per unionId): Array.prototype
|
|
@@ -216,20 +156,20 @@ export function unionToStrHelper(E, unionId) {
|
|
|
216
156
|
* f64/bool via the JS-exact formatters). The frontend admits only unions
|
|
217
157
|
* of f64/string/bool/unit arms here. Borrows the array and separator;
|
|
218
158
|
* the result is owned (+1). */
|
|
219
|
-
export function unionJoinHelper(
|
|
220
|
-
const existing =
|
|
159
|
+
export function unionJoinHelper(emitter, unionId) {
|
|
160
|
+
const existing = emitter.unionJoinFns.get(unionId);
|
|
221
161
|
if (existing)
|
|
222
162
|
return existing;
|
|
223
|
-
const def =
|
|
163
|
+
const def = emitter.unionsById.get(unionId);
|
|
224
164
|
if (!def)
|
|
225
|
-
throw new
|
|
226
|
-
const name = `sc_uj_${
|
|
227
|
-
|
|
228
|
-
const toStr = unionToStrHelper(
|
|
165
|
+
throw new InternalCompilerError(`emitter bug: join of unknown union ${unionId}`);
|
|
166
|
+
const name = `sc_uj_${emitter.unionJoinFns.size}`;
|
|
167
|
+
emitter.unionJoinFns.set(unionId, name);
|
|
168
|
+
const toStr = unionToStrHelper(emitter, unionId);
|
|
229
169
|
const unitTags = def.arms.flatMap((a, i) => a.kind === "undefinedT" || a.kind === "nullT" ? [i] : []);
|
|
230
170
|
const sig = `static ScrStr *${name}(ScrArr *a, ScrStr *sep)`;
|
|
231
|
-
|
|
232
|
-
|
|
171
|
+
emitter.walkerProtos.push(`${sig}; /* join ${unionId} */`);
|
|
172
|
+
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]);`, ` ScrUnion *u = (ScrUnion *)scr_arr_get_ref(a, (double)i);`, ...(unitTags.length > 0
|
|
233
173
|
? [` if (${unitTags.map((t) => `u->tag == ${t}`).join(" || ")}) { scr_union_release(u); continue; }`]
|
|
234
174
|
: []), ` 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);`, `}`, ``);
|
|
235
175
|
return name;
|
|
@@ -241,13 +181,13 @@ export function unionJoinHelper(E, unionId) {
|
|
|
241
181
|
* with ","; null/undefined ELEMENTS print empty, nested arrays flatten
|
|
242
182
|
* through the recursion — JS-exact), plain objects as
|
|
243
183
|
* "[object Object]". The operand is borrowed; the result is owned (+1). */
|
|
244
|
-
export function dynToStrHelper(
|
|
245
|
-
if (
|
|
246
|
-
return
|
|
184
|
+
export function dynToStrHelper(emitter) {
|
|
185
|
+
if (emitter.dynToStrFn)
|
|
186
|
+
return emitter.dynToStrFn;
|
|
247
187
|
const name = "sc_ds";
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
188
|
+
emitter.dynToStrFn = name;
|
|
189
|
+
emitter.walkerProtos.push(`static void ${name}_buf(ScrJsonBuf *b, const ScrDyn *d); /* String(unknown) walker */`, `static ScrStr *${name}(const ScrDyn *d); /* String(unknown) */`);
|
|
190
|
+
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);`, `}`, ``);
|
|
251
191
|
return name;
|
|
252
192
|
}
|
|
253
193
|
/** The caught→dyn converter (interned once, type-independent): a catch
|
|
@@ -260,14 +200,14 @@ export function dynToStrHelper(E) {
|
|
|
260
200
|
* closures, unions — and non-Error hierarchy objects, type-erased at
|
|
261
201
|
* runtime) becomes an EMPTY dyn object (SEMANTICS.md 67). Borrows the
|
|
262
202
|
* snapshot; the result is a fresh tree (+1). Never throws. */
|
|
263
|
-
export function caughtToDynHelper(
|
|
264
|
-
if (
|
|
265
|
-
return
|
|
203
|
+
export function caughtToDynHelper(emitter) {
|
|
204
|
+
if (emitter.caughtToDynFn)
|
|
205
|
+
return emitter.caughtToDynFn;
|
|
266
206
|
const name = "sc_cd";
|
|
267
|
-
|
|
207
|
+
emitter.caughtToDynFn = name;
|
|
268
208
|
const sig = `static ScrDyn *${name}(const ScrCaught *c)`;
|
|
269
|
-
|
|
270
|
-
|
|
209
|
+
emitter.walkerProtos.push(`${sig}; /* caught -> unknown */`);
|
|
210
|
+
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:`, ` /* 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();`, ` }`, `}`, ``);
|
|
271
211
|
return name;
|
|
272
212
|
}
|
|
273
213
|
/** The pretty-print re-indenter (interned once, type-independent):
|
|
@@ -280,25 +220,25 @@ export function caughtToDynHelper(E) {
|
|
|
280
220
|
* commas, and colons inside JSON strings untouched. Compact input is
|
|
281
221
|
* BORROWED; the result is a fresh string (+1). An empty indent (space 0,
|
|
282
222
|
* "", null) never reaches here — the frontend drops the property. */
|
|
283
|
-
export function jsonIndentHelper(
|
|
284
|
-
if (
|
|
285
|
-
return
|
|
223
|
+
export function jsonIndentHelper(emitter) {
|
|
224
|
+
if (emitter.jsonIndentFn)
|
|
225
|
+
return emitter.jsonIndentFn;
|
|
286
226
|
const name = "sc_ji";
|
|
287
|
-
|
|
227
|
+
emitter.jsonIndentFn = name;
|
|
288
228
|
const sig = `static ScrStr *${name}(ScrStr *compact, const char *indent, size_t ilen)`;
|
|
289
|
-
|
|
290
|
-
|
|
229
|
+
emitter.walkerProtos.push(`${sig}; /* stringify space re-indent */`);
|
|
230
|
+
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);`, `}`, ``);
|
|
291
231
|
return name;
|
|
292
232
|
}
|
|
293
|
-
export function jsonWriteHelper(
|
|
233
|
+
export function jsonWriteHelper(emitter, t) {
|
|
294
234
|
const key = typeKey(t);
|
|
295
|
-
const existing =
|
|
235
|
+
const existing = emitter.jsonWriters.get(key);
|
|
296
236
|
if (existing)
|
|
297
237
|
return existing;
|
|
298
|
-
const name = `sc_jw_${
|
|
299
|
-
|
|
238
|
+
const name = `sc_jw_${emitter.jsonWriters.size}`;
|
|
239
|
+
emitter.jsonWriters.set(key, name);
|
|
300
240
|
const sig = `static void ${name}(ScrJsonBuf *b, ${cDecl(t, "v")})`;
|
|
301
|
-
|
|
241
|
+
emitter.walkerProtos.push(`${sig}; /* stringify ${key} */`);
|
|
302
242
|
const d = [`${sig} { /* stringify ${key} */`];
|
|
303
243
|
switch (t.kind) {
|
|
304
244
|
case "f64":
|
|
@@ -311,17 +251,17 @@ export function jsonWriteHelper(E, t) {
|
|
|
311
251
|
d.push(` scr_jb_put_json_str(b, v);`);
|
|
312
252
|
break;
|
|
313
253
|
case "record": {
|
|
314
|
-
const shape =
|
|
254
|
+
const shape = emitter.recordsById.get(t.shapeId);
|
|
315
255
|
if (!shape)
|
|
316
|
-
throw new
|
|
256
|
+
throw new InternalCompilerError(`emitter bug: jsonStringify of unknown shape ${t.shapeId}`);
|
|
317
257
|
// CYCLE-CAPABLE shapes (recursive record types — the collector-
|
|
318
258
|
// fixpoint set) bracket the walk with the circular-detection
|
|
319
259
|
// stack: a value already being serialized above throws V8's exact
|
|
320
260
|
// circular-structure TypeError (scr_jb_enter). Edge labels stamp
|
|
321
261
|
// only before members whose walk can re-enter (cycle-capable
|
|
322
262
|
// types); acyclic shapes pay nothing.
|
|
323
|
-
const cyclic =
|
|
324
|
-
const edgeable = (ft) => cyclic &&
|
|
263
|
+
const cyclic = emitter.traceAdapterC(t) !== null;
|
|
264
|
+
const edgeable = (ft) => cyclic && emitter.traceAdapterC(ft) !== null;
|
|
325
265
|
if (cyclic)
|
|
326
266
|
d.push(` if (!scr_jb_enter(b, v, ${shape.tuple ? "true" : "false"})) return; /* circular: pending TypeError */`);
|
|
327
267
|
// A tuple serializes as a JSON ARRAY in index order — JS-exact
|
|
@@ -335,7 +275,7 @@ export function jsonWriteHelper(E, t) {
|
|
|
335
275
|
d.push(` scr_jb_putc(b, ',');`);
|
|
336
276
|
if (edgeable(f.type))
|
|
337
277
|
d.push(` scr_jb_edge_idx(b, ${i});`);
|
|
338
|
-
d.push(` ${
|
|
278
|
+
d.push(` ${emitter.jsonWriteHelper(f.type)}(b, v->${mangleField(f.name)});`);
|
|
339
279
|
});
|
|
340
280
|
d.push(` scr_jb_putc(b, ']');`);
|
|
341
281
|
if (cyclic)
|
|
@@ -354,7 +294,7 @@ export function jsonWriteHelper(E, t) {
|
|
|
354
294
|
const order = shape.declaredOrder ?? shape.fields.map((f) => f.name);
|
|
355
295
|
const inOrder = new Set(order);
|
|
356
296
|
if (shape.fields.some((f) => !inOrder.has(f.name) && !f.name.startsWith("%"))) {
|
|
357
|
-
throw new
|
|
297
|
+
throw new InternalCompilerError(`emitter bug: declaredOrder of shape ${t.shapeId} omits a non-internal field`);
|
|
358
298
|
}
|
|
359
299
|
const byName = new Map(shape.fields.map((f) => [f.name, f]));
|
|
360
300
|
const emitFields = order.map((n) => byName.get(n)).filter((f) => f !== undefined);
|
|
@@ -364,7 +304,7 @@ export function jsonWriteHelper(E, t) {
|
|
|
364
304
|
// flag); all-required shapes keep the static prefix labels. An
|
|
365
305
|
// overflow portion forces the dynamic path too (entry count is
|
|
366
306
|
// runtime state).
|
|
367
|
-
const droppable = emitFields.some((f) =>
|
|
307
|
+
const droppable = emitFields.some((f) => undefinedArmTag(f.type, emitter.unionsById) >= 0) || !!shape.indexValue;
|
|
368
308
|
d.push(` scr_jb_putc(b, '{');`);
|
|
369
309
|
if (!droppable) {
|
|
370
310
|
emitFields.forEach((f, i) => {
|
|
@@ -374,14 +314,14 @@ export function jsonWriteHelper(E, t) {
|
|
|
374
314
|
d.push(` scr_jb_edge_prop(b, ${cStringLiteral(Buffer.from(f.name, "utf8"))});`);
|
|
375
315
|
// Refcounted fields are BORROWED straight off the struct (the
|
|
376
316
|
// record itself is borrowed for the whole call).
|
|
377
|
-
d.push(` ${
|
|
317
|
+
d.push(` ${emitter.jsonWriteHelper(f.type)}(b, v->${mangleField(f.name)});`);
|
|
378
318
|
});
|
|
379
319
|
}
|
|
380
320
|
else {
|
|
381
321
|
d.push(` bool first = true;`);
|
|
382
322
|
for (const f of emitFields) {
|
|
383
323
|
const label = cStringLiteral(Buffer.from(`"${f.name}":`, "utf8"));
|
|
384
|
-
const utag =
|
|
324
|
+
const utag = undefinedArmTag(f.type, emitter.unionsById);
|
|
385
325
|
const pad = utag >= 0 ? " " : " ";
|
|
386
326
|
if (utag >= 0) {
|
|
387
327
|
d.push(` if (v->${mangleField(f.name)}->tag != ${utag}) { /* undefined-valued field: dropped, like Node */`);
|
|
@@ -391,7 +331,7 @@ export function jsonWriteHelper(E, t) {
|
|
|
391
331
|
d.push(`${pad}scr_jb_puts(b, ${label});`);
|
|
392
332
|
if (edgeable(f.type))
|
|
393
333
|
d.push(`${pad}scr_jb_edge_prop(b, ${cStringLiteral(Buffer.from(f.name, "utf8"))});`);
|
|
394
|
-
d.push(`${pad}${
|
|
334
|
+
d.push(`${pad}${emitter.jsonWriteHelper(f.type)}(b, v->${mangleField(f.name)});`);
|
|
395
335
|
if (utag >= 0)
|
|
396
336
|
d.push(` }`);
|
|
397
337
|
}
|
|
@@ -419,8 +359,8 @@ export function jsonWriteHelper(E, t) {
|
|
|
419
359
|
}
|
|
420
360
|
const skipUndef = iv.kind === "dyn"
|
|
421
361
|
? `e->kind == SCR_DYN_UNDEF`
|
|
422
|
-
:
|
|
423
|
-
? `e->tag == ${
|
|
362
|
+
: undefinedArmTag(iv, emitter.unionsById) >= 0
|
|
363
|
+
? `e->tag == ${undefinedArmTag(iv, emitter.unionsById)}`
|
|
424
364
|
: null;
|
|
425
365
|
if (skipUndef) {
|
|
426
366
|
d.push(` if (${skipUndef}) { /* undefined-valued entry: dropped, like Node */`);
|
|
@@ -435,7 +375,7 @@ export function jsonWriteHelper(E, t) {
|
|
|
435
375
|
d.push(` scr_jb_putc(b, ':');`);
|
|
436
376
|
if (edgeable(iv))
|
|
437
377
|
d.push(` scr_jb_edge_key(b, k);`);
|
|
438
|
-
d.push(` ${
|
|
378
|
+
d.push(` ${emitter.jsonWriteHelper(iv)}(b, e);`);
|
|
439
379
|
d.push(` scr_str_release(k);`);
|
|
440
380
|
if (isRefCounted(iv))
|
|
441
381
|
d.push(` ${releaseCallC(iv, "e")};`);
|
|
@@ -459,10 +399,10 @@ export function jsonWriteHelper(E, t) {
|
|
|
459
399
|
break;
|
|
460
400
|
case "array": {
|
|
461
401
|
const elem = t.elem;
|
|
462
|
-
const w =
|
|
402
|
+
const w = emitter.jsonWriteHelper(elem);
|
|
463
403
|
// A cycle-capable array (elements can point back at it) joins the
|
|
464
404
|
// circular-detection stack exactly like a cycle-capable record.
|
|
465
|
-
const cyclic =
|
|
405
|
+
const cyclic = emitter.traceAdapterC(t) !== null;
|
|
466
406
|
if (cyclic)
|
|
467
407
|
d.push(` if (!scr_jb_enter(b, v, true)) return; /* circular: pending TypeError */`);
|
|
468
408
|
d.push(` scr_jb_putc(b, '[');`);
|
|
@@ -489,9 +429,9 @@ export function jsonWriteHelper(E, t) {
|
|
|
489
429
|
break;
|
|
490
430
|
}
|
|
491
431
|
case "union": {
|
|
492
|
-
const def =
|
|
432
|
+
const def = emitter.unionsById.get(t.unionId);
|
|
493
433
|
if (!def)
|
|
494
|
-
throw new
|
|
434
|
+
throw new InternalCompilerError(`emitter bug: jsonStringify of unknown union ${t.unionId}`);
|
|
495
435
|
d.push(` switch (v->tag) {`);
|
|
496
436
|
def.arms.forEach((arm, i) => {
|
|
497
437
|
if (arm.kind === "nullT") {
|
|
@@ -509,7 +449,7 @@ export function jsonWriteHelper(E, t) {
|
|
|
509
449
|
d.push(` scr_trap("scriptc: internal error: stringify reached an undefined arm\\n");`);
|
|
510
450
|
return;
|
|
511
451
|
}
|
|
512
|
-
const w =
|
|
452
|
+
const w = emitter.jsonWriteHelper(arm);
|
|
513
453
|
if (arm.kind === "f64") {
|
|
514
454
|
d.push(` case ${i}: ${w}(b, scr_union_get_f64(v)); break;`);
|
|
515
455
|
}
|
|
@@ -526,10 +466,10 @@ export function jsonWriteHelper(E, t) {
|
|
|
526
466
|
break;
|
|
527
467
|
}
|
|
528
468
|
default:
|
|
529
|
-
throw new
|
|
469
|
+
throw new InternalCompilerError(`emitter bug: jsonStringify of non-JSON type ${t.kind}`);
|
|
530
470
|
}
|
|
531
471
|
d.push(`}`, ``);
|
|
532
|
-
|
|
472
|
+
emitter.walkerDefs.push(...d);
|
|
533
473
|
return name;
|
|
534
474
|
}
|
|
535
475
|
/** The emitted match predicate for one dynCheck target type:
|
|
@@ -537,15 +477,15 @@ export function jsonWriteHelper(E, t) {
|
|
|
537
477
|
* Never throws, builds nothing; union builders use it to try arms in
|
|
538
478
|
* canonical order (first FULL match wins). Records are width-tolerant
|
|
539
479
|
* here too: extra keys are ignored, only declared fields are examined. */
|
|
540
|
-
export function dynMatchHelper(
|
|
480
|
+
export function dynMatchHelper(emitter, t) {
|
|
541
481
|
const key = typeKey(t);
|
|
542
|
-
const existing =
|
|
482
|
+
const existing = emitter.dynMatchers.get(key);
|
|
543
483
|
if (existing)
|
|
544
484
|
return existing;
|
|
545
|
-
const name = `sc_dm_${
|
|
546
|
-
|
|
485
|
+
const name = `sc_dm_${emitter.dynMatchers.size}`;
|
|
486
|
+
emitter.dynMatchers.set(key, name);
|
|
547
487
|
const sig = `static bool ${name}(const ScrDyn *d)`;
|
|
548
|
-
|
|
488
|
+
emitter.walkerProtos.push(`${sig}; /* matches ${key} */`);
|
|
549
489
|
const d = [`${sig} { /* matches ${key} */`];
|
|
550
490
|
if (isRefCounted(t) && t.kind !== "dyn") {
|
|
551
491
|
const keyLit = cStringLiteral(Buffer.from(key, "utf8"));
|
|
@@ -583,13 +523,13 @@ export function dynMatchHelper(E, t) {
|
|
|
583
523
|
case "bytes":
|
|
584
524
|
// A Uint8Array target (the checked-dynamic tree carries u8 payloads only).
|
|
585
525
|
if (t.elem !== "u8")
|
|
586
|
-
throw new
|
|
526
|
+
throw new InternalCompilerError(`emitter bug: dynMatch of bytes<${t.elem}>`);
|
|
587
527
|
d.push(` return d->kind == SCR_DYN_BYTES;`);
|
|
588
528
|
break;
|
|
589
529
|
case "record": {
|
|
590
|
-
const shape =
|
|
530
|
+
const shape = emitter.recordsById.get(t.shapeId);
|
|
591
531
|
if (!shape)
|
|
592
|
-
throw new
|
|
532
|
+
throw new InternalCompilerError(`emitter bug: dynCheck of unknown shape ${t.shapeId}`);
|
|
593
533
|
// A tuple matches a JSON ARRAY of EXACTLY its arity whose elements
|
|
594
534
|
// match positionally (arity is part of the type — width tolerance
|
|
595
535
|
// is an object-key concept and does not apply).
|
|
@@ -597,7 +537,7 @@ export function dynMatchHelper(E, t) {
|
|
|
597
537
|
const byIndex = [...shape.fields].sort((a, b) => Number(a.name) - Number(b.name));
|
|
598
538
|
d.push(` if (d->kind != SCR_DYN_ARR || d->v.arr.len != ${byIndex.length}) return false;`);
|
|
599
539
|
byIndex.forEach((f, i) => {
|
|
600
|
-
d.push(` if (!${
|
|
540
|
+
d.push(` if (!${emitter.dynMatchHelper(f.type)}(d->v.arr.items[${i}])) return false;`);
|
|
601
541
|
});
|
|
602
542
|
d.push(` return true;`);
|
|
603
543
|
break;
|
|
@@ -613,13 +553,13 @@ export function dynMatchHelper(E, t) {
|
|
|
613
553
|
const keyLit = cStringLiteral(Buffer.from(f.name, "utf8"));
|
|
614
554
|
const keyLen = Buffer.byteLength(f.name, "utf8");
|
|
615
555
|
d.push(` m = scr_dyn_obj_get(d, ${keyLit}, ${keyLen});`);
|
|
616
|
-
if (
|
|
556
|
+
if (undefinedArmTag(f.type, emitter.unionsById) >= 0) {
|
|
617
557
|
// Optional-flavored field: a MISSING key is the undefined arm
|
|
618
558
|
// (a match); a PRESENT key must fit the union as usual.
|
|
619
|
-
d.push(` if (m && !${
|
|
559
|
+
d.push(` if (m && !${emitter.dynMatchHelper(f.type)}(m)) return false;`);
|
|
620
560
|
}
|
|
621
561
|
else {
|
|
622
|
-
d.push(` if (!m || !${
|
|
562
|
+
d.push(` if (!m || !${emitter.dynMatchHelper(f.type)}(m)) return false;`);
|
|
623
563
|
}
|
|
624
564
|
}
|
|
625
565
|
// Index-signature shapes: UNDECLARED keys must fit the overflow
|
|
@@ -638,14 +578,14 @@ export function dynMatchHelper(E, t) {
|
|
|
638
578
|
d.push(` const ScrDynEntry *e = &d->v.obj.entries[i];`);
|
|
639
579
|
if (shape.fields.length > 0)
|
|
640
580
|
d.push(` if (${skip}) continue;`);
|
|
641
|
-
d.push(` if (!${
|
|
581
|
+
d.push(` if (!${emitter.dynMatchHelper(shape.indexValue)}(e->value)) return false;`);
|
|
642
582
|
d.push(` }`);
|
|
643
583
|
}
|
|
644
584
|
d.push(` return true;`);
|
|
645
585
|
break;
|
|
646
586
|
}
|
|
647
587
|
case "array": {
|
|
648
|
-
const m =
|
|
588
|
+
const m = emitter.dynMatchHelper(t.elem);
|
|
649
589
|
d.push(` if (d->kind != SCR_DYN_ARR) return false;`);
|
|
650
590
|
d.push(` for (size_t i = 0; i < d->v.arr.len; i++) {`);
|
|
651
591
|
d.push(` if (!${m}(d->v.arr.items[i])) return false;`);
|
|
@@ -654,23 +594,23 @@ export function dynMatchHelper(E, t) {
|
|
|
654
594
|
break;
|
|
655
595
|
}
|
|
656
596
|
case "union": {
|
|
657
|
-
const def =
|
|
597
|
+
const def = emitter.unionsById.get(t.unionId);
|
|
658
598
|
if (!def)
|
|
659
|
-
throw new
|
|
599
|
+
throw new InternalCompilerError(`emitter bug: dynCheck of unknown union ${t.unionId}`);
|
|
660
600
|
// The undefined arm participates: parsed JSON never contains
|
|
661
601
|
// undefined (a MISSING record key was the arm's only source), but
|
|
662
602
|
// the checked-dynamic tree can hold the undefined value now — overflow entries
|
|
663
603
|
// under `unknown` index signatures — and it matches exactly the
|
|
664
604
|
// undefined arm.
|
|
665
|
-
const arms = def.arms.map((a) => `${
|
|
605
|
+
const arms = def.arms.map((a) => `${emitter.dynMatchHelper(a)}(d)`);
|
|
666
606
|
d.push(` return ${arms.join(" || ")};`);
|
|
667
607
|
break;
|
|
668
608
|
}
|
|
669
609
|
default:
|
|
670
|
-
throw new
|
|
610
|
+
throw new InternalCompilerError(`emitter bug: dynMatch of non-JSON type ${t.kind}`);
|
|
671
611
|
}
|
|
672
612
|
d.push(`}`, ``);
|
|
673
|
-
|
|
613
|
+
emitter.walkerDefs.push(...d);
|
|
674
614
|
return name;
|
|
675
615
|
}
|
|
676
616
|
/** The emitted keyed read on a dyn value:
|
|
@@ -688,16 +628,16 @@ export function dynMatchHelper(E, t) {
|
|
|
688
628
|
* is undefined." (or "…null."), the property form "Cannot destructure
|
|
689
629
|
* property 'PROP' of 'SPELL' …" when firstProp is non-NULL — V8's exact
|
|
690
630
|
* strings, source spelling included. Non-nullish values pass silently. */
|
|
691
|
-
export function dynDestrCheckHelper(
|
|
631
|
+
export function dynDestrCheckHelper(emitter) {
|
|
692
632
|
const memoKey = "%dynDestrCheck";
|
|
693
|
-
const existing =
|
|
633
|
+
const existing = emitter.dynBuilders.get(memoKey);
|
|
694
634
|
if (existing)
|
|
695
635
|
return existing;
|
|
696
636
|
const name = "sc_dyn_destr_check";
|
|
697
|
-
|
|
637
|
+
emitter.dynBuilders.set(memoKey, name);
|
|
698
638
|
const sig = `static void ${name}(const ScrDyn *d, const char *spell, const char *firstProp)`;
|
|
699
|
-
|
|
700
|
-
|
|
639
|
+
emitter.walkerProtos.push(`${sig}; /* destructuring RequireObjectCoercible */`);
|
|
640
|
+
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));`, `}`, ``);
|
|
701
641
|
return name;
|
|
702
642
|
}
|
|
703
643
|
/** GetIterator + first-N steps over a dyn value (the dynIterN node), as
|
|
@@ -709,27 +649,27 @@ export function dynDestrCheckHelper(E) {
|
|
|
709
649
|
* "function …" — each with the "(cannot read property
|
|
710
650
|
* Symbol(Symbol.iterator))" tail). Returns a fresh +1 dyn array of
|
|
711
651
|
* exactly n elements, undefined-padded past the end. */
|
|
712
|
-
export function dynIterNHelper(
|
|
652
|
+
export function dynIterNHelper(emitter) {
|
|
713
653
|
const memoKey = "%dynIterN";
|
|
714
|
-
const existing =
|
|
654
|
+
const existing = emitter.dynBuilders.get(memoKey);
|
|
715
655
|
if (existing)
|
|
716
656
|
return existing;
|
|
717
657
|
const name = "sc_dyn_iter_n";
|
|
718
|
-
|
|
658
|
+
emitter.dynBuilders.set(memoKey, name);
|
|
719
659
|
const sig = `static ScrDyn *${name}(const ScrDyn *d, size_t n)`;
|
|
720
|
-
|
|
721
|
-
|
|
660
|
+
emitter.walkerProtos.push(`${sig}; /* destructuring GetIterator + N steps */`);
|
|
661
|
+
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;`, `}`, ``);
|
|
722
662
|
return name;
|
|
723
663
|
}
|
|
724
|
-
export function dynKeyGetHelper(
|
|
664
|
+
export function dynKeyGetHelper(emitter) {
|
|
725
665
|
const memoKey = "%dynKeyGet";
|
|
726
|
-
const existing =
|
|
666
|
+
const existing = emitter.dynBuilders.get(memoKey);
|
|
727
667
|
if (existing)
|
|
728
668
|
return existing;
|
|
729
669
|
const name = "sc_dyn_key_get";
|
|
730
|
-
|
|
670
|
+
emitter.dynBuilders.set(memoKey, name);
|
|
731
671
|
const sig = `static ScrDyn *${name}(ScrDyn *d, ScrStr *k, bool opt)`;
|
|
732
|
-
|
|
672
|
+
emitter.walkerProtos.push(`${sig}; /* d[k] on dyn */`);
|
|
733
673
|
const d = [`${sig} { /* d[k] on dyn */`];
|
|
734
674
|
d.push(` if (d->kind == SCR_DYN_UNDEF || d->kind == SCR_DYN_NULL) {`);
|
|
735
675
|
d.push(` if (opt) return scr_dyn_retain(scr_dyn_undefined());`);
|
|
@@ -815,7 +755,7 @@ export function dynKeyGetHelper(E) {
|
|
|
815
755
|
d.push(` }`);
|
|
816
756
|
d.push(` return scr_dyn_retain(scr_dyn_undefined());`);
|
|
817
757
|
d.push(`}`, ``);
|
|
818
|
-
|
|
758
|
+
emitter.walkerDefs.push(...d);
|
|
819
759
|
return name;
|
|
820
760
|
}
|
|
821
761
|
/** The emitted checked builder for one dynCheck target type:
|
|
@@ -826,16 +766,16 @@ export function dynKeyGetHelper(E) {
|
|
|
826
766
|
* Recursive calls propagate a pending exception by releasing the
|
|
827
767
|
* partially-built value and returning — the same pending-check discipline
|
|
828
768
|
* emitted function bodies follow. */
|
|
829
|
-
export function dynCheckHelper(
|
|
769
|
+
export function dynCheckHelper(emitter, t) {
|
|
830
770
|
const key = typeKey(t);
|
|
831
|
-
const existing =
|
|
771
|
+
const existing = emitter.dynBuilders.get(key);
|
|
832
772
|
if (existing)
|
|
833
773
|
return existing;
|
|
834
|
-
const name = `sc_dc_${
|
|
835
|
-
|
|
774
|
+
const name = `sc_dc_${emitter.dynBuilders.size}`;
|
|
775
|
+
emitter.dynBuilders.set(key, name);
|
|
836
776
|
const sig = `static ${cType(t)}${cType(t).endsWith("*") ? "" : " "}${name}(const ScrDyn *d, const ScrDynPath *path)`;
|
|
837
|
-
|
|
838
|
-
const want = cStringLiteral(Buffer.from(
|
|
777
|
+
emitter.walkerProtos.push(`${sig}; /* check ${key} */`);
|
|
778
|
+
const want = cStringLiteral(Buffer.from(dynDesc(t, emitter.recordsById, emitter.unionsById), "utf8"));
|
|
839
779
|
const d = [`${sig} { /* check ${key} */`];
|
|
840
780
|
if (isRefCounted(t) && t.kind !== "dyn") {
|
|
841
781
|
const keyLit = cStringLiteral(Buffer.from(key, "utf8"));
|
|
@@ -849,9 +789,9 @@ export function dynCheckHelper(E, t) {
|
|
|
849
789
|
}
|
|
850
790
|
d.push(` ScrDyn *sc_materialized = scr_dyn_typed_ref_materialize(d);`, ` ${cDecl(t, "sc_out")} = ${name}(sc_materialized, path);`, ` scr_dyn_release(sc_materialized);`);
|
|
851
791
|
if (t.kind === "record") {
|
|
852
|
-
const shape =
|
|
792
|
+
const shape = emitter.recordsById.get(t.shapeId);
|
|
853
793
|
if (!shape) {
|
|
854
|
-
throw new
|
|
794
|
+
throw new InternalCompilerError(`emitter bug: cached typed-ref cast of unknown shape ${t.shapeId}`);
|
|
855
795
|
}
|
|
856
796
|
d.push(` if (sc_out && sc_cached) {`);
|
|
857
797
|
for (const field of shape.fields) {
|
|
@@ -893,7 +833,7 @@ export function dynCheckHelper(E, t) {
|
|
|
893
833
|
// `u as Uint8Array`: kind check, then a fresh COPY out (the
|
|
894
834
|
// boundary's aliasing stance in both directions).
|
|
895
835
|
if (t.elem !== "u8")
|
|
896
|
-
throw new
|
|
836
|
+
throw new InternalCompilerError(`emitter bug: dynCheck of bytes<${t.elem}>`);
|
|
897
837
|
d.push(` if (d->kind != SCR_DYN_BYTES) { scr_dyn_check_fail(path, ${want}, d); return NULL; }`);
|
|
898
838
|
d.push(` return scr_dyn_bytes_copy_out(d);`);
|
|
899
839
|
break;
|
|
@@ -906,15 +846,15 @@ export function dynCheckHelper(E, t) {
|
|
|
906
846
|
// compare reference-equal (the tracing suite's shape); alien
|
|
907
847
|
// %error objects rebuild once and cache the pair.
|
|
908
848
|
if (t.className !== "%Error") {
|
|
909
|
-
throw new
|
|
849
|
+
throw new InternalCompilerError(`emitter bug: dynCheck of class ${t.className} (only %Error extracts from the checked-dynamic tree)`);
|
|
910
850
|
}
|
|
911
851
|
d.push(` if (d->kind != SCR_DYN_OBJ || !scr_dyn_obj_get(d, "%error", 6)) { scr_dyn_check_fail(path, ${want}, d); return NULL; }`);
|
|
912
852
|
d.push(` return scr_error_from_dyn(d);`);
|
|
913
853
|
break;
|
|
914
854
|
case "record": {
|
|
915
|
-
const shape =
|
|
855
|
+
const shape = emitter.recordsById.get(t.shapeId);
|
|
916
856
|
if (!shape)
|
|
917
|
-
throw new
|
|
857
|
+
throw new InternalCompilerError(`emitter bug: dynCheck of unknown shape ${t.shapeId}`);
|
|
918
858
|
const rel = (v) => releaseCallC(t, v);
|
|
919
859
|
// Tuple targets: a JSON ARRAY of exactly the arity, validated and
|
|
920
860
|
// extracted positionally with index paths ("$.pairs[3][1]").
|
|
@@ -927,7 +867,7 @@ export function dynCheckHelper(E, t) {
|
|
|
927
867
|
byIndex.forEach((f, i) => {
|
|
928
868
|
d.push(` {`);
|
|
929
869
|
d.push(` ScrDynPath p = { path, NULL, ${i} };`);
|
|
930
|
-
d.push(` r->${mangleField(f.name)} = ${
|
|
870
|
+
d.push(` r->${mangleField(f.name)} = ${emitter.dynCheckHelper(f.type)}(d->v.arr.items[${i}], &p);`);
|
|
931
871
|
d.push(` if (scr_exc_pending()) { ${rel("r")}; return NULL; }`);
|
|
932
872
|
d.push(` }`);
|
|
933
873
|
});
|
|
@@ -939,14 +879,14 @@ export function dynCheckHelper(E, t) {
|
|
|
939
879
|
for (const f of shape.fields) {
|
|
940
880
|
const keyLit = cStringLiteral(Buffer.from(f.name, "utf8"));
|
|
941
881
|
const keyLen = Buffer.byteLength(f.name, "utf8");
|
|
942
|
-
const fieldWant = cStringLiteral(Buffer.from(
|
|
882
|
+
const fieldWant = cStringLiteral(Buffer.from(dynDesc(f.type, emitter.recordsById, emitter.unionsById), "utf8"));
|
|
943
883
|
// Width tolerance: only declared fields are looked up — extra JSON
|
|
944
884
|
// keys are simply never examined (check-and-extract, not shape
|
|
945
885
|
// equality). A missing field fails as "got undefined" — except
|
|
946
886
|
// optional-flavored fields (undefined-armed unions), where the
|
|
947
887
|
// missing key IS the undefined arm: the interned immortal
|
|
948
888
|
// instance, no retain owed (rc == SIZE_MAX).
|
|
949
|
-
const utag = f.type.kind === "union" ?
|
|
889
|
+
const utag = f.type.kind === "union" ? undefinedArmTag(f.type, emitter.unionsById) : -1;
|
|
950
890
|
d.push(` {`);
|
|
951
891
|
d.push(` ScrDynPath p = { path, ${keyLit}, 0 };`);
|
|
952
892
|
d.push(` const ScrDyn *m = scr_dyn_obj_get(d, ${keyLit}, ${keyLen});`);
|
|
@@ -955,20 +895,20 @@ export function dynCheckHelper(E, t) {
|
|
|
955
895
|
// one IS the undefined dyn value (JS's missing-property read).
|
|
956
896
|
// Go through the dyn builder so a Web-stream typed-ref capsule
|
|
957
897
|
// cannot escape inside a checked record field.
|
|
958
|
-
d.push(` r->${mangleField(f.name)} = ${
|
|
898
|
+
d.push(` r->${mangleField(f.name)} = ${emitter.dynCheckHelper(f.type)}(m ? m : scr_dyn_undefined(), &p);`);
|
|
959
899
|
}
|
|
960
900
|
else if (utag >= 0 && f.type.kind === "union") {
|
|
961
|
-
const unit =
|
|
901
|
+
const unit = emitter.unitInstanceRef(f.type.unionId, utag);
|
|
962
902
|
d.push(` if (!m) {`);
|
|
963
903
|
d.push(` r->${mangleField(f.name)} = ${unit}; /* absent key -> the undefined arm */`);
|
|
964
904
|
d.push(` } else {`);
|
|
965
|
-
d.push(` r->${mangleField(f.name)} = ${
|
|
905
|
+
d.push(` r->${mangleField(f.name)} = ${emitter.dynCheckHelper(f.type)}(m, &p);`);
|
|
966
906
|
d.push(` if (scr_exc_pending()) { ${rel("r")}; return NULL; }`);
|
|
967
907
|
d.push(` }`);
|
|
968
908
|
}
|
|
969
909
|
else {
|
|
970
910
|
d.push(` if (!m) { scr_dyn_check_fail(&p, ${fieldWant}, NULL); ${rel("r")}; return NULL; }`);
|
|
971
|
-
d.push(` r->${mangleField(f.name)} = ${
|
|
911
|
+
d.push(` r->${mangleField(f.name)} = ${emitter.dynCheckHelper(f.type)}(m, &p);`);
|
|
972
912
|
d.push(` if (scr_exc_pending()) { ${rel("r")}; return NULL; }`);
|
|
973
913
|
}
|
|
974
914
|
d.push(` }`);
|
|
@@ -995,7 +935,7 @@ export function dynCheckHelper(E, t) {
|
|
|
995
935
|
}
|
|
996
936
|
else {
|
|
997
937
|
d.push(` ScrDynPath p = { path, e->key, 0 };`);
|
|
998
|
-
d.push(` ${cDecl(iv, "ev")} = ${
|
|
938
|
+
d.push(` ${cDecl(iv, "ev")} = ${emitter.dynCheckHelper(iv)}(e->value, &p);`);
|
|
999
939
|
d.push(` if (scr_exc_pending()) { ${rel("r")}; return NULL; }`);
|
|
1000
940
|
}
|
|
1001
941
|
d.push(` ScrStr *ek = scr_str_new(e->key, e->key_len);`);
|
|
@@ -1013,9 +953,9 @@ export function dynCheckHelper(E, t) {
|
|
|
1013
953
|
}
|
|
1014
954
|
case "array": {
|
|
1015
955
|
const elem = t.elem;
|
|
1016
|
-
const c =
|
|
956
|
+
const c = emitter.dynCheckHelper(elem);
|
|
1017
957
|
d.push(` if (d->kind != SCR_DYN_ARR) { scr_dyn_check_fail(path, ${want}, d); return NULL; }`);
|
|
1018
|
-
d.push(` ScrArr *a = ${
|
|
958
|
+
d.push(` ScrArr *a = ${emitter.arrNewC(elem, "d->v.arr.len")};`);
|
|
1019
959
|
d.push(` for (size_t i = 0; i < d->v.arr.len; i++) {`);
|
|
1020
960
|
d.push(` ScrDynPath p = { path, NULL, i };`);
|
|
1021
961
|
d.push(` ${cDecl(elem, "e")} = ${c}(d->v.arr.items[i], &p);`);
|
|
@@ -1026,14 +966,14 @@ export function dynCheckHelper(E, t) {
|
|
|
1026
966
|
break;
|
|
1027
967
|
}
|
|
1028
968
|
case "union": {
|
|
1029
|
-
const def =
|
|
969
|
+
const def = emitter.unionsById.get(t.unionId);
|
|
1030
970
|
if (!def)
|
|
1031
|
-
throw new
|
|
971
|
+
throw new InternalCompilerError(`emitter bug: dynCheck of unknown union ${t.unionId}`);
|
|
1032
972
|
// Arms in CANONICAL order, first FULL match wins (discriminated
|
|
1033
973
|
// unions disambiguate naturally: the arm whose declared fields all
|
|
1034
974
|
// fit). The matched arm's builder can no longer fail.
|
|
1035
975
|
def.arms.forEach((arm, i) => {
|
|
1036
|
-
const m =
|
|
976
|
+
const m = emitter.dynMatchHelper(arm);
|
|
1037
977
|
if (arm.kind === "undefinedT") {
|
|
1038
978
|
// Parsed JSON never matches here (no undefined in JSON text —
|
|
1039
979
|
// a MISSING record key builds this arm in the record builder
|
|
@@ -1041,7 +981,7 @@ export function dynCheckHelper(E, t) {
|
|
|
1041
981
|
// `unknown` index-signature overflows and builds the interned
|
|
1042
982
|
// unit instance exactly like null.
|
|
1043
983
|
d.push(` if (${m}(d)) {`);
|
|
1044
|
-
d.push(` return ${
|
|
984
|
+
d.push(` return ${emitter.unitInstanceRef(t.unionId, i)};`);
|
|
1045
985
|
d.push(` }`);
|
|
1046
986
|
return;
|
|
1047
987
|
}
|
|
@@ -1050,11 +990,11 @@ export function dynCheckHelper(E, t) {
|
|
|
1050
990
|
// immortal instance (rc == SIZE_MAX — RC entry points and the
|
|
1051
991
|
// collector both skip it, so no retain is owed).
|
|
1052
992
|
d.push(` if (${m}(d)) {`);
|
|
1053
|
-
d.push(` return ${
|
|
993
|
+
d.push(` return ${emitter.unitInstanceRef(t.unionId, i)};`);
|
|
1054
994
|
d.push(` }`);
|
|
1055
995
|
return;
|
|
1056
996
|
}
|
|
1057
|
-
const c =
|
|
997
|
+
const c = emitter.dynCheckHelper(arm);
|
|
1058
998
|
d.push(` if (${m}(d)) {`);
|
|
1059
999
|
if (arm.kind === "f64") {
|
|
1060
1000
|
d.push(` return scr_union_new_f64(${i}, ${c}(d, path));`);
|
|
@@ -1064,7 +1004,7 @@ export function dynCheckHelper(E, t) {
|
|
|
1064
1004
|
}
|
|
1065
1005
|
else {
|
|
1066
1006
|
const rc = vAdapters(arm);
|
|
1067
|
-
d.push(` return scr_union_new_ref(${i}, ${c}(d, path), &${rc.retain}, &${rc.release}, ${
|
|
1007
|
+
d.push(` return scr_union_new_ref(${i}, ${c}(d, path), &${rc.retain}, &${rc.release}, ${emitter.traceArgC(arm)});`);
|
|
1068
1008
|
}
|
|
1069
1009
|
d.push(` }`);
|
|
1070
1010
|
});
|
|
@@ -1113,7 +1053,7 @@ export function dynCheckHelper(E, t) {
|
|
|
1113
1053
|
// wrapper, retained); anything else wraps in the per-target
|
|
1114
1054
|
// adapter closure, whose caps[0] obj-box owns the dyn value
|
|
1115
1055
|
// (untraced — cycles through dyn never collect, SEMANTICS.md).
|
|
1116
|
-
const adapter = dynFuncAdapterHelper(
|
|
1056
|
+
const adapter = dynFuncAdapterHelper(emitter, t);
|
|
1117
1057
|
const sigLit = cStringLiteral(Buffer.from(key, "utf8"));
|
|
1118
1058
|
d.push(` if (d->kind != SCR_DYN_FUNC) { scr_dyn_check_fail(path, ${want}, d); return NULL; }`);
|
|
1119
1059
|
d.push(` if (strcmp(d->v.fn.sig, ${sigLit}) == 0) return scr_closure_retain(d->v.fn.clo);`);
|
|
@@ -1134,11 +1074,11 @@ export function dynCheckHelper(E, t) {
|
|
|
1134
1074
|
d.push(` return (${cType(t).trim()})scr_dyn_handle_unbox(d, ${h.tag}, path, ${want});`);
|
|
1135
1075
|
break;
|
|
1136
1076
|
}
|
|
1137
|
-
throw new
|
|
1077
|
+
throw new InternalCompilerError(`emitter bug: dynCheck of non-JSON type ${t.kind}`);
|
|
1138
1078
|
}
|
|
1139
1079
|
}
|
|
1140
1080
|
d.push(`}`, ``);
|
|
1141
|
-
|
|
1081
|
+
emitter.walkerDefs.push(...d);
|
|
1142
1082
|
return name;
|
|
1143
1083
|
}
|
|
1144
1084
|
/** The emitted static→dyn converter for one type:
|
|
@@ -1148,15 +1088,15 @@ export function dynCheckHelper(E, t) {
|
|
|
1148
1088
|
* plus undefined-armed unions (the undefined arm becomes the undefined
|
|
1149
1089
|
* dyn singleton) and index-signature records (whose overflow entries
|
|
1150
1090
|
* copy over). The operand is borrowed. Never throws. */
|
|
1151
|
-
export function toDynHelper(
|
|
1091
|
+
export function toDynHelper(emitter, t) {
|
|
1152
1092
|
const key = typeKey(t);
|
|
1153
|
-
const existing =
|
|
1093
|
+
const existing = emitter.toDynFns.get(key);
|
|
1154
1094
|
if (existing)
|
|
1155
1095
|
return existing;
|
|
1156
|
-
const name = `sc_td_${
|
|
1157
|
-
|
|
1096
|
+
const name = `sc_td_${emitter.toDynFns.size}`;
|
|
1097
|
+
emitter.toDynFns.set(key, name);
|
|
1158
1098
|
const sig = `static ScrDyn *${name}(${cDecl(t, "v")})`;
|
|
1159
|
-
|
|
1099
|
+
emitter.walkerProtos.push(`${sig}; /* to-dyn ${key} */`);
|
|
1160
1100
|
const d = [`${sig} { /* to-dyn ${key} */`];
|
|
1161
1101
|
let sourceAccessor = null;
|
|
1162
1102
|
switch (t.kind) {
|
|
@@ -1180,7 +1120,7 @@ export function toDynHelper(E, t) {
|
|
|
1180
1120
|
case "object":
|
|
1181
1121
|
// %Error only (canConvertToDyn's gate): the checked-dynamic tree's error encoding.
|
|
1182
1122
|
if (t.className !== "%Error") {
|
|
1183
|
-
throw new
|
|
1123
|
+
throw new InternalCompilerError(`emitter bug: to-dyn of class ${t.className}`);
|
|
1184
1124
|
}
|
|
1185
1125
|
d.push(` return scr_dyn_from_error(v);`);
|
|
1186
1126
|
break;
|
|
@@ -1194,23 +1134,23 @@ export function toDynHelper(E, t) {
|
|
|
1194
1134
|
// Function-valued record/array fields (EventListenerObject's
|
|
1195
1135
|
// handleEvent method) box through the same identity-preserving
|
|
1196
1136
|
// closure bridge as a bare dynFrom function.
|
|
1197
|
-
d.push(` return ${dynFuncBoxHelper(
|
|
1137
|
+
d.push(` return ${dynFuncBoxHelper(emitter, t)}(v, NULL);`);
|
|
1198
1138
|
break;
|
|
1199
1139
|
case "bytes":
|
|
1200
1140
|
// bytes<u8> → the checked-dynamic tree's bytes kind, payload COPIED (the boundary
|
|
1201
1141
|
// stance; stdin chunks into unknown-typed helpers).
|
|
1202
1142
|
if (t.elem !== "u8")
|
|
1203
|
-
throw new
|
|
1143
|
+
throw new InternalCompilerError(`emitter bug: to-dyn of bytes<${t.elem}>`);
|
|
1204
1144
|
d.push(` return scr_dyn_new_bytes_copy(v);`);
|
|
1205
1145
|
break;
|
|
1206
1146
|
case "record": {
|
|
1207
|
-
const shape =
|
|
1147
|
+
const shape = emitter.recordsById.get(t.shapeId);
|
|
1208
1148
|
if (!shape)
|
|
1209
|
-
throw new
|
|
1149
|
+
throw new InternalCompilerError(`emitter bug: to-dyn of unknown shape ${t.shapeId}`);
|
|
1210
1150
|
// CYCLE-CAPABLE shapes guard the deep copy: a cyclic value has no
|
|
1211
1151
|
// finite dyn copy, so enter TRAPS on re-entry (SEMANTICS.md — Node
|
|
1212
1152
|
// shares the reference instead of copying).
|
|
1213
|
-
const cyclicRec =
|
|
1153
|
+
const cyclicRec = emitter.traceAdapterC(t) !== null;
|
|
1214
1154
|
if (cyclicRec)
|
|
1215
1155
|
d.push(` scr_dyn_from_enter(v);`);
|
|
1216
1156
|
if (shape.tuple) {
|
|
@@ -1218,7 +1158,7 @@ export function toDynHelper(E, t) {
|
|
|
1218
1158
|
const byIndex = [...shape.fields].sort((a, b) => Number(a.name) - Number(b.name));
|
|
1219
1159
|
d.push(` ScrDyn *d = scr_dyn_new_arr();`);
|
|
1220
1160
|
for (const f of byIndex) {
|
|
1221
|
-
d.push(` scr_dyn_arr_push(d, ${
|
|
1161
|
+
d.push(` scr_dyn_arr_push(d, ${emitter.toDynHelper(f.type)}(v->${mangleField(f.name)}));`);
|
|
1222
1162
|
}
|
|
1223
1163
|
if (cyclicRec)
|
|
1224
1164
|
d.push(` scr_dyn_from_leave();`);
|
|
@@ -1232,7 +1172,7 @@ export function toDynHelper(E, t) {
|
|
|
1232
1172
|
name: `${name}_source_access`,
|
|
1233
1173
|
release: rc.release,
|
|
1234
1174
|
};
|
|
1235
|
-
|
|
1175
|
+
emitter.walkerProtos.push(`static ScrDyn *${sourceAccessor.name}(void *v, bool materialize); /* live listener source ${key} */`);
|
|
1236
1176
|
d.push(` ScrDyn *d = scr_dyn_new_obj_with_identity(v, &${rc.retain}, &${sourceAccessor.name});`);
|
|
1237
1177
|
}
|
|
1238
1178
|
else {
|
|
@@ -1255,7 +1195,7 @@ export function toDynHelper(E, t) {
|
|
|
1255
1195
|
for (const f of dynFields) {
|
|
1256
1196
|
const keyLit = cStringLiteral(Buffer.from(f.name, "utf8"));
|
|
1257
1197
|
const keyLen = Buffer.byteLength(f.name, "utf8");
|
|
1258
|
-
d.push(` scr_dyn_obj_set(d, ${keyLit}, ${keyLen}, ${
|
|
1198
|
+
d.push(` scr_dyn_obj_set(d, ${keyLit}, ${keyLen}, ${emitter.toDynHelper(f.type)}(v->${mangleField(f.name)}));`);
|
|
1259
1199
|
}
|
|
1260
1200
|
}
|
|
1261
1201
|
if (shape.indexValue) {
|
|
@@ -1278,7 +1218,7 @@ export function toDynHelper(E, t) {
|
|
|
1278
1218
|
}
|
|
1279
1219
|
else {
|
|
1280
1220
|
d.push(` ${cDecl(iv, "e")} = (${cType(iv).trim()})scr_map_get_str_ref(${m}, k);`);
|
|
1281
|
-
d.push(` scr_dyn_obj_set(d, k->data, k->len, ${
|
|
1221
|
+
d.push(` scr_dyn_obj_set(d, k->data, k->len, ${emitter.toDynHelper(iv)}(e));`);
|
|
1282
1222
|
d.push(` ${releaseCallC(iv, "e")};`);
|
|
1283
1223
|
}
|
|
1284
1224
|
d.push(` scr_str_release(k);`);
|
|
@@ -1294,7 +1234,7 @@ export function toDynHelper(E, t) {
|
|
|
1294
1234
|
case "array": {
|
|
1295
1235
|
const elem = t.elem;
|
|
1296
1236
|
// Cycle-capable arrays guard the deep copy like records above.
|
|
1297
|
-
const cyclicArr =
|
|
1237
|
+
const cyclicArr = emitter.traceAdapterC(t) !== null;
|
|
1298
1238
|
if (cyclicArr)
|
|
1299
1239
|
d.push(` scr_dyn_from_enter(v);`);
|
|
1300
1240
|
d.push(` ScrDyn *d = scr_dyn_new_arr();`);
|
|
@@ -1307,7 +1247,7 @@ export function toDynHelper(E, t) {
|
|
|
1307
1247
|
}
|
|
1308
1248
|
else {
|
|
1309
1249
|
d.push(` ${cDecl(elem, "e")} = (${cType(elem).trim()})scr_arr_get_ref(v, (double)i);`);
|
|
1310
|
-
d.push(` scr_dyn_arr_push(d, ${
|
|
1250
|
+
d.push(` scr_dyn_arr_push(d, ${emitter.toDynHelper(elem)}(e));`);
|
|
1311
1251
|
d.push(` ${releaseCallC(elem, "e")};`);
|
|
1312
1252
|
}
|
|
1313
1253
|
d.push(` }`);
|
|
@@ -1317,9 +1257,9 @@ export function toDynHelper(E, t) {
|
|
|
1317
1257
|
break;
|
|
1318
1258
|
}
|
|
1319
1259
|
case "union": {
|
|
1320
|
-
const def =
|
|
1260
|
+
const def = emitter.unionsById.get(t.unionId);
|
|
1321
1261
|
if (!def)
|
|
1322
|
-
throw new
|
|
1262
|
+
throw new InternalCompilerError(`emitter bug: to-dyn of unknown union ${t.unionId}`);
|
|
1323
1263
|
d.push(` switch (v->tag) {`);
|
|
1324
1264
|
def.arms.forEach((arm, i) => {
|
|
1325
1265
|
if (arm.kind === "undefinedT") {
|
|
@@ -1337,10 +1277,10 @@ export function toDynHelper(E, t) {
|
|
|
1337
1277
|
else if (arm.kind === "func") {
|
|
1338
1278
|
// A boxable function arm crosses through the checked-dynamic
|
|
1339
1279
|
// function boundary (the dynFrom func special case, sans name).
|
|
1340
|
-
d.push(` case ${i}: return ${dynFuncBoxHelper(
|
|
1280
|
+
d.push(` case ${i}: return ${dynFuncBoxHelper(emitter, arm)}((ScrClosure *)scr_union_peek(v), NULL);`);
|
|
1341
1281
|
}
|
|
1342
1282
|
else {
|
|
1343
|
-
d.push(` case ${i}: return ${
|
|
1283
|
+
d.push(` case ${i}: return ${emitter.toDynHelper(arm)}((${cType(arm).trim()})scr_union_peek(v));`);
|
|
1344
1284
|
}
|
|
1345
1285
|
});
|
|
1346
1286
|
d.push(` default: scr_trap("scriptc: internal error: invalid union tag\\n");`);
|
|
@@ -1357,7 +1297,7 @@ export function toDynHelper(E, t) {
|
|
|
1357
1297
|
d.push(` return scr_dyn_new_promise(v);`);
|
|
1358
1298
|
break;
|
|
1359
1299
|
}
|
|
1360
|
-
d.push(` return scr_dyn_new_promise_adapting(v, &${promiseDynAdapterHelper(
|
|
1300
|
+
d.push(` return scr_dyn_new_promise_adapting(v, &${promiseDynAdapterHelper(emitter, t.inner)});`);
|
|
1361
1301
|
break;
|
|
1362
1302
|
}
|
|
1363
1303
|
default: {
|
|
@@ -1369,13 +1309,13 @@ export function toDynHelper(E, t) {
|
|
|
1369
1309
|
d.push(` return scr_dyn_new_handle(v, ${h.tag});`);
|
|
1370
1310
|
break;
|
|
1371
1311
|
}
|
|
1372
|
-
throw new
|
|
1312
|
+
throw new InternalCompilerError(`emitter bug: to-dyn of unsupported type ${t.kind}`);
|
|
1373
1313
|
}
|
|
1374
1314
|
}
|
|
1375
1315
|
d.push(`}`, ``);
|
|
1376
|
-
|
|
1316
|
+
emitter.walkerDefs.push(...d);
|
|
1377
1317
|
if (sourceAccessor) {
|
|
1378
|
-
|
|
1318
|
+
emitter.walkerDefs.push(`static ScrDyn *${sourceAccessor.name}(void *v, bool materialize) {`, ` if (materialize) return ${name}((${cType(t).trim()})v);`, ` ${sourceAccessor.release}(v);`, ` return NULL;`, `}`, ``);
|
|
1379
1319
|
}
|
|
1380
1320
|
return name;
|
|
1381
1321
|
}
|
|
@@ -1385,15 +1325,15 @@ export function toDynHelper(E, t) {
|
|
|
1385
1325
|
* value, and fulfill dst with it (scr_dyn_new_promise_adapting's
|
|
1386
1326
|
* callback; rejections never reach an adapter — the runtime copies them
|
|
1387
1327
|
* raw). Interned per inner typeKey. */
|
|
1388
|
-
|
|
1328
|
+
function promiseDynAdapterHelper(emitter, inner) {
|
|
1389
1329
|
const key = typeKey(inner);
|
|
1390
|
-
const existing =
|
|
1330
|
+
const existing = emitter.promiseDynAdapters.get(key);
|
|
1391
1331
|
if (existing)
|
|
1392
1332
|
return existing;
|
|
1393
|
-
const name = `sc_pda_${
|
|
1394
|
-
|
|
1333
|
+
const name = `sc_pda_${emitter.promiseDynAdapters.size}`;
|
|
1334
|
+
emitter.promiseDynAdapters.set(key, name);
|
|
1395
1335
|
const sig = `static void ${name}(ScrPromise *dst, ScrPromise *src)`;
|
|
1396
|
-
|
|
1336
|
+
emitter.walkerProtos.push(`${sig}; /* dyn-box settle adapter for promise<${key}> */`);
|
|
1397
1337
|
const d = [`${sig} { /* dyn-box settle adapter for promise<${key}> */`];
|
|
1398
1338
|
const fulfill = (expr) => ` scr_promise_fulfill_ref(dst, ${expr}, scr_dyn_retain_v, scr_dyn_release_v, NULL);`;
|
|
1399
1339
|
switch (inner.kind) {
|
|
@@ -1423,7 +1363,7 @@ export function promiseDynAdapterHelper(E, inner) {
|
|
|
1423
1363
|
// nested promises, handles): extract (+1 via the stored retain),
|
|
1424
1364
|
// convert through the shared to-dyn spelling, release the extract.
|
|
1425
1365
|
d.push(` ${cDecl(inner, "pv")} = (${cType(inner).trim()})scr_promise_payload_ref(src);`);
|
|
1426
|
-
d.push(` ScrDyn *dv = ${toDynExprC(
|
|
1366
|
+
d.push(` ScrDyn *dv = ${toDynExprC(emitter, inner, "pv")};`);
|
|
1427
1367
|
if (isRefCounted(inner))
|
|
1428
1368
|
d.push(` ${releaseCallC(inner, "pv")};`);
|
|
1429
1369
|
d.push(fulfill(`dv`));
|
|
@@ -1431,10 +1371,10 @@ export function promiseDynAdapterHelper(E, inner) {
|
|
|
1431
1371
|
}
|
|
1432
1372
|
}
|
|
1433
1373
|
d.push(`}`, ``);
|
|
1434
|
-
|
|
1374
|
+
emitter.walkerDefs.push(...d);
|
|
1435
1375
|
return name;
|
|
1436
1376
|
}
|
|
1437
|
-
/* ── the checked-dynamic function boundary (
|
|
1377
|
+
/* ── the checked-dynamic function boundary (ir.ts) ─────────────────
|
|
1438
1378
|
* Three interned per-signature helpers:
|
|
1439
1379
|
*
|
|
1440
1380
|
* sc_dfk_<n> — the CALL THUNK a dyn-boxed closure carries: validate
|
|
@@ -1459,27 +1399,27 @@ export function promiseDynAdapterHelper(E, inner) {
|
|
|
1459
1399
|
* result uniformly), funcs box (anonymous — the static name is gone by
|
|
1460
1400
|
* the time a value flows through an adapter; SEMANTICS.md), everything
|
|
1461
1401
|
* else rides the toDyn converter. `expr` is BORROWED in every arm. */
|
|
1462
|
-
function toDynExprC(
|
|
1402
|
+
function toDynExprC(emitter, t, expr) {
|
|
1463
1403
|
if (t.kind === "dyn")
|
|
1464
1404
|
return `scr_dyn_retain(${expr})`;
|
|
1465
1405
|
if (t.kind === "func")
|
|
1466
|
-
return `${
|
|
1406
|
+
return `${emitter.dynFuncBoxHelper(t)}(${expr}, NULL)`;
|
|
1467
1407
|
// An island value wraps by reference (scalar-normalizing) — the
|
|
1468
1408
|
// jsval-returning callback shape of the routed-dispatch lane.
|
|
1469
1409
|
if (t.kind === "jsval")
|
|
1470
1410
|
return `scr_dyn_from_jsval(${expr})`;
|
|
1471
|
-
return `${
|
|
1411
|
+
return `${emitter.toDynHelper(t)}(${expr})`;
|
|
1472
1412
|
}
|
|
1473
1413
|
/** The call thunk for one closure signature (see the block comment). */
|
|
1474
|
-
|
|
1414
|
+
function dynFuncThunkHelper(emitter, t) {
|
|
1475
1415
|
const key = typeKey(t);
|
|
1476
|
-
const existing =
|
|
1416
|
+
const existing = emitter.dynFuncThunks.get(key);
|
|
1477
1417
|
if (existing)
|
|
1478
1418
|
return existing;
|
|
1479
|
-
const name = `sc_dfk_${
|
|
1480
|
-
|
|
1419
|
+
const name = `sc_dfk_${emitter.dynFuncThunks.size}`;
|
|
1420
|
+
emitter.dynFuncThunks.set(key, name);
|
|
1481
1421
|
const sig = `static ScrDyn *${name}(ScrClosure *c, ScrDyn *const *args, size_t argc)`;
|
|
1482
|
-
|
|
1422
|
+
emitter.walkerProtos.push(`${sig}; /* dyn call thunk for ${key} */`);
|
|
1483
1423
|
const d = [`${sig} { /* dyn call thunk for ${key} */`];
|
|
1484
1424
|
if (t.params.length === 0)
|
|
1485
1425
|
d.push(` (void)args;`);
|
|
@@ -1507,7 +1447,7 @@ export function dynFuncThunkHelper(E, t) {
|
|
|
1507
1447
|
}
|
|
1508
1448
|
else {
|
|
1509
1449
|
d.push(` ScrDynPath pp = { NULL, NULL, ${i} };`);
|
|
1510
|
-
d.push(` a${i} = ${
|
|
1450
|
+
d.push(` a${i} = ${emitter.dynCheckHelper(p)}(ad, &pp);`);
|
|
1511
1451
|
const undo = t.params
|
|
1512
1452
|
.slice(0, i)
|
|
1513
1453
|
.flatMap((q, j) => (isRefCounted(q) ? [`${releaseCallC(q, `a${j}`)};`] : []));
|
|
@@ -1542,44 +1482,44 @@ export function dynFuncThunkHelper(E, t) {
|
|
|
1542
1482
|
else {
|
|
1543
1483
|
d.push(` ${cDecl(t.ret, "r")} = ${call};`);
|
|
1544
1484
|
d.push(` if (scr_exc_pending()) return NULL;`);
|
|
1545
|
-
d.push(` ScrDyn *out = ${toDynExprC(
|
|
1485
|
+
d.push(` ScrDyn *out = ${toDynExprC(emitter, t.ret, "r")};`);
|
|
1546
1486
|
if (isRefCounted(t.ret))
|
|
1547
1487
|
d.push(` ${releaseCallC(t.ret, "r")};`);
|
|
1548
1488
|
d.push(` return out;`);
|
|
1549
1489
|
}
|
|
1550
1490
|
d.push(`}`, ``);
|
|
1551
|
-
|
|
1491
|
+
emitter.walkerDefs.push(...d);
|
|
1552
1492
|
return name;
|
|
1553
1493
|
}
|
|
1554
1494
|
/** The box builder dynFrom emits for one closure signature. */
|
|
1555
|
-
export function dynFuncBoxHelper(
|
|
1495
|
+
export function dynFuncBoxHelper(emitter, t) {
|
|
1556
1496
|
const key = typeKey(t);
|
|
1557
|
-
const existing =
|
|
1497
|
+
const existing = emitter.dynFuncBoxes.get(key);
|
|
1558
1498
|
if (existing)
|
|
1559
1499
|
return existing;
|
|
1560
|
-
const name = `sc_dfb_${
|
|
1561
|
-
|
|
1500
|
+
const name = `sc_dfb_${emitter.dynFuncBoxes.size}`;
|
|
1501
|
+
emitter.dynFuncBoxes.set(key, name);
|
|
1562
1502
|
const sig = `static ScrDyn *${name}(ScrClosure *v, const char *fname)`;
|
|
1563
|
-
|
|
1564
|
-
const thunk = dynFuncThunkHelper(
|
|
1503
|
+
emitter.walkerProtos.push(`${sig}; /* box ${key} into dyn */`);
|
|
1504
|
+
const thunk = dynFuncThunkHelper(emitter, t);
|
|
1565
1505
|
const sigLit = cStringLiteral(Buffer.from(key, "utf8"));
|
|
1566
|
-
|
|
1506
|
+
emitter.walkerDefs.push(`${sig} { /* box ${key} into dyn */`, ` return scr_dyn_new_func(scr_closure_retain(v), &${thunk}, ${t.params.length}, ${sigLit}, fname);`, `}`, ``);
|
|
1567
1507
|
return name;
|
|
1568
1508
|
}
|
|
1569
1509
|
/** The adapter closure body for one TARGET signature: the emitted C
|
|
1570
1510
|
* function a func-targeted dynCheck wraps a non-identical boxed
|
|
1571
1511
|
* signature in. caps[0] is an untraced obj-box owning the dyn function
|
|
1572
1512
|
* value. */
|
|
1573
|
-
|
|
1513
|
+
function dynFuncAdapterHelper(emitter, t) {
|
|
1574
1514
|
const key = typeKey(t);
|
|
1575
|
-
const existing =
|
|
1515
|
+
const existing = emitter.dynFuncAdapters.get(key);
|
|
1576
1516
|
if (existing)
|
|
1577
1517
|
return existing;
|
|
1578
|
-
const name = `sc_dfa_${
|
|
1579
|
-
|
|
1518
|
+
const name = `sc_dfa_${emitter.dynFuncAdapters.size}`;
|
|
1519
|
+
emitter.dynFuncAdapters.set(key, name);
|
|
1580
1520
|
const params = ["ScrClosure *sc_env", ...t.params.map((p, i) => cDecl(p, `a${i}`))].join(", ");
|
|
1581
1521
|
const sig = `static ${cType(t.ret)}${cType(t.ret).endsWith("*") ? "" : " "}${name}(${params})`;
|
|
1582
|
-
|
|
1522
|
+
emitter.walkerProtos.push(`${sig}; /* dyn fn adapter to ${key} */`);
|
|
1583
1523
|
const dummy = t.ret.kind === "void" ? "" : t.ret.kind === "f64" ? "0" : t.ret.kind === "bool" ? "false" : "NULL";
|
|
1584
1524
|
const d = [`${sig} { /* dyn fn adapter to ${key} */`];
|
|
1585
1525
|
d.push(` ScrDyn *sc_fn = (ScrDyn *)scr_box_get_ref(sc_env->caps[0]); /* +1 */`);
|
|
@@ -1588,7 +1528,7 @@ export function dynFuncAdapterHelper(E, t) {
|
|
|
1588
1528
|
if (t.params.length > 0) {
|
|
1589
1529
|
d.push(` ScrDyn *sc_args[${t.params.length}];`);
|
|
1590
1530
|
t.params.forEach((p, i) => {
|
|
1591
|
-
d.push(` sc_args[${i}] = ${toDynExprC(
|
|
1531
|
+
d.push(` sc_args[${i}] = ${toDynExprC(emitter, p, `a${i}`)};`);
|
|
1592
1532
|
if (isRefCounted(p))
|
|
1593
1533
|
d.push(` ${releaseCallC(p, `a${i}`)};`);
|
|
1594
1534
|
});
|
|
@@ -1610,12 +1550,12 @@ export function dynFuncAdapterHelper(E, t) {
|
|
|
1610
1550
|
// Validate the dyn result into the target's return type — a lying
|
|
1611
1551
|
// wrapper throws the catchable TypeError here (path "$"), exactly
|
|
1612
1552
|
// the dynCheck stance; the dummy result rides the pending unwind.
|
|
1613
|
-
d.push(` ${cDecl(t.ret, "out")} = ${
|
|
1553
|
+
d.push(` ${cDecl(t.ret, "out")} = ${emitter.dynCheckHelper(t.ret)}(sc_r, NULL);`);
|
|
1614
1554
|
d.push(` scr_dyn_release(sc_r);`);
|
|
1615
1555
|
d.push(` return out;`);
|
|
1616
1556
|
}
|
|
1617
1557
|
d.push(`}`, ``);
|
|
1618
|
-
|
|
1558
|
+
emitter.walkerDefs.push(...d);
|
|
1619
1559
|
return name;
|
|
1620
1560
|
}
|
|
1621
1561
|
/** The emitted dynamic-keyed READ helper for one (shape, result type):
|
|
@@ -1627,19 +1567,19 @@ export function dynFuncAdapterHelper(E, t) {
|
|
|
1627
1567
|
* arm (T undefined-armed union), or TRAPS with the key text (the array
|
|
1628
1568
|
* OOB policy — the checker claimed T and no undefined is representable).
|
|
1629
1569
|
* Borrows both; refcounted results are owned (+1). */
|
|
1630
|
-
export function recordKeyGetHelper(
|
|
1570
|
+
export function recordKeyGetHelper(emitter, shapeId, t, overflowOnly = false) {
|
|
1631
1571
|
const key = `${shapeId}|${typeKey(t)}${overflowOnly ? "|ovf" : ""}`;
|
|
1632
|
-
const existing =
|
|
1572
|
+
const existing = emitter.recordKeyGetFns.get(key);
|
|
1633
1573
|
if (existing)
|
|
1634
1574
|
return existing;
|
|
1635
|
-
const shape =
|
|
1575
|
+
const shape = emitter.recordsById.get(shapeId);
|
|
1636
1576
|
if (!shape)
|
|
1637
|
-
throw new
|
|
1638
|
-
const name = `sc_rkg_${
|
|
1639
|
-
|
|
1577
|
+
throw new InternalCompilerError(`emitter bug: keyed read of unknown shape ${shapeId}`);
|
|
1578
|
+
const name = `sc_rkg_${emitter.recordKeyGetFns.size}`;
|
|
1579
|
+
emitter.recordKeyGetFns.set(key, name);
|
|
1640
1580
|
const struct = mangleRecordStruct(shapeId);
|
|
1641
1581
|
const sig = `static ${cType(t)}${cType(t).endsWith("*") ? "" : " "}${name}(${struct} *r, ScrStr *k)`;
|
|
1642
|
-
|
|
1582
|
+
emitter.walkerProtos.push(`${sig}; /* r[k] on ${shapeId} as ${typeKey(t)} */`);
|
|
1643
1583
|
const d = [`${sig} { /* r[k] on ${shapeId} as ${typeKey(t)} */`];
|
|
1644
1584
|
// How a value of type `vt` (a field, or the overflow hit) surfaces as T.
|
|
1645
1585
|
const surface = (vt, expr, owned) => {
|
|
@@ -1648,27 +1588,27 @@ export function recordKeyGetHelper(E, shapeId, t, overflowOnly = false) {
|
|
|
1648
1588
|
}
|
|
1649
1589
|
if (t.kind === "dyn") {
|
|
1650
1590
|
// toDyn borrows — an owned operand would leak; callers pass borrowed.
|
|
1651
|
-
return `${
|
|
1591
|
+
return `${emitter.toDynHelper(vt)}(${expr})`;
|
|
1652
1592
|
}
|
|
1653
1593
|
if (t.kind === "union") {
|
|
1654
|
-
const def =
|
|
1594
|
+
const def = emitter.unionsById.get(t.unionId);
|
|
1655
1595
|
const tag = def?.arms.findIndex((a) => typeEquals(a, vt)) ?? -1;
|
|
1656
1596
|
if (tag < 0)
|
|
1657
|
-
throw new
|
|
1597
|
+
throw new InternalCompilerError(`emitter bug: keyed read arm for ${typeKey(vt)} in ${typeKey(t)}`);
|
|
1658
1598
|
if (vt.kind === "f64")
|
|
1659
1599
|
return `scr_union_new_f64(${tag}, ${expr})`;
|
|
1660
1600
|
if (vt.kind === "bool")
|
|
1661
1601
|
return `scr_union_new_bool(${tag}, ${expr})`;
|
|
1662
1602
|
const rc = vAdapters(vt);
|
|
1663
1603
|
const payload = owned ? expr : retainCallC(vt, expr);
|
|
1664
|
-
return `scr_union_new_ref(${tag}, ${payload}, &${rc.retain}, &${rc.release}, ${
|
|
1604
|
+
return `scr_union_new_ref(${tag}, ${payload}, &${rc.retain}, &${rc.release}, ${emitter.traceArgC(vt)})`;
|
|
1665
1605
|
}
|
|
1666
|
-
throw new
|
|
1606
|
+
throw new InternalCompilerError(`emitter bug: keyed read cannot surface ${typeKey(vt)} as ${typeKey(t)}`);
|
|
1667
1607
|
};
|
|
1668
1608
|
// overflowOnly (a literal key naming no declared field): the declared
|
|
1669
1609
|
// switch can never hit — only the overflow answers.
|
|
1670
1610
|
for (const f of overflowOnly ? [] : shape.fields) {
|
|
1671
|
-
const lit =
|
|
1611
|
+
const lit = emitter.internLiteral(f.name);
|
|
1672
1612
|
d.push(` if (scr_str_eq(k, (ScrStr *)&${lit})) { /* ${f.name} */`);
|
|
1673
1613
|
d.push(` return ${surface(f.type, `r->${mangleField(f.name)}`, false)};`);
|
|
1674
1614
|
d.push(` }`);
|
|
@@ -1693,7 +1633,7 @@ export function recordKeyGetHelper(E, shapeId, t, overflowOnly = false) {
|
|
|
1693
1633
|
d.push(` return ${surface(iv, "hit", true)};`);
|
|
1694
1634
|
}
|
|
1695
1635
|
else {
|
|
1696
|
-
throw new
|
|
1636
|
+
throw new InternalCompilerError(`emitter bug: keyed read overflow ${typeKey(iv)} as ${typeKey(t)}`);
|
|
1697
1637
|
}
|
|
1698
1638
|
d.push(` }`);
|
|
1699
1639
|
}
|
|
@@ -1702,17 +1642,17 @@ export function recordKeyGetHelper(E, shapeId, t, overflowOnly = false) {
|
|
|
1702
1642
|
if (t.kind === "dyn") {
|
|
1703
1643
|
d.push(` return scr_dyn_retain(scr_dyn_undefined());`);
|
|
1704
1644
|
}
|
|
1705
|
-
else if (t.kind === "union" &&
|
|
1706
|
-
d.push(` return ${
|
|
1645
|
+
else if (t.kind === "union" && undefinedArmTag(t, emitter.unionsById) >= 0) {
|
|
1646
|
+
d.push(` return ${emitter.unitInstanceRef(t.unionId, undefinedArmTag(t, emitter.unionsById))};`);
|
|
1707
1647
|
}
|
|
1708
1648
|
else {
|
|
1709
1649
|
// JS would answer undefined; T has no way to say it (the checker
|
|
1710
1650
|
// claimed T without noUncheckedIndexedAccess) — trap like an array
|
|
1711
1651
|
// OOB read instead of corrupting a typed slot (SEMANTICS.md).
|
|
1712
|
-
d.push(` scr_trap_fmt("scriptc: TypeError: record has no key '%.*s' (typed '${
|
|
1652
|
+
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);`);
|
|
1713
1653
|
}
|
|
1714
1654
|
d.push(`}`, ``);
|
|
1715
|
-
|
|
1655
|
+
emitter.walkerDefs.push(...d);
|
|
1716
1656
|
return name;
|
|
1717
1657
|
}
|
|
1718
1658
|
/** The emitted dynamic-keyed WRITE helper for one index-signature shape:
|
|
@@ -1723,32 +1663,32 @@ export function recordKeyGetHelper(E, shapeId, t, overflowOnly = false) {
|
|
|
1723
1663
|
* anything, the documented divergence; typed values store directly),
|
|
1724
1664
|
* an undeclared key inserts/replaces in the overflow map. Borrows r and
|
|
1725
1665
|
* k; OWNS v (+1 moves in — released on the validation-failure path). */
|
|
1726
|
-
export function recordKeySetHelper(
|
|
1727
|
-
const existing =
|
|
1666
|
+
export function recordKeySetHelper(emitter, shapeId) {
|
|
1667
|
+
const existing = emitter.recordKeySetFns.get(shapeId);
|
|
1728
1668
|
if (existing)
|
|
1729
1669
|
return existing;
|
|
1730
|
-
const shape =
|
|
1670
|
+
const shape = emitter.recordsById.get(shapeId);
|
|
1731
1671
|
// Signature-free shapes dispatch over their (one-typed) declared
|
|
1732
1672
|
// fields and TRAP on a miss (scr_record_key_miss — JS would add the
|
|
1733
1673
|
// property, which a monomorphic struct cannot); overflow shapes keep
|
|
1734
1674
|
// the map insert tail.
|
|
1735
1675
|
const iv = shape?.indexValue ?? shape?.fields[0]?.type;
|
|
1736
1676
|
if (!shape || !iv)
|
|
1737
|
-
throw new
|
|
1738
|
-
const name = `sc_rks_${
|
|
1739
|
-
|
|
1677
|
+
throw new InternalCompilerError(`emitter bug: keyed write on field-free non-overflow shape ${shapeId}`);
|
|
1678
|
+
const name = `sc_rks_${emitter.recordKeySetFns.size}`;
|
|
1679
|
+
emitter.recordKeySetFns.set(shapeId, name);
|
|
1740
1680
|
const struct = mangleRecordStruct(shapeId);
|
|
1741
1681
|
const sig = `static void ${name}(${struct} *r, ScrStr *k, ${cDecl(iv, "v")})`;
|
|
1742
|
-
|
|
1682
|
+
emitter.walkerProtos.push(`${sig}; /* r[k] = v on ${shapeId} */`);
|
|
1743
1683
|
const d = [`${sig} { /* r[k] = v on ${shapeId} */`];
|
|
1744
1684
|
for (const f of shape.fields) {
|
|
1745
|
-
const lit =
|
|
1685
|
+
const lit = emitter.internLiteral(f.name);
|
|
1746
1686
|
const member = `r->${mangleField(f.name)}`;
|
|
1747
1687
|
d.push(` if (scr_str_eq(k, (ScrStr *)&${lit})) { /* ${f.name} */`);
|
|
1748
1688
|
if (iv.kind === "dyn" && shape.indexValue) {
|
|
1749
1689
|
const keyLit = cStringLiteral(Buffer.from(f.name, "utf8"));
|
|
1750
1690
|
d.push(` ScrDynPath p = { NULL, ${keyLit}, 0 };`);
|
|
1751
|
-
d.push(` ${cDecl(f.type, "nv")} = ${
|
|
1691
|
+
d.push(` ${cDecl(f.type, "nv")} = ${emitter.dynCheckHelper(f.type)}(v, &p);`);
|
|
1752
1692
|
d.push(` scr_dyn_release(v);`);
|
|
1753
1693
|
d.push(` if (scr_exc_pending()) return; /* mismatched write: TypeError, field untouched */`);
|
|
1754
1694
|
d.push(` ${isRefCounted(f.type) ? `if (${member}) ${releaseCallC(f.type, member)};` : `(void)0;`}`);
|
|
@@ -1782,7 +1722,7 @@ export function recordKeySetHelper(E, shapeId) {
|
|
|
1782
1722
|
}
|
|
1783
1723
|
}
|
|
1784
1724
|
d.push(`}`, ``);
|
|
1785
|
-
|
|
1725
|
+
emitter.walkerDefs.push(...d);
|
|
1786
1726
|
return name;
|
|
1787
1727
|
}
|
|
1788
|
-
//# sourceMappingURL=
|
|
1728
|
+
//# sourceMappingURL=walkers.js.map
|