@eagleoutice/flowr 2.2.12 → 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.
Files changed (256) hide show
  1. package/README.md +82 -20
  2. package/benchmark/slicer.js +2 -2
  3. package/benchmark/summarizer/first-phase/input.js +1 -1
  4. package/benchmark/summarizer/first-phase/process.js +3 -3
  5. package/benchmark/summarizer/second-phase/process.js +1 -1
  6. package/benchmark/summarizer/summarizer.js +1 -1
  7. package/cli/common/options.js +4 -4
  8. package/cli/common/script.js +1 -1
  9. package/cli/flowr.js +1 -1
  10. package/cli/repl/commands/repl-cfg.d.ts +2 -0
  11. package/cli/repl/commands/repl-cfg.js +38 -24
  12. package/cli/repl/commands/repl-commands.js +4 -2
  13. package/cli/repl/commands/repl-dataflow.js +3 -3
  14. package/cli/repl/commands/repl-execute.js +1 -1
  15. package/cli/repl/commands/repl-main.d.ts +1 -1
  16. package/cli/repl/commands/repl-main.js +1 -1
  17. package/cli/repl/commands/repl-normalize.js +1 -1
  18. package/cli/repl/commands/repl-query.js +2 -2
  19. package/cli/repl/core.js +1 -1
  20. package/cli/repl/prompt.js +1 -1
  21. package/cli/repl/server/connection.js +4 -4
  22. package/cli/repl/server/messages/message-analysis.d.ts +1 -1
  23. package/cli/script-core/statistics-core.js +1 -1
  24. package/cli/script-core/statistics-helper-core.js +4 -4
  25. package/config.d.ts +47 -24
  26. package/config.js +3 -3
  27. package/control-flow/basic-cfg-guided-visitor.d.ts +39 -0
  28. package/control-flow/basic-cfg-guided-visitor.js +114 -0
  29. package/control-flow/cfg-properties.d.ts +26 -0
  30. package/control-flow/cfg-properties.js +100 -0
  31. package/control-flow/cfg-simplification.d.ts +18 -0
  32. package/control-flow/cfg-simplification.js +55 -0
  33. package/control-flow/cfg-to-basic-blocks.d.ts +5 -0
  34. package/control-flow/cfg-to-basic-blocks.js +81 -0
  35. package/control-flow/control-flow-graph.d.ts +247 -0
  36. package/control-flow/control-flow-graph.js +290 -0
  37. package/control-flow/dfg-cfg-guided-visitor.d.ts +32 -0
  38. package/control-flow/dfg-cfg-guided-visitor.js +71 -0
  39. package/control-flow/diff-cfg.d.ts +11 -0
  40. package/control-flow/diff-cfg.js +161 -0
  41. package/control-flow/extract-cfg.d.ts +30 -0
  42. package/control-flow/extract-cfg.js +475 -0
  43. package/control-flow/happens-before.d.ts +7 -0
  44. package/{util/cfg → control-flow}/happens-before.js +3 -3
  45. package/control-flow/semantic-cfg-guided-visitor.d.ts +452 -0
  46. package/control-flow/semantic-cfg-guided-visitor.js +492 -0
  47. package/control-flow/simple-visitor.d.ts +25 -0
  48. package/control-flow/simple-visitor.js +80 -0
  49. package/control-flow/syntax-cfg-guided-visitor.d.ts +128 -0
  50. package/control-flow/syntax-cfg-guided-visitor.js +166 -0
  51. package/core/print/print.d.ts +1 -1
  52. package/core/print/slice-diff-ansi.js +1 -1
  53. package/core/steps/pipeline/create-pipeline.js +1 -1
  54. package/dataflow/environments/built-in-config.js +9 -6
  55. package/dataflow/environments/built-in.d.ts +8 -4
  56. package/dataflow/environments/built-in.js +47 -5
  57. package/dataflow/environments/default-builtin-config.d.ts +2 -0
  58. package/dataflow/environments/default-builtin-config.js +81 -14
  59. package/dataflow/environments/resolve-by-name.js +15 -4
  60. package/dataflow/extractor.js +2 -2
  61. package/dataflow/graph/dataflowgraph-builder.d.ts +3 -1
  62. package/dataflow/graph/dataflowgraph-builder.js +4 -2
  63. package/dataflow/graph/diff-dataflow-graph.d.ts +16 -0
  64. package/dataflow/graph/{diff.js → diff-dataflow-graph.js} +30 -56
  65. package/dataflow/graph/graph.d.ts +11 -3
  66. package/dataflow/graph/graph.js +27 -12
  67. package/dataflow/graph/vertex.d.ts +17 -2
  68. package/dataflow/internal/linker.d.ts +3 -2
  69. package/dataflow/internal/linker.js +33 -24
  70. package/dataflow/internal/process/functions/call/argument/unpack-argument.d.ts +1 -1
  71. package/dataflow/internal/process/functions/call/argument/unpack-argument.js +1 -1
  72. package/dataflow/internal/process/functions/call/built-in/built-in-access.js +12 -9
  73. package/dataflow/internal/process/functions/call/built-in/built-in-apply.d.ts +1 -1
  74. package/dataflow/internal/process/functions/call/built-in/built-in-apply.js +84 -16
  75. package/dataflow/internal/process/functions/call/built-in/built-in-assignment.js +23 -16
  76. package/dataflow/internal/process/functions/call/built-in/built-in-eval.js +5 -5
  77. package/dataflow/internal/process/functions/call/built-in/built-in-expression-list.js +9 -4
  78. package/dataflow/internal/process/functions/call/built-in/built-in-for-loop.js +3 -2
  79. package/dataflow/internal/process/functions/call/built-in/built-in-function-definition.js +15 -4
  80. package/dataflow/internal/process/functions/call/built-in/built-in-get.js +4 -3
  81. package/dataflow/internal/process/functions/call/built-in/built-in-if-then-else.js +4 -3
  82. package/dataflow/internal/process/functions/call/built-in/built-in-library.js +4 -3
  83. package/dataflow/internal/process/functions/call/built-in/built-in-list.js +1 -1
  84. package/dataflow/internal/process/functions/call/built-in/built-in-pipe.js +1 -1
  85. package/dataflow/internal/process/functions/call/built-in/built-in-quote.js +9 -7
  86. package/dataflow/internal/process/functions/call/built-in/built-in-repeat-loop.js +3 -2
  87. package/dataflow/internal/process/functions/call/built-in/built-in-replacement.d.ts +1 -0
  88. package/dataflow/internal/process/functions/call/built-in/built-in-replacement.js +19 -4
  89. package/dataflow/internal/process/functions/call/built-in/built-in-rm.js +2 -2
  90. package/dataflow/internal/process/functions/call/built-in/built-in-source.js +19 -4
  91. package/dataflow/internal/process/functions/call/built-in/built-in-special-bin-op.js +4 -3
  92. package/dataflow/internal/process/functions/call/built-in/built-in-vector.js +3 -3
  93. package/dataflow/internal/process/functions/call/built-in/built-in-while-loop.js +3 -3
  94. package/dataflow/internal/process/functions/call/common.d.ts +4 -1
  95. package/dataflow/internal/process/functions/call/common.js +5 -3
  96. package/dataflow/internal/process/functions/call/known-call-handling.d.ts +3 -2
  97. package/dataflow/internal/process/functions/call/known-call-handling.js +2 -1
  98. package/dataflow/internal/process/functions/call/named-call-handling.js +1 -1
  99. package/dataflow/internal/process/functions/call/unnamed-call-handling.d.ts +1 -0
  100. package/dataflow/internal/process/functions/call/unnamed-call-handling.js +6 -4
  101. package/dataflow/internal/process/process-named-call.d.ts +1 -1
  102. package/dataflow/internal/process/process-named-call.js +5 -5
  103. package/dataflow/origin/dfg-get-origin.d.ts +82 -0
  104. package/dataflow/origin/dfg-get-origin.js +116 -0
  105. package/documentation/doc-util/doc-cfg.d.ts +13 -6
  106. package/documentation/doc-util/doc-cfg.js +19 -14
  107. package/documentation/doc-util/doc-cli-option.js +4 -2
  108. package/documentation/doc-util/doc-dfg.js +3 -3
  109. package/documentation/doc-util/doc-escape.d.ts +7 -0
  110. package/documentation/doc-util/doc-escape.js +19 -0
  111. package/documentation/doc-util/doc-files.d.ts +1 -0
  112. package/documentation/doc-util/doc-files.js +2 -1
  113. package/documentation/doc-util/doc-normalized-ast.js +3 -3
  114. package/documentation/doc-util/doc-query.js +2 -2
  115. package/documentation/doc-util/doc-repl.js +1 -1
  116. package/documentation/doc-util/doc-search.js +1 -1
  117. package/documentation/doc-util/doc-server-message.js +2 -2
  118. package/documentation/doc-util/doc-structure.d.ts +1 -0
  119. package/documentation/doc-util/doc-structure.js +5 -0
  120. package/documentation/doc-util/doc-types.d.ts +7 -1
  121. package/documentation/doc-util/doc-types.js +13 -2
  122. package/documentation/print-capabilities-markdown.js +27 -1
  123. package/documentation/print-cfg-wiki.js +505 -17
  124. package/documentation/print-dataflow-graph-wiki.js +180 -25
  125. package/documentation/print-engines-wiki.js +1 -1
  126. package/documentation/print-faq-wiki.d.ts +1 -0
  127. package/documentation/print-faq-wiki.js +75 -0
  128. package/documentation/print-interface-wiki.js +1 -1
  129. package/documentation/print-linting-and-testing-wiki.js +52 -36
  130. package/documentation/print-normalized-ast-wiki.js +1 -1
  131. package/documentation/print-onboarding-wiki.d.ts +1 -0
  132. package/documentation/print-onboarding-wiki.js +42 -0
  133. package/documentation/print-query-wiki.js +21 -1
  134. package/documentation/print-readme.js +10 -3
  135. package/package.json +9 -6
  136. package/queries/catalog/call-context-query/call-context-query-executor.js +5 -5
  137. package/queries/catalog/call-context-query/call-context-query-format.d.ts +1 -1
  138. package/queries/catalog/call-context-query/call-context-query-format.js +2 -2
  139. package/queries/catalog/call-context-query/identify-link-to-last-call-relation.d.ts +2 -2
  140. package/queries/catalog/call-context-query/identify-link-to-last-call-relation.js +24 -21
  141. package/queries/catalog/cluster-query/cluster-query-format.d.ts +1 -1
  142. package/queries/catalog/cluster-query/cluster-query-format.js +1 -1
  143. package/queries/catalog/config-query/config-query-format.d.ts +1 -1
  144. package/queries/catalog/config-query/config-query-format.js +2 -2
  145. package/queries/catalog/dataflow-lens-query/dataflow-lens-query-format.d.ts +1 -1
  146. package/queries/catalog/dataflow-lens-query/dataflow-lens-query-format.js +2 -2
  147. package/queries/catalog/dataflow-query/dataflow-query-format.d.ts +1 -1
  148. package/queries/catalog/dataflow-query/dataflow-query-format.js +2 -2
  149. package/queries/catalog/dependencies-query/dependencies-query-executor.js +4 -2
  150. package/queries/catalog/dependencies-query/dependencies-query-format.d.ts +1 -1
  151. package/queries/catalog/dependencies-query/dependencies-query-format.js +2 -2
  152. package/queries/catalog/happens-before-query/happens-before-query-executor.d.ts +1 -1
  153. package/queries/catalog/happens-before-query/happens-before-query-executor.js +4 -4
  154. package/queries/catalog/happens-before-query/happens-before-query-format.d.ts +1 -1
  155. package/queries/catalog/happens-before-query/happens-before-query-format.js +2 -2
  156. package/queries/catalog/id-map-query/id-map-query-format.d.ts +1 -1
  157. package/queries/catalog/id-map-query/id-map-query-format.js +2 -2
  158. package/queries/catalog/lineage-query/lineage-query-format.d.ts +1 -1
  159. package/queries/catalog/lineage-query/lineage-query-format.js +2 -2
  160. package/queries/catalog/location-map-query/location-map-query-format.d.ts +1 -1
  161. package/queries/catalog/location-map-query/location-map-query-format.js +2 -2
  162. package/queries/catalog/normalized-ast-query/normalized-ast-query-format.d.ts +1 -1
  163. package/queries/catalog/normalized-ast-query/normalized-ast-query-format.js +2 -2
  164. package/queries/catalog/origin-query/origin-query-executor.d.ts +5 -0
  165. package/queries/catalog/origin-query/origin-query-executor.js +33 -0
  166. package/queries/catalog/origin-query/origin-query-format.d.ts +71 -0
  167. package/queries/catalog/origin-query/origin-query-format.js +27 -0
  168. package/queries/catalog/project-query/project-query-format.d.ts +1 -1
  169. package/queries/catalog/project-query/project-query-format.js +2 -2
  170. package/queries/catalog/resolve-value-query/resolve-value-query-format.d.ts +1 -1
  171. package/queries/catalog/resolve-value-query/resolve-value-query-format.js +2 -2
  172. package/queries/catalog/search-query/search-query-format.d.ts +1 -1
  173. package/queries/catalog/search-query/search-query-format.js +2 -2
  174. package/queries/catalog/static-slice-query/static-slice-query-format.d.ts +1 -1
  175. package/queries/catalog/static-slice-query/static-slice-query-format.js +2 -2
  176. package/queries/query-print.d.ts +1 -1
  177. package/queries/query-print.js +4 -4
  178. package/queries/query.d.ts +61 -2
  179. package/queries/query.js +3 -1
  180. package/r-bridge/lang-4.x/ast/model/nodes/r-number.d.ts +3 -2
  181. package/r-bridge/lang-4.x/ast/model/nodes/r-number.js +5 -0
  182. package/r-bridge/lang-4.x/ast/model/nodes/r-string.d.ts +3 -2
  183. package/r-bridge/lang-4.x/ast/model/nodes/r-string.js +5 -0
  184. package/r-bridge/lang-4.x/ast/model/processing/decorate.d.ts +1 -1
  185. package/r-bridge/lang-4.x/ast/model/processing/decorate.js +1 -1
  186. package/r-bridge/lang-4.x/ast/model/processing/fold.js +3 -1
  187. package/r-bridge/lang-4.x/ast/model/processing/stateful-fold.d.ts +1 -1
  188. package/r-bridge/lang-4.x/ast/parser/main/internal/expression/normalize-expression.js +1 -1
  189. package/r-bridge/lang-4.x/ast/parser/main/internal/functions/normalize-argument.js +1 -1
  190. package/r-bridge/lang-4.x/ast/parser/main/internal/functions/normalize-call.js +1 -1
  191. package/r-bridge/lang-4.x/ast/parser/main/internal/functions/normalize-definition.js +1 -1
  192. package/r-bridge/lang-4.x/ast/parser/main/internal/normalize-access.js +1 -1
  193. package/r-bridge/lang-4.x/ast/parser/main/internal/operators/normalize-binary.js +1 -1
  194. package/r-bridge/lang-4.x/ast/parser/main/internal/structure/normalize-root.js +1 -1
  195. package/r-bridge/lang-4.x/ast/parser/main/internal/values/normalize-symbol.js +1 -1
  196. package/r-bridge/lang-4.x/tree-sitter/tree-sitter-executor.d.ts +2 -2
  197. package/r-bridge/lang-4.x/tree-sitter/tree-sitter-executor.js +4 -4
  198. package/r-bridge/lang-4.x/tree-sitter/tree-sitter-normalize.js +26 -8
  199. package/r-bridge/retriever.js +1 -1
  200. package/search/search-executor/search-generators.d.ts +1 -1
  201. package/search/search-executor/search-transformer.d.ts +1 -1
  202. package/slicing/criterion/collect-all.js +1 -1
  203. package/slicing/static/slice-call.js +13 -3
  204. package/statistics/features/supported/assignments/post-process.js +1 -1
  205. package/statistics/features/supported/defined-functions/post-process.js +2 -2
  206. package/statistics/features/supported/used-functions/post-process.js +1 -1
  207. package/statistics/features/supported/used-packages/post-process.js +2 -2
  208. package/statistics/features/supported/values/post-process.js +2 -2
  209. package/statistics/output/print-stats.js +2 -2
  210. package/statistics/summarizer/post-process/clusterer.d.ts +1 -1
  211. package/statistics/summarizer/post-process/clusterer.js +1 -1
  212. package/statistics/summarizer/post-process/histogram.js +3 -3
  213. package/statistics/summarizer/post-process/post-process-output.js +3 -3
  214. package/statistics/summarizer/second-phase/process.js +2 -2
  215. package/statistics/summarizer/summarizer.js +2 -2
  216. package/util/assert.js +36 -1
  217. package/util/cfg/cfg.d.ts +0 -80
  218. package/util/cfg/cfg.js +0 -549
  219. package/util/{arrays.d.ts → collections/arrays.d.ts} +1 -1
  220. package/util/{arrays.js → collections/arrays.js} +3 -3
  221. package/util/collections/set.js +17 -0
  222. package/util/diff-graph.d.ts +47 -0
  223. package/util/diff-graph.js +61 -0
  224. package/util/diff.d.ts +6 -6
  225. package/util/diff.js +1 -1
  226. package/util/mermaid/cfg.d.ts +9 -2
  227. package/util/mermaid/cfg.js +64 -12
  228. package/util/mermaid/dfg.d.ts +2 -1
  229. package/util/mermaid/dfg.js +26 -10
  230. package/util/mermaid/mermaid.d.ts +2 -0
  231. package/util/mermaid/mermaid.js +6 -0
  232. package/util/quads.js +1 -1
  233. package/util/schema.d.ts +1 -1
  234. package/util/schema.js +1 -1
  235. package/util/summarizer.js +1 -1
  236. package/util/{text.js → text/text.js} +1 -1
  237. package/util/{time.js → text/time.js} +1 -1
  238. package/util/version.js +1 -1
  239. package/dataflow/graph/diff.d.ts +0 -36
  240. package/util/cfg/happens-before.d.ts +0 -7
  241. package/util/cfg/visitor.d.ts +0 -9
  242. package/util/cfg/visitor.js +0 -30
  243. package/util/set.js +0 -31
  244. /package/util/{bimap.d.ts → collections/bimap.d.ts} +0 -0
  245. /package/util/{bimap.js → collections/bimap.js} +0 -0
  246. /package/util/{defaultmap.d.ts → collections/defaultmap.d.ts} +0 -0
  247. /package/util/{defaultmap.js → collections/defaultmap.js} +0 -0
  248. /package/util/{set.d.ts → collections/set.d.ts} +0 -0
  249. /package/util/{ansi.d.ts → text/ansi.d.ts} +0 -0
  250. /package/util/{ansi.js → text/ansi.js} +0 -0
  251. /package/util/{args.d.ts → text/args.d.ts} +0 -0
  252. /package/util/{args.js → text/args.js} +0 -0
  253. /package/util/{strings.d.ts → text/strings.d.ts} +0 -0
  254. /package/util/{strings.js → text/strings.js} +0 -0
  255. /package/util/{text.d.ts → text/text.d.ts} +0 -0
  256. /package/util/{time.d.ts → text/time.d.ts} +0 -0
