@eagleoutice/flowr 2.2.11 → 2.2.13
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 +82 -20
- package/benchmark/slicer.d.ts +49 -22
- package/benchmark/slicer.js +89 -29
- package/benchmark/stats/print.js +16 -10
- package/benchmark/stats/size-of.js +18 -1
- package/benchmark/stats/stats.d.ts +3 -0
- package/benchmark/summarizer/first-phase/input.js +1 -1
- package/benchmark/summarizer/first-phase/process.js +3 -3
- package/benchmark/summarizer/second-phase/process.js +9 -3
- package/benchmark/summarizer/summarizer.js +1 -1
- package/cli/benchmark-app.d.ts +5 -0
- package/cli/benchmark-app.js +49 -6
- package/cli/benchmark-helper-app.d.ts +4 -0
- package/cli/benchmark-helper-app.js +20 -4
- package/cli/common/options.js +15 -6
- package/cli/common/script.js +1 -1
- package/cli/flowr.js +1 -1
- package/cli/repl/commands/repl-cfg.d.ts +2 -0
- package/cli/repl/commands/repl-cfg.js +38 -24
- package/cli/repl/commands/repl-commands.js +6 -2
- package/cli/repl/commands/repl-dataflow.d.ts +2 -0
- package/cli/repl/commands/repl-dataflow.js +37 -3
- package/cli/repl/commands/repl-execute.js +1 -1
- package/cli/repl/commands/repl-main.d.ts +1 -1
- package/cli/repl/commands/repl-main.js +1 -1
- package/cli/repl/commands/repl-normalize.js +1 -1
- package/cli/repl/commands/repl-query.js +2 -2
- package/cli/repl/core.js +1 -1
- package/cli/repl/prompt.js +1 -1
- package/cli/repl/server/connection.js +4 -4
- package/cli/repl/server/messages/message-analysis.d.ts +1 -1
- package/cli/script-core/statistics-core.js +1 -1
- package/cli/script-core/statistics-helper-core.js +4 -4
- package/config.d.ts +60 -21
- package/config.js +24 -4
- package/control-flow/basic-cfg-guided-visitor.d.ts +39 -0
- package/control-flow/basic-cfg-guided-visitor.js +114 -0
- package/control-flow/cfg-properties.d.ts +26 -0
- package/control-flow/cfg-properties.js +100 -0
- package/control-flow/cfg-simplification.d.ts +18 -0
- package/control-flow/cfg-simplification.js +55 -0
- package/control-flow/cfg-to-basic-blocks.d.ts +5 -0
- package/control-flow/cfg-to-basic-blocks.js +81 -0
- package/control-flow/control-flow-graph.d.ts +247 -0
- package/control-flow/control-flow-graph.js +290 -0
- package/control-flow/dfg-cfg-guided-visitor.d.ts +32 -0
- package/control-flow/dfg-cfg-guided-visitor.js +71 -0
- package/control-flow/diff-cfg.d.ts +11 -0
- package/control-flow/diff-cfg.js +161 -0
- package/control-flow/extract-cfg.d.ts +30 -0
- package/control-flow/extract-cfg.js +475 -0
- package/control-flow/happens-before.d.ts +7 -0
- package/{util/cfg → control-flow}/happens-before.js +3 -3
- package/control-flow/semantic-cfg-guided-visitor.d.ts +452 -0
- package/control-flow/semantic-cfg-guided-visitor.js +492 -0
- package/control-flow/simple-visitor.d.ts +25 -0
- package/control-flow/simple-visitor.js +80 -0
- package/control-flow/syntax-cfg-guided-visitor.d.ts +128 -0
- package/control-flow/syntax-cfg-guided-visitor.js +166 -0
- package/core/print/print.d.ts +1 -1
- package/core/print/slice-diff-ansi.js +1 -1
- package/core/steps/pipeline/create-pipeline.js +1 -1
- package/dataflow/environments/built-in-config.d.ts +5 -2
- package/dataflow/environments/built-in-config.js +17 -8
- package/dataflow/environments/built-in.d.ts +16 -5
- package/dataflow/environments/built-in.js +55 -6
- package/dataflow/environments/clone.d.ts +5 -0
- package/dataflow/environments/clone.js +5 -0
- package/dataflow/environments/default-builtin-config.d.ts +2 -0
- package/dataflow/environments/default-builtin-config.js +164 -13
- package/dataflow/environments/define.d.ts +5 -1
- package/dataflow/environments/define.js +36 -10
- package/dataflow/environments/overwrite.js +4 -0
- package/dataflow/environments/remove.d.ts +6 -0
- package/dataflow/environments/remove.js +24 -0
- package/dataflow/environments/resolve-by-name.js +16 -5
- package/dataflow/extractor.js +2 -2
- package/dataflow/graph/dataflowgraph-builder.d.ts +79 -7
- package/dataflow/graph/dataflowgraph-builder.js +106 -8
- package/dataflow/graph/diff-dataflow-graph.d.ts +16 -0
- package/dataflow/graph/{diff.js → diff-dataflow-graph.js} +30 -56
- package/dataflow/graph/graph.d.ts +17 -4
- package/dataflow/graph/graph.js +51 -12
- package/dataflow/graph/vertex.d.ts +59 -4
- package/dataflow/graph/vertex.js +32 -0
- package/dataflow/internal/linker.d.ts +3 -2
- package/dataflow/internal/linker.js +36 -25
- package/dataflow/internal/process/functions/call/argument/unpack-argument.d.ts +1 -1
- package/dataflow/internal/process/functions/call/argument/unpack-argument.js +1 -1
- package/dataflow/internal/process/functions/call/built-in/built-in-access.d.ts +1 -0
- package/dataflow/internal/process/functions/call/built-in/built-in-access.js +67 -54
- package/dataflow/internal/process/functions/call/built-in/built-in-apply.d.ts +6 -4
- package/dataflow/internal/process/functions/call/built-in/built-in-apply.js +108 -21
- package/dataflow/internal/process/functions/call/built-in/built-in-assignment.js +54 -17
- package/dataflow/internal/process/functions/call/built-in/built-in-eval.d.ts +10 -0
- package/dataflow/internal/process/functions/call/built-in/built-in-eval.js +140 -0
- package/dataflow/internal/process/functions/call/built-in/built-in-expression-list.js +9 -4
- package/dataflow/internal/process/functions/call/built-in/built-in-for-loop.js +3 -2
- package/dataflow/internal/process/functions/call/built-in/built-in-function-definition.js +15 -4
- package/dataflow/internal/process/functions/call/built-in/built-in-get.js +4 -3
- package/dataflow/internal/process/functions/call/built-in/built-in-if-then-else.js +4 -3
- package/dataflow/internal/process/functions/call/built-in/built-in-library.js +4 -3
- package/dataflow/internal/process/functions/call/built-in/built-in-list.js +51 -17
- package/dataflow/internal/process/functions/call/built-in/built-in-pipe.js +1 -1
- package/dataflow/internal/process/functions/call/built-in/built-in-quote.js +9 -7
- package/dataflow/internal/process/functions/call/built-in/built-in-repeat-loop.js +3 -2
- package/dataflow/internal/process/functions/call/built-in/built-in-replacement.d.ts +4 -0
- package/dataflow/internal/process/functions/call/built-in/built-in-replacement.js +100 -31
- package/dataflow/internal/process/functions/call/built-in/built-in-rm.d.ts +7 -0
- package/dataflow/internal/process/functions/call/built-in/built-in-rm.js +41 -0
- package/dataflow/internal/process/functions/call/built-in/built-in-source.js +35 -8
- package/dataflow/internal/process/functions/call/built-in/built-in-special-bin-op.js +4 -3
- package/dataflow/internal/process/functions/call/built-in/built-in-vector.d.ts +15 -0
- package/dataflow/internal/process/functions/call/built-in/built-in-vector.js +75 -0
- package/dataflow/internal/process/functions/call/built-in/built-in-while-loop.js +3 -3
- package/dataflow/internal/process/functions/call/common.d.ts +5 -2
- package/dataflow/internal/process/functions/call/common.js +9 -5
- package/dataflow/internal/process/functions/call/known-call-handling.d.ts +3 -2
- package/dataflow/internal/process/functions/call/known-call-handling.js +2 -1
- package/dataflow/internal/process/functions/call/named-call-handling.d.ts +2 -0
- package/dataflow/internal/process/functions/call/named-call-handling.js +10 -6
- package/dataflow/internal/process/functions/call/unnamed-call-handling.d.ts +1 -0
- package/dataflow/internal/process/functions/call/unnamed-call-handling.js +6 -4
- package/dataflow/internal/process/process-named-call.d.ts +4 -1
- package/dataflow/internal/process/process-named-call.js +8 -5
- package/dataflow/origin/dfg-get-origin.d.ts +82 -0
- package/dataflow/origin/dfg-get-origin.js +116 -0
- package/documentation/doc-util/doc-cfg.d.ts +20 -4
- package/documentation/doc-util/doc-cfg.js +41 -7
- package/documentation/doc-util/doc-cli-option.js +4 -2
- package/documentation/doc-util/doc-code.js +10 -2
- package/documentation/doc-util/doc-dfg.js +3 -3
- package/documentation/doc-util/doc-escape.d.ts +7 -0
- package/documentation/doc-util/doc-escape.js +19 -0
- package/documentation/doc-util/doc-files.d.ts +1 -0
- package/documentation/doc-util/doc-files.js +2 -1
- package/documentation/doc-util/doc-normalized-ast.js +3 -3
- package/documentation/doc-util/doc-query.js +2 -2
- package/documentation/doc-util/doc-repl.js +1 -1
- package/documentation/doc-util/doc-search.js +1 -1
- package/documentation/doc-util/doc-server-message.js +2 -2
- package/documentation/doc-util/doc-structure.d.ts +1 -0
- package/documentation/doc-util/doc-structure.js +5 -0
- package/documentation/doc-util/doc-types.d.ts +7 -1
- package/documentation/doc-util/doc-types.js +13 -2
- package/documentation/print-capabilities-markdown.js +28 -2
- package/documentation/print-cfg-wiki.d.ts +1 -0
- package/documentation/print-cfg-wiki.js +572 -0
- package/documentation/print-core-wiki.js +2 -2
- package/documentation/print-dataflow-graph-wiki.js +180 -25
- package/documentation/print-engines-wiki.js +1 -1
- package/documentation/print-faq-wiki.d.ts +1 -0
- package/documentation/print-faq-wiki.js +75 -0
- package/documentation/print-interface-wiki.js +2 -1
- package/documentation/print-linting-and-testing-wiki.js +52 -36
- package/documentation/print-normalized-ast-wiki.js +1 -1
- package/documentation/print-onboarding-wiki.d.ts +1 -0
- package/documentation/print-onboarding-wiki.js +42 -0
- package/documentation/print-query-wiki.js +23 -3
- package/documentation/print-readme.js +10 -3
- package/package.json +10 -6
- package/queries/catalog/call-context-query/call-context-query-executor.js +5 -5
- package/queries/catalog/call-context-query/call-context-query-format.d.ts +1 -1
- package/queries/catalog/call-context-query/call-context-query-format.js +2 -2
- package/queries/catalog/call-context-query/identify-link-to-last-call-relation.d.ts +2 -2
- package/queries/catalog/call-context-query/identify-link-to-last-call-relation.js +24 -21
- package/queries/catalog/cluster-query/cluster-query-format.d.ts +1 -1
- package/queries/catalog/cluster-query/cluster-query-format.js +1 -1
- package/queries/catalog/config-query/config-query-format.d.ts +1 -1
- package/queries/catalog/config-query/config-query-format.js +2 -2
- package/queries/catalog/dataflow-lens-query/dataflow-lens-query-format.d.ts +1 -1
- package/queries/catalog/dataflow-lens-query/dataflow-lens-query-format.js +2 -2
- package/queries/catalog/dataflow-query/dataflow-query-format.d.ts +1 -1
- package/queries/catalog/dataflow-query/dataflow-query-format.js +2 -2
- package/queries/catalog/dependencies-query/dependencies-query-executor.js +17 -7
- package/queries/catalog/dependencies-query/dependencies-query-format.d.ts +2 -26
- package/queries/catalog/dependencies-query/dependencies-query-format.js +4 -147
- package/queries/catalog/dependencies-query/function-info/function-info.d.ts +24 -0
- package/queries/catalog/dependencies-query/function-info/function-info.js +10 -0
- package/queries/catalog/dependencies-query/function-info/library-functions.d.ts +2 -0
- package/queries/catalog/dependencies-query/function-info/library-functions.js +18 -0
- package/queries/catalog/dependencies-query/function-info/read-functions.d.ts +2 -0
- package/queries/catalog/dependencies-query/function-info/read-functions.js +101 -0
- package/queries/catalog/dependencies-query/function-info/source-functions.d.ts +2 -0
- package/queries/catalog/dependencies-query/function-info/source-functions.js +11 -0
- package/queries/catalog/dependencies-query/function-info/write-functions.d.ts +2 -0
- package/queries/catalog/dependencies-query/function-info/write-functions.js +87 -0
- package/queries/catalog/happens-before-query/happens-before-query-executor.d.ts +1 -1
- package/queries/catalog/happens-before-query/happens-before-query-executor.js +4 -4
- package/queries/catalog/happens-before-query/happens-before-query-format.d.ts +1 -1
- package/queries/catalog/happens-before-query/happens-before-query-format.js +2 -2
- package/queries/catalog/id-map-query/id-map-query-format.d.ts +1 -1
- package/queries/catalog/id-map-query/id-map-query-format.js +2 -2
- package/queries/catalog/lineage-query/lineage-query-format.d.ts +1 -1
- package/queries/catalog/lineage-query/lineage-query-format.js +2 -2
- package/queries/catalog/location-map-query/location-map-query-format.d.ts +1 -1
- package/queries/catalog/location-map-query/location-map-query-format.js +2 -2
- package/queries/catalog/normalized-ast-query/normalized-ast-query-format.d.ts +1 -1
- package/queries/catalog/normalized-ast-query/normalized-ast-query-format.js +2 -2
- package/queries/catalog/origin-query/origin-query-executor.d.ts +5 -0
- package/queries/catalog/origin-query/origin-query-executor.js +33 -0
- package/queries/catalog/origin-query/origin-query-format.d.ts +71 -0
- package/queries/catalog/origin-query/origin-query-format.js +27 -0
- package/queries/catalog/project-query/project-query-format.d.ts +1 -1
- package/queries/catalog/project-query/project-query-format.js +2 -2
- package/queries/catalog/resolve-value-query/resolve-value-query-format.d.ts +1 -1
- package/queries/catalog/resolve-value-query/resolve-value-query-format.js +2 -2
- package/queries/catalog/search-query/search-query-format.d.ts +1 -1
- package/queries/catalog/search-query/search-query-format.js +2 -2
- package/queries/catalog/static-slice-query/static-slice-query-format.d.ts +1 -1
- package/queries/catalog/static-slice-query/static-slice-query-format.js +2 -2
- package/queries/query-print.d.ts +1 -1
- package/queries/query-print.js +4 -4
- package/queries/query.d.ts +61 -2
- package/queries/query.js +3 -1
- package/r-bridge/data/data.d.ts +2 -2
- package/r-bridge/data/data.js +2 -2
- package/r-bridge/lang-4.x/ast/model/nodes/r-number.d.ts +3 -2
- package/r-bridge/lang-4.x/ast/model/nodes/r-number.js +5 -0
- package/r-bridge/lang-4.x/ast/model/nodes/r-string.d.ts +3 -2
- package/r-bridge/lang-4.x/ast/model/nodes/r-string.js +5 -0
- package/r-bridge/lang-4.x/ast/model/processing/decorate.d.ts +1 -1
- package/r-bridge/lang-4.x/ast/model/processing/decorate.js +1 -1
- package/r-bridge/lang-4.x/ast/model/processing/fold.js +3 -1
- package/r-bridge/lang-4.x/ast/model/processing/stateful-fold.d.ts +1 -1
- package/r-bridge/lang-4.x/ast/parser/main/internal/expression/normalize-expression.js +1 -1
- package/r-bridge/lang-4.x/ast/parser/main/internal/functions/normalize-argument.js +1 -1
- package/r-bridge/lang-4.x/ast/parser/main/internal/functions/normalize-call.js +1 -1
- package/r-bridge/lang-4.x/ast/parser/main/internal/functions/normalize-definition.js +1 -1
- package/r-bridge/lang-4.x/ast/parser/main/internal/normalize-access.js +1 -1
- package/r-bridge/lang-4.x/ast/parser/main/internal/operators/normalize-binary.js +1 -1
- package/r-bridge/lang-4.x/ast/parser/main/internal/structure/normalize-root.js +1 -1
- package/r-bridge/lang-4.x/ast/parser/main/internal/values/normalize-symbol.js +1 -1
- package/r-bridge/lang-4.x/tree-sitter/tree-sitter-executor.d.ts +2 -2
- package/r-bridge/lang-4.x/tree-sitter/tree-sitter-executor.js +4 -4
- package/r-bridge/lang-4.x/tree-sitter/tree-sitter-normalize.js +26 -8
- package/r-bridge/retriever.js +1 -1
- package/search/search-executor/search-generators.d.ts +1 -1
- package/search/search-executor/search-transformer.d.ts +1 -1
- package/slicing/criterion/collect-all.js +1 -1
- package/slicing/static/slice-call.js +13 -3
- package/statistics/features/supported/assignments/post-process.js +1 -1
- package/statistics/features/supported/defined-functions/post-process.js +2 -2
- package/statistics/features/supported/used-functions/post-process.js +1 -1
- package/statistics/features/supported/used-packages/post-process.js +2 -2
- package/statistics/features/supported/values/post-process.js +2 -2
- package/statistics/output/print-stats.js +2 -2
- package/statistics/summarizer/post-process/clusterer.d.ts +1 -1
- package/statistics/summarizer/post-process/clusterer.js +1 -1
- package/statistics/summarizer/post-process/histogram.js +3 -3
- package/statistics/summarizer/post-process/post-process-output.js +3 -3
- package/statistics/summarizer/second-phase/process.js +2 -2
- package/statistics/summarizer/summarizer.js +2 -2
- package/util/assert.js +36 -1
- package/util/cfg/cfg.d.ts +0 -80
- package/util/cfg/cfg.js +0 -549
- package/util/{arrays.d.ts → collections/arrays.d.ts} +24 -1
- package/util/{arrays.js → collections/arrays.js} +44 -3
- package/util/collections/set.js +17 -0
- package/util/{list-access.d.ts → containers.d.ts} +24 -4
- package/util/{list-access.js → containers.js} +42 -12
- package/util/diff-graph.d.ts +47 -0
- package/util/diff-graph.js +61 -0
- package/util/diff.d.ts +6 -6
- package/util/diff.js +1 -1
- package/util/mermaid/ast.js +12 -1
- package/util/mermaid/cfg.d.ts +9 -2
- package/util/mermaid/cfg.js +65 -13
- package/util/mermaid/dfg.d.ts +2 -1
- package/util/mermaid/dfg.js +26 -10
- package/util/mermaid/mermaid.d.ts +2 -0
- package/util/mermaid/mermaid.js +6 -0
- package/util/parallel.d.ts +2 -1
- package/util/parallel.js +11 -2
- package/util/prefix.d.ts +13 -0
- package/util/prefix.js +34 -0
- package/util/quads.js +1 -1
- package/util/schema.d.ts +1 -1
- package/util/schema.js +1 -1
- package/util/summarizer.js +1 -1
- package/util/{text.js → text/text.js} +1 -1
- package/util/{time.js → text/time.js} +1 -1
- package/util/version.js +1 -1
- package/dataflow/graph/diff.d.ts +0 -36
- package/util/cfg/happens-before.d.ts +0 -7
- package/util/cfg/visitor.d.ts +0 -9
- package/util/cfg/visitor.js +0 -30
- package/util/set.js +0 -31
- /package/util/{bimap.d.ts → collections/bimap.d.ts} +0 -0
- /package/util/{bimap.js → collections/bimap.js} +0 -0
- /package/util/{defaultmap.d.ts → collections/defaultmap.d.ts} +0 -0
- /package/util/{defaultmap.js → collections/defaultmap.js} +0 -0
- /package/util/{set.d.ts → collections/set.d.ts} +0 -0
- /package/util/{ansi.d.ts → text/ansi.d.ts} +0 -0
- /package/util/{ansi.js → text/ansi.js} +0 -0
- /package/util/{args.d.ts → text/args.d.ts} +0 -0
- /package/util/{args.js → text/args.js} +0 -0
- /package/util/{strings.d.ts → text/strings.d.ts} +0 -0
- /package/util/{strings.js → text/strings.js} +0 -0
- /package/util/{text.d.ts → text/text.d.ts} +0 -0
- /package/util/{time.d.ts → text/time.d.ts} +0 -0
package/util/cfg/cfg.js
CHANGED
|
@@ -1,551 +1,2 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.ControlFlowGraph = void 0;
|
|
4
|
-
exports.emptyControlFlowInformation = emptyControlFlowInformation;
|
|
5
|
-
exports.extractCFG = extractCFG;
|
|
6
|
-
exports.equalCfg = equalCfg;
|
|
7
|
-
exports.cfg2quads = cfg2quads;
|
|
8
|
-
const set_1 = require("../set");
|
|
9
|
-
const quads_1 = require("../quads");
|
|
10
|
-
const log_1 = require("../log");
|
|
11
|
-
const json_1 = require("../json");
|
|
12
|
-
const fold_1 = require("../../r-bridge/lang-4.x/ast/model/processing/fold");
|
|
13
|
-
const convert_values_1 = require("../../r-bridge/lang-4.x/convert-values");
|
|
14
|
-
const r_function_call_1 = require("../../r-bridge/lang-4.x/ast/model/nodes/r-function-call");
|
|
15
|
-
const linker_1 = require("../../dataflow/internal/linker");
|
|
16
|
-
const vertex_1 = require("../../dataflow/graph/vertex");
|
|
17
|
-
/**
|
|
18
|
-
* This class represents the control flow graph of an R program.
|
|
19
|
-
* The control flow may be hierarchical when confronted with function definitions (see {@link CfgVertex} and {@link CFG#rootVertexIds|rootVertexIds()}).
|
|
20
|
-
*/
|
|
21
|
-
class ControlFlowGraph {
|
|
22
|
-
rootVertices = new Set();
|
|
23
|
-
vertexInformation = new Map();
|
|
24
|
-
edgeInformation = new Map();
|
|
25
|
-
addVertex(vertex, rootVertex = true) {
|
|
26
|
-
if (this.vertexInformation.has(vertex.id)) {
|
|
27
|
-
throw new Error(`Node with id ${vertex.id} already exists`);
|
|
28
|
-
}
|
|
29
|
-
this.vertexInformation.set(vertex.id, vertex);
|
|
30
|
-
if (rootVertex) {
|
|
31
|
-
this.rootVertices.add(vertex.id);
|
|
32
|
-
}
|
|
33
|
-
return this;
|
|
34
|
-
}
|
|
35
|
-
addEdge(from, to, edge) {
|
|
36
|
-
if (!this.edgeInformation.has(from)) {
|
|
37
|
-
this.edgeInformation.set(from, new Map());
|
|
38
|
-
}
|
|
39
|
-
this.edgeInformation.get(from)?.set(to, edge);
|
|
40
|
-
return this;
|
|
41
|
-
}
|
|
42
|
-
outgoing(node) {
|
|
43
|
-
return this.edgeInformation.get(node);
|
|
44
|
-
}
|
|
45
|
-
rootVertexIds() {
|
|
46
|
-
return this.rootVertices;
|
|
47
|
-
}
|
|
48
|
-
vertices() {
|
|
49
|
-
return this.vertexInformation;
|
|
50
|
-
}
|
|
51
|
-
edges() {
|
|
52
|
-
return this.edgeInformation;
|
|
53
|
-
}
|
|
54
|
-
merge(other, forceNested = false) {
|
|
55
|
-
for (const [id, node] of other.vertexInformation) {
|
|
56
|
-
this.addVertex(node, forceNested ? false : other.rootVertices.has(id));
|
|
57
|
-
}
|
|
58
|
-
for (const [from, edges] of other.edgeInformation) {
|
|
59
|
-
for (const [to, edge] of edges) {
|
|
60
|
-
this.addEdge(from, to, edge);
|
|
61
|
-
}
|
|
62
|
-
}
|
|
63
|
-
return this;
|
|
64
|
-
}
|
|
65
|
-
}
|
|
66
|
-
exports.ControlFlowGraph = ControlFlowGraph;
|
|
67
|
-
function emptyControlFlowInformation() {
|
|
68
|
-
return {
|
|
69
|
-
returns: [],
|
|
70
|
-
breaks: [],
|
|
71
|
-
nexts: [],
|
|
72
|
-
entryPoints: [],
|
|
73
|
-
exitPoints: [],
|
|
74
|
-
graph: new ControlFlowGraph()
|
|
75
|
-
};
|
|
76
|
-
}
|
|
77
|
-
const cfgFolds = {
|
|
78
|
-
foldNumber: cfgLeaf("expression" /* CfgVertexType.Expression */),
|
|
79
|
-
foldString: cfgLeaf("expression" /* CfgVertexType.Expression */),
|
|
80
|
-
foldLogical: cfgLeaf("expression" /* CfgVertexType.Expression */),
|
|
81
|
-
foldSymbol: cfgLeaf("expression" /* CfgVertexType.Expression */),
|
|
82
|
-
foldAccess: cfgAccess,
|
|
83
|
-
foldBinaryOp: cfgBinaryOp,
|
|
84
|
-
foldPipe: cfgBinaryOp,
|
|
85
|
-
foldUnaryOp: cfgUnaryOp,
|
|
86
|
-
other: {
|
|
87
|
-
foldComment: cfgIgnore,
|
|
88
|
-
foldLineDirective: cfgIgnore
|
|
89
|
-
},
|
|
90
|
-
loop: {
|
|
91
|
-
foldFor: cfgFor,
|
|
92
|
-
foldRepeat: cfgRepeat,
|
|
93
|
-
foldWhile: cfgWhile,
|
|
94
|
-
foldBreak: cfgBreak,
|
|
95
|
-
foldNext: cfgNext
|
|
96
|
-
},
|
|
97
|
-
foldIfThenElse: cfgIfThenElse,
|
|
98
|
-
foldExprList: cfgExprList,
|
|
99
|
-
functions: {
|
|
100
|
-
foldFunctionDefinition: cfgFunctionDefinition,
|
|
101
|
-
foldFunctionCall: cfgFunctionCall,
|
|
102
|
-
foldParameter: cfgArgumentOrParameter,
|
|
103
|
-
foldArgument: cfgArgumentOrParameter
|
|
104
|
-
}
|
|
105
|
-
};
|
|
106
|
-
function dataflowCfgFolds(dataflowGraph) {
|
|
107
|
-
return {
|
|
108
|
-
...cfgFolds,
|
|
109
|
-
functions: {
|
|
110
|
-
...cfgFolds.functions,
|
|
111
|
-
foldFunctionCall: cfgFunctionCallWithDataflow(dataflowGraph)
|
|
112
|
-
}
|
|
113
|
-
};
|
|
114
|
-
}
|
|
115
|
-
/**
|
|
116
|
-
* Given a normalized AST this approximates the control flow graph of the program.
|
|
117
|
-
* This few is different from the computation of the dataflow graph and may differ,
|
|
118
|
-
* especially because it focuses on intra-procedural analysis.
|
|
119
|
-
*
|
|
120
|
-
* @param ast - the normalized AST
|
|
121
|
-
* @param graph - additional dataflow facts to consider by the control flow extraction
|
|
122
|
-
*/
|
|
123
|
-
function extractCFG(ast, graph) {
|
|
124
|
-
return (0, fold_1.foldAst)(ast.ast, graph ? dataflowCfgFolds(graph) : cfgFolds);
|
|
125
|
-
}
|
|
126
|
-
function cfgLeaf(type) {
|
|
127
|
-
return (leaf) => {
|
|
128
|
-
const graph = new ControlFlowGraph();
|
|
129
|
-
graph.addVertex({ id: leaf.info.id, name: leaf.type, type });
|
|
130
|
-
return { graph, breaks: [], nexts: [], returns: [], exitPoints: [leaf.info.id], entryPoints: [leaf.info.id] };
|
|
131
|
-
};
|
|
132
|
-
}
|
|
133
|
-
function cfgBreak(leaf) {
|
|
134
|
-
return { ...cfgLeaf("statement" /* CfgVertexType.Statement */)(leaf), breaks: [leaf.info.id] };
|
|
135
|
-
}
|
|
136
|
-
function cfgNext(leaf) {
|
|
137
|
-
return { ...cfgLeaf("statement" /* CfgVertexType.Statement */)(leaf), nexts: [leaf.info.id] };
|
|
138
|
-
}
|
|
139
|
-
function cfgIgnore(_leaf) {
|
|
140
|
-
return { graph: new ControlFlowGraph(), breaks: [], nexts: [], returns: [], exitPoints: [], entryPoints: [] };
|
|
141
|
-
}
|
|
142
|
-
function identifyMayStatementType(node) {
|
|
143
|
-
return node.info.role === "expr-list-child" /* RoleInParent.ExpressionListChild */ ? "statement" /* CfgVertexType.Statement */ : "expression" /* CfgVertexType.Expression */;
|
|
144
|
-
}
|
|
145
|
-
function cfgIfThenElse(ifNode, condition, then, otherwise) {
|
|
146
|
-
const graph = new ControlFlowGraph();
|
|
147
|
-
graph.addVertex({ id: ifNode.info.id, name: ifNode.type, type: identifyMayStatementType(ifNode) });
|
|
148
|
-
graph.addVertex({ id: ifNode.info.id + '-exit', name: 'if-exit', type: "end-marker" /* CfgVertexType.EndMarker */ });
|
|
149
|
-
graph.merge(condition.graph);
|
|
150
|
-
graph.merge(then.graph);
|
|
151
|
-
if (otherwise) {
|
|
152
|
-
graph.merge(otherwise.graph);
|
|
153
|
-
}
|
|
154
|
-
for (const exitPoint of condition.exitPoints) {
|
|
155
|
-
for (const entryPoint of then.entryPoints) {
|
|
156
|
-
graph.addEdge(entryPoint, exitPoint, { label: 'CD', when: convert_values_1.RTrue, caused: ifNode.info.id });
|
|
157
|
-
}
|
|
158
|
-
for (const entryPoint of otherwise?.entryPoints ?? []) {
|
|
159
|
-
graph.addEdge(entryPoint, exitPoint, { label: 'CD', when: convert_values_1.RFalse, caused: ifNode.info.id });
|
|
160
|
-
}
|
|
161
|
-
}
|
|
162
|
-
for (const entryPoint of condition.entryPoints) {
|
|
163
|
-
graph.addEdge(entryPoint, ifNode.info.id, { label: 'FD' });
|
|
164
|
-
}
|
|
165
|
-
for (const exit of [...then.exitPoints, ...otherwise?.exitPoints ?? []]) {
|
|
166
|
-
graph.addEdge(ifNode.info.id + '-exit', exit, { label: 'FD' });
|
|
167
|
-
}
|
|
168
|
-
if (!otherwise) {
|
|
169
|
-
for (const exitPoint of condition.exitPoints) {
|
|
170
|
-
graph.addEdge(ifNode.info.id + '-exit', exitPoint, { label: 'CD', when: convert_values_1.RFalse, caused: ifNode.info.id });
|
|
171
|
-
}
|
|
172
|
-
}
|
|
173
|
-
return {
|
|
174
|
-
graph,
|
|
175
|
-
breaks: [...then.breaks, ...otherwise?.breaks ?? []],
|
|
176
|
-
nexts: [...then.nexts, ...otherwise?.nexts ?? []],
|
|
177
|
-
returns: [...then.returns, ...otherwise?.returns ?? []],
|
|
178
|
-
exitPoints: [ifNode.info.id + '-exit'],
|
|
179
|
-
entryPoints: [ifNode.info.id]
|
|
180
|
-
};
|
|
181
|
-
}
|
|
182
|
-
function cfgRepeat(repeat, body) {
|
|
183
|
-
const graph = body.graph;
|
|
184
|
-
graph.addVertex({ id: repeat.info.id, name: repeat.type, type: identifyMayStatementType(repeat) });
|
|
185
|
-
graph.addVertex({ id: repeat.info.id + '-exit', name: 'repeat-exit', type: "end-marker" /* CfgVertexType.EndMarker */ });
|
|
186
|
-
for (const entryPoint of body.entryPoints) {
|
|
187
|
-
graph.addEdge(entryPoint, repeat.info.id, { label: 'FD' });
|
|
188
|
-
}
|
|
189
|
-
// loops automatically
|
|
190
|
-
for (const next of [...body.nexts, ...body.exitPoints]) {
|
|
191
|
-
graph.addEdge(repeat.info.id, next, { label: 'FD' });
|
|
192
|
-
}
|
|
193
|
-
for (const breakPoint of body.breaks) {
|
|
194
|
-
graph.addEdge(repeat.info.id + '-exit', breakPoint, { label: 'FD' });
|
|
195
|
-
}
|
|
196
|
-
return { graph, breaks: [], nexts: [], returns: body.returns, exitPoints: [repeat.info.id + '-exit'], entryPoints: [repeat.info.id] };
|
|
197
|
-
}
|
|
198
|
-
function cfgWhile(whileLoop, condition, body) {
|
|
199
|
-
const graph = condition.graph;
|
|
200
|
-
graph.addVertex({ id: whileLoop.info.id, name: whileLoop.type, type: identifyMayStatementType(whileLoop) });
|
|
201
|
-
graph.addVertex({ id: whileLoop.info.id + '-exit', name: 'while-exit', type: "end-marker" /* CfgVertexType.EndMarker */ });
|
|
202
|
-
graph.merge(body.graph);
|
|
203
|
-
for (const entry of condition.entryPoints) {
|
|
204
|
-
graph.addEdge(entry, whileLoop.info.id, { label: 'FD' });
|
|
205
|
-
}
|
|
206
|
-
for (const exit of condition.exitPoints) {
|
|
207
|
-
for (const entry of body.entryPoints) {
|
|
208
|
-
graph.addEdge(entry, exit, { label: 'CD', when: convert_values_1.RTrue, caused: whileLoop.info.id });
|
|
209
|
-
}
|
|
210
|
-
}
|
|
211
|
-
for (const entryPoint of body.entryPoints) {
|
|
212
|
-
graph.addEdge(whileLoop.info.id, entryPoint, { label: 'FD' });
|
|
213
|
-
}
|
|
214
|
-
for (const next of [...body.nexts, ...body.exitPoints]) {
|
|
215
|
-
graph.addEdge(whileLoop.info.id, next, { label: 'FD' });
|
|
216
|
-
}
|
|
217
|
-
for (const breakPoint of body.breaks) {
|
|
218
|
-
graph.addEdge(whileLoop.info.id + '-exit', breakPoint, { label: 'FD' });
|
|
219
|
-
}
|
|
220
|
-
// while can break on the condition as well
|
|
221
|
-
for (const exit of condition.exitPoints) {
|
|
222
|
-
graph.addEdge(whileLoop.info.id + '-exit', exit, { label: 'CD', when: convert_values_1.RFalse, caused: whileLoop.info.id });
|
|
223
|
-
}
|
|
224
|
-
return { graph, breaks: [], nexts: [], returns: body.returns, exitPoints: [whileLoop.info.id + '-exit'], entryPoints: [whileLoop.info.id] };
|
|
225
|
-
}
|
|
226
|
-
function cfgFor(forLoop, variable, vector, body) {
|
|
227
|
-
const graph = variable.graph;
|
|
228
|
-
graph.addVertex({ id: forLoop.info.id, name: forLoop.type, type: identifyMayStatementType(forLoop) });
|
|
229
|
-
graph.addVertex({ id: forLoop.info.id + '-exit', name: 'for-exit', type: "end-marker" /* CfgVertexType.EndMarker */ });
|
|
230
|
-
graph.merge(vector.graph);
|
|
231
|
-
graph.merge(body.graph);
|
|
232
|
-
for (const entry of vector.entryPoints) {
|
|
233
|
-
graph.addEdge(entry, forLoop.info.id, { label: 'FD' });
|
|
234
|
-
}
|
|
235
|
-
for (const exit of vector.exitPoints) {
|
|
236
|
-
for (const entry of variable.entryPoints) {
|
|
237
|
-
graph.addEdge(entry, exit, { label: 'FD' });
|
|
238
|
-
}
|
|
239
|
-
}
|
|
240
|
-
for (const exit of variable.exitPoints) {
|
|
241
|
-
for (const entry of body.entryPoints) {
|
|
242
|
-
graph.addEdge(entry, exit, { label: 'CD', when: convert_values_1.RTrue, caused: forLoop.info.id });
|
|
243
|
-
}
|
|
244
|
-
}
|
|
245
|
-
for (const next of [...body.nexts, ...body.exitPoints]) {
|
|
246
|
-
graph.addEdge(forLoop.info.id, next, { label: 'FD' });
|
|
247
|
-
}
|
|
248
|
-
for (const breakPoint of body.breaks) {
|
|
249
|
-
graph.addEdge(forLoop.info.id + '-exit', breakPoint, { label: 'FD' });
|
|
250
|
-
}
|
|
251
|
-
// while can break on the condition as well
|
|
252
|
-
for (const exit of variable.exitPoints) {
|
|
253
|
-
graph.addEdge(forLoop.info.id + '-exit', exit, { label: 'CD', when: convert_values_1.RFalse, caused: forLoop.info.id });
|
|
254
|
-
}
|
|
255
|
-
return { graph, breaks: [], nexts: [], returns: body.returns, exitPoints: [forLoop.info.id + '-exit'], entryPoints: [forLoop.info.id] };
|
|
256
|
-
}
|
|
257
|
-
function cfgFunctionDefinition(fn, params, body) {
|
|
258
|
-
const graph = new ControlFlowGraph();
|
|
259
|
-
const children = [fn.info.id + '-params', fn.info.id + '-exit'];
|
|
260
|
-
graph.addVertex({ id: fn.info.id + '-params', name: 'function-parameters', type: "mid-marker" /* CfgVertexType.MidMarker */ }, false);
|
|
261
|
-
graph.addVertex({ id: fn.info.id + '-exit', name: 'function-exit', type: "end-marker" /* CfgVertexType.EndMarker */ }, false);
|
|
262
|
-
graph.addVertex({ id: fn.info.id, name: fn.type, children, type: identifyMayStatementType(fn) });
|
|
263
|
-
graph.merge(body.graph, true);
|
|
264
|
-
children.push(...body.graph.rootVertexIds());
|
|
265
|
-
for (const param of params) {
|
|
266
|
-
graph.merge(param.graph, true);
|
|
267
|
-
children.push(...param.graph.rootVertexIds());
|
|
268
|
-
for (const entry of param.entryPoints) {
|
|
269
|
-
graph.addEdge(entry, fn.info.id, { label: 'FD' });
|
|
270
|
-
}
|
|
271
|
-
for (const exit of param.exitPoints) {
|
|
272
|
-
graph.addEdge(fn.info.id + '-params', exit, { label: 'FD' });
|
|
273
|
-
}
|
|
274
|
-
}
|
|
275
|
-
if (params.length === 0) {
|
|
276
|
-
graph.addEdge(fn.info.id + '-params', fn.info.id, { label: 'FD' });
|
|
277
|
-
}
|
|
278
|
-
for (const entry of body.entryPoints) {
|
|
279
|
-
graph.addEdge(entry, fn.info.id + '-params', { label: 'FD' });
|
|
280
|
-
}
|
|
281
|
-
// breaks and nexts should be illegal but safe is safe i guess
|
|
282
|
-
for (const next of [...body.returns, ...body.breaks, ...body.nexts, ...body.exitPoints]) {
|
|
283
|
-
graph.addEdge(fn.info.id + '-exit', next, { label: 'FD' });
|
|
284
|
-
}
|
|
285
|
-
return { graph: graph, breaks: [], nexts: [], returns: body.returns, exitPoints: [fn.info.id], entryPoints: [fn.info.id] };
|
|
286
|
-
}
|
|
287
|
-
function cfgFunctionCall(call, name, args) {
|
|
288
|
-
const graph = name.graph;
|
|
289
|
-
const info = { graph, breaks: [...name.breaks], nexts: [...name.nexts], returns: [...name.returns], exitPoints: [call.info.id + '-exit'], entryPoints: [call.info.id] };
|
|
290
|
-
graph.addVertex({ id: call.info.id, name: call.type, type: identifyMayStatementType(call) });
|
|
291
|
-
for (const entryPoint of name.entryPoints) {
|
|
292
|
-
graph.addEdge(entryPoint, call.info.id, { label: 'FD' });
|
|
293
|
-
}
|
|
294
|
-
graph.addVertex({ id: call.info.id + '-name', name: 'call-name', type: "mid-marker" /* CfgVertexType.MidMarker */ });
|
|
295
|
-
for (const exitPoint of name.exitPoints) {
|
|
296
|
-
graph.addEdge(call.info.id + '-name', exitPoint, { label: 'FD' });
|
|
297
|
-
}
|
|
298
|
-
graph.addVertex({ id: call.info.id + '-exit', name: 'call-exit', type: "end-marker" /* CfgVertexType.EndMarker */ });
|
|
299
|
-
let lastArgExits = [call.info.id + '-name'];
|
|
300
|
-
for (const arg of args) {
|
|
301
|
-
if (arg === r_function_call_1.EmptyArgument) {
|
|
302
|
-
continue;
|
|
303
|
-
}
|
|
304
|
-
graph.merge(arg.graph);
|
|
305
|
-
info.breaks.push(...arg.breaks);
|
|
306
|
-
info.nexts.push(...arg.nexts);
|
|
307
|
-
info.returns.push(...arg.returns);
|
|
308
|
-
for (const entry of arg.entryPoints) {
|
|
309
|
-
for (const exit of lastArgExits) {
|
|
310
|
-
graph.addEdge(entry, exit, { label: 'FD' });
|
|
311
|
-
}
|
|
312
|
-
}
|
|
313
|
-
lastArgExits = arg.exitPoints;
|
|
314
|
-
}
|
|
315
|
-
for (const exit of lastArgExits) {
|
|
316
|
-
graph.addEdge(call.info.id + '-exit', exit, { label: 'FD' });
|
|
317
|
-
}
|
|
318
|
-
// should not contain any breaks, nexts, or returns, (except for the body if something like 'break()')
|
|
319
|
-
return info;
|
|
320
|
-
}
|
|
321
|
-
function cfgFunctionCallWithDataflow(graph) {
|
|
322
|
-
return (call, name, args) => {
|
|
323
|
-
const baseCFG = cfgFunctionCall(call, name, args);
|
|
324
|
-
/* try to resolve the call and link the target definitions */
|
|
325
|
-
const targets = (0, linker_1.getAllFunctionCallTargets)(call.info.id, graph);
|
|
326
|
-
const exits = [];
|
|
327
|
-
for (const target of targets) {
|
|
328
|
-
// we have to filter out non func-call targets as the call targets contains names and call ids
|
|
329
|
-
if ((0, vertex_1.isFunctionDefinitionVertex)(graph.getVertex(target))) {
|
|
330
|
-
baseCFG.graph.addEdge(call.info.id, target, { label: 'FD' });
|
|
331
|
-
exits.push(target + '-exit');
|
|
332
|
-
}
|
|
333
|
-
}
|
|
334
|
-
if (exits.length > 0) {
|
|
335
|
-
baseCFG.graph.addVertex({
|
|
336
|
-
id: call.info.id + '-resolved-call-exit',
|
|
337
|
-
name: 'resolved-call-exit',
|
|
338
|
-
type: "end-marker" /* CfgVertexType.EndMarker */
|
|
339
|
-
});
|
|
340
|
-
for (const exit of [...baseCFG.exitPoints, ...exits]) {
|
|
341
|
-
baseCFG.graph.addEdge(call.info.id + '-resolved-call-exit', exit, { label: 'FD' });
|
|
342
|
-
}
|
|
343
|
-
return {
|
|
344
|
-
...baseCFG,
|
|
345
|
-
exitPoints: [call.info.id + '-resolved-call-exit']
|
|
346
|
-
};
|
|
347
|
-
}
|
|
348
|
-
else {
|
|
349
|
-
return baseCFG;
|
|
350
|
-
}
|
|
351
|
-
};
|
|
352
|
-
}
|
|
353
|
-
function cfgArgumentOrParameter(node, name, value) {
|
|
354
|
-
const graph = new ControlFlowGraph();
|
|
355
|
-
const info = { graph, breaks: [], nexts: [], returns: [], exitPoints: [node.info.id + '-exit'], entryPoints: [node.info.id] };
|
|
356
|
-
graph.addVertex({ id: node.info.id, name: node.type, type: "expression" /* CfgVertexType.Expression */ });
|
|
357
|
-
let currentExitPoint = [node.info.id];
|
|
358
|
-
if (name) {
|
|
359
|
-
graph.merge(name.graph);
|
|
360
|
-
info.breaks.push(...name.breaks);
|
|
361
|
-
info.nexts.push(...name.nexts);
|
|
362
|
-
info.returns.push(...name.returns);
|
|
363
|
-
for (const entry of name.entryPoints) {
|
|
364
|
-
graph.addEdge(entry, node.info.id, { label: 'FD' });
|
|
365
|
-
}
|
|
366
|
-
currentExitPoint = name.exitPoints;
|
|
367
|
-
}
|
|
368
|
-
graph.addVertex({ id: node.info.id + '-before-value', name: 'before-value', type: "mid-marker" /* CfgVertexType.MidMarker */ });
|
|
369
|
-
for (const exitPoints of currentExitPoint) {
|
|
370
|
-
graph.addEdge(node.info.id + '-before-value', exitPoints, { label: 'FD' });
|
|
371
|
-
}
|
|
372
|
-
currentExitPoint = [node.info.id + '-before-value'];
|
|
373
|
-
if (value) {
|
|
374
|
-
graph.merge(value.graph);
|
|
375
|
-
info.breaks.push(...value.breaks);
|
|
376
|
-
info.nexts.push(...value.nexts);
|
|
377
|
-
info.returns.push(...value.returns);
|
|
378
|
-
for (const exitPoint of currentExitPoint) {
|
|
379
|
-
for (const entry of value.entryPoints) {
|
|
380
|
-
graph.addEdge(entry, exitPoint, { label: 'FD' });
|
|
381
|
-
}
|
|
382
|
-
}
|
|
383
|
-
currentExitPoint = value.exitPoints;
|
|
384
|
-
}
|
|
385
|
-
graph.addVertex({ id: node.info.id + '-exit', name: 'exit', type: "end-marker" /* CfgVertexType.EndMarker */ });
|
|
386
|
-
for (const exit of currentExitPoint) {
|
|
387
|
-
graph.addEdge(node.info.id + '-exit', exit, { label: 'FD' });
|
|
388
|
-
}
|
|
389
|
-
return info;
|
|
390
|
-
}
|
|
391
|
-
function cfgBinaryOp(binOp, lhs, rhs) {
|
|
392
|
-
const graph = new ControlFlowGraph().merge(lhs.graph).merge(rhs.graph);
|
|
393
|
-
const result = { graph, breaks: [...lhs.breaks, ...rhs.breaks], nexts: [...lhs.nexts, ...rhs.nexts], returns: [...lhs.returns, ...rhs.returns], entryPoints: [binOp.info.id], exitPoints: [binOp.info.id + '-exit'] };
|
|
394
|
-
graph.addVertex({ id: binOp.info.id, name: binOp.type, type: binOp.flavor === 'assignment' ? "statement" /* CfgVertexType.Statement */ : "expression" /* CfgVertexType.Expression */ });
|
|
395
|
-
graph.addVertex({ id: binOp.info.id + '-exit', name: 'binOp-exit', type: "end-marker" /* CfgVertexType.EndMarker */ });
|
|
396
|
-
for (const exitPoint of lhs.exitPoints) {
|
|
397
|
-
for (const entryPoint of rhs.entryPoints) {
|
|
398
|
-
result.graph.addEdge(entryPoint, exitPoint, { label: 'FD' });
|
|
399
|
-
}
|
|
400
|
-
}
|
|
401
|
-
for (const entryPoint of lhs.entryPoints) {
|
|
402
|
-
graph.addEdge(entryPoint, binOp.info.id, { label: 'FD' });
|
|
403
|
-
}
|
|
404
|
-
for (const exitPoint of rhs.exitPoints) {
|
|
405
|
-
graph.addEdge(binOp.info.id + '-exit', exitPoint, { label: 'FD' });
|
|
406
|
-
}
|
|
407
|
-
return result;
|
|
408
|
-
}
|
|
409
|
-
function cfgAccess(access, name, accessors) {
|
|
410
|
-
const result = name;
|
|
411
|
-
const graph = result.graph;
|
|
412
|
-
graph.addVertex({ id: access.info.id, name: access.type, type: "expression" /* CfgVertexType.Expression */ });
|
|
413
|
-
graph.addVertex({ id: access.info.id + '-exit', name: 'access-exit', type: "end-marker" /* CfgVertexType.EndMarker */ });
|
|
414
|
-
for (const entry of name.entryPoints) {
|
|
415
|
-
graph.addEdge(entry, access.info.id, { label: 'FD' });
|
|
416
|
-
}
|
|
417
|
-
for (const exit of name.exitPoints) {
|
|
418
|
-
graph.addEdge(access.info.id, exit, { label: 'FD' });
|
|
419
|
-
}
|
|
420
|
-
result.entryPoints = [access.info.id];
|
|
421
|
-
result.exitPoints = [access.info.id + '-exit'];
|
|
422
|
-
for (const accessor of accessors) {
|
|
423
|
-
if (accessor === r_function_call_1.EmptyArgument) {
|
|
424
|
-
continue;
|
|
425
|
-
}
|
|
426
|
-
graph.merge(accessor.graph);
|
|
427
|
-
for (const entry of accessor.entryPoints) {
|
|
428
|
-
graph.addEdge(entry, access.info.id, { label: 'FD' });
|
|
429
|
-
}
|
|
430
|
-
for (const exit of accessor.exitPoints) {
|
|
431
|
-
graph.addEdge(access.info.id + '-exit', exit, { label: 'FD' });
|
|
432
|
-
}
|
|
433
|
-
}
|
|
434
|
-
return result;
|
|
435
|
-
}
|
|
436
|
-
function cfgUnaryOp(unary, operand) {
|
|
437
|
-
const graph = operand.graph;
|
|
438
|
-
graph.addVertex({ id: unary.info.id, name: unary.type, type: "end-marker" /* CfgVertexType.EndMarker */ });
|
|
439
|
-
for (const entry of operand.exitPoints) {
|
|
440
|
-
graph.addEdge(unary.info.id, entry, { label: 'FD' });
|
|
441
|
-
}
|
|
442
|
-
return { ...operand, graph, exitPoints: [unary.info.id] };
|
|
443
|
-
}
|
|
444
|
-
function cfgExprList(_node, _grouping, expressions) {
|
|
445
|
-
const result = { graph: new ControlFlowGraph(), breaks: [], nexts: [], returns: [], exitPoints: [], entryPoints: [] };
|
|
446
|
-
let first = true;
|
|
447
|
-
for (const expression of expressions) {
|
|
448
|
-
if (first) {
|
|
449
|
-
result.entryPoints = expression.entryPoints;
|
|
450
|
-
first = false;
|
|
451
|
-
}
|
|
452
|
-
else {
|
|
453
|
-
for (const previousExitPoint of result.exitPoints) {
|
|
454
|
-
for (const entryPoint of expression.entryPoints) {
|
|
455
|
-
result.graph.addEdge(entryPoint, previousExitPoint, { label: 'FD' });
|
|
456
|
-
}
|
|
457
|
-
}
|
|
458
|
-
}
|
|
459
|
-
result.graph.merge(expression.graph);
|
|
460
|
-
result.breaks.push(...expression.breaks);
|
|
461
|
-
result.nexts.push(...expression.nexts);
|
|
462
|
-
result.returns.push(...expression.returns);
|
|
463
|
-
result.exitPoints = expression.exitPoints;
|
|
464
|
-
}
|
|
465
|
-
return result;
|
|
466
|
-
}
|
|
467
|
-
function equalChildren(a, b) {
|
|
468
|
-
if (!a || !b || a.length !== b.length) {
|
|
469
|
-
return false;
|
|
470
|
-
}
|
|
471
|
-
for (let i = 0; i < a.length; ++i) {
|
|
472
|
-
if (a[i] !== b[i]) {
|
|
473
|
-
return false;
|
|
474
|
-
}
|
|
475
|
-
}
|
|
476
|
-
return true;
|
|
477
|
-
}
|
|
478
|
-
/**
|
|
479
|
-
* Returns true if the given CFG equals the other CFG. False otherwise.
|
|
480
|
-
*/
|
|
481
|
-
function equalCfg(a, b) {
|
|
482
|
-
if (!a || !b) {
|
|
483
|
-
return a === b;
|
|
484
|
-
}
|
|
485
|
-
else if (!(0, set_1.setEquals)(a.rootVertexIds(), b.rootVertexIds())) {
|
|
486
|
-
log_1.log.debug(`root vertex ids differ ${JSON.stringify(a.rootVertexIds(), json_1.jsonReplacer)} vs. ${JSON.stringify(b.rootVertexIds(), json_1.jsonReplacer)}.`);
|
|
487
|
-
return false;
|
|
488
|
-
}
|
|
489
|
-
const aVert = a.vertices();
|
|
490
|
-
const bVert = b.vertices();
|
|
491
|
-
if (aVert.size !== bVert.size) {
|
|
492
|
-
log_1.log.debug(`vertex count differs ${aVert.size} vs. ${bVert.size}.`);
|
|
493
|
-
return false;
|
|
494
|
-
}
|
|
495
|
-
for (const [id, aInfo] of aVert) {
|
|
496
|
-
const bInfo = bVert.get(id);
|
|
497
|
-
if (bInfo === undefined || aInfo.name !== bInfo.name || equalChildren(aInfo.children, bInfo.children)) {
|
|
498
|
-
log_1.log.debug(`vertex ${id} differs ${JSON.stringify(aInfo, json_1.jsonReplacer)} vs. ${JSON.stringify(bInfo, json_1.jsonReplacer)}.`);
|
|
499
|
-
return false;
|
|
500
|
-
}
|
|
501
|
-
}
|
|
502
|
-
const aEdges = a.edges();
|
|
503
|
-
const bEdges = b.edges();
|
|
504
|
-
if (aEdges.size !== bEdges.size) {
|
|
505
|
-
log_1.log.debug(`edge count differs ${aEdges.size} vs. ${bEdges.size}.`);
|
|
506
|
-
return false;
|
|
507
|
-
}
|
|
508
|
-
for (const [from, aTo] of aEdges) {
|
|
509
|
-
const bTo = bEdges.get(from);
|
|
510
|
-
if (bTo === undefined || aTo.size !== bTo.size) {
|
|
511
|
-
log_1.log.debug(`edge count for ${from} differs ${aTo.size} vs. ${bTo?.size ?? '?'}.`);
|
|
512
|
-
return false;
|
|
513
|
-
}
|
|
514
|
-
for (const [to, aEdge] of aTo) {
|
|
515
|
-
const bEdge = bTo.get(to);
|
|
516
|
-
if (bEdge === undefined || aEdge.label !== bEdge.label) {
|
|
517
|
-
log_1.log.debug(`edge ${from} -> ${to} differs ${JSON.stringify(aEdge, json_1.jsonReplacer)} vs. ${JSON.stringify(bEdge, json_1.jsonReplacer)}.`);
|
|
518
|
-
return false;
|
|
519
|
-
}
|
|
520
|
-
}
|
|
521
|
-
}
|
|
522
|
-
return true;
|
|
523
|
-
}
|
|
524
|
-
/**
|
|
525
|
-
* @see df2quads
|
|
526
|
-
* @see serialize2quads
|
|
527
|
-
* @see graph2quads
|
|
528
|
-
*/
|
|
529
|
-
function cfg2quads(cfg, config) {
|
|
530
|
-
return (0, quads_1.graph2quads)({
|
|
531
|
-
rootIds: [...cfg.graph.rootVertexIds()],
|
|
532
|
-
vertices: [...cfg.graph.vertices().entries()]
|
|
533
|
-
.map(([id, v]) => ({
|
|
534
|
-
id,
|
|
535
|
-
name: v.name,
|
|
536
|
-
children: v.children
|
|
537
|
-
})),
|
|
538
|
-
edges: [...cfg.graph.edges()].flatMap(([fromId, targets]) => [...targets].map(([toId, info]) => ({
|
|
539
|
-
from: fromId,
|
|
540
|
-
to: toId,
|
|
541
|
-
type: info.label,
|
|
542
|
-
when: info.when
|
|
543
|
-
}))),
|
|
544
|
-
entryPoints: cfg.entryPoints,
|
|
545
|
-
exitPoints: cfg.exitPoints,
|
|
546
|
-
breaks: cfg.breaks,
|
|
547
|
-
nexts: cfg.nexts,
|
|
548
|
-
returns: cfg.returns
|
|
549
|
-
}, config);
|
|
550
|
-
}
|
|
551
2
|
//# sourceMappingURL=cfg.js.map
|
|
@@ -64,4 +64,27 @@ export declare function arraySum(arr: readonly number[]): number;
|
|
|
64
64
|
* Converts an array into a bag data-structure (in the form of a map mapping the entries/keys to their counts)
|
|
65
65
|
*/
|
|
66
66
|
export declare function array2bag<T>(arr: T[]): Map<T, number>;
|
|
67
|
-
export declare function arrayEqual<T>(a: readonly T[] | undefined, b: readonly T[] | undefined): boolean;
|
|
67
|
+
export declare function arrayEqual<T>(a: readonly T[] | undefined, b: readonly T[] | undefined, cmp?: (a: T, b: T) => boolean): boolean;
|
|
68
|
+
/**
|
|
69
|
+
* Samples elements from a list such that the distance between the sampled elements is as equal as possible.
|
|
70
|
+
*
|
|
71
|
+
* If the number of elements to sample is greater or equal to the number of elements in the list, the list is returned as is.
|
|
72
|
+
* If the number of elements to sample is less than or equal to 0, an empty list is returned.
|
|
73
|
+
*
|
|
74
|
+
* @param list - list of elements
|
|
75
|
+
* @param sampleCount - number of elements to sample
|
|
76
|
+
* @param rounding - rounding mode to use for the index calculation
|
|
77
|
+
* @returns - a list of elements equidistantly sampled from the input list
|
|
78
|
+
*/
|
|
79
|
+
export declare function equidistantSampling<T>(list: readonly T[], sampleCount: number, rounding?: 'floor' | 'ceil'): T[];
|
|
80
|
+
/**
|
|
81
|
+
* Returns the cartesian product of the given arrays.
|
|
82
|
+
* @example
|
|
83
|
+
*
|
|
84
|
+
* ```ts
|
|
85
|
+
* cartesianProduct([1, 2], ['a', 'b', 'c'], [true, false])
|
|
86
|
+
* // -> [[1, 'a', true], [1, 'a', false], [1, 'b', true], [1, 'b', false], [1, 'c', true], [1, 'c', false], [2, 'a', true], [2, 'a', false], [2, 'b', true], [2, 'b', false], [2, 'c', true], [2, 'c', false]]
|
|
87
|
+
* ```
|
|
88
|
+
*
|
|
89
|
+
*/
|
|
90
|
+
export declare function cartesianProduct<T>(...arrays: T[][]): T[][];
|
|
@@ -8,7 +8,9 @@ exports.getUniqueCombinationsOfSize = getUniqueCombinationsOfSize;
|
|
|
8
8
|
exports.arraySum = arraySum;
|
|
9
9
|
exports.array2bag = array2bag;
|
|
10
10
|
exports.arrayEqual = arrayEqual;
|
|
11
|
-
|
|
11
|
+
exports.equidistantSampling = equidistantSampling;
|
|
12
|
+
exports.cartesianProduct = cartesianProduct;
|
|
13
|
+
const assert_1 = require("../assert");
|
|
12
14
|
/**
|
|
13
15
|
* Splits the array every time the given predicate fires.
|
|
14
16
|
* The element the split appears on will not be included!
|
|
@@ -160,7 +162,7 @@ function array2bag(arr) {
|
|
|
160
162
|
}
|
|
161
163
|
return result;
|
|
162
164
|
}
|
|
163
|
-
function arrayEqual(a, b) {
|
|
165
|
+
function arrayEqual(a, b, cmp = (a, b) => a === b) {
|
|
164
166
|
if (a === undefined || b === undefined) {
|
|
165
167
|
return a === b;
|
|
166
168
|
}
|
|
@@ -168,10 +170,49 @@ function arrayEqual(a, b) {
|
|
|
168
170
|
return false;
|
|
169
171
|
}
|
|
170
172
|
for (let i = 0; i < a.length; i++) {
|
|
171
|
-
if (a[i]
|
|
173
|
+
if (!cmp(a[i], b[i])) {
|
|
172
174
|
return false;
|
|
173
175
|
}
|
|
174
176
|
}
|
|
175
177
|
return true;
|
|
176
178
|
}
|
|
179
|
+
/**
|
|
180
|
+
* Samples elements from a list such that the distance between the sampled elements is as equal as possible.
|
|
181
|
+
*
|
|
182
|
+
* If the number of elements to sample is greater or equal to the number of elements in the list, the list is returned as is.
|
|
183
|
+
* If the number of elements to sample is less than or equal to 0, an empty list is returned.
|
|
184
|
+
*
|
|
185
|
+
* @param list - list of elements
|
|
186
|
+
* @param sampleCount - number of elements to sample
|
|
187
|
+
* @param rounding - rounding mode to use for the index calculation
|
|
188
|
+
* @returns - a list of elements equidistantly sampled from the input list
|
|
189
|
+
*/
|
|
190
|
+
function equidistantSampling(list, sampleCount, rounding = 'ceil') {
|
|
191
|
+
if (sampleCount >= list.length) {
|
|
192
|
+
return list.slice();
|
|
193
|
+
}
|
|
194
|
+
else if (sampleCount <= 0) {
|
|
195
|
+
return [];
|
|
196
|
+
}
|
|
197
|
+
const result = [];
|
|
198
|
+
const step = list.length / sampleCount;
|
|
199
|
+
for (let i = 0; i < sampleCount; i++) {
|
|
200
|
+
const index = rounding === 'floor' ? Math.floor(i * step) : Math.ceil(i * step);
|
|
201
|
+
result.push(list[index]);
|
|
202
|
+
}
|
|
203
|
+
return result;
|
|
204
|
+
}
|
|
205
|
+
/**
|
|
206
|
+
* Returns the cartesian product of the given arrays.
|
|
207
|
+
* @example
|
|
208
|
+
*
|
|
209
|
+
* ```ts
|
|
210
|
+
* cartesianProduct([1, 2], ['a', 'b', 'c'], [true, false])
|
|
211
|
+
* // -> [[1, 'a', true], [1, 'a', false], [1, 'b', true], [1, 'b', false], [1, 'c', true], [1, 'c', false], [2, 'a', true], [2, 'a', false], [2, 'b', true], [2, 'b', false], [2, 'c', true], [2, 'c', false]]
|
|
212
|
+
* ```
|
|
213
|
+
*
|
|
214
|
+
*/
|
|
215
|
+
function cartesianProduct(...arrays) {
|
|
216
|
+
return arrays.reduce((a, b) => a.flatMap(x => b.map(y => x.concat(y))), [[]]);
|
|
217
|
+
}
|
|
177
218
|
//# sourceMappingURL=arrays.js.map
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.setEquals = setEquals;
|
|
4
|
+
exports.setMinus = setMinus;
|
|
5
|
+
/**
|
|
6
|
+
* Given both sets, this checks if they contain the same elements.
|
|
7
|
+
*/
|
|
8
|
+
function setEquals(a, b) {
|
|
9
|
+
return a.symmetricDifference(b).size === 0;
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Returns `A – B`
|
|
13
|
+
*/
|
|
14
|
+
function setMinus(a, b) {
|
|
15
|
+
return a.difference(b);
|
|
16
|
+
}
|
|
17
|
+
//# sourceMappingURL=set.js.map
|