@scriptc/compiler 0.0.35 → 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/ambient/scriptc-node-fallback.d.ts +14 -11
- package/ambient/scriptc-overrides.d.ts +0 -7
- package/ambient/scriptc.d.ts +1 -1
- 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 +7937 -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 +4 -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} +395 -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} +242 -304
- package/dist/backend/c/walkers.js.map +1 -0
- package/dist/backend/external-c.d.ts +33 -0
- package/dist/backend/external-c.js +51 -0
- package/dist/backend/external-c.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/link-plan.d.ts +37 -0
- package/dist/backend/link-plan.js +26 -0
- package/dist/backend/link-plan.js.map +1 -0
- package/dist/backend/linker.d.ts +22 -0
- package/dist/backend/linker.js +236 -0
- package/dist/backend/linker.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 +159 -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 +548 -9988
- 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 +637 -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 +153 -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 +642 -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 +420 -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/unsupported.d.ts +1 -1
- package/dist/backend/llvm/walkers.d.ts +2 -3
- package/dist/backend/llvm/walkers.js +195 -222
- package/dist/backend/llvm/walkers.js.map +1 -1
- package/dist/backend/native-codegen.d.ts +45 -0
- package/dist/backend/native-codegen.js +275 -0
- package/dist/backend/native-codegen.js.map +1 -0
- package/dist/backend/native-codegen.test.js +226 -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 +243 -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} +54 -34
- package/dist/backend/{cc.js → native-toolchain.js} +231 -810
- 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} +219 -7
- package/dist/backend/native-toolchain.test.js.map +1 -0
- package/dist/backend/object-localize.js +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-targets.test.d.ts +1 -0
- package/dist/backend/runtime-pack-targets.test.js +54 -0
- package/dist/backend/runtime-pack-targets.test.js.map +1 -0
- package/dist/backend/runtime-pack.d.ts +112 -0
- package/dist/backend/runtime-pack.js +305 -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 +473 -0
- package/dist/backend/runtime-pack.test.js.map +1 -0
- package/dist/backend/targets.d.ts +76 -0
- package/dist/backend/targets.js +262 -0
- package/dist/backend/targets.js.map +1 -0
- package/dist/backend/targets.test.d.ts +1 -0
- package/dist/backend/targets.test.js +41 -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 +35 -33
- 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/{early-cache.d.ts → executable-cache.d.ts} +2 -2
- package/dist/executable/{early-cache.js → executable-cache.js} +36 -98
- package/dist/executable/executable-cache.js.map +1 -0
- package/dist/executable/executable-cache.test.d.ts +1 -0
- package/dist/executable/{early-cache.test.js → executable-cache.test.js} +3 -3
- package/dist/executable/executable-cache.test.js.map +1 -0
- package/dist/ffi/{profile.js → ffi-manifest.js} +1 -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/array-values.d.ts +8 -0
- package/dist/frontend/lowering/array-values.js +60 -0
- package/dist/frontend/lowering/array-values.js.map +1 -0
- 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-array-sort.d.ts +22 -0
- package/dist/frontend/lowering/lower-array-sort.js +619 -0
- package/dist/frontend/lowering/lower-array-sort.js.map +1 -0
- 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 +1285 -1233
- package/dist/frontend/lowering/lower-builtins.js.map +1 -1
- package/dist/frontend/lowering/lower-calls.d.ts +59 -192
- package/dist/frontend/lowering/lower-calls.js +1644 -1506
- 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 +1984 -2227
- 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 +60 -264
- package/dist/frontend/lowering/lower-exprs.js +2361 -1765
- 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 +273 -261
- package/dist/frontend/lowering/lower-inspect.js.map +1 -1
- package/dist/frontend/lowering/lower-island.d.ts +39 -49
- package/dist/frontend/lowering/lower-island.js +447 -513
- 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 +85 -85
- 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 +909 -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 +1463 -1285
- 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 +134 -22
- package/dist/frontend/lowering/lowerer.js +1277 -126
- 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 +24 -35
- package/dist/frontend/lowering/surfaces.js +78 -66
- 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 +9 -4
- 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.js +2 -36
- 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} +12 -11
- 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 +113 -31
- package/dist/index.js +536 -128
- 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} +119 -37
- package/dist/ir/{nodes.js → ir.js} +170 -166
- 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 +2 -2
- package/dist/ir/serialize.js +3 -2
- package/dist/ir/serialize.js.map +1 -1
- package/dist/ir/validate.d.ts +1 -1
- package/dist/ir/validate.js +93 -41
- 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/{implementation-identity.js → compiler-self-identity.js} +1 -1
- 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 +8 -2
- package/dist/library/fence-eval.js.map +1 -1
- package/dist/library/int-infer.d.ts +1 -36
- package/dist/library/int-infer.js +29 -18
- package/dist/library/int-infer.js.map +1 -1
- package/dist/library/int-infer.test.js +4 -4
- package/dist/library/{early-cache.d.ts → library-cache.d.ts} +1 -1
- package/dist/library/{early-cache.js → library-cache.js} +34 -89
- 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} +7 -7
- 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 +11 -3
- package/dist/startup-cache.js +17 -2
- package/dist/startup-cache.js.map +1 -1
- package/package.json +19 -2
- package/surface-manifest.json +5 -5
- 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/executable/early-cache.js.map +0 -1
- package/dist/executable/early-cache.test.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/implementation-identity.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/{executable/early-cache.test.d.ts → backend/llvm/shapes.test.d.ts} +0 -0
- /package/dist/{library/early-cache.test.d.ts → backend/native-codegen.test.d.ts} +0 -0
- /package/dist/ffi/{profile.d.ts → ffi-manifest.d.ts} +0 -0
- /package/dist/frontend/ts7/{program.d.ts → program-adapter.d.ts} +0 -0
- /package/dist/library/{implementation-identity.d.ts → compiler-self-identity.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]);`, ` /* Holes and payload-free present undefined both stringify empty. */`, ` if (scr_arr_state(a, (double)i) != SCR_ARR_VALUE) continue;`, ` ScrUnion *u = (ScrUnion *)scr_arr_get_ref(a, (double)i);`, ...(unitTags.length > 0
|
|
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,15 +399,16 @@ 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, '[');`);
|
|
469
409
|
d.push(` for (size_t i = 0; i < v->len; i++) {`);
|
|
470
410
|
d.push(` if (i > 0) scr_jb_putc(b, ',');`);
|
|
411
|
+
d.push(` if (scr_arr_state(v, (double)i) != SCR_ARR_VALUE) { scr_jb_puts(b, "null"); continue; }`);
|
|
471
412
|
if (cyclic)
|
|
472
413
|
d.push(` scr_jb_edge_idx(b, i);`);
|
|
473
414
|
if (elem.kind === "f64") {
|
|
@@ -489,9 +430,9 @@ export function jsonWriteHelper(E, t) {
|
|
|
489
430
|
break;
|
|
490
431
|
}
|
|
491
432
|
case "union": {
|
|
492
|
-
const def =
|
|
433
|
+
const def = emitter.unionsById.get(t.unionId);
|
|
493
434
|
if (!def)
|
|
494
|
-
throw new
|
|
435
|
+
throw new InternalCompilerError(`emitter bug: jsonStringify of unknown union ${t.unionId}`);
|
|
495
436
|
d.push(` switch (v->tag) {`);
|
|
496
437
|
def.arms.forEach((arm, i) => {
|
|
497
438
|
if (arm.kind === "nullT") {
|
|
@@ -501,15 +442,12 @@ export function jsonWriteHelper(E, t) {
|
|
|
501
442
|
return;
|
|
502
443
|
}
|
|
503
444
|
if (arm.kind === "undefinedT") {
|
|
504
|
-
//
|
|
505
|
-
//
|
|
506
|
-
|
|
507
|
-
// calling — so the tag can never arrive here.
|
|
508
|
-
d.push(` case ${i}: /* undefined arm: the field dropped at the record level */`);
|
|
509
|
-
d.push(` scr_trap("scriptc: internal error: stringify reached an undefined arm\\n");`);
|
|
445
|
+
// Array and tuple slots stringify undefined as null. Ordinary
|
|
446
|
+
// record fields drop the key before invoking this writer.
|
|
447
|
+
d.push(` case ${i}: scr_jb_puts(b, "null"); break;`);
|
|
510
448
|
return;
|
|
511
449
|
}
|
|
512
|
-
const w =
|
|
450
|
+
const w = emitter.jsonWriteHelper(arm);
|
|
513
451
|
if (arm.kind === "f64") {
|
|
514
452
|
d.push(` case ${i}: ${w}(b, scr_union_get_f64(v)); break;`);
|
|
515
453
|
}
|
|
@@ -526,10 +464,10 @@ export function jsonWriteHelper(E, t) {
|
|
|
526
464
|
break;
|
|
527
465
|
}
|
|
528
466
|
default:
|
|
529
|
-
throw new
|
|
467
|
+
throw new InternalCompilerError(`emitter bug: jsonStringify of non-JSON type ${t.kind}`);
|
|
530
468
|
}
|
|
531
469
|
d.push(`}`, ``);
|
|
532
|
-
|
|
470
|
+
emitter.walkerDefs.push(...d);
|
|
533
471
|
return name;
|
|
534
472
|
}
|
|
535
473
|
/** The emitted match predicate for one dynCheck target type:
|
|
@@ -537,15 +475,15 @@ export function jsonWriteHelper(E, t) {
|
|
|
537
475
|
* Never throws, builds nothing; union builders use it to try arms in
|
|
538
476
|
* canonical order (first FULL match wins). Records are width-tolerant
|
|
539
477
|
* here too: extra keys are ignored, only declared fields are examined. */
|
|
540
|
-
export function dynMatchHelper(
|
|
478
|
+
export function dynMatchHelper(emitter, t) {
|
|
541
479
|
const key = typeKey(t);
|
|
542
|
-
const existing =
|
|
480
|
+
const existing = emitter.dynMatchers.get(key);
|
|
543
481
|
if (existing)
|
|
544
482
|
return existing;
|
|
545
|
-
const name = `sc_dm_${
|
|
546
|
-
|
|
483
|
+
const name = `sc_dm_${emitter.dynMatchers.size}`;
|
|
484
|
+
emitter.dynMatchers.set(key, name);
|
|
547
485
|
const sig = `static bool ${name}(const ScrDyn *d)`;
|
|
548
|
-
|
|
486
|
+
emitter.walkerProtos.push(`${sig}; /* matches ${key} */`);
|
|
549
487
|
const d = [`${sig} { /* matches ${key} */`];
|
|
550
488
|
if (isRefCounted(t) && t.kind !== "dyn") {
|
|
551
489
|
const keyLit = cStringLiteral(Buffer.from(key, "utf8"));
|
|
@@ -583,13 +521,13 @@ export function dynMatchHelper(E, t) {
|
|
|
583
521
|
case "bytes":
|
|
584
522
|
// A Uint8Array target (the checked-dynamic tree carries u8 payloads only).
|
|
585
523
|
if (t.elem !== "u8")
|
|
586
|
-
throw new
|
|
524
|
+
throw new InternalCompilerError(`emitter bug: dynMatch of bytes<${t.elem}>`);
|
|
587
525
|
d.push(` return d->kind == SCR_DYN_BYTES;`);
|
|
588
526
|
break;
|
|
589
527
|
case "record": {
|
|
590
|
-
const shape =
|
|
528
|
+
const shape = emitter.recordsById.get(t.shapeId);
|
|
591
529
|
if (!shape)
|
|
592
|
-
throw new
|
|
530
|
+
throw new InternalCompilerError(`emitter bug: dynCheck of unknown shape ${t.shapeId}`);
|
|
593
531
|
// A tuple matches a JSON ARRAY of EXACTLY its arity whose elements
|
|
594
532
|
// match positionally (arity is part of the type — width tolerance
|
|
595
533
|
// is an object-key concept and does not apply).
|
|
@@ -597,7 +535,7 @@ export function dynMatchHelper(E, t) {
|
|
|
597
535
|
const byIndex = [...shape.fields].sort((a, b) => Number(a.name) - Number(b.name));
|
|
598
536
|
d.push(` if (d->kind != SCR_DYN_ARR || d->v.arr.len != ${byIndex.length}) return false;`);
|
|
599
537
|
byIndex.forEach((f, i) => {
|
|
600
|
-
d.push(` if (!${
|
|
538
|
+
d.push(` if (!${emitter.dynMatchHelper(f.type)}(d->v.arr.items[${i}])) return false;`);
|
|
601
539
|
});
|
|
602
540
|
d.push(` return true;`);
|
|
603
541
|
break;
|
|
@@ -613,13 +551,13 @@ export function dynMatchHelper(E, t) {
|
|
|
613
551
|
const keyLit = cStringLiteral(Buffer.from(f.name, "utf8"));
|
|
614
552
|
const keyLen = Buffer.byteLength(f.name, "utf8");
|
|
615
553
|
d.push(` m = scr_dyn_obj_get(d, ${keyLit}, ${keyLen});`);
|
|
616
|
-
if (
|
|
554
|
+
if (undefinedArmTag(f.type, emitter.unionsById) >= 0) {
|
|
617
555
|
// Optional-flavored field: a MISSING key is the undefined arm
|
|
618
556
|
// (a match); a PRESENT key must fit the union as usual.
|
|
619
|
-
d.push(` if (m && !${
|
|
557
|
+
d.push(` if (m && !${emitter.dynMatchHelper(f.type)}(m)) return false;`);
|
|
620
558
|
}
|
|
621
559
|
else {
|
|
622
|
-
d.push(` if (!m || !${
|
|
560
|
+
d.push(` if (!m || !${emitter.dynMatchHelper(f.type)}(m)) return false;`);
|
|
623
561
|
}
|
|
624
562
|
}
|
|
625
563
|
// Index-signature shapes: UNDECLARED keys must fit the overflow
|
|
@@ -638,14 +576,14 @@ export function dynMatchHelper(E, t) {
|
|
|
638
576
|
d.push(` const ScrDynEntry *e = &d->v.obj.entries[i];`);
|
|
639
577
|
if (shape.fields.length > 0)
|
|
640
578
|
d.push(` if (${skip}) continue;`);
|
|
641
|
-
d.push(` if (!${
|
|
579
|
+
d.push(` if (!${emitter.dynMatchHelper(shape.indexValue)}(e->value)) return false;`);
|
|
642
580
|
d.push(` }`);
|
|
643
581
|
}
|
|
644
582
|
d.push(` return true;`);
|
|
645
583
|
break;
|
|
646
584
|
}
|
|
647
585
|
case "array": {
|
|
648
|
-
const m =
|
|
586
|
+
const m = emitter.dynMatchHelper(t.elem);
|
|
649
587
|
d.push(` if (d->kind != SCR_DYN_ARR) return false;`);
|
|
650
588
|
d.push(` for (size_t i = 0; i < d->v.arr.len; i++) {`);
|
|
651
589
|
d.push(` if (!${m}(d->v.arr.items[i])) return false;`);
|
|
@@ -654,23 +592,23 @@ export function dynMatchHelper(E, t) {
|
|
|
654
592
|
break;
|
|
655
593
|
}
|
|
656
594
|
case "union": {
|
|
657
|
-
const def =
|
|
595
|
+
const def = emitter.unionsById.get(t.unionId);
|
|
658
596
|
if (!def)
|
|
659
|
-
throw new
|
|
597
|
+
throw new InternalCompilerError(`emitter bug: dynCheck of unknown union ${t.unionId}`);
|
|
660
598
|
// The undefined arm participates: parsed JSON never contains
|
|
661
599
|
// undefined (a MISSING record key was the arm's only source), but
|
|
662
600
|
// the checked-dynamic tree can hold the undefined value now — overflow entries
|
|
663
601
|
// under `unknown` index signatures — and it matches exactly the
|
|
664
602
|
// undefined arm.
|
|
665
|
-
const arms = def.arms.map((a) => `${
|
|
603
|
+
const arms = def.arms.map((a) => `${emitter.dynMatchHelper(a)}(d)`);
|
|
666
604
|
d.push(` return ${arms.join(" || ")};`);
|
|
667
605
|
break;
|
|
668
606
|
}
|
|
669
607
|
default:
|
|
670
|
-
throw new
|
|
608
|
+
throw new InternalCompilerError(`emitter bug: dynMatch of non-JSON type ${t.kind}`);
|
|
671
609
|
}
|
|
672
610
|
d.push(`}`, ``);
|
|
673
|
-
|
|
611
|
+
emitter.walkerDefs.push(...d);
|
|
674
612
|
return name;
|
|
675
613
|
}
|
|
676
614
|
/** The emitted keyed read on a dyn value:
|
|
@@ -688,16 +626,16 @@ export function dynMatchHelper(E, t) {
|
|
|
688
626
|
* is undefined." (or "…null."), the property form "Cannot destructure
|
|
689
627
|
* property 'PROP' of 'SPELL' …" when firstProp is non-NULL — V8's exact
|
|
690
628
|
* strings, source spelling included. Non-nullish values pass silently. */
|
|
691
|
-
export function dynDestrCheckHelper(
|
|
629
|
+
export function dynDestrCheckHelper(emitter) {
|
|
692
630
|
const memoKey = "%dynDestrCheck";
|
|
693
|
-
const existing =
|
|
631
|
+
const existing = emitter.dynBuilders.get(memoKey);
|
|
694
632
|
if (existing)
|
|
695
633
|
return existing;
|
|
696
634
|
const name = "sc_dyn_destr_check";
|
|
697
|
-
|
|
635
|
+
emitter.dynBuilders.set(memoKey, name);
|
|
698
636
|
const sig = `static void ${name}(const ScrDyn *d, const char *spell, const char *firstProp)`;
|
|
699
|
-
|
|
700
|
-
|
|
637
|
+
emitter.walkerProtos.push(`${sig}; /* destructuring RequireObjectCoercible */`);
|
|
638
|
+
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
639
|
return name;
|
|
702
640
|
}
|
|
703
641
|
/** GetIterator + first-N steps over a dyn value (the dynIterN node), as
|
|
@@ -709,27 +647,27 @@ export function dynDestrCheckHelper(E) {
|
|
|
709
647
|
* "function …" — each with the "(cannot read property
|
|
710
648
|
* Symbol(Symbol.iterator))" tail). Returns a fresh +1 dyn array of
|
|
711
649
|
* exactly n elements, undefined-padded past the end. */
|
|
712
|
-
export function dynIterNHelper(
|
|
650
|
+
export function dynIterNHelper(emitter) {
|
|
713
651
|
const memoKey = "%dynIterN";
|
|
714
|
-
const existing =
|
|
652
|
+
const existing = emitter.dynBuilders.get(memoKey);
|
|
715
653
|
if (existing)
|
|
716
654
|
return existing;
|
|
717
655
|
const name = "sc_dyn_iter_n";
|
|
718
|
-
|
|
656
|
+
emitter.dynBuilders.set(memoKey, name);
|
|
719
657
|
const sig = `static ScrDyn *${name}(const ScrDyn *d, size_t n)`;
|
|
720
|
-
|
|
721
|
-
|
|
658
|
+
emitter.walkerProtos.push(`${sig}; /* destructuring GetIterator + N steps */`);
|
|
659
|
+
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
660
|
return name;
|
|
723
661
|
}
|
|
724
|
-
export function dynKeyGetHelper(
|
|
662
|
+
export function dynKeyGetHelper(emitter) {
|
|
725
663
|
const memoKey = "%dynKeyGet";
|
|
726
|
-
const existing =
|
|
664
|
+
const existing = emitter.dynBuilders.get(memoKey);
|
|
727
665
|
if (existing)
|
|
728
666
|
return existing;
|
|
729
667
|
const name = "sc_dyn_key_get";
|
|
730
|
-
|
|
668
|
+
emitter.dynBuilders.set(memoKey, name);
|
|
731
669
|
const sig = `static ScrDyn *${name}(ScrDyn *d, ScrStr *k, bool opt)`;
|
|
732
|
-
|
|
670
|
+
emitter.walkerProtos.push(`${sig}; /* d[k] on dyn */`);
|
|
733
671
|
const d = [`${sig} { /* d[k] on dyn */`];
|
|
734
672
|
d.push(` if (d->kind == SCR_DYN_UNDEF || d->kind == SCR_DYN_NULL) {`);
|
|
735
673
|
d.push(` if (opt) return scr_dyn_retain(scr_dyn_undefined());`);
|
|
@@ -815,7 +753,7 @@ export function dynKeyGetHelper(E) {
|
|
|
815
753
|
d.push(` }`);
|
|
816
754
|
d.push(` return scr_dyn_retain(scr_dyn_undefined());`);
|
|
817
755
|
d.push(`}`, ``);
|
|
818
|
-
|
|
756
|
+
emitter.walkerDefs.push(...d);
|
|
819
757
|
return name;
|
|
820
758
|
}
|
|
821
759
|
/** The emitted checked builder for one dynCheck target type:
|
|
@@ -826,16 +764,16 @@ export function dynKeyGetHelper(E) {
|
|
|
826
764
|
* Recursive calls propagate a pending exception by releasing the
|
|
827
765
|
* partially-built value and returning — the same pending-check discipline
|
|
828
766
|
* emitted function bodies follow. */
|
|
829
|
-
export function dynCheckHelper(
|
|
767
|
+
export function dynCheckHelper(emitter, t) {
|
|
830
768
|
const key = typeKey(t);
|
|
831
|
-
const existing =
|
|
769
|
+
const existing = emitter.dynBuilders.get(key);
|
|
832
770
|
if (existing)
|
|
833
771
|
return existing;
|
|
834
|
-
const name = `sc_dc_${
|
|
835
|
-
|
|
772
|
+
const name = `sc_dc_${emitter.dynBuilders.size}`;
|
|
773
|
+
emitter.dynBuilders.set(key, name);
|
|
836
774
|
const sig = `static ${cType(t)}${cType(t).endsWith("*") ? "" : " "}${name}(const ScrDyn *d, const ScrDynPath *path)`;
|
|
837
|
-
|
|
838
|
-
const want = cStringLiteral(Buffer.from(
|
|
775
|
+
emitter.walkerProtos.push(`${sig}; /* check ${key} */`);
|
|
776
|
+
const want = cStringLiteral(Buffer.from(dynDesc(t, emitter.recordsById, emitter.unionsById), "utf8"));
|
|
839
777
|
const d = [`${sig} { /* check ${key} */`];
|
|
840
778
|
if (isRefCounted(t) && t.kind !== "dyn") {
|
|
841
779
|
const keyLit = cStringLiteral(Buffer.from(key, "utf8"));
|
|
@@ -849,9 +787,9 @@ export function dynCheckHelper(E, t) {
|
|
|
849
787
|
}
|
|
850
788
|
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
789
|
if (t.kind === "record") {
|
|
852
|
-
const shape =
|
|
790
|
+
const shape = emitter.recordsById.get(t.shapeId);
|
|
853
791
|
if (!shape) {
|
|
854
|
-
throw new
|
|
792
|
+
throw new InternalCompilerError(`emitter bug: cached typed-ref cast of unknown shape ${t.shapeId}`);
|
|
855
793
|
}
|
|
856
794
|
d.push(` if (sc_out && sc_cached) {`);
|
|
857
795
|
for (const field of shape.fields) {
|
|
@@ -893,7 +831,7 @@ export function dynCheckHelper(E, t) {
|
|
|
893
831
|
// `u as Uint8Array`: kind check, then a fresh COPY out (the
|
|
894
832
|
// boundary's aliasing stance in both directions).
|
|
895
833
|
if (t.elem !== "u8")
|
|
896
|
-
throw new
|
|
834
|
+
throw new InternalCompilerError(`emitter bug: dynCheck of bytes<${t.elem}>`);
|
|
897
835
|
d.push(` if (d->kind != SCR_DYN_BYTES) { scr_dyn_check_fail(path, ${want}, d); return NULL; }`);
|
|
898
836
|
d.push(` return scr_dyn_bytes_copy_out(d);`);
|
|
899
837
|
break;
|
|
@@ -906,15 +844,15 @@ export function dynCheckHelper(E, t) {
|
|
|
906
844
|
// compare reference-equal (the tracing suite's shape); alien
|
|
907
845
|
// %error objects rebuild once and cache the pair.
|
|
908
846
|
if (t.className !== "%Error") {
|
|
909
|
-
throw new
|
|
847
|
+
throw new InternalCompilerError(`emitter bug: dynCheck of class ${t.className} (only %Error extracts from the checked-dynamic tree)`);
|
|
910
848
|
}
|
|
911
849
|
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
850
|
d.push(` return scr_error_from_dyn(d);`);
|
|
913
851
|
break;
|
|
914
852
|
case "record": {
|
|
915
|
-
const shape =
|
|
853
|
+
const shape = emitter.recordsById.get(t.shapeId);
|
|
916
854
|
if (!shape)
|
|
917
|
-
throw new
|
|
855
|
+
throw new InternalCompilerError(`emitter bug: dynCheck of unknown shape ${t.shapeId}`);
|
|
918
856
|
const rel = (v) => releaseCallC(t, v);
|
|
919
857
|
// Tuple targets: a JSON ARRAY of exactly the arity, validated and
|
|
920
858
|
// extracted positionally with index paths ("$.pairs[3][1]").
|
|
@@ -927,7 +865,7 @@ export function dynCheckHelper(E, t) {
|
|
|
927
865
|
byIndex.forEach((f, i) => {
|
|
928
866
|
d.push(` {`);
|
|
929
867
|
d.push(` ScrDynPath p = { path, NULL, ${i} };`);
|
|
930
|
-
d.push(` r->${mangleField(f.name)} = ${
|
|
868
|
+
d.push(` r->${mangleField(f.name)} = ${emitter.dynCheckHelper(f.type)}(d->v.arr.items[${i}], &p);`);
|
|
931
869
|
d.push(` if (scr_exc_pending()) { ${rel("r")}; return NULL; }`);
|
|
932
870
|
d.push(` }`);
|
|
933
871
|
});
|
|
@@ -939,14 +877,14 @@ export function dynCheckHelper(E, t) {
|
|
|
939
877
|
for (const f of shape.fields) {
|
|
940
878
|
const keyLit = cStringLiteral(Buffer.from(f.name, "utf8"));
|
|
941
879
|
const keyLen = Buffer.byteLength(f.name, "utf8");
|
|
942
|
-
const fieldWant = cStringLiteral(Buffer.from(
|
|
880
|
+
const fieldWant = cStringLiteral(Buffer.from(dynDesc(f.type, emitter.recordsById, emitter.unionsById), "utf8"));
|
|
943
881
|
// Width tolerance: only declared fields are looked up — extra JSON
|
|
944
882
|
// keys are simply never examined (check-and-extract, not shape
|
|
945
883
|
// equality). A missing field fails as "got undefined" — except
|
|
946
884
|
// optional-flavored fields (undefined-armed unions), where the
|
|
947
885
|
// missing key IS the undefined arm: the interned immortal
|
|
948
886
|
// instance, no retain owed (rc == SIZE_MAX).
|
|
949
|
-
const utag = f.type.kind === "union" ?
|
|
887
|
+
const utag = f.type.kind === "union" ? undefinedArmTag(f.type, emitter.unionsById) : -1;
|
|
950
888
|
d.push(` {`);
|
|
951
889
|
d.push(` ScrDynPath p = { path, ${keyLit}, 0 };`);
|
|
952
890
|
d.push(` const ScrDyn *m = scr_dyn_obj_get(d, ${keyLit}, ${keyLen});`);
|
|
@@ -955,20 +893,20 @@ export function dynCheckHelper(E, t) {
|
|
|
955
893
|
// one IS the undefined dyn value (JS's missing-property read).
|
|
956
894
|
// Go through the dyn builder so a Web-stream typed-ref capsule
|
|
957
895
|
// cannot escape inside a checked record field.
|
|
958
|
-
d.push(` r->${mangleField(f.name)} = ${
|
|
896
|
+
d.push(` r->${mangleField(f.name)} = ${emitter.dynCheckHelper(f.type)}(m ? m : scr_dyn_undefined(), &p);`);
|
|
959
897
|
}
|
|
960
898
|
else if (utag >= 0 && f.type.kind === "union") {
|
|
961
|
-
const unit =
|
|
899
|
+
const unit = emitter.unitInstanceRef(f.type.unionId, utag);
|
|
962
900
|
d.push(` if (!m) {`);
|
|
963
901
|
d.push(` r->${mangleField(f.name)} = ${unit}; /* absent key -> the undefined arm */`);
|
|
964
902
|
d.push(` } else {`);
|
|
965
|
-
d.push(` r->${mangleField(f.name)} = ${
|
|
903
|
+
d.push(` r->${mangleField(f.name)} = ${emitter.dynCheckHelper(f.type)}(m, &p);`);
|
|
966
904
|
d.push(` if (scr_exc_pending()) { ${rel("r")}; return NULL; }`);
|
|
967
905
|
d.push(` }`);
|
|
968
906
|
}
|
|
969
907
|
else {
|
|
970
908
|
d.push(` if (!m) { scr_dyn_check_fail(&p, ${fieldWant}, NULL); ${rel("r")}; return NULL; }`);
|
|
971
|
-
d.push(` r->${mangleField(f.name)} = ${
|
|
909
|
+
d.push(` r->${mangleField(f.name)} = ${emitter.dynCheckHelper(f.type)}(m, &p);`);
|
|
972
910
|
d.push(` if (scr_exc_pending()) { ${rel("r")}; return NULL; }`);
|
|
973
911
|
}
|
|
974
912
|
d.push(` }`);
|
|
@@ -995,7 +933,7 @@ export function dynCheckHelper(E, t) {
|
|
|
995
933
|
}
|
|
996
934
|
else {
|
|
997
935
|
d.push(` ScrDynPath p = { path, e->key, 0 };`);
|
|
998
|
-
d.push(` ${cDecl(iv, "ev")} = ${
|
|
936
|
+
d.push(` ${cDecl(iv, "ev")} = ${emitter.dynCheckHelper(iv)}(e->value, &p);`);
|
|
999
937
|
d.push(` if (scr_exc_pending()) { ${rel("r")}; return NULL; }`);
|
|
1000
938
|
}
|
|
1001
939
|
d.push(` ScrStr *ek = scr_str_new(e->key, e->key_len);`);
|
|
@@ -1013,9 +951,9 @@ export function dynCheckHelper(E, t) {
|
|
|
1013
951
|
}
|
|
1014
952
|
case "array": {
|
|
1015
953
|
const elem = t.elem;
|
|
1016
|
-
const c =
|
|
954
|
+
const c = emitter.dynCheckHelper(elem);
|
|
1017
955
|
d.push(` if (d->kind != SCR_DYN_ARR) { scr_dyn_check_fail(path, ${want}, d); return NULL; }`);
|
|
1018
|
-
d.push(` ScrArr *a = ${
|
|
956
|
+
d.push(` ScrArr *a = ${emitter.arrNewC(elem, "d->v.arr.len")};`);
|
|
1019
957
|
d.push(` for (size_t i = 0; i < d->v.arr.len; i++) {`);
|
|
1020
958
|
d.push(` ScrDynPath p = { path, NULL, i };`);
|
|
1021
959
|
d.push(` ${cDecl(elem, "e")} = ${c}(d->v.arr.items[i], &p);`);
|
|
@@ -1026,14 +964,14 @@ export function dynCheckHelper(E, t) {
|
|
|
1026
964
|
break;
|
|
1027
965
|
}
|
|
1028
966
|
case "union": {
|
|
1029
|
-
const def =
|
|
967
|
+
const def = emitter.unionsById.get(t.unionId);
|
|
1030
968
|
if (!def)
|
|
1031
|
-
throw new
|
|
969
|
+
throw new InternalCompilerError(`emitter bug: dynCheck of unknown union ${t.unionId}`);
|
|
1032
970
|
// Arms in CANONICAL order, first FULL match wins (discriminated
|
|
1033
971
|
// unions disambiguate naturally: the arm whose declared fields all
|
|
1034
972
|
// fit). The matched arm's builder can no longer fail.
|
|
1035
973
|
def.arms.forEach((arm, i) => {
|
|
1036
|
-
const m =
|
|
974
|
+
const m = emitter.dynMatchHelper(arm);
|
|
1037
975
|
if (arm.kind === "undefinedT") {
|
|
1038
976
|
// Parsed JSON never matches here (no undefined in JSON text —
|
|
1039
977
|
// a MISSING record key builds this arm in the record builder
|
|
@@ -1041,7 +979,7 @@ export function dynCheckHelper(E, t) {
|
|
|
1041
979
|
// `unknown` index-signature overflows and builds the interned
|
|
1042
980
|
// unit instance exactly like null.
|
|
1043
981
|
d.push(` if (${m}(d)) {`);
|
|
1044
|
-
d.push(` return ${
|
|
982
|
+
d.push(` return ${emitter.unitInstanceRef(t.unionId, i)};`);
|
|
1045
983
|
d.push(` }`);
|
|
1046
984
|
return;
|
|
1047
985
|
}
|
|
@@ -1050,11 +988,11 @@ export function dynCheckHelper(E, t) {
|
|
|
1050
988
|
// immortal instance (rc == SIZE_MAX — RC entry points and the
|
|
1051
989
|
// collector both skip it, so no retain is owed).
|
|
1052
990
|
d.push(` if (${m}(d)) {`);
|
|
1053
|
-
d.push(` return ${
|
|
991
|
+
d.push(` return ${emitter.unitInstanceRef(t.unionId, i)};`);
|
|
1054
992
|
d.push(` }`);
|
|
1055
993
|
return;
|
|
1056
994
|
}
|
|
1057
|
-
const c =
|
|
995
|
+
const c = emitter.dynCheckHelper(arm);
|
|
1058
996
|
d.push(` if (${m}(d)) {`);
|
|
1059
997
|
if (arm.kind === "f64") {
|
|
1060
998
|
d.push(` return scr_union_new_f64(${i}, ${c}(d, path));`);
|
|
@@ -1064,7 +1002,7 @@ export function dynCheckHelper(E, t) {
|
|
|
1064
1002
|
}
|
|
1065
1003
|
else {
|
|
1066
1004
|
const rc = vAdapters(arm);
|
|
1067
|
-
d.push(` return scr_union_new_ref(${i}, ${c}(d, path), &${rc.retain}, &${rc.release}, ${
|
|
1005
|
+
d.push(` return scr_union_new_ref(${i}, ${c}(d, path), &${rc.retain}, &${rc.release}, ${emitter.traceArgC(arm)});`);
|
|
1068
1006
|
}
|
|
1069
1007
|
d.push(` }`);
|
|
1070
1008
|
});
|
|
@@ -1113,7 +1051,7 @@ export function dynCheckHelper(E, t) {
|
|
|
1113
1051
|
// wrapper, retained); anything else wraps in the per-target
|
|
1114
1052
|
// adapter closure, whose caps[0] obj-box owns the dyn value
|
|
1115
1053
|
// (untraced — cycles through dyn never collect, SEMANTICS.md).
|
|
1116
|
-
const adapter = dynFuncAdapterHelper(
|
|
1054
|
+
const adapter = dynFuncAdapterHelper(emitter, t);
|
|
1117
1055
|
const sigLit = cStringLiteral(Buffer.from(key, "utf8"));
|
|
1118
1056
|
d.push(` if (d->kind != SCR_DYN_FUNC) { scr_dyn_check_fail(path, ${want}, d); return NULL; }`);
|
|
1119
1057
|
d.push(` if (strcmp(d->v.fn.sig, ${sigLit}) == 0) return scr_closure_retain(d->v.fn.clo);`);
|
|
@@ -1134,11 +1072,11 @@ export function dynCheckHelper(E, t) {
|
|
|
1134
1072
|
d.push(` return (${cType(t).trim()})scr_dyn_handle_unbox(d, ${h.tag}, path, ${want});`);
|
|
1135
1073
|
break;
|
|
1136
1074
|
}
|
|
1137
|
-
throw new
|
|
1075
|
+
throw new InternalCompilerError(`emitter bug: dynCheck of non-JSON type ${t.kind}`);
|
|
1138
1076
|
}
|
|
1139
1077
|
}
|
|
1140
1078
|
d.push(`}`, ``);
|
|
1141
|
-
|
|
1079
|
+
emitter.walkerDefs.push(...d);
|
|
1142
1080
|
return name;
|
|
1143
1081
|
}
|
|
1144
1082
|
/** The emitted static→dyn converter for one type:
|
|
@@ -1148,15 +1086,15 @@ export function dynCheckHelper(E, t) {
|
|
|
1148
1086
|
* plus undefined-armed unions (the undefined arm becomes the undefined
|
|
1149
1087
|
* dyn singleton) and index-signature records (whose overflow entries
|
|
1150
1088
|
* copy over). The operand is borrowed. Never throws. */
|
|
1151
|
-
export function toDynHelper(
|
|
1089
|
+
export function toDynHelper(emitter, t) {
|
|
1152
1090
|
const key = typeKey(t);
|
|
1153
|
-
const existing =
|
|
1091
|
+
const existing = emitter.toDynFns.get(key);
|
|
1154
1092
|
if (existing)
|
|
1155
1093
|
return existing;
|
|
1156
|
-
const name = `sc_td_${
|
|
1157
|
-
|
|
1094
|
+
const name = `sc_td_${emitter.toDynFns.size}`;
|
|
1095
|
+
emitter.toDynFns.set(key, name);
|
|
1158
1096
|
const sig = `static ScrDyn *${name}(${cDecl(t, "v")})`;
|
|
1159
|
-
|
|
1097
|
+
emitter.walkerProtos.push(`${sig}; /* to-dyn ${key} */`);
|
|
1160
1098
|
const d = [`${sig} { /* to-dyn ${key} */`];
|
|
1161
1099
|
let sourceAccessor = null;
|
|
1162
1100
|
switch (t.kind) {
|
|
@@ -1180,7 +1118,7 @@ export function toDynHelper(E, t) {
|
|
|
1180
1118
|
case "object":
|
|
1181
1119
|
// %Error only (canConvertToDyn's gate): the checked-dynamic tree's error encoding.
|
|
1182
1120
|
if (t.className !== "%Error") {
|
|
1183
|
-
throw new
|
|
1121
|
+
throw new InternalCompilerError(`emitter bug: to-dyn of class ${t.className}`);
|
|
1184
1122
|
}
|
|
1185
1123
|
d.push(` return scr_dyn_from_error(v);`);
|
|
1186
1124
|
break;
|
|
@@ -1194,23 +1132,23 @@ export function toDynHelper(E, t) {
|
|
|
1194
1132
|
// Function-valued record/array fields (EventListenerObject's
|
|
1195
1133
|
// handleEvent method) box through the same identity-preserving
|
|
1196
1134
|
// closure bridge as a bare dynFrom function.
|
|
1197
|
-
d.push(` return ${dynFuncBoxHelper(
|
|
1135
|
+
d.push(` return ${dynFuncBoxHelper(emitter, t)}(v, NULL);`);
|
|
1198
1136
|
break;
|
|
1199
1137
|
case "bytes":
|
|
1200
1138
|
// bytes<u8> → the checked-dynamic tree's bytes kind, payload COPIED (the boundary
|
|
1201
1139
|
// stance; stdin chunks into unknown-typed helpers).
|
|
1202
1140
|
if (t.elem !== "u8")
|
|
1203
|
-
throw new
|
|
1141
|
+
throw new InternalCompilerError(`emitter bug: to-dyn of bytes<${t.elem}>`);
|
|
1204
1142
|
d.push(` return scr_dyn_new_bytes_copy(v);`);
|
|
1205
1143
|
break;
|
|
1206
1144
|
case "record": {
|
|
1207
|
-
const shape =
|
|
1145
|
+
const shape = emitter.recordsById.get(t.shapeId);
|
|
1208
1146
|
if (!shape)
|
|
1209
|
-
throw new
|
|
1147
|
+
throw new InternalCompilerError(`emitter bug: to-dyn of unknown shape ${t.shapeId}`);
|
|
1210
1148
|
// CYCLE-CAPABLE shapes guard the deep copy: a cyclic value has no
|
|
1211
1149
|
// finite dyn copy, so enter TRAPS on re-entry (SEMANTICS.md — Node
|
|
1212
1150
|
// shares the reference instead of copying).
|
|
1213
|
-
const cyclicRec =
|
|
1151
|
+
const cyclicRec = emitter.traceAdapterC(t) !== null;
|
|
1214
1152
|
if (cyclicRec)
|
|
1215
1153
|
d.push(` scr_dyn_from_enter(v);`);
|
|
1216
1154
|
if (shape.tuple) {
|
|
@@ -1218,7 +1156,7 @@ export function toDynHelper(E, t) {
|
|
|
1218
1156
|
const byIndex = [...shape.fields].sort((a, b) => Number(a.name) - Number(b.name));
|
|
1219
1157
|
d.push(` ScrDyn *d = scr_dyn_new_arr();`);
|
|
1220
1158
|
for (const f of byIndex) {
|
|
1221
|
-
d.push(` scr_dyn_arr_push(d, ${
|
|
1159
|
+
d.push(` scr_dyn_arr_push(d, ${emitter.toDynHelper(f.type)}(v->${mangleField(f.name)}));`);
|
|
1222
1160
|
}
|
|
1223
1161
|
if (cyclicRec)
|
|
1224
1162
|
d.push(` scr_dyn_from_leave();`);
|
|
@@ -1232,7 +1170,7 @@ export function toDynHelper(E, t) {
|
|
|
1232
1170
|
name: `${name}_source_access`,
|
|
1233
1171
|
release: rc.release,
|
|
1234
1172
|
};
|
|
1235
|
-
|
|
1173
|
+
emitter.walkerProtos.push(`static ScrDyn *${sourceAccessor.name}(void *v, bool materialize); /* live listener source ${key} */`);
|
|
1236
1174
|
d.push(` ScrDyn *d = scr_dyn_new_obj_with_identity(v, &${rc.retain}, &${sourceAccessor.name});`);
|
|
1237
1175
|
}
|
|
1238
1176
|
else {
|
|
@@ -1255,7 +1193,7 @@ export function toDynHelper(E, t) {
|
|
|
1255
1193
|
for (const f of dynFields) {
|
|
1256
1194
|
const keyLit = cStringLiteral(Buffer.from(f.name, "utf8"));
|
|
1257
1195
|
const keyLen = Buffer.byteLength(f.name, "utf8");
|
|
1258
|
-
d.push(` scr_dyn_obj_set(d, ${keyLit}, ${keyLen}, ${
|
|
1196
|
+
d.push(` scr_dyn_obj_set(d, ${keyLit}, ${keyLen}, ${emitter.toDynHelper(f.type)}(v->${mangleField(f.name)}));`);
|
|
1259
1197
|
}
|
|
1260
1198
|
}
|
|
1261
1199
|
if (shape.indexValue) {
|
|
@@ -1278,7 +1216,7 @@ export function toDynHelper(E, t) {
|
|
|
1278
1216
|
}
|
|
1279
1217
|
else {
|
|
1280
1218
|
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, ${
|
|
1219
|
+
d.push(` scr_dyn_obj_set(d, k->data, k->len, ${emitter.toDynHelper(iv)}(e));`);
|
|
1282
1220
|
d.push(` ${releaseCallC(iv, "e")};`);
|
|
1283
1221
|
}
|
|
1284
1222
|
d.push(` scr_str_release(k);`);
|
|
@@ -1294,7 +1232,7 @@ export function toDynHelper(E, t) {
|
|
|
1294
1232
|
case "array": {
|
|
1295
1233
|
const elem = t.elem;
|
|
1296
1234
|
// Cycle-capable arrays guard the deep copy like records above.
|
|
1297
|
-
const cyclicArr =
|
|
1235
|
+
const cyclicArr = emitter.traceAdapterC(t) !== null;
|
|
1298
1236
|
if (cyclicArr)
|
|
1299
1237
|
d.push(` scr_dyn_from_enter(v);`);
|
|
1300
1238
|
d.push(` ScrDyn *d = scr_dyn_new_arr();`);
|
|
@@ -1307,7 +1245,7 @@ export function toDynHelper(E, t) {
|
|
|
1307
1245
|
}
|
|
1308
1246
|
else {
|
|
1309
1247
|
d.push(` ${cDecl(elem, "e")} = (${cType(elem).trim()})scr_arr_get_ref(v, (double)i);`);
|
|
1310
|
-
d.push(` scr_dyn_arr_push(d, ${
|
|
1248
|
+
d.push(` scr_dyn_arr_push(d, ${emitter.toDynHelper(elem)}(e));`);
|
|
1311
1249
|
d.push(` ${releaseCallC(elem, "e")};`);
|
|
1312
1250
|
}
|
|
1313
1251
|
d.push(` }`);
|
|
@@ -1317,9 +1255,9 @@ export function toDynHelper(E, t) {
|
|
|
1317
1255
|
break;
|
|
1318
1256
|
}
|
|
1319
1257
|
case "union": {
|
|
1320
|
-
const def =
|
|
1258
|
+
const def = emitter.unionsById.get(t.unionId);
|
|
1321
1259
|
if (!def)
|
|
1322
|
-
throw new
|
|
1260
|
+
throw new InternalCompilerError(`emitter bug: to-dyn of unknown union ${t.unionId}`);
|
|
1323
1261
|
d.push(` switch (v->tag) {`);
|
|
1324
1262
|
def.arms.forEach((arm, i) => {
|
|
1325
1263
|
if (arm.kind === "undefinedT") {
|
|
@@ -1337,10 +1275,10 @@ export function toDynHelper(E, t) {
|
|
|
1337
1275
|
else if (arm.kind === "func") {
|
|
1338
1276
|
// A boxable function arm crosses through the checked-dynamic
|
|
1339
1277
|
// function boundary (the dynFrom func special case, sans name).
|
|
1340
|
-
d.push(` case ${i}: return ${dynFuncBoxHelper(
|
|
1278
|
+
d.push(` case ${i}: return ${dynFuncBoxHelper(emitter, arm)}((ScrClosure *)scr_union_peek(v), NULL);`);
|
|
1341
1279
|
}
|
|
1342
1280
|
else {
|
|
1343
|
-
d.push(` case ${i}: return ${
|
|
1281
|
+
d.push(` case ${i}: return ${emitter.toDynHelper(arm)}((${cType(arm).trim()})scr_union_peek(v));`);
|
|
1344
1282
|
}
|
|
1345
1283
|
});
|
|
1346
1284
|
d.push(` default: scr_trap("scriptc: internal error: invalid union tag\\n");`);
|
|
@@ -1357,7 +1295,7 @@ export function toDynHelper(E, t) {
|
|
|
1357
1295
|
d.push(` return scr_dyn_new_promise(v);`);
|
|
1358
1296
|
break;
|
|
1359
1297
|
}
|
|
1360
|
-
d.push(` return scr_dyn_new_promise_adapting(v, &${promiseDynAdapterHelper(
|
|
1298
|
+
d.push(` return scr_dyn_new_promise_adapting(v, &${promiseDynAdapterHelper(emitter, t.inner)});`);
|
|
1361
1299
|
break;
|
|
1362
1300
|
}
|
|
1363
1301
|
default: {
|
|
@@ -1369,13 +1307,13 @@ export function toDynHelper(E, t) {
|
|
|
1369
1307
|
d.push(` return scr_dyn_new_handle(v, ${h.tag});`);
|
|
1370
1308
|
break;
|
|
1371
1309
|
}
|
|
1372
|
-
throw new
|
|
1310
|
+
throw new InternalCompilerError(`emitter bug: to-dyn of unsupported type ${t.kind}`);
|
|
1373
1311
|
}
|
|
1374
1312
|
}
|
|
1375
1313
|
d.push(`}`, ``);
|
|
1376
|
-
|
|
1314
|
+
emitter.walkerDefs.push(...d);
|
|
1377
1315
|
if (sourceAccessor) {
|
|
1378
|
-
|
|
1316
|
+
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
1317
|
}
|
|
1380
1318
|
return name;
|
|
1381
1319
|
}
|
|
@@ -1385,15 +1323,15 @@ export function toDynHelper(E, t) {
|
|
|
1385
1323
|
* value, and fulfill dst with it (scr_dyn_new_promise_adapting's
|
|
1386
1324
|
* callback; rejections never reach an adapter — the runtime copies them
|
|
1387
1325
|
* raw). Interned per inner typeKey. */
|
|
1388
|
-
|
|
1326
|
+
function promiseDynAdapterHelper(emitter, inner) {
|
|
1389
1327
|
const key = typeKey(inner);
|
|
1390
|
-
const existing =
|
|
1328
|
+
const existing = emitter.promiseDynAdapters.get(key);
|
|
1391
1329
|
if (existing)
|
|
1392
1330
|
return existing;
|
|
1393
|
-
const name = `sc_pda_${
|
|
1394
|
-
|
|
1331
|
+
const name = `sc_pda_${emitter.promiseDynAdapters.size}`;
|
|
1332
|
+
emitter.promiseDynAdapters.set(key, name);
|
|
1395
1333
|
const sig = `static void ${name}(ScrPromise *dst, ScrPromise *src)`;
|
|
1396
|
-
|
|
1334
|
+
emitter.walkerProtos.push(`${sig}; /* dyn-box settle adapter for promise<${key}> */`);
|
|
1397
1335
|
const d = [`${sig} { /* dyn-box settle adapter for promise<${key}> */`];
|
|
1398
1336
|
const fulfill = (expr) => ` scr_promise_fulfill_ref(dst, ${expr}, scr_dyn_retain_v, scr_dyn_release_v, NULL);`;
|
|
1399
1337
|
switch (inner.kind) {
|
|
@@ -1423,7 +1361,7 @@ export function promiseDynAdapterHelper(E, inner) {
|
|
|
1423
1361
|
// nested promises, handles): extract (+1 via the stored retain),
|
|
1424
1362
|
// convert through the shared to-dyn spelling, release the extract.
|
|
1425
1363
|
d.push(` ${cDecl(inner, "pv")} = (${cType(inner).trim()})scr_promise_payload_ref(src);`);
|
|
1426
|
-
d.push(` ScrDyn *dv = ${toDynExprC(
|
|
1364
|
+
d.push(` ScrDyn *dv = ${toDynExprC(emitter, inner, "pv")};`);
|
|
1427
1365
|
if (isRefCounted(inner))
|
|
1428
1366
|
d.push(` ${releaseCallC(inner, "pv")};`);
|
|
1429
1367
|
d.push(fulfill(`dv`));
|
|
@@ -1431,10 +1369,10 @@ export function promiseDynAdapterHelper(E, inner) {
|
|
|
1431
1369
|
}
|
|
1432
1370
|
}
|
|
1433
1371
|
d.push(`}`, ``);
|
|
1434
|
-
|
|
1372
|
+
emitter.walkerDefs.push(...d);
|
|
1435
1373
|
return name;
|
|
1436
1374
|
}
|
|
1437
|
-
/* ── the checked-dynamic function boundary (
|
|
1375
|
+
/* ── the checked-dynamic function boundary (ir.ts) ─────────────────
|
|
1438
1376
|
* Three interned per-signature helpers:
|
|
1439
1377
|
*
|
|
1440
1378
|
* sc_dfk_<n> — the CALL THUNK a dyn-boxed closure carries: validate
|
|
@@ -1459,27 +1397,27 @@ export function promiseDynAdapterHelper(E, inner) {
|
|
|
1459
1397
|
* result uniformly), funcs box (anonymous — the static name is gone by
|
|
1460
1398
|
* the time a value flows through an adapter; SEMANTICS.md), everything
|
|
1461
1399
|
* else rides the toDyn converter. `expr` is BORROWED in every arm. */
|
|
1462
|
-
function toDynExprC(
|
|
1400
|
+
function toDynExprC(emitter, t, expr) {
|
|
1463
1401
|
if (t.kind === "dyn")
|
|
1464
1402
|
return `scr_dyn_retain(${expr})`;
|
|
1465
1403
|
if (t.kind === "func")
|
|
1466
|
-
return `${
|
|
1404
|
+
return `${emitter.dynFuncBoxHelper(t)}(${expr}, NULL)`;
|
|
1467
1405
|
// An island value wraps by reference (scalar-normalizing) — the
|
|
1468
1406
|
// jsval-returning callback shape of the routed-dispatch lane.
|
|
1469
1407
|
if (t.kind === "jsval")
|
|
1470
1408
|
return `scr_dyn_from_jsval(${expr})`;
|
|
1471
|
-
return `${
|
|
1409
|
+
return `${emitter.toDynHelper(t)}(${expr})`;
|
|
1472
1410
|
}
|
|
1473
1411
|
/** The call thunk for one closure signature (see the block comment). */
|
|
1474
|
-
|
|
1412
|
+
function dynFuncThunkHelper(emitter, t) {
|
|
1475
1413
|
const key = typeKey(t);
|
|
1476
|
-
const existing =
|
|
1414
|
+
const existing = emitter.dynFuncThunks.get(key);
|
|
1477
1415
|
if (existing)
|
|
1478
1416
|
return existing;
|
|
1479
|
-
const name = `sc_dfk_${
|
|
1480
|
-
|
|
1417
|
+
const name = `sc_dfk_${emitter.dynFuncThunks.size}`;
|
|
1418
|
+
emitter.dynFuncThunks.set(key, name);
|
|
1481
1419
|
const sig = `static ScrDyn *${name}(ScrClosure *c, ScrDyn *const *args, size_t argc)`;
|
|
1482
|
-
|
|
1420
|
+
emitter.walkerProtos.push(`${sig}; /* dyn call thunk for ${key} */`);
|
|
1483
1421
|
const d = [`${sig} { /* dyn call thunk for ${key} */`];
|
|
1484
1422
|
if (t.params.length === 0)
|
|
1485
1423
|
d.push(` (void)args;`);
|
|
@@ -1507,7 +1445,7 @@ export function dynFuncThunkHelper(E, t) {
|
|
|
1507
1445
|
}
|
|
1508
1446
|
else {
|
|
1509
1447
|
d.push(` ScrDynPath pp = { NULL, NULL, ${i} };`);
|
|
1510
|
-
d.push(` a${i} = ${
|
|
1448
|
+
d.push(` a${i} = ${emitter.dynCheckHelper(p)}(ad, &pp);`);
|
|
1511
1449
|
const undo = t.params
|
|
1512
1450
|
.slice(0, i)
|
|
1513
1451
|
.flatMap((q, j) => (isRefCounted(q) ? [`${releaseCallC(q, `a${j}`)};`] : []));
|
|
@@ -1542,44 +1480,44 @@ export function dynFuncThunkHelper(E, t) {
|
|
|
1542
1480
|
else {
|
|
1543
1481
|
d.push(` ${cDecl(t.ret, "r")} = ${call};`);
|
|
1544
1482
|
d.push(` if (scr_exc_pending()) return NULL;`);
|
|
1545
|
-
d.push(` ScrDyn *out = ${toDynExprC(
|
|
1483
|
+
d.push(` ScrDyn *out = ${toDynExprC(emitter, t.ret, "r")};`);
|
|
1546
1484
|
if (isRefCounted(t.ret))
|
|
1547
1485
|
d.push(` ${releaseCallC(t.ret, "r")};`);
|
|
1548
1486
|
d.push(` return out;`);
|
|
1549
1487
|
}
|
|
1550
1488
|
d.push(`}`, ``);
|
|
1551
|
-
|
|
1489
|
+
emitter.walkerDefs.push(...d);
|
|
1552
1490
|
return name;
|
|
1553
1491
|
}
|
|
1554
1492
|
/** The box builder dynFrom emits for one closure signature. */
|
|
1555
|
-
export function dynFuncBoxHelper(
|
|
1493
|
+
export function dynFuncBoxHelper(emitter, t) {
|
|
1556
1494
|
const key = typeKey(t);
|
|
1557
|
-
const existing =
|
|
1495
|
+
const existing = emitter.dynFuncBoxes.get(key);
|
|
1558
1496
|
if (existing)
|
|
1559
1497
|
return existing;
|
|
1560
|
-
const name = `sc_dfb_${
|
|
1561
|
-
|
|
1498
|
+
const name = `sc_dfb_${emitter.dynFuncBoxes.size}`;
|
|
1499
|
+
emitter.dynFuncBoxes.set(key, name);
|
|
1562
1500
|
const sig = `static ScrDyn *${name}(ScrClosure *v, const char *fname)`;
|
|
1563
|
-
|
|
1564
|
-
const thunk = dynFuncThunkHelper(
|
|
1501
|
+
emitter.walkerProtos.push(`${sig}; /* box ${key} into dyn */`);
|
|
1502
|
+
const thunk = dynFuncThunkHelper(emitter, t);
|
|
1565
1503
|
const sigLit = cStringLiteral(Buffer.from(key, "utf8"));
|
|
1566
|
-
|
|
1504
|
+
emitter.walkerDefs.push(`${sig} { /* box ${key} into dyn */`, ` return scr_dyn_new_func(scr_closure_retain(v), &${thunk}, ${t.params.length}, ${sigLit}, fname);`, `}`, ``);
|
|
1567
1505
|
return name;
|
|
1568
1506
|
}
|
|
1569
1507
|
/** The adapter closure body for one TARGET signature: the emitted C
|
|
1570
1508
|
* function a func-targeted dynCheck wraps a non-identical boxed
|
|
1571
1509
|
* signature in. caps[0] is an untraced obj-box owning the dyn function
|
|
1572
1510
|
* value. */
|
|
1573
|
-
|
|
1511
|
+
function dynFuncAdapterHelper(emitter, t) {
|
|
1574
1512
|
const key = typeKey(t);
|
|
1575
|
-
const existing =
|
|
1513
|
+
const existing = emitter.dynFuncAdapters.get(key);
|
|
1576
1514
|
if (existing)
|
|
1577
1515
|
return existing;
|
|
1578
|
-
const name = `sc_dfa_${
|
|
1579
|
-
|
|
1516
|
+
const name = `sc_dfa_${emitter.dynFuncAdapters.size}`;
|
|
1517
|
+
emitter.dynFuncAdapters.set(key, name);
|
|
1580
1518
|
const params = ["ScrClosure *sc_env", ...t.params.map((p, i) => cDecl(p, `a${i}`))].join(", ");
|
|
1581
1519
|
const sig = `static ${cType(t.ret)}${cType(t.ret).endsWith("*") ? "" : " "}${name}(${params})`;
|
|
1582
|
-
|
|
1520
|
+
emitter.walkerProtos.push(`${sig}; /* dyn fn adapter to ${key} */`);
|
|
1583
1521
|
const dummy = t.ret.kind === "void" ? "" : t.ret.kind === "f64" ? "0" : t.ret.kind === "bool" ? "false" : "NULL";
|
|
1584
1522
|
const d = [`${sig} { /* dyn fn adapter to ${key} */`];
|
|
1585
1523
|
d.push(` ScrDyn *sc_fn = (ScrDyn *)scr_box_get_ref(sc_env->caps[0]); /* +1 */`);
|
|
@@ -1588,7 +1526,7 @@ export function dynFuncAdapterHelper(E, t) {
|
|
|
1588
1526
|
if (t.params.length > 0) {
|
|
1589
1527
|
d.push(` ScrDyn *sc_args[${t.params.length}];`);
|
|
1590
1528
|
t.params.forEach((p, i) => {
|
|
1591
|
-
d.push(` sc_args[${i}] = ${toDynExprC(
|
|
1529
|
+
d.push(` sc_args[${i}] = ${toDynExprC(emitter, p, `a${i}`)};`);
|
|
1592
1530
|
if (isRefCounted(p))
|
|
1593
1531
|
d.push(` ${releaseCallC(p, `a${i}`)};`);
|
|
1594
1532
|
});
|
|
@@ -1610,12 +1548,12 @@ export function dynFuncAdapterHelper(E, t) {
|
|
|
1610
1548
|
// Validate the dyn result into the target's return type — a lying
|
|
1611
1549
|
// wrapper throws the catchable TypeError here (path "$"), exactly
|
|
1612
1550
|
// the dynCheck stance; the dummy result rides the pending unwind.
|
|
1613
|
-
d.push(` ${cDecl(t.ret, "out")} = ${
|
|
1551
|
+
d.push(` ${cDecl(t.ret, "out")} = ${emitter.dynCheckHelper(t.ret)}(sc_r, NULL);`);
|
|
1614
1552
|
d.push(` scr_dyn_release(sc_r);`);
|
|
1615
1553
|
d.push(` return out;`);
|
|
1616
1554
|
}
|
|
1617
1555
|
d.push(`}`, ``);
|
|
1618
|
-
|
|
1556
|
+
emitter.walkerDefs.push(...d);
|
|
1619
1557
|
return name;
|
|
1620
1558
|
}
|
|
1621
1559
|
/** The emitted dynamic-keyed READ helper for one (shape, result type):
|
|
@@ -1627,19 +1565,19 @@ export function dynFuncAdapterHelper(E, t) {
|
|
|
1627
1565
|
* arm (T undefined-armed union), or TRAPS with the key text (the array
|
|
1628
1566
|
* OOB policy — the checker claimed T and no undefined is representable).
|
|
1629
1567
|
* Borrows both; refcounted results are owned (+1). */
|
|
1630
|
-
export function recordKeyGetHelper(
|
|
1568
|
+
export function recordKeyGetHelper(emitter, shapeId, t, overflowOnly = false) {
|
|
1631
1569
|
const key = `${shapeId}|${typeKey(t)}${overflowOnly ? "|ovf" : ""}`;
|
|
1632
|
-
const existing =
|
|
1570
|
+
const existing = emitter.recordKeyGetFns.get(key);
|
|
1633
1571
|
if (existing)
|
|
1634
1572
|
return existing;
|
|
1635
|
-
const shape =
|
|
1573
|
+
const shape = emitter.recordsById.get(shapeId);
|
|
1636
1574
|
if (!shape)
|
|
1637
|
-
throw new
|
|
1638
|
-
const name = `sc_rkg_${
|
|
1639
|
-
|
|
1575
|
+
throw new InternalCompilerError(`emitter bug: keyed read of unknown shape ${shapeId}`);
|
|
1576
|
+
const name = `sc_rkg_${emitter.recordKeyGetFns.size}`;
|
|
1577
|
+
emitter.recordKeyGetFns.set(key, name);
|
|
1640
1578
|
const struct = mangleRecordStruct(shapeId);
|
|
1641
1579
|
const sig = `static ${cType(t)}${cType(t).endsWith("*") ? "" : " "}${name}(${struct} *r, ScrStr *k)`;
|
|
1642
|
-
|
|
1580
|
+
emitter.walkerProtos.push(`${sig}; /* r[k] on ${shapeId} as ${typeKey(t)} */`);
|
|
1643
1581
|
const d = [`${sig} { /* r[k] on ${shapeId} as ${typeKey(t)} */`];
|
|
1644
1582
|
// How a value of type `vt` (a field, or the overflow hit) surfaces as T.
|
|
1645
1583
|
const surface = (vt, expr, owned) => {
|
|
@@ -1648,27 +1586,27 @@ export function recordKeyGetHelper(E, shapeId, t, overflowOnly = false) {
|
|
|
1648
1586
|
}
|
|
1649
1587
|
if (t.kind === "dyn") {
|
|
1650
1588
|
// toDyn borrows — an owned operand would leak; callers pass borrowed.
|
|
1651
|
-
return `${
|
|
1589
|
+
return `${emitter.toDynHelper(vt)}(${expr})`;
|
|
1652
1590
|
}
|
|
1653
1591
|
if (t.kind === "union") {
|
|
1654
|
-
const def =
|
|
1592
|
+
const def = emitter.unionsById.get(t.unionId);
|
|
1655
1593
|
const tag = def?.arms.findIndex((a) => typeEquals(a, vt)) ?? -1;
|
|
1656
1594
|
if (tag < 0)
|
|
1657
|
-
throw new
|
|
1595
|
+
throw new InternalCompilerError(`emitter bug: keyed read arm for ${typeKey(vt)} in ${typeKey(t)}`);
|
|
1658
1596
|
if (vt.kind === "f64")
|
|
1659
1597
|
return `scr_union_new_f64(${tag}, ${expr})`;
|
|
1660
1598
|
if (vt.kind === "bool")
|
|
1661
1599
|
return `scr_union_new_bool(${tag}, ${expr})`;
|
|
1662
1600
|
const rc = vAdapters(vt);
|
|
1663
1601
|
const payload = owned ? expr : retainCallC(vt, expr);
|
|
1664
|
-
return `scr_union_new_ref(${tag}, ${payload}, &${rc.retain}, &${rc.release}, ${
|
|
1602
|
+
return `scr_union_new_ref(${tag}, ${payload}, &${rc.retain}, &${rc.release}, ${emitter.traceArgC(vt)})`;
|
|
1665
1603
|
}
|
|
1666
|
-
throw new
|
|
1604
|
+
throw new InternalCompilerError(`emitter bug: keyed read cannot surface ${typeKey(vt)} as ${typeKey(t)}`);
|
|
1667
1605
|
};
|
|
1668
1606
|
// overflowOnly (a literal key naming no declared field): the declared
|
|
1669
1607
|
// switch can never hit — only the overflow answers.
|
|
1670
1608
|
for (const f of overflowOnly ? [] : shape.fields) {
|
|
1671
|
-
const lit =
|
|
1609
|
+
const lit = emitter.internLiteral(f.name);
|
|
1672
1610
|
d.push(` if (scr_str_eq(k, (ScrStr *)&${lit})) { /* ${f.name} */`);
|
|
1673
1611
|
d.push(` return ${surface(f.type, `r->${mangleField(f.name)}`, false)};`);
|
|
1674
1612
|
d.push(` }`);
|
|
@@ -1693,7 +1631,7 @@ export function recordKeyGetHelper(E, shapeId, t, overflowOnly = false) {
|
|
|
1693
1631
|
d.push(` return ${surface(iv, "hit", true)};`);
|
|
1694
1632
|
}
|
|
1695
1633
|
else {
|
|
1696
|
-
throw new
|
|
1634
|
+
throw new InternalCompilerError(`emitter bug: keyed read overflow ${typeKey(iv)} as ${typeKey(t)}`);
|
|
1697
1635
|
}
|
|
1698
1636
|
d.push(` }`);
|
|
1699
1637
|
}
|
|
@@ -1702,17 +1640,17 @@ export function recordKeyGetHelper(E, shapeId, t, overflowOnly = false) {
|
|
|
1702
1640
|
if (t.kind === "dyn") {
|
|
1703
1641
|
d.push(` return scr_dyn_retain(scr_dyn_undefined());`);
|
|
1704
1642
|
}
|
|
1705
|
-
else if (t.kind === "union" &&
|
|
1706
|
-
d.push(` return ${
|
|
1643
|
+
else if (t.kind === "union" && undefinedArmTag(t, emitter.unionsById) >= 0) {
|
|
1644
|
+
d.push(` return ${emitter.unitInstanceRef(t.unionId, undefinedArmTag(t, emitter.unionsById))};`);
|
|
1707
1645
|
}
|
|
1708
1646
|
else {
|
|
1709
1647
|
// JS would answer undefined; T has no way to say it (the checker
|
|
1710
1648
|
// claimed T without noUncheckedIndexedAccess) — trap like an array
|
|
1711
1649
|
// OOB read instead of corrupting a typed slot (SEMANTICS.md).
|
|
1712
|
-
d.push(` scr_trap_fmt("scriptc: TypeError: record has no key '%.*s' (typed '${
|
|
1650
|
+
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
1651
|
}
|
|
1714
1652
|
d.push(`}`, ``);
|
|
1715
|
-
|
|
1653
|
+
emitter.walkerDefs.push(...d);
|
|
1716
1654
|
return name;
|
|
1717
1655
|
}
|
|
1718
1656
|
/** The emitted dynamic-keyed WRITE helper for one index-signature shape:
|
|
@@ -1723,32 +1661,32 @@ export function recordKeyGetHelper(E, shapeId, t, overflowOnly = false) {
|
|
|
1723
1661
|
* anything, the documented divergence; typed values store directly),
|
|
1724
1662
|
* an undeclared key inserts/replaces in the overflow map. Borrows r and
|
|
1725
1663
|
* k; OWNS v (+1 moves in — released on the validation-failure path). */
|
|
1726
|
-
export function recordKeySetHelper(
|
|
1727
|
-
const existing =
|
|
1664
|
+
export function recordKeySetHelper(emitter, shapeId) {
|
|
1665
|
+
const existing = emitter.recordKeySetFns.get(shapeId);
|
|
1728
1666
|
if (existing)
|
|
1729
1667
|
return existing;
|
|
1730
|
-
const shape =
|
|
1668
|
+
const shape = emitter.recordsById.get(shapeId);
|
|
1731
1669
|
// Signature-free shapes dispatch over their (one-typed) declared
|
|
1732
1670
|
// fields and TRAP on a miss (scr_record_key_miss — JS would add the
|
|
1733
1671
|
// property, which a monomorphic struct cannot); overflow shapes keep
|
|
1734
1672
|
// the map insert tail.
|
|
1735
1673
|
const iv = shape?.indexValue ?? shape?.fields[0]?.type;
|
|
1736
1674
|
if (!shape || !iv)
|
|
1737
|
-
throw new
|
|
1738
|
-
const name = `sc_rks_${
|
|
1739
|
-
|
|
1675
|
+
throw new InternalCompilerError(`emitter bug: keyed write on field-free non-overflow shape ${shapeId}`);
|
|
1676
|
+
const name = `sc_rks_${emitter.recordKeySetFns.size}`;
|
|
1677
|
+
emitter.recordKeySetFns.set(shapeId, name);
|
|
1740
1678
|
const struct = mangleRecordStruct(shapeId);
|
|
1741
1679
|
const sig = `static void ${name}(${struct} *r, ScrStr *k, ${cDecl(iv, "v")})`;
|
|
1742
|
-
|
|
1680
|
+
emitter.walkerProtos.push(`${sig}; /* r[k] = v on ${shapeId} */`);
|
|
1743
1681
|
const d = [`${sig} { /* r[k] = v on ${shapeId} */`];
|
|
1744
1682
|
for (const f of shape.fields) {
|
|
1745
|
-
const lit =
|
|
1683
|
+
const lit = emitter.internLiteral(f.name);
|
|
1746
1684
|
const member = `r->${mangleField(f.name)}`;
|
|
1747
1685
|
d.push(` if (scr_str_eq(k, (ScrStr *)&${lit})) { /* ${f.name} */`);
|
|
1748
1686
|
if (iv.kind === "dyn" && shape.indexValue) {
|
|
1749
1687
|
const keyLit = cStringLiteral(Buffer.from(f.name, "utf8"));
|
|
1750
1688
|
d.push(` ScrDynPath p = { NULL, ${keyLit}, 0 };`);
|
|
1751
|
-
d.push(` ${cDecl(f.type, "nv")} = ${
|
|
1689
|
+
d.push(` ${cDecl(f.type, "nv")} = ${emitter.dynCheckHelper(f.type)}(v, &p);`);
|
|
1752
1690
|
d.push(` scr_dyn_release(v);`);
|
|
1753
1691
|
d.push(` if (scr_exc_pending()) return; /* mismatched write: TypeError, field untouched */`);
|
|
1754
1692
|
d.push(` ${isRefCounted(f.type) ? `if (${member}) ${releaseCallC(f.type, member)};` : `(void)0;`}`);
|
|
@@ -1782,7 +1720,7 @@ export function recordKeySetHelper(E, shapeId) {
|
|
|
1782
1720
|
}
|
|
1783
1721
|
}
|
|
1784
1722
|
d.push(`}`, ``);
|
|
1785
|
-
|
|
1723
|
+
emitter.walkerDefs.push(...d);
|
|
1786
1724
|
return name;
|
|
1787
1725
|
}
|
|
1788
|
-
//# sourceMappingURL=
|
|
1726
|
+
//# sourceMappingURL=walkers.js.map
|