@eagleoutice/flowr 2.2.12 → 2.2.14

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 (282) 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 +20 -15
  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 +508 -20
  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-linter-wiki.d.ts +1 -0
  130. package/documentation/print-linter-wiki.js +76 -0
  131. package/documentation/print-linting-and-testing-wiki.js +52 -36
  132. package/documentation/print-normalized-ast-wiki.js +1 -1
  133. package/documentation/print-onboarding-wiki.d.ts +1 -0
  134. package/documentation/print-onboarding-wiki.js +42 -0
  135. package/documentation/print-query-wiki.js +21 -1
  136. package/documentation/print-readme.js +10 -3
  137. package/linter/linter-executor.d.ts +9 -0
  138. package/linter/linter-executor.js +26 -0
  139. package/linter/linter-format.d.ts +65 -0
  140. package/linter/linter-format.js +9 -0
  141. package/linter/linter-rules.d.ts +42 -0
  142. package/linter/linter-rules.js +14 -0
  143. package/linter/rules/1-deprecated-functions.d.ts +34 -0
  144. package/linter/rules/1-deprecated-functions.js +54 -0
  145. package/linter/rules/2-file-path-validity.d.ts +48 -0
  146. package/linter/rules/2-file-path-validity.js +93 -0
  147. package/package.json +10 -6
  148. package/queries/catalog/call-context-query/call-context-query-executor.js +5 -5
  149. package/queries/catalog/call-context-query/call-context-query-format.d.ts +3 -3
  150. package/queries/catalog/call-context-query/call-context-query-format.js +7 -3
  151. package/queries/catalog/call-context-query/identify-link-to-last-call-relation.d.ts +2 -2
  152. package/queries/catalog/call-context-query/identify-link-to-last-call-relation.js +24 -21
  153. package/queries/catalog/cluster-query/cluster-query-format.d.ts +3 -1
  154. package/queries/catalog/cluster-query/cluster-query-format.js +6 -2
  155. package/queries/catalog/config-query/config-query-format.d.ts +2 -1
  156. package/queries/catalog/config-query/config-query-format.js +4 -3
  157. package/queries/catalog/dataflow-lens-query/dataflow-lens-query-format.d.ts +2 -1
  158. package/queries/catalog/dataflow-lens-query/dataflow-lens-query-format.js +4 -3
  159. package/queries/catalog/dataflow-query/dataflow-query-format.d.ts +3 -1
  160. package/queries/catalog/dataflow-query/dataflow-query-format.js +11 -3
  161. package/queries/catalog/dependencies-query/dependencies-query-executor.js +4 -2
  162. package/queries/catalog/dependencies-query/dependencies-query-format.d.ts +2 -1
  163. package/queries/catalog/dependencies-query/dependencies-query-format.js +12 -3
  164. package/queries/catalog/happens-before-query/happens-before-query-executor.d.ts +1 -1
  165. package/queries/catalog/happens-before-query/happens-before-query-executor.js +4 -4
  166. package/queries/catalog/happens-before-query/happens-before-query-format.d.ts +2 -1
  167. package/queries/catalog/happens-before-query/happens-before-query-format.js +4 -3
  168. package/queries/catalog/id-map-query/id-map-query-format.d.ts +2 -1
  169. package/queries/catalog/id-map-query/id-map-query-format.js +4 -3
  170. package/queries/catalog/lineage-query/lineage-query-format.d.ts +2 -1
  171. package/queries/catalog/lineage-query/lineage-query-format.js +7 -3
  172. package/queries/catalog/linter-query/linter-query-executor.d.ts +3 -0
  173. package/queries/catalog/linter-query/linter-query-executor.js +28 -0
  174. package/queries/catalog/linter-query/linter-query-format.d.ts +80 -0
  175. package/queries/catalog/linter-query/linter-query-format.js +43 -0
  176. package/queries/catalog/location-map-query/location-map-query-format.d.ts +2 -1
  177. package/queries/catalog/location-map-query/location-map-query-format.js +4 -3
  178. package/queries/catalog/normalized-ast-query/normalized-ast-query-format.d.ts +2 -1
  179. package/queries/catalog/normalized-ast-query/normalized-ast-query-format.js +4 -3
  180. package/queries/catalog/origin-query/origin-query-executor.d.ts +5 -0
  181. package/queries/catalog/origin-query/origin-query-executor.js +33 -0
  182. package/queries/catalog/origin-query/origin-query-format.d.ts +73 -0
  183. package/queries/catalog/origin-query/origin-query-format.js +31 -0
  184. package/queries/catalog/project-query/project-query-executor.js +1 -1
  185. package/queries/catalog/project-query/project-query-format.d.ts +2 -1
  186. package/queries/catalog/project-query/project-query-format.js +4 -3
  187. package/queries/catalog/resolve-value-query/resolve-value-query-format.d.ts +2 -1
  188. package/queries/catalog/resolve-value-query/resolve-value-query-format.js +4 -3
  189. package/queries/catalog/search-query/search-query-format.d.ts +2 -1
  190. package/queries/catalog/search-query/search-query-format.js +7 -3
  191. package/queries/catalog/static-slice-query/static-slice-query-format.d.ts +3 -1
  192. package/queries/catalog/static-slice-query/static-slice-query-format.js +11 -3
  193. package/queries/query-print.d.ts +1 -1
  194. package/queries/query-print.js +4 -4
  195. package/queries/query.d.ts +143 -2
  196. package/queries/query.js +5 -1
  197. package/r-bridge/lang-4.x/ast/model/nodes/r-number.d.ts +3 -2
  198. package/r-bridge/lang-4.x/ast/model/nodes/r-number.js +5 -0
  199. package/r-bridge/lang-4.x/ast/model/nodes/r-string.d.ts +3 -2
  200. package/r-bridge/lang-4.x/ast/model/nodes/r-string.js +5 -0
  201. package/r-bridge/lang-4.x/ast/model/processing/decorate.d.ts +1 -1
  202. package/r-bridge/lang-4.x/ast/model/processing/decorate.js +1 -1
  203. package/r-bridge/lang-4.x/ast/model/processing/fold.js +3 -1
  204. package/r-bridge/lang-4.x/ast/model/processing/stateful-fold.d.ts +1 -1
  205. package/r-bridge/lang-4.x/ast/parser/main/internal/expression/normalize-expression.js +1 -1
  206. package/r-bridge/lang-4.x/ast/parser/main/internal/functions/normalize-argument.js +1 -1
  207. package/r-bridge/lang-4.x/ast/parser/main/internal/functions/normalize-call.js +1 -1
  208. package/r-bridge/lang-4.x/ast/parser/main/internal/functions/normalize-definition.js +1 -1
  209. package/r-bridge/lang-4.x/ast/parser/main/internal/normalize-access.js +1 -1
  210. package/r-bridge/lang-4.x/ast/parser/main/internal/operators/normalize-binary.js +1 -1
  211. package/r-bridge/lang-4.x/ast/parser/main/internal/structure/normalize-root.js +1 -1
  212. package/r-bridge/lang-4.x/ast/parser/main/internal/values/normalize-symbol.js +1 -1
  213. package/r-bridge/lang-4.x/tree-sitter/tree-sitter-executor.d.ts +2 -2
  214. package/r-bridge/lang-4.x/tree-sitter/tree-sitter-executor.js +4 -4
  215. package/r-bridge/lang-4.x/tree-sitter/tree-sitter-normalize.js +26 -8
  216. package/r-bridge/retriever.js +2 -2
  217. package/search/flowr-search-builder.d.ts +31 -2
  218. package/search/flowr-search-builder.js +30 -0
  219. package/search/flowr-search.d.ts +7 -1
  220. package/search/search-executor/search-enrichers.d.ts +73 -0
  221. package/search/search-executor/search-enrichers.js +98 -0
  222. package/search/search-executor/search-generators.d.ts +7 -2
  223. package/search/search-executor/search-generators.js +21 -1
  224. package/search/search-executor/search-mappers.d.ts +19 -0
  225. package/search/search-executor/search-mappers.js +21 -0
  226. package/search/search-executor/search-transformer.d.ts +13 -1
  227. package/search/search-executor/search-transformer.js +11 -1
  228. package/slicing/criterion/collect-all.js +1 -1
  229. package/slicing/static/slice-call.js +13 -3
  230. package/statistics/features/supported/assignments/post-process.js +1 -1
  231. package/statistics/features/supported/defined-functions/post-process.js +2 -2
  232. package/statistics/features/supported/used-functions/post-process.js +1 -1
  233. package/statistics/features/supported/used-packages/post-process.js +2 -2
  234. package/statistics/features/supported/values/post-process.js +2 -2
  235. package/statistics/output/print-stats.js +2 -2
  236. package/statistics/summarizer/post-process/clusterer.d.ts +1 -1
  237. package/statistics/summarizer/post-process/clusterer.js +1 -1
  238. package/statistics/summarizer/post-process/histogram.js +3 -3
  239. package/statistics/summarizer/post-process/post-process-output.js +3 -3
  240. package/statistics/summarizer/second-phase/process.js +2 -2
  241. package/statistics/summarizer/summarizer.js +2 -2
  242. package/util/assert.js +36 -1
  243. package/util/cfg/cfg.d.ts +0 -80
  244. package/util/cfg/cfg.js +0 -549
  245. package/util/{arrays.d.ts → collections/arrays.d.ts} +1 -1
  246. package/util/{arrays.js → collections/arrays.js} +3 -3
  247. package/util/collections/set.js +17 -0
  248. package/util/diff-graph.d.ts +47 -0
  249. package/util/diff-graph.js +61 -0
  250. package/util/diff.d.ts +6 -6
  251. package/util/diff.js +1 -1
  252. package/util/mermaid/cfg.d.ts +9 -2
  253. package/util/mermaid/cfg.js +64 -12
  254. package/util/mermaid/dfg.d.ts +2 -1
  255. package/util/mermaid/dfg.js +26 -10
  256. package/util/mermaid/mermaid.d.ts +2 -0
  257. package/util/mermaid/mermaid.js +6 -0
  258. package/util/quads.js +1 -1
  259. package/util/schema.d.ts +1 -1
  260. package/util/schema.js +1 -1
  261. package/util/summarizer.js +1 -1
  262. package/util/{text.js → text/text.js} +1 -1
  263. package/util/{time.js → text/time.js} +1 -1
  264. package/util/version.js +1 -1
  265. package/dataflow/graph/diff.d.ts +0 -36
  266. package/util/cfg/happens-before.d.ts +0 -7
  267. package/util/cfg/visitor.d.ts +0 -9
  268. package/util/cfg/visitor.js +0 -30
  269. package/util/set.js +0 -31
  270. /package/util/{bimap.d.ts → collections/bimap.d.ts} +0 -0
  271. /package/util/{bimap.js → collections/bimap.js} +0 -0
  272. /package/util/{defaultmap.d.ts → collections/defaultmap.d.ts} +0 -0
  273. /package/util/{defaultmap.js → collections/defaultmap.js} +0 -0
  274. /package/util/{set.d.ts → collections/set.d.ts} +0 -0
  275. /package/util/{ansi.d.ts → text/ansi.d.ts} +0 -0
  276. /package/util/{ansi.js → text/ansi.js} +0 -0
  277. /package/util/{args.d.ts → text/args.d.ts} +0 -0
  278. /package/util/{args.js → text/args.js} +0 -0
  279. /package/util/{strings.d.ts → text/strings.d.ts} +0 -0
  280. /package/util/{strings.js → text/strings.js} +0 -0
  281. /package/util/{text.d.ts → text/text.d.ts} +0 -0
  282. /package/util/{time.d.ts → text/time.d.ts} +0 -0
