gitnexus 1.6.8-rc.9 → 1.6.8
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/README.md +3 -3
- package/dist/_shared/graph/types.d.ts +31 -1
- package/dist/_shared/graph/types.d.ts.map +1 -1
- package/dist/_shared/language-detection.d.ts.map +1 -1
- package/dist/_shared/language-detection.js +11 -1
- package/dist/_shared/language-detection.js.map +1 -1
- package/dist/_shared/lbug/schema-constants.d.ts +1 -1
- package/dist/_shared/lbug/schema-constants.d.ts.map +1 -1
- package/dist/_shared/lbug/schema-constants.js +6 -0
- package/dist/_shared/lbug/schema-constants.js.map +1 -1
- package/dist/_shared/scope-resolution/parsed-file.d.ts +21 -0
- package/dist/_shared/scope-resolution/parsed-file.d.ts.map +1 -1
- package/dist/_shared/scope-resolution/symbol-definition.d.ts +6 -0
- package/dist/_shared/scope-resolution/symbol-definition.d.ts.map +1 -1
- package/dist/cli/ai-context.d.ts +31 -1
- package/dist/cli/ai-context.js +18 -16
- package/dist/cli/analyze-config.js +11 -0
- package/dist/cli/analyze.d.ts +14 -0
- package/dist/cli/analyze.js +98 -0
- package/dist/cli/embedding-dims.d.ts +33 -0
- package/dist/cli/embedding-dims.js +39 -0
- package/dist/cli/eval-server.d.ts +8 -0
- package/dist/cli/eval-server.js +242 -2
- package/dist/cli/help-i18n.js +19 -0
- package/dist/cli/i18n/en.d.ts +15 -1
- package/dist/cli/i18n/en.js +15 -1
- package/dist/cli/i18n/resources.d.ts +29 -1
- package/dist/cli/i18n/zh-CN.d.ts +14 -0
- package/dist/cli/i18n/zh-CN.js +15 -1
- package/dist/cli/index.js +89 -1
- package/dist/cli/mcp.d.ts +6 -1
- package/dist/cli/mcp.js +26 -1
- package/dist/cli/optional-grammars.d.ts +6 -8
- package/dist/cli/optional-grammars.js +8 -11
- package/dist/cli/setup.d.ts +3 -1
- package/dist/cli/setup.js +67 -17
- package/dist/cli/skill-gen.js +2 -1
- package/dist/cli/tool.d.ts +19 -1
- package/dist/cli/tool.js +96 -3
- package/dist/core/embeddings/hf-env.d.ts +0 -66
- package/dist/core/embeddings/http-client.d.ts +7 -0
- package/dist/core/embeddings/http-client.js +5 -3
- package/dist/core/embeddings/server-mapping.d.ts +1 -1
- package/dist/core/embeddings/server-mapping.js +7 -3
- package/dist/core/graph/import-cycles.d.ts +10 -0
- package/dist/core/graph/import-cycles.js +103 -0
- package/dist/core/group/cross-impact.d.ts +2 -1
- package/dist/core/group/cross-impact.js +5 -1
- package/dist/core/group/extractors/grpc-patterns/proto.js +10 -6
- package/dist/core/group/extractors/http-patterns/kotlin.js +7 -7
- package/dist/core/group/extractors/http-route-extractor.d.ts +24 -0
- package/dist/core/group/extractors/http-route-extractor.js +22 -4
- package/dist/core/group/extractors/include-extractor.js +22 -13
- package/dist/core/group/sync.d.ts +27 -1
- package/dist/core/group/sync.js +0 -0
- package/dist/core/incremental/subgraph-extract.js +18 -1
- package/dist/core/ingestion/cfg/cfg-builder.d.ts +114 -0
- package/dist/core/ingestion/cfg/cfg-builder.js +196 -0
- package/dist/core/ingestion/cfg/collect.d.ts +51 -0
- package/dist/core/ingestion/cfg/collect.js +77 -0
- package/dist/core/ingestion/cfg/control-dependence.d.ts +58 -0
- package/dist/core/ingestion/cfg/control-dependence.js +182 -0
- package/dist/core/ingestion/cfg/control-flow-context.d.ts +106 -0
- package/dist/core/ingestion/cfg/control-flow-context.js +124 -0
- package/dist/core/ingestion/cfg/emit.d.ts +293 -0
- package/dist/core/ingestion/cfg/emit.js +646 -0
- package/dist/core/ingestion/cfg/post-dominators.d.ts +79 -0
- package/dist/core/ingestion/cfg/post-dominators.js +176 -0
- package/dist/core/ingestion/cfg/reaching-def-reason-codec.d.ts +106 -0
- package/dist/core/ingestion/cfg/reaching-def-reason-codec.js +133 -0
- package/dist/core/ingestion/cfg/reaching-defs-graph.d.ts +18 -0
- package/dist/core/ingestion/cfg/reaching-defs-graph.js +312 -0
- package/dist/core/ingestion/cfg/reaching-defs.d.ts +162 -0
- package/dist/core/ingestion/cfg/reaching-defs.js +785 -0
- package/dist/core/ingestion/cfg/synthetic-escape.d.ts +124 -0
- package/dist/core/ingestion/cfg/synthetic-escape.js +300 -0
- package/dist/core/ingestion/cfg/traversal-result.d.ts +20 -0
- package/dist/core/ingestion/cfg/traversal-result.js +2 -0
- package/dist/core/ingestion/cfg/types.d.ts +274 -0
- package/dist/core/ingestion/cfg/types.js +13 -0
- package/dist/core/ingestion/cfg/visitors/c-cpp-harvest.d.ts +111 -0
- package/dist/core/ingestion/cfg/visitors/c-cpp-harvest.js +541 -0
- package/dist/core/ingestion/cfg/visitors/c-cpp.d.ts +74 -0
- package/dist/core/ingestion/cfg/visitors/c-cpp.js +584 -0
- package/dist/core/ingestion/cfg/visitors/call-site-harvest.d.ts +195 -0
- package/dist/core/ingestion/cfg/visitors/call-site-harvest.js +350 -0
- package/dist/core/ingestion/cfg/visitors/csharp-harvest.d.ts +124 -0
- package/dist/core/ingestion/cfg/visitors/csharp-harvest.js +589 -0
- package/dist/core/ingestion/cfg/visitors/csharp.d.ts +87 -0
- package/dist/core/ingestion/cfg/visitors/csharp.js +867 -0
- package/dist/core/ingestion/cfg/visitors/dart-harvest.d.ts +278 -0
- package/dist/core/ingestion/cfg/visitors/dart-harvest.js +870 -0
- package/dist/core/ingestion/cfg/visitors/dart.d.ts +119 -0
- package/dist/core/ingestion/cfg/visitors/dart.js +836 -0
- package/dist/core/ingestion/cfg/visitors/go-harvest.d.ts +160 -0
- package/dist/core/ingestion/cfg/visitors/go-harvest.js +621 -0
- package/dist/core/ingestion/cfg/visitors/go.d.ts +108 -0
- package/dist/core/ingestion/cfg/visitors/go.js +638 -0
- package/dist/core/ingestion/cfg/visitors/java-harvest.d.ts +108 -0
- package/dist/core/ingestion/cfg/visitors/java-harvest.js +513 -0
- package/dist/core/ingestion/cfg/visitors/java.d.ts +101 -0
- package/dist/core/ingestion/cfg/visitors/java.js +812 -0
- package/dist/core/ingestion/cfg/visitors/kotlin-harvest.d.ts +253 -0
- package/dist/core/ingestion/cfg/visitors/kotlin-harvest.js +719 -0
- package/dist/core/ingestion/cfg/visitors/kotlin.d.ts +121 -0
- package/dist/core/ingestion/cfg/visitors/kotlin.js +809 -0
- package/dist/core/ingestion/cfg/visitors/php-harvest.d.ts +172 -0
- package/dist/core/ingestion/cfg/visitors/php-harvest.js +626 -0
- package/dist/core/ingestion/cfg/visitors/php.d.ts +96 -0
- package/dist/core/ingestion/cfg/visitors/php.js +721 -0
- package/dist/core/ingestion/cfg/visitors/python-harvest.d.ts +212 -0
- package/dist/core/ingestion/cfg/visitors/python-harvest.js +739 -0
- package/dist/core/ingestion/cfg/visitors/python.d.ts +103 -0
- package/dist/core/ingestion/cfg/visitors/python.js +558 -0
- package/dist/core/ingestion/cfg/visitors/ruby-harvest.d.ts +223 -0
- package/dist/core/ingestion/cfg/visitors/ruby-harvest.js +587 -0
- package/dist/core/ingestion/cfg/visitors/ruby.d.ts +112 -0
- package/dist/core/ingestion/cfg/visitors/ruby.js +756 -0
- package/dist/core/ingestion/cfg/visitors/rust-harvest.d.ts +324 -0
- package/dist/core/ingestion/cfg/visitors/rust-harvest.js +873 -0
- package/dist/core/ingestion/cfg/visitors/rust.d.ts +95 -0
- package/dist/core/ingestion/cfg/visitors/rust.js +558 -0
- package/dist/core/ingestion/cfg/visitors/scope-tree-harvest.d.ts +87 -0
- package/dist/core/ingestion/cfg/visitors/scope-tree-harvest.js +116 -0
- package/dist/core/ingestion/cfg/visitors/swift-harvest.d.ts +255 -0
- package/dist/core/ingestion/cfg/visitors/swift-harvest.js +679 -0
- package/dist/core/ingestion/cfg/visitors/swift.d.ts +116 -0
- package/dist/core/ingestion/cfg/visitors/swift.js +787 -0
- package/dist/core/ingestion/cfg/visitors/typescript-harvest.d.ts +149 -0
- package/dist/core/ingestion/cfg/visitors/typescript-harvest.js +1056 -0
- package/dist/core/ingestion/cfg/visitors/typescript.d.ts +66 -0
- package/dist/core/ingestion/cfg/visitors/typescript.js +583 -0
- package/dist/core/ingestion/import-resolvers/utils.js +2 -0
- package/dist/core/ingestion/language-provider.d.ts +11 -0
- package/dist/core/ingestion/languages/c-cpp.js +6 -1
- package/dist/core/ingestion/languages/cobol.js +4 -0
- package/dist/core/ingestion/languages/cpp/arity-metadata.js +41 -2
- package/dist/core/ingestion/languages/cpp/captures.js +50 -1
- package/dist/core/ingestion/languages/cpp/conversion-rank.d.ts +2 -0
- package/dist/core/ingestion/languages/cpp/conversion-rank.js +89 -0
- package/dist/core/ingestion/languages/cpp/header-scan.d.ts +1 -1
- package/dist/core/ingestion/languages/cpp/header-scan.js +2 -2
- package/dist/core/ingestion/languages/cpp/inline-namespaces.js +7 -2
- package/dist/core/ingestion/languages/cpp/member-lookup.js +2 -1
- package/dist/core/ingestion/languages/cpp/query.js +23 -0
- package/dist/core/ingestion/languages/cpp/scope-resolver.js +2 -1
- package/dist/core/ingestion/languages/csharp.js +2 -0
- package/dist/core/ingestion/languages/dart.js +2 -0
- package/dist/core/ingestion/languages/go.js +2 -0
- package/dist/core/ingestion/languages/java.js +3 -0
- package/dist/core/ingestion/languages/kotlin/query.js +3 -2
- package/dist/core/ingestion/languages/kotlin.js +3 -0
- package/dist/core/ingestion/languages/php.js +2 -0
- package/dist/core/ingestion/languages/python.js +2 -0
- package/dist/core/ingestion/languages/ruby.js +2 -0
- package/dist/core/ingestion/languages/rust.js +2 -0
- package/dist/core/ingestion/languages/swift.js +2 -0
- package/dist/core/ingestion/languages/typescript.js +5 -0
- package/dist/core/ingestion/languages/vue.js +6 -0
- package/dist/core/ingestion/method-extractors/configs/c-cpp.js +6 -13
- package/dist/core/ingestion/method-extractors/generic.js +1 -0
- package/dist/core/ingestion/method-types.d.ts +2 -0
- package/dist/core/ingestion/model/symbol-table.d.ts +1 -0
- package/dist/core/ingestion/model/symbol-table.js +1 -0
- package/dist/core/ingestion/mro-processor.js +109 -0
- package/dist/core/ingestion/parsing-processor.js +23 -0
- package/dist/core/ingestion/pipeline-phases/call-summaries.d.ts +26 -0
- package/dist/core/ingestion/pipeline-phases/call-summaries.js +46 -0
- package/dist/core/ingestion/pipeline-phases/index.d.ts +2 -0
- package/dist/core/ingestion/pipeline-phases/index.js +2 -0
- package/dist/core/ingestion/pipeline-phases/parse-impl.d.ts +0 -21
- package/dist/core/ingestion/pipeline-phases/parse-impl.js +18 -1
- package/dist/core/ingestion/pipeline-phases/routes.d.ts +10 -0
- package/dist/core/ingestion/pipeline-phases/routes.js +30 -1
- package/dist/core/ingestion/pipeline-phases/taint-summaries.d.ts +30 -0
- package/dist/core/ingestion/pipeline-phases/taint-summaries.js +81 -0
- package/dist/core/ingestion/pipeline.d.ts +92 -10
- package/dist/core/ingestion/pipeline.js +11 -2
- package/dist/core/ingestion/scope-extractor.js +12 -2
- package/dist/core/ingestion/scope-resolution/contract/scope-resolver.d.ts +9 -0
- package/dist/core/ingestion/scope-resolution/graph-bridge/callee-id-sink.d.ts +75 -0
- package/dist/core/ingestion/scope-resolution/graph-bridge/callee-id-sink.js +67 -0
- package/dist/core/ingestion/scope-resolution/graph-bridge/edges.d.ts +12 -2
- package/dist/core/ingestion/scope-resolution/graph-bridge/edges.js +14 -2
- package/dist/core/ingestion/scope-resolution/graph-bridge/references-to-edges.d.ts +6 -1
- package/dist/core/ingestion/scope-resolution/graph-bridge/references-to-edges.js +13 -1
- package/dist/core/ingestion/scope-resolution/passes/free-call-fallback.d.ts +9 -1
- package/dist/core/ingestion/scope-resolution/passes/free-call-fallback.js +28 -2
- package/dist/core/ingestion/scope-resolution/passes/overload-narrowing.d.ts +4 -0
- package/dist/core/ingestion/scope-resolution/passes/overload-narrowing.js +9 -0
- package/dist/core/ingestion/scope-resolution/passes/receiver-bound-calls.d.ts +6 -1
- package/dist/core/ingestion/scope-resolution/passes/receiver-bound-calls.js +174 -40
- package/dist/core/ingestion/scope-resolution/pipeline/phase.d.ts +24 -0
- package/dist/core/ingestion/scope-resolution/pipeline/phase.js +276 -190
- package/dist/core/ingestion/scope-resolution/pipeline/reconcile-ownership.js +43 -3
- package/dist/core/ingestion/scope-resolution/pipeline/run.d.ts +75 -0
- package/dist/core/ingestion/scope-resolution/pipeline/run.js +349 -1
- package/dist/core/ingestion/scope-resolution/resolution-outcome.d.ts +1 -1
- package/dist/core/ingestion/taint/call-summary-codec.d.ts +75 -0
- package/dist/core/ingestion/taint/call-summary-codec.js +128 -0
- package/dist/core/ingestion/taint/call-summary-emit.d.ts +43 -0
- package/dist/core/ingestion/taint/call-summary-emit.js +70 -0
- package/dist/core/ingestion/taint/call-summary-harvest.d.ts +77 -0
- package/dist/core/ingestion/taint/call-summary-harvest.js +179 -0
- package/dist/core/ingestion/taint/call-summary-model.d.ts +47 -0
- package/dist/core/ingestion/taint/call-summary-model.js +25 -0
- package/dist/core/ingestion/taint/emit.d.ts +125 -0
- package/dist/core/ingestion/taint/emit.js +208 -0
- package/dist/core/ingestion/taint/interproc-emit.d.ts +50 -0
- package/dist/core/ingestion/taint/interproc-emit.js +88 -0
- package/dist/core/ingestion/taint/interproc-solver.d.ts +110 -0
- package/dist/core/ingestion/taint/interproc-solver.js +312 -0
- package/dist/core/ingestion/taint/match.d.ts +153 -0
- package/dist/core/ingestion/taint/match.js +278 -0
- package/dist/core/ingestion/taint/path-codec.d.ts +134 -0
- package/dist/core/ingestion/taint/path-codec.js +190 -0
- package/dist/core/ingestion/taint/propagate.d.ts +216 -0
- package/dist/core/ingestion/taint/propagate.js +659 -0
- package/dist/core/ingestion/taint/site-safety.d.ts +29 -0
- package/dist/core/ingestion/taint/site-safety.js +98 -0
- package/dist/core/ingestion/taint/source-sink-config.d.ts +107 -23
- package/dist/core/ingestion/taint/source-sink-config.js +35 -12
- package/dist/core/ingestion/taint/source-sink-registry.d.ts +6 -4
- package/dist/core/ingestion/taint/source-sink-registry.js +6 -4
- package/dist/core/ingestion/taint/summary-harvest-driver.d.ts +80 -0
- package/dist/core/ingestion/taint/summary-harvest-driver.js +179 -0
- package/dist/core/ingestion/taint/summary-harvest.d.ts +89 -0
- package/dist/core/ingestion/taint/summary-harvest.js +537 -0
- package/dist/core/ingestion/taint/summary-model.d.ts +200 -0
- package/dist/core/ingestion/taint/summary-model.js +86 -0
- package/dist/core/ingestion/taint/typescript-model.d.ts +38 -0
- package/dist/core/ingestion/taint/typescript-model.js +102 -0
- package/dist/core/ingestion/type-extractors/c-cpp.js +21 -0
- package/dist/core/ingestion/utils/env.d.ts +7 -0
- package/dist/core/ingestion/utils/env.js +12 -0
- package/dist/core/ingestion/utils/method-props.js +1 -0
- package/dist/core/ingestion/workers/parse-worker.d.ts +13 -0
- package/dist/core/ingestion/workers/parse-worker.js +76 -17
- package/dist/core/ingestion/workers/worker-pool.d.ts +9 -40
- package/dist/core/ingestion/workers/worker-pool.js +15 -2
- package/dist/core/lbug/csv-generator.d.ts +51 -3
- package/dist/core/lbug/csv-generator.js +369 -255
- package/dist/core/lbug/lbug-adapter.d.ts +58 -18
- package/dist/core/lbug/lbug-adapter.js +346 -84
- package/dist/core/lbug/lbug-config.d.ts +19 -0
- package/dist/core/lbug/lbug-config.js +29 -0
- package/dist/core/lbug/pdg-emit-sink.d.ts +127 -0
- package/dist/core/lbug/pdg-emit-sink.js +358 -0
- package/dist/core/lbug/pool-adapter.d.ts +35 -0
- package/dist/core/lbug/pool-adapter.js +90 -1
- package/dist/core/lbug/rel-pair-routing.d.ts +54 -0
- package/dist/core/lbug/rel-pair-routing.js +140 -0
- package/dist/core/lbug/schema.d.ts +2 -2
- package/dist/core/lbug/schema.js +3 -0
- package/dist/core/logger.d.ts +0 -5
- package/dist/core/run-analyze.d.ts +96 -0
- package/dist/core/run-analyze.js +207 -3
- package/dist/core/tree-sitter/parser-loader.js +5 -4
- package/dist/core/tree-sitter/safe-parse.d.ts +0 -5
- package/dist/core/tree-sitter/vendored-grammars.d.ts +39 -0
- package/dist/core/tree-sitter/vendored-grammars.js +57 -0
- package/dist/core/wiki/generator.js +3 -1
- package/dist/core/wiki/graph-queries.d.ts +6 -0
- package/dist/core/wiki/graph-queries.js +9 -1
- package/dist/mcp/http-transport.d.ts +134 -0
- package/dist/mcp/http-transport.js +503 -0
- package/dist/mcp/local/local-backend.d.ts +110 -24
- package/dist/mcp/local/local-backend.js +1225 -19
- package/dist/mcp/local/pdg-impact.d.ts +384 -0
- package/dist/mcp/local/pdg-impact.js +1972 -0
- package/dist/mcp/resources.js +13 -1
- package/dist/mcp/tools.d.ts +12 -0
- package/dist/mcp/tools.js +214 -7
- package/dist/server/analyze-launch.d.ts +29 -0
- package/dist/server/analyze-launch.js +137 -0
- package/dist/server/analyze-upload.d.ts +33 -0
- package/dist/server/analyze-upload.js +123 -0
- package/dist/server/analyze-worker.d.ts +17 -1
- package/dist/server/api.d.ts +17 -0
- package/dist/server/api.js +132 -168
- package/dist/server/git-clone.d.ts +43 -2
- package/dist/server/git-clone.js +211 -16
- package/dist/server/mcp-http.d.ts +5 -6
- package/dist/server/mcp-http.js +9 -82
- package/dist/server/middleware.d.ts +40 -0
- package/dist/server/middleware.js +92 -0
- package/dist/server/private-ip.d.ts +1 -0
- package/dist/server/private-ip.js +15 -0
- package/dist/server/upload-ingest.d.ts +56 -0
- package/dist/server/upload-ingest.js +276 -0
- package/dist/server/upload-paths.d.ts +37 -0
- package/dist/server/upload-paths.js +57 -0
- package/dist/server/upload-sweep.d.ts +20 -0
- package/dist/server/upload-sweep.js +57 -0
- package/dist/storage/git.js +5 -8
- package/dist/storage/parse-cache.d.ts +22 -1
- package/dist/storage/parse-cache.js +41 -10
- package/dist/storage/repo-manager.d.ts +121 -10
- package/dist/storage/repo-manager.js +43 -5
- package/dist/types/pipeline.d.ts +9 -0
- package/hooks/antigravity/gitnexus-antigravity-hook.cjs +110 -10
- package/hooks/claude/gitnexus-hook.cjs +110 -13
- package/hooks/claude/hook-db-lock-probe.cjs +513 -26
- package/package.json +8 -2
- package/scripts/assert-publish-grammar-coverage.cjs +31 -0
- package/scripts/build-tree-sitter-grammars.cjs +16 -10
- package/scripts/cross-platform-tests.ts +1 -0
- package/skills/gitnexus-debugging.md +16 -4
- package/skills/gitnexus-exploring.md +3 -3
- package/skills/gitnexus-guide.md +33 -0
- package/skills/gitnexus-pdg-query.md +89 -0
- package/skills/gitnexus-refactoring.md +1 -1
- package/skills/gitnexus-taint-analysis.md +178 -0
- package/vendor/tree-sitter-c/package.json +1 -1
- package/vendor/tree-sitter-dart/package.json +1 -1
- package/vendor/tree-sitter-kotlin/package.json +1 -1
- package/vendor/tree-sitter-proto/package.json +1 -1
- package/vendor/tree-sitter-swift/package.json +1 -1
- package/web/assets/{agent-CKPMqImC.js → agent-D3Xd7zZE.js} +123 -123
- package/web/assets/architecture-7EHR7CIX-6QZW5X65-DxJw65fT.js +1 -0
- package/web/assets/architectureDiagram-UL44E2DR-ChH9xW-N.js +36 -0
- package/web/assets/{blockDiagram-7IZFK4PR-B4niSLvR.js → blockDiagram-7IZFK4PR-BkWhpzWB.js} +1 -1
- package/web/assets/{c4Diagram-Y2BXMSZH-DIzEXalR.js → c4Diagram-Y2BXMSZH-DtBvpzWD.js} +1 -1
- package/web/assets/{chunk-3SSMPTDK-BzGeeheI.js → chunk-3SSMPTDK-B4_etUhr.js} +2 -2
- package/web/assets/{chunk-5IMINLNL-CnTLsXIV.js → chunk-5IMINLNL-DOdTeQri.js} +1 -1
- package/web/assets/{chunk-5VCL7Z4A-w1BCx98Z.js → chunk-5VCL7Z4A-CQ-2dYWj.js} +1 -1
- package/web/assets/chunk-6764PJDD-DpIS7hxD.js +1 -0
- package/web/assets/{chunk-67TQ5CYL-CChC2cAv.js → chunk-67TQ5CYL-4sNPJU1q.js} +3 -3
- package/web/assets/{chunk-7W6UQGC5-CgFyfZ6k.js → chunk-7W6UQGC5-KyEG0HQg.js} +1 -1
- package/web/assets/{chunk-AZZRMDJM-5E9ARdDQ.js → chunk-AZZRMDJM-y-xJBuMz.js} +1 -1
- package/web/assets/{chunk-INKRHTLW-ELpfuk9h.js → chunk-INKRHTLW-Nu4ri9P-.js} +1 -1
- package/web/assets/{chunk-JQRUD6KW-Dcq_Qnyy.js → chunk-JQRUD6KW-Dbva2Z17.js} +1 -1
- package/web/assets/{chunk-KGFNY3KK-W-VR57xb.js → chunk-KGFNY3KK-JGMJvKCK.js} +1 -1
- package/web/assets/chunk-KGYTTC2M-CWC_c3H9.js +161 -0
- package/web/assets/{chunk-KNLZD3CH-BuZBOcso.js → chunk-KNLZD3CH-BGlP6X9R.js} +1 -1
- package/web/assets/{chunk-KRXBNO2N-DH2NPM7I.js → chunk-KRXBNO2N-BW5o0KUN.js} +1 -1
- package/web/assets/{chunk-LCXTWHL2-Dfmux4m1.js → chunk-LCXTWHL2-zoomRtWX.js} +1 -1
- package/web/assets/{chunk-LII3EMHJ-3X33tCpU.js → chunk-LII3EMHJ-D-jm-dLa.js} +1 -1
- package/web/assets/{chunk-QA3QBVWF-D5Ha3GgB.js → chunk-QA3QBVWF-BgRW3SXd.js} +1 -1
- package/web/assets/{chunk-RG4AUYOV-CAkzcoRj.js → chunk-RG4AUYOV-DD0B2N2B.js} +1 -1
- package/web/assets/{chunk-T2UQINTJ-kGYG7ppP.js → chunk-T2UQINTJ-DSBqkzH7.js} +1 -1
- package/web/assets/chunk-T5OCTHI4-DdZvN-9i.js +1 -0
- package/web/assets/{chunk-UY5QBCOK-Du-c56gs.js → chunk-UY5QBCOK-DyF0vyGd.js} +1 -1
- package/web/assets/{chunk-W44A43WB-lrCpuupA.js → chunk-W44A43WB-JqMLIpR0.js} +1 -1
- package/web/assets/{chunk-ZXARS5L4-CSZRiyOf.js → chunk-ZXARS5L4-CxN8oiwI.js} +1 -1
- package/web/assets/classDiagram-KGZ6W3CR-DJm9BgF-.js +1 -0
- package/web/assets/classDiagram-v2-72OJOZXJ-DJm9BgF-.js +1 -0
- package/web/assets/{context-builder-_HS0v2ma.js → context-builder-BHiFUA8O.js} +10 -2
- package/web/assets/{cose-bilkent-UX7MHV2Q-BHv2bbtl.js → cose-bilkent-UX7MHV2Q-D71wNYRJ.js} +1 -1
- package/web/assets/dagre-ND4H6XIP-BIkxmhcu.js +4 -0
- package/web/assets/diagram-3NCE3AQN-BTa6iH0T.js +43 -0
- package/web/assets/diagram-GF46GFSD-DZDV0vBj.js +24 -0
- package/web/assets/{diagram-HNR7UZ2L-fUWreZzx.js → diagram-HNR7UZ2L-DFCfd5LI.js} +2 -2
- package/web/assets/diagram-QXG6HAR7-BzM--Jj0.js +24 -0
- package/web/assets/diagram-WEQXMOUZ-DFFwz0k4.js +10 -0
- package/web/assets/{erDiagram-L5TCEMPS-QN2eEP1e.js → erDiagram-L5TCEMPS-CfHMJJqo.js} +1 -1
- package/web/assets/eventmodeling-FCH6USID-MREXMVOE-BQm9QzEa.js +1 -0
- package/web/assets/{flowDiagram-H6V6AXG4-CXbXImlN.js → flowDiagram-H6V6AXG4-Be805QiJ.js} +3 -3
- package/web/assets/{ganttDiagram-JCBTUEKG-BHQssTz6.js → ganttDiagram-JCBTUEKG-D3iL2Aet.js} +1 -1
- package/web/assets/gitGraph-WXDBUCRP-R675I2BI-Cr_Bm2Nb.js +1 -0
- package/web/assets/gitGraphDiagram-S2ZK5IYY-CPIDgxGm.js +106 -0
- package/web/assets/index-BvYev1UJ.js +635 -0
- package/web/assets/index-_lgn7hs5.css +2 -0
- package/web/assets/info-J43DQDTF-KCYPFFUO-Cs4p2oyk.js +1 -0
- package/web/assets/infoDiagram-3YFTVSEB-Y7BKSoke.js +2 -0
- package/web/assets/{ishikawaDiagram-BNXS4ZKH-6LKOvBfp.js → ishikawaDiagram-BNXS4ZKH-CT4SHFuI.js} +1 -1
- package/web/assets/{journeyDiagram-M6C3CM3L-DNPYCpvq.js → journeyDiagram-M6C3CM3L-CvArszLo.js} +1 -1
- package/web/assets/{kanban-definition-75IXJCU3-DgDi9oJT.js → kanban-definition-75IXJCU3-C6yDxr7N.js} +3 -3
- package/web/assets/{katex-K3KEBU37-CrVLz8l7.js → katex-K3KEBU37-CTc5BslQ.js} +1 -1
- package/web/assets/{mindmap-definition-2TDM6QVE-CwR5sBB-.js → mindmap-definition-2TDM6QVE-BOc2WEne.js} +1 -1
- package/web/assets/packet-YPE3B663-LP52Z2RK-CKCrztD2.js +1 -0
- package/web/assets/pie-LRSECV5Y-TCRJHUBD-BB7pHqoD.js +1 -0
- package/web/assets/{pieDiagram-CU6KROY3-By8g6f6B.js → pieDiagram-CU6KROY3-Cvc0f_Pd.js} +1 -1
- package/web/assets/{quadrantDiagram-VICAPDV7-bAm6Hi_5.js → quadrantDiagram-VICAPDV7-yXSZ2lLz.js} +1 -1
- package/web/assets/radar-GUYGQ44K-RDLRG3WG-DhoTOcuK.js +1 -0
- package/web/assets/{requirementDiagram-JXO7QTGE-7oDcJ1_J.js → requirementDiagram-JXO7QTGE-BRcZvHs4.js} +1 -1
- package/web/assets/{sankeyDiagram-URQDO5SZ-LFJz53u5.js → sankeyDiagram-URQDO5SZ-1qEjlFIB.js} +1 -1
- package/web/assets/{sequenceDiagram-VS2MUI6T-FySeKCUy.js → sequenceDiagram-VS2MUI6T-PcSCuvrB.js} +3 -3
- package/web/assets/stateDiagram-7D4R322I-D6qYSV1E.js +1 -0
- package/web/assets/stateDiagram-v2-36443NZ5-Bg-ImOSX.js +1 -0
- package/web/assets/{timeline-definition-O6YCAMPW-Ds2CnVZK.js → timeline-definition-O6YCAMPW-QWkh01xw.js} +1 -1
- package/web/assets/treeView-BLDUP644-QA4HXRO3-ODehyGKL.js +1 -0
- package/web/assets/treemap-LRROVOQU-LLAWBHMP-BfpgC-7o.js +1 -0
- package/web/assets/{vennDiagram-MWXL3ELB-DUIEwXWp.js → vennDiagram-MWXL3ELB-ak4DfwuM.js} +3 -3
- package/web/assets/wardley-L42UT6IY-5TKZOOLJ-CNeL6VHE.js +1 -0
- package/web/assets/{wardleyDiagram-CUQ6CDDI-DEiFPQih.js → wardleyDiagram-CUQ6CDDI-CTzR4Loq.js} +1 -1
- package/web/assets/{xychartDiagram-N2JHSOCM-BUbayhST.js → xychartDiagram-N2JHSOCM-DA1BEaQz.js} +1 -1
- package/web/index.html +13 -15
- package/scripts/materialize-vendor-grammars.cjs +0 -97
- package/web/assets/architecture-7EHR7CIX-6QZW5X65-BETj2x4g.js +0 -1
- package/web/assets/architectureDiagram-UL44E2DR-D1EXI0zA.js +0 -36
- package/web/assets/chunk-2T2R6R2M-n6s9JZqv.js +0 -4
- package/web/assets/chunk-2UTLFMKG-CMBB1TMN.js +0 -1
- package/web/assets/chunk-4R4BOZG6-mKhL59ul.js +0 -159
- package/web/assets/chunk-6764PJDD-ChwMM2z4.js +0 -1
- package/web/assets/chunk-7J6CGLKN-DT-b53FT.js +0 -10
- package/web/assets/chunk-C62D2QBJ-CDAWj26E.js +0 -1
- package/web/assets/chunk-CEXFNPSA-D68Tk6ls.js +0 -1
- package/web/assets/chunk-CilyBKbf.js +0 -1
- package/web/assets/chunk-J5EP6P6S-DxWW0yvu.js +0 -1
- package/web/assets/chunk-KGYTTC2M-C6PHeuay.js +0 -1
- package/web/assets/chunk-RERM46MO-DQNbXtfw.js +0 -1
- package/web/assets/chunk-RKZBBQEN-BmTPLSyv.js +0 -1
- package/web/assets/chunk-RLI5ZMPA-DExu2DOK.js +0 -1
- package/web/assets/chunk-T5OCTHI4--9wWpVws.js +0 -1
- package/web/assets/chunk-UP6H54XL-DsKdC6jC.js +0 -1
- package/web/assets/chunk-UXSXWOXI-DR81EqLr.js +0 -1
- package/web/assets/classDiagram-KGZ6W3CR-Bv93af_b.js +0 -1
- package/web/assets/classDiagram-v2-72OJOZXJ-CLfEqHUa.js +0 -1
- package/web/assets/dagre-ND4H6XIP-DsIr9MOv.js +0 -4
- package/web/assets/diagram-3NCE3AQN-BqAtKUpW.js +0 -43
- package/web/assets/diagram-GF46GFSD-CaBG6n6o.js +0 -24
- package/web/assets/diagram-QXG6HAR7-CZ-O3rcV.js +0 -24
- package/web/assets/diagram-WEQXMOUZ-P4lSL4GH.js +0 -10
- package/web/assets/eventmodeling-FCH6USID-MREXMVOE-B3myHUst.js +0 -1
- package/web/assets/gitGraph-WXDBUCRP-R675I2BI-DF3rtf4A.js +0 -1
- package/web/assets/gitGraphDiagram-S2ZK5IYY-CCwVLT__.js +0 -106
- package/web/assets/index-BKWA-m7o.css +0 -2
- package/web/assets/index-CG6q8eTs.js +0 -626
- package/web/assets/info-J43DQDTF-KCYPFFUO-R4XV_akJ.js +0 -1
- package/web/assets/infoDiagram-3YFTVSEB-DmLICZx1.js +0 -2
- package/web/assets/packet-YPE3B663-LP52Z2RK-CgQPdNZa.js +0 -1
- package/web/assets/pie-LRSECV5Y-TCRJHUBD-BzWOwc_c.js +0 -1
- package/web/assets/radar-GUYGQ44K-RDLRG3WG-B7KG0FN7.js +0 -1
- package/web/assets/stateDiagram-7D4R322I-CB2nABwH.js +0 -1
- package/web/assets/stateDiagram-v2-36443NZ5-COBGd2RL.js +0 -1
- package/web/assets/treeView-BLDUP644-QA4HXRO3-CRSxEwLO.js +0 -1
- package/web/assets/treemap-LRROVOQU-LLAWBHMP-a0PfKoVn.js +0 -1
- package/web/assets/wardley-L42UT6IY-5TKZOOLJ-BKQ6e5mC.js +0 -1
- /package/web/assets/{chunk-AQ6EADP3-CCFje6lL.js → chunk-AQ6EADP3-CZhslHi-.js} +0 -0
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Post-dominators (#2085 M5 U2) — the immediate-post-dominator tree of one
|
|
3
|
+
* function's CFG, the substrate the Ferrante control-dependence pass walks.
|
|
4
|
+
*
|
|
5
|
+
* A block `p` post-dominates a block `b` iff every path from `b` to the
|
|
6
|
+
* function EXIT passes through `p`. Post-dominators are exactly the DOMINATORS
|
|
7
|
+
* of the REVERSE CFG rooted at EXIT, so this is the Cooper–Harvey–Kennedy
|
|
8
|
+
* "A Simple, Fast Dominance Algorithm" run over reversed edges. KTD2 of the M5
|
|
9
|
+
* plan picks CHK over Lengauer–Tarjan: per-function CFGs are small and
|
|
10
|
+
* line-capped, CHK is near-linear in practice, and its iterative shape matches
|
|
11
|
+
* the reaching-defs fixpoint already in this module.
|
|
12
|
+
*
|
|
13
|
+
* PURE AND DETERMINISTIC (load-bearing, mirrors reaching-defs.ts): no graph, no
|
|
14
|
+
* logger, importable outside the worker; predecessors/successors are sorted and
|
|
15
|
+
* iteration is reverse-postorder so the `ipdom` array is identical across runs
|
|
16
|
+
* (snapshot tests and content-derived edge ids depend on it).
|
|
17
|
+
*
|
|
18
|
+
* The single-EXIT invariant the M1 TS visitor preserves (visitors/typescript.ts)
|
|
19
|
+
* makes EXIT the unique reverse-CFG root. Blocks that cannot reach EXIT in the
|
|
20
|
+
* forward CFG (an exit-less infinite loop) are not reverse-reachable from it and
|
|
21
|
+
* have NO post-dominator: their `ipdom` is {@link NO_IPDOM}. The control-
|
|
22
|
+
* dependence pass treats "no post-dominator" as "does not post-dominate" (KTD5).
|
|
23
|
+
*
|
|
24
|
+
* NOTE (issue #2188 F2): this is NOT a fully sound over-approximation. Inside a
|
|
25
|
+
* region where NO block reaches EXIT, every `ipdom` is `NO_IPDOM`, so the
|
|
26
|
+
* Ferrante walk degenerates to one edge per control point — it can both DROP a
|
|
27
|
+
* real control dependence and INVENT a spurious one. This does not arise for the
|
|
28
|
+
* current TS visitor (every loop is given a structural `header → loopExit`
|
|
29
|
+
* `cond-false` edge, so EXIT stays reverse-reachable), but it is unsound for
|
|
30
|
+
* hand-built CFGs and any future language visitor lacking that exit edge.
|
|
31
|
+
* Nontermination-sensitive post-dominance (a virtual root over the
|
|
32
|
+
* non-terminating SCCs) would be the correct treatment — tracked for follow-up.
|
|
33
|
+
*/
|
|
34
|
+
import type { FunctionCfg } from './types.js';
|
|
35
|
+
/**
|
|
36
|
+
* Sentinel `ipdom` value: the block has no immediate post-dominator. True for
|
|
37
|
+
* the EXIT block itself (the reverse-CFG root) and for any block that cannot
|
|
38
|
+
* reach EXIT. Chosen as -1 so the {@link postDominates} climb terminates
|
|
39
|
+
* naturally instead of self-looping on the root.
|
|
40
|
+
*/
|
|
41
|
+
export declare const NO_IPDOM = -1;
|
|
42
|
+
export interface PostDomTree {
|
|
43
|
+
/**
|
|
44
|
+
* `ipdom[b]` = the index of `b`'s immediate post-dominator, or
|
|
45
|
+
* {@link NO_IPDOM} when `b` has none (EXIT, or a block that cannot reach EXIT).
|
|
46
|
+
*/
|
|
47
|
+
readonly ipdom: readonly number[];
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Compute the immediate-post-dominator tree for one function's CFG. See the
|
|
51
|
+
* module doc for the purity/determinism contract and EXIT-root assumptions.
|
|
52
|
+
*/
|
|
53
|
+
export declare function computePostDominators(cfg: FunctionCfg): PostDomTree;
|
|
54
|
+
/**
|
|
55
|
+
* Does block `p` post-dominate block `b`? Climbs the post-dom tree from `b`
|
|
56
|
+
* toward EXIT and tests membership of `p`. Reflexive: a block post-dominates
|
|
57
|
+
* itself. A block with no post-dominator (EXIT, or one that cannot reach EXIT)
|
|
58
|
+
* is post-dominated only by itself. The step guard is purely defensive — the
|
|
59
|
+
* `ipdom` chain is a tree and always terminates at {@link NO_IPDOM}.
|
|
60
|
+
*/
|
|
61
|
+
export declare function postDominates(tree: PostDomTree, p: number, b: number): boolean;
|
|
62
|
+
/**
|
|
63
|
+
* Precondition for SOUND post-dominance (#2188 review): EXIT must be reachable
|
|
64
|
+
* (forward) from every block that is itself reachable from ENTRY. When it
|
|
65
|
+
* fails — an entry-reachable region that cannot reach EXIT, e.g. a
|
|
66
|
+
* non-terminating loop or a multi-terminal CFG a future language visitor might
|
|
67
|
+
* emit — the EXIT-rooted reverse walk degenerates (every such block gets
|
|
68
|
+
* {@link NO_IPDOM}), which both DROPS real control dependences and INVENTS
|
|
69
|
+
* spurious ones (the unsoundness documented in the module header). Consumers
|
|
70
|
+
* ({@link emitFileCdg}) check this and skip CDG for the function rather than
|
|
71
|
+
* persist an unsound projection — CFG and REACHING_DEF, which do not depend on
|
|
72
|
+
* post-dominance, are unaffected.
|
|
73
|
+
*
|
|
74
|
+
* The current TS visitor always satisfies this (every loop is given a
|
|
75
|
+
* structural `header → loopExit` edge, keeping EXIT reverse-reachable), so this
|
|
76
|
+
* is a guard for future visitors and hand-built CFGs, not a behavior change
|
|
77
|
+
* today. Pure and O(V+E).
|
|
78
|
+
*/
|
|
79
|
+
export declare function isExitReachableFromAllBlocks(cfg: FunctionCfg): boolean;
|
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Sentinel `ipdom` value: the block has no immediate post-dominator. True for
|
|
3
|
+
* the EXIT block itself (the reverse-CFG root) and for any block that cannot
|
|
4
|
+
* reach EXIT. Chosen as -1 so the {@link postDominates} climb terminates
|
|
5
|
+
* naturally instead of self-looping on the root.
|
|
6
|
+
*/
|
|
7
|
+
export const NO_IPDOM = -1;
|
|
8
|
+
/**
|
|
9
|
+
* Compute the immediate-post-dominator tree for one function's CFG. See the
|
|
10
|
+
* module doc for the purity/determinism contract and EXIT-root assumptions.
|
|
11
|
+
*/
|
|
12
|
+
export function computePostDominators(cfg) {
|
|
13
|
+
const n = cfg.blocks.length;
|
|
14
|
+
const exit = cfg.exitIndex;
|
|
15
|
+
if (n === 0 || exit < 0 || exit >= n) {
|
|
16
|
+
return { ipdom: new Array(n).fill(NO_IPDOM) };
|
|
17
|
+
}
|
|
18
|
+
// Forward adjacency (sorted for deterministic intersect order). The reverse
|
|
19
|
+
// CFG, on which we compute dominators, flips these: a node's reverse-CFG
|
|
20
|
+
// successors are its CFG predecessors, and its reverse-CFG predecessors
|
|
21
|
+
// (the "preds" CHK intersects over) are its CFG successors.
|
|
22
|
+
const cfgPreds = Array.from({ length: n }, () => []);
|
|
23
|
+
const cfgSuccs = Array.from({ length: n }, () => []);
|
|
24
|
+
for (const e of cfg.edges) {
|
|
25
|
+
if (e.from < 0 || e.from >= n || e.to < 0 || e.to >= n)
|
|
26
|
+
continue;
|
|
27
|
+
cfgSuccs[e.from].push(e.to);
|
|
28
|
+
cfgPreds[e.to].push(e.from);
|
|
29
|
+
}
|
|
30
|
+
for (const l of cfgPreds)
|
|
31
|
+
l.sort((a, b) => a - b);
|
|
32
|
+
for (const l of cfgSuccs)
|
|
33
|
+
l.sort((a, b) => a - b);
|
|
34
|
+
// Postorder of the reverse CFG from EXIT (traversing CFG-predecessor edges).
|
|
35
|
+
// Iterative DFS with an explicit phase stack; children pushed in sorted order
|
|
36
|
+
// for determinism. postNum is the CHK comparison key: higher = closer to root.
|
|
37
|
+
const postNum = new Array(n).fill(-1);
|
|
38
|
+
const postorder = [];
|
|
39
|
+
const visited = new Array(n).fill(false);
|
|
40
|
+
const stack = [{ node: exit, childIdx: 0 }];
|
|
41
|
+
visited[exit] = true;
|
|
42
|
+
while (stack.length) {
|
|
43
|
+
const top = stack[stack.length - 1];
|
|
44
|
+
const revSuccs = cfgPreds[top.node]; // reverse-CFG successors
|
|
45
|
+
if (top.childIdx < revSuccs.length) {
|
|
46
|
+
const next = revSuccs[top.childIdx];
|
|
47
|
+
top.childIdx += 1;
|
|
48
|
+
if (!visited[next]) {
|
|
49
|
+
visited[next] = true;
|
|
50
|
+
stack.push({ node: next, childIdx: 0 });
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
else {
|
|
54
|
+
postNum[top.node] = postorder.length;
|
|
55
|
+
postorder.push(top.node);
|
|
56
|
+
stack.pop();
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
const rpo = [...postorder].reverse();
|
|
60
|
+
// CHK fixpoint. ipdom[exit] = exit DURING computation (the root dominates
|
|
61
|
+
// itself, so the intersect climb has a common terminus); it is reset to
|
|
62
|
+
// NO_IPDOM before returning so callers' climbs terminate at the root.
|
|
63
|
+
const ipdom = new Array(n).fill(NO_IPDOM);
|
|
64
|
+
ipdom[exit] = exit;
|
|
65
|
+
const intersect = (a, b) => {
|
|
66
|
+
let f1 = a;
|
|
67
|
+
let f2 = b;
|
|
68
|
+
while (f1 !== f2) {
|
|
69
|
+
while (postNum[f1] < postNum[f2])
|
|
70
|
+
f1 = ipdom[f1];
|
|
71
|
+
while (postNum[f2] < postNum[f1])
|
|
72
|
+
f2 = ipdom[f2];
|
|
73
|
+
}
|
|
74
|
+
return f1;
|
|
75
|
+
};
|
|
76
|
+
let changed = true;
|
|
77
|
+
while (changed) {
|
|
78
|
+
changed = false;
|
|
79
|
+
for (const b of rpo) {
|
|
80
|
+
if (b === exit)
|
|
81
|
+
continue;
|
|
82
|
+
// CHK "predecessors in the reverse CFG" = this block's CFG successors.
|
|
83
|
+
// Fold only those already processed (ipdom assigned); RPO guarantees at
|
|
84
|
+
// least one for every block reverse-reachable from EXIT.
|
|
85
|
+
let newIpdom = NO_IPDOM;
|
|
86
|
+
for (const s of cfgSuccs[b]) {
|
|
87
|
+
if (ipdom[s] !== NO_IPDOM) {
|
|
88
|
+
newIpdom = newIpdom === NO_IPDOM ? s : intersect(s, newIpdom);
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
if (newIpdom !== NO_IPDOM && ipdom[b] !== newIpdom) {
|
|
92
|
+
ipdom[b] = newIpdom;
|
|
93
|
+
changed = true;
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
ipdom[exit] = NO_IPDOM; // root: no post-dominator above it
|
|
98
|
+
return { ipdom };
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* Does block `p` post-dominate block `b`? Climbs the post-dom tree from `b`
|
|
102
|
+
* toward EXIT and tests membership of `p`. Reflexive: a block post-dominates
|
|
103
|
+
* itself. A block with no post-dominator (EXIT, or one that cannot reach EXIT)
|
|
104
|
+
* is post-dominated only by itself. The step guard is purely defensive — the
|
|
105
|
+
* `ipdom` chain is a tree and always terminates at {@link NO_IPDOM}.
|
|
106
|
+
*/
|
|
107
|
+
export function postDominates(tree, p, b) {
|
|
108
|
+
const { ipdom } = tree;
|
|
109
|
+
const n = ipdom.length;
|
|
110
|
+
if (p < 0 || b < 0 || p >= n || b >= n)
|
|
111
|
+
return false;
|
|
112
|
+
let cur = b;
|
|
113
|
+
let steps = 0;
|
|
114
|
+
while (cur !== NO_IPDOM && steps <= n) {
|
|
115
|
+
if (cur === p)
|
|
116
|
+
return true;
|
|
117
|
+
cur = ipdom[cur];
|
|
118
|
+
steps += 1;
|
|
119
|
+
}
|
|
120
|
+
return false;
|
|
121
|
+
}
|
|
122
|
+
/**
|
|
123
|
+
* Precondition for SOUND post-dominance (#2188 review): EXIT must be reachable
|
|
124
|
+
* (forward) from every block that is itself reachable from ENTRY. When it
|
|
125
|
+
* fails — an entry-reachable region that cannot reach EXIT, e.g. a
|
|
126
|
+
* non-terminating loop or a multi-terminal CFG a future language visitor might
|
|
127
|
+
* emit — the EXIT-rooted reverse walk degenerates (every such block gets
|
|
128
|
+
* {@link NO_IPDOM}), which both DROPS real control dependences and INVENTS
|
|
129
|
+
* spurious ones (the unsoundness documented in the module header). Consumers
|
|
130
|
+
* ({@link emitFileCdg}) check this and skip CDG for the function rather than
|
|
131
|
+
* persist an unsound projection — CFG and REACHING_DEF, which do not depend on
|
|
132
|
+
* post-dominance, are unaffected.
|
|
133
|
+
*
|
|
134
|
+
* The current TS visitor always satisfies this (every loop is given a
|
|
135
|
+
* structural `header → loopExit` edge, keeping EXIT reverse-reachable), so this
|
|
136
|
+
* is a guard for future visitors and hand-built CFGs, not a behavior change
|
|
137
|
+
* today. Pure and O(V+E).
|
|
138
|
+
*/
|
|
139
|
+
export function isExitReachableFromAllBlocks(cfg) {
|
|
140
|
+
const n = cfg.blocks.length;
|
|
141
|
+
if (n === 0)
|
|
142
|
+
return true;
|
|
143
|
+
const { entryIndex, exitIndex } = cfg;
|
|
144
|
+
if (entryIndex < 0 || entryIndex >= n || exitIndex < 0 || exitIndex >= n)
|
|
145
|
+
return false;
|
|
146
|
+
const succ = Array.from({ length: n }, () => []);
|
|
147
|
+
const pred = Array.from({ length: n }, () => []);
|
|
148
|
+
for (const e of cfg.edges) {
|
|
149
|
+
if (e.from < 0 || e.from >= n || e.to < 0 || e.to >= n)
|
|
150
|
+
continue;
|
|
151
|
+
succ[e.from].push(e.to);
|
|
152
|
+
pred[e.to].push(e.from);
|
|
153
|
+
}
|
|
154
|
+
const reach = (start, adj) => {
|
|
155
|
+
const seen = new Uint8Array(n);
|
|
156
|
+
const stack = [start];
|
|
157
|
+
seen[start] = 1;
|
|
158
|
+
while (stack.length > 0) {
|
|
159
|
+
const b = stack.pop();
|
|
160
|
+
for (const next of adj[b]) {
|
|
161
|
+
if (!seen[next]) {
|
|
162
|
+
seen[next] = 1;
|
|
163
|
+
stack.push(next);
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
return seen;
|
|
168
|
+
};
|
|
169
|
+
const fromEntry = reach(entryIndex, succ); // forward-reachable from ENTRY
|
|
170
|
+
const canReachExit = reach(exitIndex, pred); // can reach EXIT (reverse from EXIT)
|
|
171
|
+
for (let i = 0; i < n; i++) {
|
|
172
|
+
if (fromEntry[i] && !canReachExit[i])
|
|
173
|
+
return false;
|
|
174
|
+
}
|
|
175
|
+
return true;
|
|
176
|
+
}
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* REACHING_DEF reason codec (PDG FU-B-2) — the ONE shared encoder/decoder for
|
|
3
|
+
* the source-level annotation carried on a persisted `REACHING_DEF` edge's
|
|
4
|
+
* `reason` column.
|
|
5
|
+
*
|
|
6
|
+
* A `REACHING_DEF` edge is `(defBlock:BasicBlock)->(useBlock:BasicBlock)` for one
|
|
7
|
+
* binding. The persisted columns (`from,to,type,confidence,reason,step`) are
|
|
8
|
+
* DEDUPED to `(defBlock, useBlock, bindingIdx)` (emit.ts), so the persisted
|
|
9
|
+
* edge cannot, by itself, recover the def→use chain WITHIN a coalesced
|
|
10
|
+
* straight-line BasicBlock: lines 7-9 of `chainCompute` collapse to one block
|
|
11
|
+
* and `a@7 -> b@8 -> c@9` become block-self edges with no line information. This
|
|
12
|
+
* codec ANNOTATES each edge with the ORDERED LIST of (defLine, useLine) source
|
|
13
|
+
* lines for that (block-pair, binding) group — the full set of def→use steps the
|
|
14
|
+
* solver produced for it — so the statement-granular intra-block chain is
|
|
15
|
+
* recoverable at projection time (pdg-impact.ts) WITHOUT widening the dedup key:
|
|
16
|
+
* the edge COUNT is unchanged (still one edge per group), only the `reason`
|
|
17
|
+
* carries the pair LIST (RD/taint substrate + cfg-bench budgets protected — the
|
|
18
|
+
* cfg-bench canon does not include the persisted `reason`).
|
|
19
|
+
*
|
|
20
|
+
* Carrying the FULL list (not just the FIRST pair) is what makes a SAME-BINDING
|
|
21
|
+
* reassignment chain recoverable: `acc = f(acc); acc = g(acc); acc = h(acc)`
|
|
22
|
+
* coalesces into one block, and ALL of `acc@24->acc@25`, `acc@25->acc@26`,
|
|
23
|
+
* `acc@26->acc@27` share the one `(self-block, self-block, accIdx)` group. A
|
|
24
|
+
* first-pair-only annotation could chain `24->25` but never reach `26`; the full
|
|
25
|
+
* list lets the projection walk the whole chain to fixpoint.
|
|
26
|
+
*
|
|
27
|
+
* ## Wire format (version `1`)
|
|
28
|
+
*
|
|
29
|
+
* ```
|
|
30
|
+
* <name> (legacy / pre-FU-B-2 — bare name)
|
|
31
|
+
* <name>|1:<d1>:<u1> (FU-B-2, single pair)
|
|
32
|
+
* <name>|1:<d1>:<u1>;<d2>:<u2>;... (FU-B-2, ordered pair LIST)
|
|
33
|
+
* ```
|
|
34
|
+
*
|
|
35
|
+
* The binding NAME comes FIRST, verbatim, so the established read paths keep
|
|
36
|
+
* working with a trivial change: `pdg_query` mode:'flows' filters the variable
|
|
37
|
+
* by `r.reason = $variable OR r.reason STARTS WITH $variable|` and projects the
|
|
38
|
+
* name via {@link decodeReachingDefReason}. Source identifiers never contain `|`
|
|
39
|
+
* (the structural separator), so the name is unambiguously the substring before
|
|
40
|
+
* the first `|`; an un-annotated reason has no `|` and decodes to itself with no
|
|
41
|
+
* line info. Within the annotation, `;` separates pairs and `:` separates the
|
|
42
|
+
* version + the two lines of each pair. `<defLine>`/`<useLine>` are 1-based
|
|
43
|
+
* decimal source lines.
|
|
44
|
+
*
|
|
45
|
+
* ## Delimiter / round-trip discipline (mirrors call-summary-codec KTD6)
|
|
46
|
+
*
|
|
47
|
+
* Every structural character (`|`, `:`, `;`, the version digit, decimal digits)
|
|
48
|
+
* is printable ASCII, so the encoding survives `escapeCSVField ∘ sanitizeUTF8`
|
|
49
|
+
* (csv-generator.ts) byte-exact. The decoder NEVER throws — anything not a
|
|
50
|
+
* well-formed version-`1` annotation degrades to "name only, no pairs" (the sound
|
|
51
|
+
* default: the projection then falls back to block-start granularity exactly as
|
|
52
|
+
* before FU-B-2). A malformed individual pair within an otherwise-well-formed
|
|
53
|
+
* list is dropped; the well-formed pairs are kept.
|
|
54
|
+
*/
|
|
55
|
+
/** One-character format version prefix. Bump on any wire-format change. */
|
|
56
|
+
export declare const REACHING_DEF_REASON_CODEC_VERSION = "1";
|
|
57
|
+
/** One def→use source-line step within a coalesced block's self chain. */
|
|
58
|
+
export interface DefUseLinePair {
|
|
59
|
+
/** 1-based def source line. */
|
|
60
|
+
readonly defLine: number;
|
|
61
|
+
/** 1-based use source line. */
|
|
62
|
+
readonly useLine: number;
|
|
63
|
+
}
|
|
64
|
+
/** A decoded REACHING_DEF reason. `pairs` is empty for a legacy (un-annotated)
|
|
65
|
+
* reason. `defLine`/`useLine` mirror the FIRST pair for back-compat consumers. */
|
|
66
|
+
export interface DecodedReachingDefReason {
|
|
67
|
+
/** The source-level binding name (always present — the legacy payload). */
|
|
68
|
+
readonly name: string;
|
|
69
|
+
/**
|
|
70
|
+
* The ordered list of (defLine, useLine) steps the FU-B-2 annotation carries.
|
|
71
|
+
* Empty for a legacy / malformed / un-annotated reason.
|
|
72
|
+
*/
|
|
73
|
+
readonly pairs: readonly DefUseLinePair[];
|
|
74
|
+
/** 1-based def source line of the FIRST pair (back-compat; absent if none). */
|
|
75
|
+
readonly defLine?: number;
|
|
76
|
+
/** 1-based use source line of the FIRST pair (back-compat; absent if none). */
|
|
77
|
+
readonly useLine?: number;
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Encode a binding name + its ordered (defLine, useLine) step list into the
|
|
81
|
+
* versioned `reason` wire string. Deterministic; never throws. Malformed /
|
|
82
|
+
* negative pairs are dropped (defensive — the solver always passes 1-based
|
|
83
|
+
* integers); if NO valid pair survives the result degrades to the bare name
|
|
84
|
+
* (legacy form) so a malformed annotation never fabricates bad lines. The name
|
|
85
|
+
* is written verbatim FIRST (see the module doc), so a name that —
|
|
86
|
+
* pathologically — already contains `|` would be re-decoded with a truncated
|
|
87
|
+
* name; binding names are source identifiers, which never contain `|`, so this
|
|
88
|
+
* cannot occur for real input (and would only lose line precision, never corrupt
|
|
89
|
+
* the substrate).
|
|
90
|
+
*/
|
|
91
|
+
export declare function encodeReachingDefReasonPairs(name: string, pairs: ReadonlyArray<DefUseLinePair>): string;
|
|
92
|
+
/**
|
|
93
|
+
* Single-pair convenience over {@link encodeReachingDefReasonPairs} — kept for
|
|
94
|
+
* call sites and tests that carry exactly one def→use step.
|
|
95
|
+
*/
|
|
96
|
+
export declare function encodeReachingDefReason(name: string, defLine: number, useLine: number): string;
|
|
97
|
+
/**
|
|
98
|
+
* Decode a REACHING_DEF `reason` wire string into its binding name + (when
|
|
99
|
+
* present) the FU-B-2 def/use source-line pair LIST. Never throws — a non-string,
|
|
100
|
+
* an un-annotated bare name, or a malformed annotation all yield `{ name, pairs:
|
|
101
|
+
* [] }` (the sound default: the consumer falls back to block-start granularity).
|
|
102
|
+
* A well-formed `<name>|1:<d1>:<u1>;<d2>:<u2>;...` yields every well-formed pair
|
|
103
|
+
* (a single malformed pair is dropped, the rest kept); `defLine`/`useLine` mirror
|
|
104
|
+
* the first pair for back-compat consumers.
|
|
105
|
+
*/
|
|
106
|
+
export declare function decodeReachingDefReason(reason: unknown): DecodedReachingDefReason;
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* REACHING_DEF reason codec (PDG FU-B-2) — the ONE shared encoder/decoder for
|
|
3
|
+
* the source-level annotation carried on a persisted `REACHING_DEF` edge's
|
|
4
|
+
* `reason` column.
|
|
5
|
+
*
|
|
6
|
+
* A `REACHING_DEF` edge is `(defBlock:BasicBlock)->(useBlock:BasicBlock)` for one
|
|
7
|
+
* binding. The persisted columns (`from,to,type,confidence,reason,step`) are
|
|
8
|
+
* DEDUPED to `(defBlock, useBlock, bindingIdx)` (emit.ts), so the persisted
|
|
9
|
+
* edge cannot, by itself, recover the def→use chain WITHIN a coalesced
|
|
10
|
+
* straight-line BasicBlock: lines 7-9 of `chainCompute` collapse to one block
|
|
11
|
+
* and `a@7 -> b@8 -> c@9` become block-self edges with no line information. This
|
|
12
|
+
* codec ANNOTATES each edge with the ORDERED LIST of (defLine, useLine) source
|
|
13
|
+
* lines for that (block-pair, binding) group — the full set of def→use steps the
|
|
14
|
+
* solver produced for it — so the statement-granular intra-block chain is
|
|
15
|
+
* recoverable at projection time (pdg-impact.ts) WITHOUT widening the dedup key:
|
|
16
|
+
* the edge COUNT is unchanged (still one edge per group), only the `reason`
|
|
17
|
+
* carries the pair LIST (RD/taint substrate + cfg-bench budgets protected — the
|
|
18
|
+
* cfg-bench canon does not include the persisted `reason`).
|
|
19
|
+
*
|
|
20
|
+
* Carrying the FULL list (not just the FIRST pair) is what makes a SAME-BINDING
|
|
21
|
+
* reassignment chain recoverable: `acc = f(acc); acc = g(acc); acc = h(acc)`
|
|
22
|
+
* coalesces into one block, and ALL of `acc@24->acc@25`, `acc@25->acc@26`,
|
|
23
|
+
* `acc@26->acc@27` share the one `(self-block, self-block, accIdx)` group. A
|
|
24
|
+
* first-pair-only annotation could chain `24->25` but never reach `26`; the full
|
|
25
|
+
* list lets the projection walk the whole chain to fixpoint.
|
|
26
|
+
*
|
|
27
|
+
* ## Wire format (version `1`)
|
|
28
|
+
*
|
|
29
|
+
* ```
|
|
30
|
+
* <name> (legacy / pre-FU-B-2 — bare name)
|
|
31
|
+
* <name>|1:<d1>:<u1> (FU-B-2, single pair)
|
|
32
|
+
* <name>|1:<d1>:<u1>;<d2>:<u2>;... (FU-B-2, ordered pair LIST)
|
|
33
|
+
* ```
|
|
34
|
+
*
|
|
35
|
+
* The binding NAME comes FIRST, verbatim, so the established read paths keep
|
|
36
|
+
* working with a trivial change: `pdg_query` mode:'flows' filters the variable
|
|
37
|
+
* by `r.reason = $variable OR r.reason STARTS WITH $variable|` and projects the
|
|
38
|
+
* name via {@link decodeReachingDefReason}. Source identifiers never contain `|`
|
|
39
|
+
* (the structural separator), so the name is unambiguously the substring before
|
|
40
|
+
* the first `|`; an un-annotated reason has no `|` and decodes to itself with no
|
|
41
|
+
* line info. Within the annotation, `;` separates pairs and `:` separates the
|
|
42
|
+
* version + the two lines of each pair. `<defLine>`/`<useLine>` are 1-based
|
|
43
|
+
* decimal source lines.
|
|
44
|
+
*
|
|
45
|
+
* ## Delimiter / round-trip discipline (mirrors call-summary-codec KTD6)
|
|
46
|
+
*
|
|
47
|
+
* Every structural character (`|`, `:`, `;`, the version digit, decimal digits)
|
|
48
|
+
* is printable ASCII, so the encoding survives `escapeCSVField ∘ sanitizeUTF8`
|
|
49
|
+
* (csv-generator.ts) byte-exact. The decoder NEVER throws — anything not a
|
|
50
|
+
* well-formed version-`1` annotation degrades to "name only, no pairs" (the sound
|
|
51
|
+
* default: the projection then falls back to block-start granularity exactly as
|
|
52
|
+
* before FU-B-2). A malformed individual pair within an otherwise-well-formed
|
|
53
|
+
* list is dropped; the well-formed pairs are kept.
|
|
54
|
+
*/
|
|
55
|
+
/** One-character format version prefix. Bump on any wire-format change. */
|
|
56
|
+
export const REACHING_DEF_REASON_CODEC_VERSION = '1';
|
|
57
|
+
/**
|
|
58
|
+
* Structural separator between the binding name and the versioned annotation.
|
|
59
|
+
* Source identifiers cannot contain it, so the name is the substring before the
|
|
60
|
+
* first occurrence (and a name with no occurrence is a legacy bare-name reason).
|
|
61
|
+
*/
|
|
62
|
+
const NAME_SEP = '|';
|
|
63
|
+
/** Separator between consecutive (defLine:useLine) pairs in the annotation. */
|
|
64
|
+
const PAIR_SEP = ';';
|
|
65
|
+
/** Whether a (defLine, useLine) pair is a well-formed 1-based-or-0 integer pair. */
|
|
66
|
+
function isValidPair(defLine, useLine) {
|
|
67
|
+
return Number.isInteger(defLine) && Number.isInteger(useLine) && defLine >= 0 && useLine >= 0;
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Encode a binding name + its ordered (defLine, useLine) step list into the
|
|
71
|
+
* versioned `reason` wire string. Deterministic; never throws. Malformed /
|
|
72
|
+
* negative pairs are dropped (defensive — the solver always passes 1-based
|
|
73
|
+
* integers); if NO valid pair survives the result degrades to the bare name
|
|
74
|
+
* (legacy form) so a malformed annotation never fabricates bad lines. The name
|
|
75
|
+
* is written verbatim FIRST (see the module doc), so a name that —
|
|
76
|
+
* pathologically — already contains `|` would be re-decoded with a truncated
|
|
77
|
+
* name; binding names are source identifiers, which never contain `|`, so this
|
|
78
|
+
* cannot occur for real input (and would only lose line precision, never corrupt
|
|
79
|
+
* the substrate).
|
|
80
|
+
*/
|
|
81
|
+
export function encodeReachingDefReasonPairs(name, pairs) {
|
|
82
|
+
const valid = pairs.filter((p) => isValidPair(p.defLine, p.useLine));
|
|
83
|
+
if (valid.length === 0)
|
|
84
|
+
return name;
|
|
85
|
+
const body = valid.map((p) => `${p.defLine}:${p.useLine}`).join(PAIR_SEP);
|
|
86
|
+
return `${name}${NAME_SEP}${REACHING_DEF_REASON_CODEC_VERSION}:${body}`;
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* Single-pair convenience over {@link encodeReachingDefReasonPairs} — kept for
|
|
90
|
+
* call sites and tests that carry exactly one def→use step.
|
|
91
|
+
*/
|
|
92
|
+
export function encodeReachingDefReason(name, defLine, useLine) {
|
|
93
|
+
return encodeReachingDefReasonPairs(name, [{ defLine, useLine }]);
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* Decode a REACHING_DEF `reason` wire string into its binding name + (when
|
|
97
|
+
* present) the FU-B-2 def/use source-line pair LIST. Never throws — a non-string,
|
|
98
|
+
* an un-annotated bare name, or a malformed annotation all yield `{ name, pairs:
|
|
99
|
+
* [] }` (the sound default: the consumer falls back to block-start granularity).
|
|
100
|
+
* A well-formed `<name>|1:<d1>:<u1>;<d2>:<u2>;...` yields every well-formed pair
|
|
101
|
+
* (a single malformed pair is dropped, the rest kept); `defLine`/`useLine` mirror
|
|
102
|
+
* the first pair for back-compat consumers.
|
|
103
|
+
*/
|
|
104
|
+
export function decodeReachingDefReason(reason) {
|
|
105
|
+
const raw = typeof reason === 'string' ? reason : '';
|
|
106
|
+
const sep = raw.indexOf(NAME_SEP);
|
|
107
|
+
if (sep === -1)
|
|
108
|
+
return { name: raw, pairs: [] };
|
|
109
|
+
const name = raw.slice(0, sep);
|
|
110
|
+
const annotation = raw.slice(sep + 1);
|
|
111
|
+
// Annotation is `<version>:<d1>:<u1>;<d2>:<u2>;...`. Split off the version
|
|
112
|
+
// prefix once: the first colon ends the version token; the remainder is the
|
|
113
|
+
// `;`-separated pair body.
|
|
114
|
+
const firstColon = annotation.indexOf(':');
|
|
115
|
+
if (firstColon === -1 || annotation.slice(0, firstColon) !== REACHING_DEF_REASON_CODEC_VERSION) {
|
|
116
|
+
return { name, pairs: [] };
|
|
117
|
+
}
|
|
118
|
+
const body = annotation.slice(firstColon + 1);
|
|
119
|
+
const pairs = [];
|
|
120
|
+
for (const chunk of body.split(PAIR_SEP)) {
|
|
121
|
+
const parts = chunk.split(':');
|
|
122
|
+
if (parts.length !== 2)
|
|
123
|
+
continue; // malformed pair — drop it, keep the rest
|
|
124
|
+
const defLine = Number(parts[0]);
|
|
125
|
+
const useLine = Number(parts[1]);
|
|
126
|
+
if (!isValidPair(defLine, useLine))
|
|
127
|
+
continue;
|
|
128
|
+
pairs.push({ defLine, useLine });
|
|
129
|
+
}
|
|
130
|
+
if (pairs.length === 0)
|
|
131
|
+
return { name, pairs: [] };
|
|
132
|
+
return { name, pairs, defLine: pairs[0].defLine, useLine: pairs[0].useLine };
|
|
133
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pure graph sub-stages for the reaching-definitions solvers (#2201 review R4).
|
|
3
|
+
*
|
|
4
|
+
* Extracted from reaching-defs.ts to keep that module focused on the
|
|
5
|
+
* orchestrator, the dense oracle, the statement sweep, and the dispatcher.
|
|
6
|
+
* Everything here is a pure function of plain arrays — no CFG, no harvest, no
|
|
7
|
+
* solver state — so this module has NO dependency on reaching-defs.ts (a strict
|
|
8
|
+
* one-way import) and each stage is independently testable. The SSA pipeline
|
|
9
|
+
* (dominators → dominance frontiers → Tarjan SCC → reach-set condensation)
|
|
10
|
+
* implements Cooper-Harvey-Kennedy + Cytron + Tarjan; reverse-post-order, the
|
|
11
|
+
* loop-reachability check, and the def-set/lattice primitives are shared with
|
|
12
|
+
* the dense GEN/KILL solver and the dispatcher.
|
|
13
|
+
*
|
|
14
|
+
* These are held byte-identical to their former inline form by the differential
|
|
15
|
+
* equivalence fuzz (test/unit/cfg/reaching-defs-equivalence.test.ts) — any diff
|
|
16
|
+
* after extraction is an extraction bug, never the oracle.
|
|
17
|
+
*/
|
|
18
|
+
export {};
|