package/util/cfg/cfg.d.ts CHANGED
@@ -1,80 +0,0 @@
1
- import type { MergeableRecord } from '../objects';
2
- import type { QuadSerializationConfiguration } from '../quads';
3
- import type { NodeId } from '../../r-bridge/lang-4.x/ast/model/processing/node-id';
4
- import type { NormalizedAst, ParentInformation } from '../../r-bridge/lang-4.x/ast/model/processing/decorate';
5
- import { RFalse, RTrue } from '../../r-bridge/lang-4.x/convert-values';
6
- import type { DataflowGraph } from '../../dataflow/graph/graph';
7
- export declare const enum CfgVertexType {
8
- /** Marks a break point in a construct (e.g., between the name and the value of an argument, or the formals and the body of a function) */
9
- MidMarker = "mid-marker",
10
- /** The explicit exit-nodes to ensure the hammock property */
11
- EndMarker = "end-marker",
12
- /** something like an if, assignment, ... even though in the classical sense of R they are still expressions */
13
- Statement = "statement",
14
- /** something like an addition, ... */
15
- Expression = "expression"
16
- }
17
- export interface CfgVertex {
18
- id: NodeId;
19
- type: CfgVertexType;
20
- name: string;
21
- /** in case of a function definition */
22
- children?: NodeId[];
23
- }
24
- interface CfgFlowDependencyEdge extends MergeableRecord {
25
- label: 'FD';
26
- }
27
- interface CfgControlDependencyEdge extends MergeableRecord {
28
- label: 'CD';
29
- /** the id which caused the control dependency */
30
- caused: NodeId;
31
- when: typeof RTrue | typeof RFalse;
32
- }
33
- export type CfgEdge = CfgFlowDependencyEdge | CfgControlDependencyEdge;
34
- /**
35
- * This class represents the control flow graph of an R program.
36
- * The control flow may be hierarchical when confronted with function definitions (see {@link CfgVertex} and {@link CFG#rootVertexIds|rootVertexIds()}).
37
- */
38
- export declare class ControlFlowGraph {
39
- private rootVertices;
40
- private vertexInformation;
41
- private edgeInformation;
42
- addVertex(vertex: CfgVertex, rootVertex?: boolean): this;
43
- addEdge(from: NodeId, to: NodeId, edge: CfgEdge): this;
44
- outgoing(node: NodeId): ReadonlyMap<NodeId, CfgEdge> | undefined;
45
- rootVertexIds(): ReadonlySet<NodeId>;
46
- vertices(): ReadonlyMap<NodeId, CfgVertex>;
47
- edges(): ReadonlyMap<NodeId, ReadonlyMap<NodeId, CfgEdge>>;
48
- merge(other: ControlFlowGraph, forceNested?: boolean): this;
49
- }
50
- export interface ControlFlowInformation extends MergeableRecord {
51
- returns: NodeId[];
52
- breaks: NodeId[];
53
- nexts: NodeId[];
54
- /** intended to construct a hammock graph, with 0 exit points representing a block that should not be part of the CFG (like a comment) */
55
- entryPoints: NodeId[];
56
- /** See {@link ControlFlowInformation#entryPoints|entryPoints} */
57
- exitPoints: NodeId[];
58
- graph: ControlFlowGraph;
59
- }
60
- export declare function emptyControlFlowInformation(): ControlFlowInformation;
61
- /**
62
- * Given a normalized AST this approximates the control flow graph of the program.
63
- * This few is different from the computation of the dataflow graph and may differ,
64
- * especially because it focuses on intra-procedural analysis.
65
- *
66
- * @param ast - the normalized AST
67
- * @param graph - additional dataflow facts to consider by the control flow extraction
68
- */
69
- export declare function extractCFG<Info = ParentInformation>(ast: NormalizedAst<Info>, graph?: DataflowGraph): ControlFlowInformation;
70
- /**
71
- * Returns true if the given CFG equals the other CFG. False otherwise.
72
- */
73
- export declare function equalCfg(a: ControlFlowGraph | undefined, b: ControlFlowGraph | undefined): boolean;
74
- /**
75
- * @see df2quads
76
- * @see serialize2quads
77
- * @see graph2quads
78
- */
79
- export declare function cfg2quads(cfg: ControlFlowInformation, config: QuadSerializationConfiguration): string;
80
- export {};
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,7 +64,7 @@ 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
68
  /**
69
69
  * Samples elements from a list such that the distance between the sampled elements is as equal as possible.
70
70
  *
@@ -10,7 +10,7 @@ exports.array2bag = array2bag;
10
10
  exports.arrayEqual = arrayEqual;
11
11
  exports.equidistantSampling = equidistantSampling;
12
12
  exports.cartesianProduct = cartesianProduct;
13
- const assert_1 = require("./assert");
13
+ const assert_1 = require("../assert");
14
14
  /**
15
15
  * Splits the array every time the given predicate fires.
16
16
  * The element the split appears on will not be included!
@@ -162,7 +162,7 @@ function array2bag(arr) {
162
162
  }
163
163
  return result;
164
164
  }
165
- function arrayEqual(a, b) {
165
+ function arrayEqual(a, b, cmp = (a, b) => a === b) {
166
166
  if (a === undefined || b === undefined) {
167
167
  return a === b;
168
168
  }
@@ -170,7 +170,7 @@ function arrayEqual(a, b) {
170
170
  return false;
171
171
  }
172
172
  for (let i = 0; i < a.length; i++) {
173
- if (a[i] !== b[i]) {
173
+ if (!cmp(a[i], b[i])) {
174
174
  return false;
175
175
  }
176
176
  }
@@ -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