@@ -45,10 +45,10 @@ const message_slice_1 = require("./messages/message-slice");
45
45
  const server_1 = require("./server");
46
46
  const message_repl_1 = require("./messages/message-repl");
47
47
  const core_1 = require("../core");
48
- const cfg_1 = require("../../../util/cfg/cfg");
48
+ const extract_cfg_1 = require("../../../control-flow/extract-cfg");
49
49
  const quads_1 = require("../../../util/quads");
50
50
  const print_1 = require("../../../core/print/print");
51
- const ansi_1 = require("../../../util/ansi");
51
+ const ansi_1 = require("../../../util/text/ansi");
52
52
  const default_pipelines_1 = require("../../../core/steps/pipeline/default-pipelines");
53
53
  const graph_1 = require("../../../dataflow/graph/graph");
54
54
  const tmp = __importStar(require("tmp"));
@@ -160,7 +160,7 @@ class FlowRServerConnection {
160
160
  async sendFileAnalysisResponse(slicer, results, message) {
161
161
  let cfg = undefined;
162
162
  if (message.cfg) {
163
- cfg = (0, cfg_1.extractCFG)(results.normalize, results.dataflow?.graph);
163
+ cfg = (0, extract_cfg_1.extractCfg)(results.normalize, results.dataflow?.graph);
164
164
  }
165
165
  const config = () => ({ context: message.filename ?? 'unknown', getId: (0, quads_1.defaultQuadIdGenerator)() });
166
166
  const sanitizedResults = sanitizeAnalysisResults(results);
@@ -174,7 +174,7 @@ class FlowRServerConnection {
174
174
  type: 'response-file-analysis',
175
175
  format: 'n-quads',
176
176
  id: message.id,
177
- cfg: cfg ? (0, cfg_1.cfg2quads)(cfg, config()) : undefined,
177
+ cfg: cfg ? (0, extract_cfg_1.cfg2quads)(cfg, config()) : undefined,
178
178
  results: {
179
179
  parse: await (0, print_1.printStepResult)(parseStep, sanitizedResults.parse, 5 /* StepOutputFormat.RdfQuads */, config()),
180
180
  normalize: await (0, print_1.printStepResult)(normalizedStep, sanitizedResults.normalize, 5 /* StepOutputFormat.RdfQuads */, config()),
@@ -1,7 +1,7 @@
1
1
  import type { IdMessageBase, MessageDefinition } from './all-messages';
2
- import type { ControlFlowInformation } from '../../../../util/cfg/cfg';
3
2
  import type { DEFAULT_DATAFLOW_PIPELINE } from '../../../../core/steps/pipeline/default-pipelines';
4
3
  import type { PipelineOutput } from '../../../../core/steps/pipeline/pipeline';
4
+ import type { ControlFlowInformation } from '../../../../control-flow/control-flow-graph';
5
5
  /**
6
6
  * Send by the client to request an analysis of a given file.
7
7
  * Answered by either an {@link FlowrErrorMessage} or a {@link FileAnalysisResponseMessageJson}.
@@ -15,7 +15,7 @@ const log_1 = require("../../util/log");
15
15
  const statistics_helper_core_1 = require("./statistics-helper-core");
16
16
  const command_line_args_1 = __importDefault(require("command-line-args"));
17
17
  const scripts_info_1 = require("../common/scripts-info");
18
- const ansi_1 = require("../../util/ansi");
18
+ const ansi_1 = require("../../util/text/ansi");
19
19
  const testRegex = /[^/]*\/test/i;
20
20
  const exampleRegex = /[^/]*\/example/i;
21
21
  function getPrefixForFile(file) {
@@ -9,7 +9,7 @@ const fs_1 = __importDefault(require("fs"));
9
9
  const shell_1 = require("../../r-bridge/shell");
10
10
  const statistics_file_1 = require("../../statistics/output/statistics-file");
11
11
  const statistics_1 = require("../../statistics/statistics");
12
- const cfg_1 = require("../../util/cfg/cfg");
12
+ const extract_cfg_1 = require("../../control-flow/extract-cfg");
13
13
  const print_1 = require("../../core/print/print");
14
14
  const _00_parse_1 = require("../../core/steps/all/core/00-parse");
15
15
  const _10_normalize_1 = require("../../core/steps/all/core/10-normalize");
@@ -17,9 +17,9 @@ const _20_dataflow_1 = require("../../core/steps/all/core/20-dataflow");
17
17
  const json_1 = require("../../util/json");
18
18
  const log_1 = require("../../util/log");
19
19
  const assert_1 = require("../../util/assert");
20
- const time_1 = require("../../util/time");
20
+ const time_1 = require("../../util/text/time");
21
21
  const tar_1 = require("tar");
22
- const ansi_1 = require("../../util/ansi");
22
+ const ansi_1 = require("../../util/text/ansi");
23
23
  function compressFolder(folder, target) {
24
24
  return (0, tar_1.create)({
25
25
  gzip: true,
@@ -58,7 +58,7 @@ async function getStatsForSingleFile(options) {
58
58
  if (stats.outputs.size === 1) {
59
59
  if (options['dump-json']) {
60
60
  const [, output] = [...stats.outputs.entries()][0];
61
- const cfg = (0, cfg_1.extractCFG)(output.normalize, output.dataflow.graph);
61
+ const cfg = (0, extract_cfg_1.extractCfg)(output.normalize, output.dataflow.graph);
62
62
  statistics_file_1.statisticsFileProvider.append('output-json', 'parse', await (0, print_1.printStepResult)(_00_parse_1.PARSE_WITH_R_SHELL_STEP, output.parse, 2 /* StepOutputFormat.Json */));
63
63
  statistics_file_1.statisticsFileProvider.append('output-json', 'normalize', await (0, print_1.printStepResult)(_10_normalize_1.NORMALIZE, output.normalize, 2 /* StepOutputFormat.Json */));
64
64
  statistics_file_1.statisticsFileProvider.append('output-json', 'dataflow', await (0, print_1.printStepResult)(_20_dataflow_1.STATIC_DATAFLOW, output.dataflow, 2 /* StepOutputFormat.Json */));
package/config.d.ts CHANGED
@@ -35,6 +35,52 @@ export declare enum DropPathsOption {
35
35
  /** try to drop every folder of the path */
36
36
  All = "all"
37
37
  }
38
+ export interface FlowrLaxSourcingOptions extends MergeableRecord {
39
+ /**
40
+ * search for filenames matching in the lowercase
41
+ */
42
+ readonly ignoreCapitalization: boolean;
43
+ /**
44
+ * try to infer the working directory from the main or any script to analyze.
45
+ */
46
+ readonly inferWorkingDirectory: InferWorkingDirectory;
47
+ /**
48
+ * Additionally search in these paths
49
+ */
50
+ readonly searchPath: readonly string[];
51
+ /**
52
+ * Allow to drop the first or all parts of the sourced path,
53
+ * if it is relative.
54
+ */
55
+ readonly dropPaths: DropPathsOption;
56
+ /**
57
+ * How often the same file can be sourced within a single run?
58
+ * Please be aware: in case of cyclic sources this may not reach a fixpoint so give this a sensible limit.
59
+ */
60
+ readonly repeatedSourceLimit?: number;
61
+ /**
62
+ * sometimes files may have a different name in the source call (e.g., due to later replacements),
63
+ * with this setting you can provide a list of replacements to apply for each sourced file.
64
+ * Every replacement consists of a record that maps a regex to a replacement string.
65
+ *
66
+ * @example
67
+ * ```ts
68
+ * [
69
+ * { }, // no replacement -> still try the original name/path
70
+ * { '.*\\.R$': 'main.R' }, // replace all .R files with main.R
71
+ * { '\s' : '_' }, // replace all spaces with underscores
72
+ * { '\s' : '-', 'oo': 'aa' }, // replace all spaces with dashes and oo with aa
73
+ * ]
74
+ * ```
75
+ *
76
+ * Given a `source("foo bar.R")` this configuration will search for (in this order):
77
+ * - `foo bar.R` (original name)
78
+ * - `main.R` (replaced with main.R)
79
+ * - `foo_bar.R` (replaced spaces)
80
+ * - `foo-bar.R` (replaced spaces and oo)
81
+ */
82
+ readonly applyReplacements?: Record<string, string>[];
83
+ }
38
84
  export interface FlowrConfigOptions extends MergeableRecord {
39
85
  /**
40
86
  * Whether source calls should be ignored, causing {@link processSourceCall}'s behavior to be skipped
@@ -88,30 +134,7 @@ export interface FlowrConfigOptions extends MergeableRecord {
88
134
  * based on the configurations you give it.
89
135
  * This option is only in effect if {@link ignoreSourceCalls} is set to false.
90
136
  */
91
- readonly resolveSource?: {
92
- /**
93
- * search for filenames matching in the lowercase
94
- */
95
- readonly ignoreCapitalization: boolean;
96
- /**
97
- * try to infer the working directory from the main or any script to analyze.
98
- */
99
- readonly inferWorkingDirectory: InferWorkingDirectory;
100
- /**
101
- * Additionally search in these paths
102
- */
103
- readonly searchPath: readonly string[];
104
- /**
105
- * Allow to drop the first or all parts of the sourced path,
106
- * if it is relative.
107
- */
108
- readonly dropPaths: DropPathsOption;
109
- /**
110
- * How often the same file can be sourced within a single run?
111
- * Please be aware: in case of cyclic sources this may not reach a fixpoint so give this a sensible limit.
112
- */
113
- readonly repeatedSourceLimit?: number;
114
- };
137
+ readonly resolveSource?: FlowrLaxSourcingOptions;
115
138
  /**
116
139
  * The configuration for flowR's slicer
117
140
  */
package/config.js CHANGED
@@ -52,7 +52,6 @@ var DropPathsOption;
52
52
  /** try to drop every folder of the path */
53
53
  DropPathsOption["All"] = "all";
54
54
  })(DropPathsOption || (exports.DropPathsOption = DropPathsOption = {}));
55
- ;
56
55
  const defaultEngineConfigs = {
57
56
  'tree-sitter': { type: 'tree-sitter' },
58
57
  'r-shell': { type: 'r-shell' }
@@ -72,7 +71,7 @@ exports.defaultConfigOptions = {
72
71
  solver: {
73
72
  variables: VariableResolve.Alias,
74
73
  evalStrings: true,
75
- pointerTracking: true,
74
+ pointerTracking: false,
76
75
  resolveSource: {
77
76
  dropPaths: DropPathsOption.No,
78
77
  ignoreCapitalization: true,
@@ -116,7 +115,8 @@ exports.flowrConfigFileSchema = joi_1.default.object({
116
115
  ignoreCapitalization: joi_1.default.boolean().description('Search for filenames matching in the lowercase.'),
117
116
  inferWorkingDirectory: joi_1.default.string().valid(...Object.values(InferWorkingDirectory)).description('Try to infer the working directory from the main or any script to analyze.'),
118
117
  searchPath: joi_1.default.array().items(joi_1.default.string()).description('Additionally search in these paths.'),
119
- repeatedSourceLimit: joi_1.default.number().optional().description('How often the same file can be sourced within a single run? Please be aware: in case of cyclic sources this may not reach a fixpoint so give this a sensible limit.')
118
+ repeatedSourceLimit: joi_1.default.number().optional().description('How often the same file can be sourced within a single run? Please be aware: in case of cyclic sources this may not reach a fixpoint so give this a sensible limit.'),
119
+ applyReplacements: joi_1.default.array().items(joi_1.default.object()).description('Provide name replacements for loaded files')
120
120
  }).optional().description('If lax source calls are active, flowR searches for sourced files much more freely, based on the configurations you give it. This option is only in effect if `ignoreSourceCalls` is set to false.'),
121
121
  slicer: joi_1.default.object({
122
122
  threshold: joi_1.default.number().optional().description('The maximum number of iterations to perform on a single function call during slicing.')
@@ -0,0 +1,39 @@
1
+ import type { CfgBasicBlockVertex, CfgEndMarkerVertex, CfgExpressionVertex, CfgMidMarkerVertex, CfgSimpleVertex, CfgStatementVertex, ControlFlowInformation } from './control-flow-graph';
2
+ import type { NodeId } from '../r-bridge/lang-4.x/ast/model/processing/node-id';
3
+ export interface BasicCfgGuidedVisitorConfiguration<Cfg extends ControlFlowInformation = ControlFlowInformation> {
4
+ readonly controlFlow: Cfg;
5
+ readonly defaultVisitingOrder: 'forward' | 'backward';
6
+ }
7
+ /**
8
+ * In contrast to {@link visitCfgInOrder} and {@link visitCfgInReverseOrder}, this visitor is not a simple visitor
9
+ * and serves as the basis for a variety of more complicated visiting orders of the control flow graph.
10
+ * It includes features to provide additional information using the {@link NormalizedAst} and the {@link DataflowGraph}.
11
+ *
12
+ * Use {@link BasicCfgGuidedVisitor#start} to start the traversal.
13
+ */
14
+ export declare class BasicCfgGuidedVisitor<Cfg extends ControlFlowInformation = ControlFlowInformation, Config extends BasicCfgGuidedVisitorConfiguration<Cfg> = BasicCfgGuidedVisitorConfiguration<Cfg>> {
15
+ protected readonly config: Config;
16
+ protected readonly visited: Map<NodeId, number>;
17
+ constructor(config: Config);
18
+ /**
19
+ * call this function to indicate that a node is to be considered visited.
20
+ *
21
+ * @returns `true` if the node was not visited before, `false` otherwise
22
+ */
23
+ protected visitNode(node: NodeId): boolean;
24
+ protected startVisitor(start: readonly NodeId[]): void;
25
+ /**
26
+ * Start the visiting process.
27
+ */
28
+ start(): void;
29
+ /**
30
+ * Get the control flow vertex for the given node id or fail if it does not exist.
31
+ */
32
+ protected getCfgVertex(id: NodeId): CfgSimpleVertex | undefined;
33
+ protected onVisitNode(node: NodeId): void;
34
+ protected onBasicBlockNode(node: CfgBasicBlockVertex): void;
35
+ protected onStatementNode(_node: CfgStatementVertex): void;
36
+ protected onExpressionNode(_node: CfgExpressionVertex): void;
37
+ protected onMidMarkerNode(_node: CfgMidMarkerVertex): void;
38
+ protected onEndMarkerNode(_node: CfgEndMarkerVertex): void;
39
+ }
@@ -0,0 +1,114 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.BasicCfgGuidedVisitor = void 0;
4
+ const control_flow_graph_1 = require("./control-flow-graph");
5
+ const assert_1 = require("../util/assert");
6
+ /**
7
+ * In contrast to {@link visitCfgInOrder} and {@link visitCfgInReverseOrder}, this visitor is not a simple visitor
8
+ * and serves as the basis for a variety of more complicated visiting orders of the control flow graph.
9
+ * It includes features to provide additional information using the {@link NormalizedAst} and the {@link DataflowGraph}.
10
+ *
11
+ * Use {@link BasicCfgGuidedVisitor#start} to start the traversal.
12
+ */
13
+ class BasicCfgGuidedVisitor {
14
+ config;
15
+ visited;
16
+ constructor(config) {
17
+ this.config = { ...config };
18
+ this.visited = new Map();
19
+ }
20
+ /**
21
+ * call this function to indicate that a node is to be considered visited.
22
+ *
23
+ * @returns `true` if the node was not visited before, `false` otherwise
24
+ */
25
+ visitNode(node) {
26
+ if (this.visited.has(node)) {
27
+ return false;
28
+ }
29
+ this.visited.set(node, 1);
30
+ this.onVisitNode(node);
31
+ return true;
32
+ }
33
+ startVisitor(start) {
34
+ const g = this.config.controlFlow.graph;
35
+ const n = this.config.defaultVisitingOrder === 'forward' ?
36
+ (n) => g.ingoingEdges(n) :
37
+ (n) => g.outgoingEdges(n);
38
+ const stack = [...start];
39
+ while (stack.length > 0) {
40
+ const current = stack.shift();
41
+ if (!this.visitNode(current)) {
42
+ continue;
43
+ }
44
+ const outgoing = n(current) ?? [];
45
+ for (const [to] of outgoing) {
46
+ stack.unshift(to);
47
+ }
48
+ }
49
+ }
50
+ /**
51
+ * Start the visiting process.
52
+ */
53
+ start() {
54
+ this.startVisitor(this.config.defaultVisitingOrder === 'forward' ? this.config.controlFlow.entryPoints : this.config.controlFlow.exitPoints);
55
+ }
56
+ /**
57
+ * Get the control flow vertex for the given node id or fail if it does not exist.
58
+ */
59
+ getCfgVertex(id) {
60
+ return this.config.controlFlow.graph.getVertex(id);
61
+ }
62
+ onVisitNode(node) {
63
+ const vertex = this.getCfgVertex(node);
64
+ if (vertex === undefined) {
65
+ return;
66
+ }
67
+ const type = vertex.type;
68
+ switch (type) {
69
+ case control_flow_graph_1.CfgVertexType.Statement:
70
+ this.onStatementNode(vertex);
71
+ break;
72
+ case control_flow_graph_1.CfgVertexType.Expression:
73
+ this.onExpressionNode(vertex);
74
+ break;
75
+ case control_flow_graph_1.CfgVertexType.MidMarker:
76
+ this.onMidMarkerNode(vertex);
77
+ break;
78
+ case control_flow_graph_1.CfgVertexType.EndMarker:
79
+ this.onEndMarkerNode(vertex);
80
+ break;
81
+ case control_flow_graph_1.CfgVertexType.Block:
82
+ this.onBasicBlockNode(vertex);
83
+ break;
84
+ default:
85
+ (0, assert_1.assertUnreachable)(type);
86
+ }
87
+ }
88
+ onBasicBlockNode(node) {
89
+ if (this.config.defaultVisitingOrder === 'forward') {
90
+ for (const elem of node.elems.toReversed()) {
91
+ this.visitNode(elem.id);
92
+ }
93
+ }
94
+ else {
95
+ for (const elem of node.elems) {
96
+ this.visitNode(elem.id);
97
+ }
98
+ }
99
+ }
100
+ onStatementNode(_node) {
101
+ /* does nothing by default */
102
+ }
103
+ onExpressionNode(_node) {
104
+ /* does nothing by default */
105
+ }
106
+ onMidMarkerNode(_node) {
107
+ /* does nothing by default */
108
+ }
109
+ onEndMarkerNode(_node) {
110
+ /* does nothing by default */
111
+ }
112
+ }
113
+ exports.BasicCfgGuidedVisitor = BasicCfgGuidedVisitor;
114
+ //# sourceMappingURL=basic-cfg-guided-visitor.js.map
@@ -0,0 +1,26 @@
1
+ import { type ControlFlowInformation } from './control-flow-graph';
2
+ /**
3
+ * The collection of properties that can be checked on a control flow graph.
4
+ */
5
+ declare const CfgProperties: {
6
+ readonly 'single-entry-and-exit': typeof checkSingleEntryAndExit;
7
+ readonly 'has-entry-and-exit': typeof hasEntryAndExit;
8
+ readonly 'entry-reaches-all': typeof checkEntryReachesAll;
9
+ readonly 'exit-reaches-all': typeof checkExitIsReachedByAll;
10
+ readonly 'no-direct-fd-cycles': (c: ControlFlowInformation<import("./control-flow-graph").CfgSimpleVertex>) => boolean;
11
+ readonly 'no-direct-cd-cycles': (c: ControlFlowInformation<import("./control-flow-graph").CfgSimpleVertex>) => boolean;
12
+ };
13
+ export type CfgProperty = keyof typeof CfgProperties;
14
+ declare function checkSingleEntryAndExit(cfg: ControlFlowInformation): boolean;
15
+ declare function hasEntryAndExit(cfg: ControlFlowInformation): boolean;
16
+ declare function checkExitIsReachedByAll(cfg: ControlFlowInformation): boolean;
17
+ declare function checkEntryReachesAll(cfg: ControlFlowInformation): boolean;
18
+ /** either returns true or the name of the property that is not satisfied */
19
+ export type PropertyReport = true | CfgProperty;
20
+ /**
21
+ * Check if the given CFG satisfies all properties.
22
+ * @param cfg - The control flow graph to check.
23
+ * @param excludeProperties - If provided, exclude the given properties, otherwise this checks all properties.
24
+ */
25
+ export declare function assertCfgSatisfiesProperties(cfg: ControlFlowInformation, excludeProperties?: readonly CfgProperty[]): PropertyReport;
26
+ export {};
@@ -0,0 +1,100 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.assertCfgSatisfiesProperties = assertCfgSatisfiesProperties;
4
+ const set_1 = require("../util/collections/set");
5
+ const log_1 = require("../util/log");
6
+ const simple_visitor_1 = require("./simple-visitor");
7
+ /**
8
+ * The collection of properties that can be checked on a control flow graph.
9
+ */
10
+ const CfgProperties = {
11
+ 'single-entry-and-exit': checkSingleEntryAndExit,
12
+ 'has-entry-and-exit': hasEntryAndExit,
13
+ 'entry-reaches-all': checkEntryReachesAll,
14
+ 'exit-reaches-all': checkExitIsReachedByAll,
15
+ /* currently not satisfied for function calls
16
+ 'at-most-one-in-fd': c => checkFdIOCount(c, 'in', 'at-most', 1),
17
+ 'exactly-one-in-fd': c => checkFdIOCount(c, 'in', 'exact', 1),
18
+ 'at-most-one-out-fd': c => checkFdIOCount(c, 'out', 'at-most', 1),
19
+ 'exactly-one-out-fd': c => checkFdIOCount(c, 'out', 'exact', 1),
20
+ */
21
+ 'no-direct-fd-cycles': c => checkNoDirectCycles(c, 0 /* CfgEdgeType.Fd */),
22
+ 'no-direct-cd-cycles': c => checkNoDirectCycles(c, 1 /* CfgEdgeType.Cd */),
23
+ };
24
+ function checkSingleEntryAndExit(cfg) {
25
+ return new Set(cfg.entryPoints).size === 1 && new Set(cfg.exitPoints).size === 1 && new Set(cfg.breaks).size === 0 &&
26
+ new Set(cfg.returns).size === 0 && new Set(cfg.nexts).size === 0;
27
+ }
28
+ function hasEntryAndExit(cfg) {
29
+ return cfg.entryPoints.every(e => cfg.graph.hasVertex(e)) && cfg.exitPoints.every(e => cfg.graph.hasVertex(e));
30
+ }
31
+ function checkReachFrom(label, cfg, start, collect) {
32
+ if (start === undefined) {
33
+ return false;
34
+ }
35
+ const collected = new Set();
36
+ collect(cfg.graph, [start], node => {
37
+ collected.add(node);
38
+ });
39
+ // we only require the roots to be there
40
+ const allVertices = cfg.graph.rootIds();
41
+ const diff = (0, set_1.setMinus)(allVertices, collected);
42
+ if (diff.size > 0) {
43
+ log_1.log.error(`Unreachable vertices from ${label}:`, diff);
44
+ return false;
45
+ }
46
+ return true;
47
+ }
48
+ function checkExitIsReachedByAll(cfg) {
49
+ return checkReachFrom('exit', cfg, cfg.exitPoints[0], simple_visitor_1.visitCfgInReverseOrder);
50
+ }
51
+ function checkEntryReachesAll(cfg) {
52
+ return checkReachFrom('entry', cfg, cfg.entryPoints[0], simple_visitor_1.visitCfgInOrder);
53
+ }
54
+ function _checkFdIOCount(cfg, dir, type, limit) {
55
+ const counts = new Map();
56
+ for (const [from, targets] of cfg.graph.edges()) {
57
+ for (const [to, edge] of targets) {
58
+ const important = dir === 'in' ? to : from;
59
+ if (edge.label === 0 /* CfgEdgeType.Fd */) {
60
+ counts.set(important, (counts.get(important) ?? 0) + 1);
61
+ }
62
+ }
63
+ }
64
+ const check = type === 'exact' ? (a) => a === limit : (a) => a <= limit;
65
+ for (const [node, count] of counts) {
66
+ if (type === 'exact' && (cfg.entryPoints.includes(node) || cfg.exitPoints.includes(node) || !cfg.graph.rootIds().has(node))) {
67
+ continue; // skip entry and exit points, they do not have to satisfy this
68
+ }
69
+ if (!check(count)) {
70
+ log_1.log.error(`Node ${node} has ${count} ${dir} edges, expected ${type} ${limit}`);
71
+ return false;
72
+ }
73
+ }
74
+ return true;
75
+ }
76
+ function checkNoDirectCycles(cfg, type) {
77
+ for (const [from, targets] of cfg.graph.edges()) {
78
+ for (const [to, edge] of targets) {
79
+ if (edge.label === type && to === from) {
80
+ log_1.log.error(`Node ${from} has a direct cycle with ${to}`);
81
+ return false;
82
+ }
83
+ }
84
+ }
85
+ return true;
86
+ }
87
+ /**
88
+ * Check if the given CFG satisfies all properties.
89
+ * @param cfg - The control flow graph to check.
90
+ * @param excludeProperties - If provided, exclude the given properties, otherwise this checks all properties.
91
+ */
92
+ function assertCfgSatisfiesProperties(cfg, excludeProperties) {
93
+ for (const [propName, prop] of Object.entries(CfgProperties)) {
94
+ if ((!excludeProperties || !excludeProperties.includes(propName)) && !prop(cfg)) {
95
+ return propName;
96
+ }
97
+ }
98
+ return true;
99
+ }
100
+ //# sourceMappingURL=cfg-properties.js.map
@@ -0,0 +1,18 @@
1
+ import type { ControlFlowInformation } from './control-flow-graph';
2
+ export type CfgSimplificationPass = (cfg: ControlFlowInformation) => ControlFlowInformation;
3
+ declare const CfgSimplificationPasses: {
4
+ readonly 'unique-cf-sets': typeof uniqueControlFlowSets;
5
+ readonly 'remove-dead-code': typeof cfgRemoveDeadCode;
6
+ readonly 'to-basic-blocks': typeof toBasicBlocks;
7
+ };
8
+ export type CfgSimplificationPassName = keyof typeof CfgSimplificationPasses;
9
+ export declare const DefaultCfgSimplificationOrder: ["unique-cf-sets"];
10
+ /**
11
+ * Simplify the control flow information by applying the given passes.
12
+ * This may reduce the vertex count, in- and outgoing edges, entry and exit points, etc.
13
+ */
14
+ export declare function simplifyControlFlowInformation(cfg: ControlFlowInformation, passes?: readonly CfgSimplificationPassName[]): ControlFlowInformation;
15
+ declare function uniqueControlFlowSets(cfg: ControlFlowInformation): ControlFlowInformation;
16
+ declare function cfgRemoveDeadCode(cfg: ControlFlowInformation): ControlFlowInformation;
17
+ declare function toBasicBlocks(cfg: ControlFlowInformation): ControlFlowInformation;
18
+ export {};
@@ -0,0 +1,55 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.DefaultCfgSimplificationOrder = void 0;
4
+ exports.simplifyControlFlowInformation = simplifyControlFlowInformation;
5
+ const simple_visitor_1 = require("./simple-visitor");
6
+ const cfg_to_basic_blocks_1 = require("./cfg-to-basic-blocks");
7
+ const CfgSimplificationPasses = {
8
+ 'unique-cf-sets': uniqueControlFlowSets,
9
+ 'remove-dead-code': cfgRemoveDeadCode,
10
+ 'to-basic-blocks': toBasicBlocks
11
+ };
12
+ exports.DefaultCfgSimplificationOrder = [
13
+ 'unique-cf-sets',
14
+ // 'remove-dead-code' // way too expensive for conventional use!
15
+ // basic blocks must be requested
16
+ ];
17
+ /**
18
+ * Simplify the control flow information by applying the given passes.
19
+ * This may reduce the vertex count, in- and outgoing edges, entry and exit points, etc.
20
+ */
21
+ function simplifyControlFlowInformation(cfg, passes = exports.DefaultCfgSimplificationOrder) {
22
+ for (const pass of passes) {
23
+ const passFn = CfgSimplificationPasses[pass];
24
+ cfg = passFn(cfg);
25
+ }
26
+ return cfg;
27
+ }
28
+ function uniqueControlFlowSets(cfg) {
29
+ return {
30
+ returns: [...new Set(cfg.returns)],
31
+ entryPoints: [...new Set(cfg.entryPoints)],
32
+ exitPoints: [...new Set(cfg.exitPoints)],
33
+ breaks: [...new Set(cfg.breaks)],
34
+ nexts: [...new Set(cfg.nexts)],
35
+ graph: cfg.graph
36
+ };
37
+ }
38
+ /* currently this does not do work on function definitions */
39
+ function cfgRemoveDeadCode(cfg) {
40
+ // remove every root level node and accompanying vertices that can not be reached from the entry points
41
+ const reachable = new Set();
42
+ (0, simple_visitor_1.visitCfgInOrder)(cfg.graph, cfg.entryPoints, node => {
43
+ reachable.add(node);
44
+ });
45
+ for (const id of cfg.graph.rootIds()) {
46
+ if (!reachable.has(id)) {
47
+ cfg.graph.removeVertex(id);
48
+ }
49
+ }
50
+ return cfg;
51
+ }
52
+ function toBasicBlocks(cfg) {
53
+ return (0, cfg_to_basic_blocks_1.convertCfgToBasicBlocks)(cfg);
54
+ }
55
+ //# sourceMappingURL=cfg-simplification.js.map
@@ -0,0 +1,5 @@
1
+ import type { ControlFlowInformation } from './control-flow-graph';
2
+ /**
3
+ * Take a control flow information of a graph without any basic blocks and convert it to a graph with basic blocks.
4
+ */
5
+ export declare function convertCfgToBasicBlocks(cfInfo: ControlFlowInformation): ControlFlowInformation;
@@ -0,0 +1,81 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.convertCfgToBasicBlocks = convertCfgToBasicBlocks;
4
+ const control_flow_graph_1 = require("./control-flow-graph");
5
+ /** if true, return the target */
6
+ function singleOutgoingFd(outgoing) {
7
+ if (!outgoing || outgoing.size !== 1) {
8
+ return undefined;
9
+ }
10
+ const next = outgoing.entries().next().value;
11
+ if (next?.[1].label === 0 /* CfgEdgeType.Fd */) {
12
+ return next[0];
13
+ }
14
+ else {
15
+ return undefined;
16
+ }
17
+ }
18
+ /**
19
+ * Take a control flow information of a graph without any basic blocks and convert it to a graph with basic blocks.
20
+ */
21
+ function convertCfgToBasicBlocks(cfInfo) {
22
+ const newCfg = wrapEveryVertexInBasicBlock(cfInfo.graph);
23
+ if (!newCfg) {
24
+ return cfInfo;
25
+ }
26
+ for (const [id, vtx] of newCfg.vertices(false)) {
27
+ if (vtx.type !== control_flow_graph_1.CfgVertexType.Block) {
28
+ continue;
29
+ }
30
+ const outgoing = newCfg.outgoingEdges(id);
31
+ const target = singleOutgoingFd(outgoing);
32
+ if (target) {
33
+ const targetIn = newCfg.ingoingEdges(target);
34
+ if (targetIn && targetIn.size === 1) {
35
+ newCfg.mergeTwoBasicBlocks(id, target);
36
+ }
37
+ }
38
+ const ingoing = newCfg.ingoingEdges(id);
39
+ const ingoingTarget = singleOutgoingFd(ingoing);
40
+ if (ingoingTarget) {
41
+ const ingoingOut = newCfg.outgoingEdges(ingoingTarget);
42
+ if (ingoingOut && ingoingOut.size === 1) {
43
+ newCfg.mergeTwoBasicBlocks(ingoingTarget, id);
44
+ }
45
+ }
46
+ }
47
+ const findEntries = cfInfo.entryPoints.map(e => newCfg.getBasicBlock(e)?.id);
48
+ const findExits = cfInfo.exitPoints.map(e => newCfg.getBasicBlock(e)?.id);
49
+ if (findEntries.some(f => f === undefined) || findExits.some(f => f === undefined)) {
50
+ /* something went wrong */
51
+ return cfInfo;
52
+ }
53
+ return {
54
+ ...cfInfo,
55
+ graph: newCfg,
56
+ entryPoints: findEntries,
57
+ exitPoints: findExits,
58
+ };
59
+ }
60
+ /** only returns undefined when the cfg already contains basic blocks */
61
+ function wrapEveryVertexInBasicBlock(existing) {
62
+ const newGraph = new control_flow_graph_1.ControlFlowGraph();
63
+ for (const [id, vertex] of existing.vertices(false)) {
64
+ if (vertex.type === control_flow_graph_1.CfgVertexType.Block) {
65
+ return undefined;
66
+ }
67
+ newGraph.addVertex({
68
+ type: control_flow_graph_1.CfgVertexType.Block,
69
+ elems: [vertex],
70
+ id: 'bb-' + id,
71
+ });
72
+ }
73
+ // promote all edges
74
+ for (const [from, outgoing] of existing.edges().entries()) {
75
+ for (const [to, edge] of outgoing.entries()) {
76
+ newGraph.addEdge('bb-' + from, 'bb-' + to, edge);
77
+ }
78
+ }
79
+ return newGraph;
80
+ }
81
+ //# sourceMappingURL=cfg-to-basic-blocks.js.map