@eagleoutice/flowr 2.2.11 → 2.2.13

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (301) hide show
  1. package/README.md +82 -20
  2. package/benchmark/slicer.d.ts +49 -22
  3. package/benchmark/slicer.js +89 -29
  4. package/benchmark/stats/print.js +16 -10
  5. package/benchmark/stats/size-of.js +18 -1
  6. package/benchmark/stats/stats.d.ts +3 -0
  7. package/benchmark/summarizer/first-phase/input.js +1 -1
  8. package/benchmark/summarizer/first-phase/process.js +3 -3
  9. package/benchmark/summarizer/second-phase/process.js +9 -3
  10. package/benchmark/summarizer/summarizer.js +1 -1
  11. package/cli/benchmark-app.d.ts +5 -0
  12. package/cli/benchmark-app.js +49 -6
  13. package/cli/benchmark-helper-app.d.ts +4 -0
  14. package/cli/benchmark-helper-app.js +20 -4
  15. package/cli/common/options.js +15 -6
  16. package/cli/common/script.js +1 -1
  17. package/cli/flowr.js +1 -1
  18. package/cli/repl/commands/repl-cfg.d.ts +2 -0
  19. package/cli/repl/commands/repl-cfg.js +38 -24
  20. package/cli/repl/commands/repl-commands.js +6 -2
  21. package/cli/repl/commands/repl-dataflow.d.ts +2 -0
  22. package/cli/repl/commands/repl-dataflow.js +37 -3
  23. package/cli/repl/commands/repl-execute.js +1 -1
  24. package/cli/repl/commands/repl-main.d.ts +1 -1
  25. package/cli/repl/commands/repl-main.js +1 -1
  26. package/cli/repl/commands/repl-normalize.js +1 -1
  27. package/cli/repl/commands/repl-query.js +2 -2
  28. package/cli/repl/core.js +1 -1
  29. package/cli/repl/prompt.js +1 -1
  30. package/cli/repl/server/connection.js +4 -4
  31. package/cli/repl/server/messages/message-analysis.d.ts +1 -1
  32. package/cli/script-core/statistics-core.js +1 -1
  33. package/cli/script-core/statistics-helper-core.js +4 -4
  34. package/config.d.ts +60 -21
  35. package/config.js +24 -4
  36. package/control-flow/basic-cfg-guided-visitor.d.ts +39 -0
  37. package/control-flow/basic-cfg-guided-visitor.js +114 -0
  38. package/control-flow/cfg-properties.d.ts +26 -0
  39. package/control-flow/cfg-properties.js +100 -0
  40. package/control-flow/cfg-simplification.d.ts +18 -0
  41. package/control-flow/cfg-simplification.js +55 -0
  42. package/control-flow/cfg-to-basic-blocks.d.ts +5 -0
  43. package/control-flow/cfg-to-basic-blocks.js +81 -0
  44. package/control-flow/control-flow-graph.d.ts +247 -0
  45. package/control-flow/control-flow-graph.js +290 -0
  46. package/control-flow/dfg-cfg-guided-visitor.d.ts +32 -0
  47. package/control-flow/dfg-cfg-guided-visitor.js +71 -0
  48. package/control-flow/diff-cfg.d.ts +11 -0
  49. package/control-flow/diff-cfg.js +161 -0
  50. package/control-flow/extract-cfg.d.ts +30 -0
  51. package/control-flow/extract-cfg.js +475 -0
  52. package/control-flow/happens-before.d.ts +7 -0
  53. package/{util/cfg → control-flow}/happens-before.js +3 -3
  54. package/control-flow/semantic-cfg-guided-visitor.d.ts +452 -0
  55. package/control-flow/semantic-cfg-guided-visitor.js +492 -0
  56. package/control-flow/simple-visitor.d.ts +25 -0
  57. package/control-flow/simple-visitor.js +80 -0
  58. package/control-flow/syntax-cfg-guided-visitor.d.ts +128 -0
  59. package/control-flow/syntax-cfg-guided-visitor.js +166 -0
  60. package/core/print/print.d.ts +1 -1
  61. package/core/print/slice-diff-ansi.js +1 -1
  62. package/core/steps/pipeline/create-pipeline.js +1 -1
  63. package/dataflow/environments/built-in-config.d.ts +5 -2
  64. package/dataflow/environments/built-in-config.js +17 -8
  65. package/dataflow/environments/built-in.d.ts +16 -5
  66. package/dataflow/environments/built-in.js +55 -6
  67. package/dataflow/environments/clone.d.ts +5 -0
  68. package/dataflow/environments/clone.js +5 -0
  69. package/dataflow/environments/default-builtin-config.d.ts +2 -0
  70. package/dataflow/environments/default-builtin-config.js +164 -13
  71. package/dataflow/environments/define.d.ts +5 -1
  72. package/dataflow/environments/define.js +36 -10
  73. package/dataflow/environments/overwrite.js +4 -0
  74. package/dataflow/environments/remove.d.ts +6 -0
  75. package/dataflow/environments/remove.js +24 -0
  76. package/dataflow/environments/resolve-by-name.js +16 -5
  77. package/dataflow/extractor.js +2 -2
  78. package/dataflow/graph/dataflowgraph-builder.d.ts +79 -7
  79. package/dataflow/graph/dataflowgraph-builder.js +106 -8
  80. package/dataflow/graph/diff-dataflow-graph.d.ts +16 -0
  81. package/dataflow/graph/{diff.js → diff-dataflow-graph.js} +30 -56
  82. package/dataflow/graph/graph.d.ts +17 -4
  83. package/dataflow/graph/graph.js +51 -12
  84. package/dataflow/graph/vertex.d.ts +59 -4
  85. package/dataflow/graph/vertex.js +32 -0
  86. package/dataflow/internal/linker.d.ts +3 -2
  87. package/dataflow/internal/linker.js +36 -25
  88. package/dataflow/internal/process/functions/call/argument/unpack-argument.d.ts +1 -1
  89. package/dataflow/internal/process/functions/call/argument/unpack-argument.js +1 -1
  90. package/dataflow/internal/process/functions/call/built-in/built-in-access.d.ts +1 -0
  91. package/dataflow/internal/process/functions/call/built-in/built-in-access.js +67 -54
  92. package/dataflow/internal/process/functions/call/built-in/built-in-apply.d.ts +6 -4
  93. package/dataflow/internal/process/functions/call/built-in/built-in-apply.js +108 -21
  94. package/dataflow/internal/process/functions/call/built-in/built-in-assignment.js +54 -17
  95. package/dataflow/internal/process/functions/call/built-in/built-in-eval.d.ts +10 -0
  96. package/dataflow/internal/process/functions/call/built-in/built-in-eval.js +140 -0
  97. package/dataflow/internal/process/functions/call/built-in/built-in-expression-list.js +9 -4
  98. package/dataflow/internal/process/functions/call/built-in/built-in-for-loop.js +3 -2
  99. package/dataflow/internal/process/functions/call/built-in/built-in-function-definition.js +15 -4
  100. package/dataflow/internal/process/functions/call/built-in/built-in-get.js +4 -3
  101. package/dataflow/internal/process/functions/call/built-in/built-in-if-then-else.js +4 -3
  102. package/dataflow/internal/process/functions/call/built-in/built-in-library.js +4 -3
  103. package/dataflow/internal/process/functions/call/built-in/built-in-list.js +51 -17
  104. package/dataflow/internal/process/functions/call/built-in/built-in-pipe.js +1 -1
  105. package/dataflow/internal/process/functions/call/built-in/built-in-quote.js +9 -7
  106. package/dataflow/internal/process/functions/call/built-in/built-in-repeat-loop.js +3 -2
  107. package/dataflow/internal/process/functions/call/built-in/built-in-replacement.d.ts +4 -0
  108. package/dataflow/internal/process/functions/call/built-in/built-in-replacement.js +100 -31
  109. package/dataflow/internal/process/functions/call/built-in/built-in-rm.d.ts +7 -0
  110. package/dataflow/internal/process/functions/call/built-in/built-in-rm.js +41 -0
  111. package/dataflow/internal/process/functions/call/built-in/built-in-source.js +35 -8
  112. package/dataflow/internal/process/functions/call/built-in/built-in-special-bin-op.js +4 -3
  113. package/dataflow/internal/process/functions/call/built-in/built-in-vector.d.ts +15 -0
  114. package/dataflow/internal/process/functions/call/built-in/built-in-vector.js +75 -0
  115. package/dataflow/internal/process/functions/call/built-in/built-in-while-loop.js +3 -3
  116. package/dataflow/internal/process/functions/call/common.d.ts +5 -2
  117. package/dataflow/internal/process/functions/call/common.js +9 -5
  118. package/dataflow/internal/process/functions/call/known-call-handling.d.ts +3 -2
  119. package/dataflow/internal/process/functions/call/known-call-handling.js +2 -1
  120. package/dataflow/internal/process/functions/call/named-call-handling.d.ts +2 -0
  121. package/dataflow/internal/process/functions/call/named-call-handling.js +10 -6
  122. package/dataflow/internal/process/functions/call/unnamed-call-handling.d.ts +1 -0
  123. package/dataflow/internal/process/functions/call/unnamed-call-handling.js +6 -4
  124. package/dataflow/internal/process/process-named-call.d.ts +4 -1
  125. package/dataflow/internal/process/process-named-call.js +8 -5
  126. package/dataflow/origin/dfg-get-origin.d.ts +82 -0
  127. package/dataflow/origin/dfg-get-origin.js +116 -0
  128. package/documentation/doc-util/doc-cfg.d.ts +20 -4
  129. package/documentation/doc-util/doc-cfg.js +41 -7
  130. package/documentation/doc-util/doc-cli-option.js +4 -2
  131. package/documentation/doc-util/doc-code.js +10 -2
  132. package/documentation/doc-util/doc-dfg.js +3 -3
  133. package/documentation/doc-util/doc-escape.d.ts +7 -0
  134. package/documentation/doc-util/doc-escape.js +19 -0
  135. package/documentation/doc-util/doc-files.d.ts +1 -0
  136. package/documentation/doc-util/doc-files.js +2 -1
  137. package/documentation/doc-util/doc-normalized-ast.js +3 -3
  138. package/documentation/doc-util/doc-query.js +2 -2
  139. package/documentation/doc-util/doc-repl.js +1 -1
  140. package/documentation/doc-util/doc-search.js +1 -1
  141. package/documentation/doc-util/doc-server-message.js +2 -2
  142. package/documentation/doc-util/doc-structure.d.ts +1 -0
  143. package/documentation/doc-util/doc-structure.js +5 -0
  144. package/documentation/doc-util/doc-types.d.ts +7 -1
  145. package/documentation/doc-util/doc-types.js +13 -2
  146. package/documentation/print-capabilities-markdown.js +28 -2
  147. package/documentation/print-cfg-wiki.d.ts +1 -0
  148. package/documentation/print-cfg-wiki.js +572 -0
  149. package/documentation/print-core-wiki.js +2 -2
  150. package/documentation/print-dataflow-graph-wiki.js +180 -25
  151. package/documentation/print-engines-wiki.js +1 -1
  152. package/documentation/print-faq-wiki.d.ts +1 -0
  153. package/documentation/print-faq-wiki.js +75 -0
  154. package/documentation/print-interface-wiki.js +2 -1
  155. package/documentation/print-linting-and-testing-wiki.js +52 -36
  156. package/documentation/print-normalized-ast-wiki.js +1 -1
  157. package/documentation/print-onboarding-wiki.d.ts +1 -0
  158. package/documentation/print-onboarding-wiki.js +42 -0
  159. package/documentation/print-query-wiki.js +23 -3
  160. package/documentation/print-readme.js +10 -3
  161. package/package.json +10 -6
  162. package/queries/catalog/call-context-query/call-context-query-executor.js +5 -5
  163. package/queries/catalog/call-context-query/call-context-query-format.d.ts +1 -1
  164. package/queries/catalog/call-context-query/call-context-query-format.js +2 -2
  165. package/queries/catalog/call-context-query/identify-link-to-last-call-relation.d.ts +2 -2
  166. package/queries/catalog/call-context-query/identify-link-to-last-call-relation.js +24 -21
  167. package/queries/catalog/cluster-query/cluster-query-format.d.ts +1 -1
  168. package/queries/catalog/cluster-query/cluster-query-format.js +1 -1
  169. package/queries/catalog/config-query/config-query-format.d.ts +1 -1
  170. package/queries/catalog/config-query/config-query-format.js +2 -2
  171. package/queries/catalog/dataflow-lens-query/dataflow-lens-query-format.d.ts +1 -1
  172. package/queries/catalog/dataflow-lens-query/dataflow-lens-query-format.js +2 -2
  173. package/queries/catalog/dataflow-query/dataflow-query-format.d.ts +1 -1
  174. package/queries/catalog/dataflow-query/dataflow-query-format.js +2 -2
  175. package/queries/catalog/dependencies-query/dependencies-query-executor.js +17 -7
  176. package/queries/catalog/dependencies-query/dependencies-query-format.d.ts +2 -26
  177. package/queries/catalog/dependencies-query/dependencies-query-format.js +4 -147
  178. package/queries/catalog/dependencies-query/function-info/function-info.d.ts +24 -0
  179. package/queries/catalog/dependencies-query/function-info/function-info.js +10 -0
  180. package/queries/catalog/dependencies-query/function-info/library-functions.d.ts +2 -0
  181. package/queries/catalog/dependencies-query/function-info/library-functions.js +18 -0
  182. package/queries/catalog/dependencies-query/function-info/read-functions.d.ts +2 -0
  183. package/queries/catalog/dependencies-query/function-info/read-functions.js +101 -0
  184. package/queries/catalog/dependencies-query/function-info/source-functions.d.ts +2 -0
  185. package/queries/catalog/dependencies-query/function-info/source-functions.js +11 -0
  186. package/queries/catalog/dependencies-query/function-info/write-functions.d.ts +2 -0
  187. package/queries/catalog/dependencies-query/function-info/write-functions.js +87 -0
  188. package/queries/catalog/happens-before-query/happens-before-query-executor.d.ts +1 -1
  189. package/queries/catalog/happens-before-query/happens-before-query-executor.js +4 -4
  190. package/queries/catalog/happens-before-query/happens-before-query-format.d.ts +1 -1
  191. package/queries/catalog/happens-before-query/happens-before-query-format.js +2 -2
  192. package/queries/catalog/id-map-query/id-map-query-format.d.ts +1 -1
  193. package/queries/catalog/id-map-query/id-map-query-format.js +2 -2
  194. package/queries/catalog/lineage-query/lineage-query-format.d.ts +1 -1
  195. package/queries/catalog/lineage-query/lineage-query-format.js +2 -2
  196. package/queries/catalog/location-map-query/location-map-query-format.d.ts +1 -1
  197. package/queries/catalog/location-map-query/location-map-query-format.js +2 -2
  198. package/queries/catalog/normalized-ast-query/normalized-ast-query-format.d.ts +1 -1
  199. package/queries/catalog/normalized-ast-query/normalized-ast-query-format.js +2 -2
  200. package/queries/catalog/origin-query/origin-query-executor.d.ts +5 -0
  201. package/queries/catalog/origin-query/origin-query-executor.js +33 -0
  202. package/queries/catalog/origin-query/origin-query-format.d.ts +71 -0
  203. package/queries/catalog/origin-query/origin-query-format.js +27 -0
  204. package/queries/catalog/project-query/project-query-format.d.ts +1 -1
  205. package/queries/catalog/project-query/project-query-format.js +2 -2
  206. package/queries/catalog/resolve-value-query/resolve-value-query-format.d.ts +1 -1
  207. package/queries/catalog/resolve-value-query/resolve-value-query-format.js +2 -2
  208. package/queries/catalog/search-query/search-query-format.d.ts +1 -1
  209. package/queries/catalog/search-query/search-query-format.js +2 -2
  210. package/queries/catalog/static-slice-query/static-slice-query-format.d.ts +1 -1
  211. package/queries/catalog/static-slice-query/static-slice-query-format.js +2 -2
  212. package/queries/query-print.d.ts +1 -1
  213. package/queries/query-print.js +4 -4
  214. package/queries/query.d.ts +61 -2
  215. package/queries/query.js +3 -1
  216. package/r-bridge/data/data.d.ts +2 -2
  217. package/r-bridge/data/data.js +2 -2
  218. package/r-bridge/lang-4.x/ast/model/nodes/r-number.d.ts +3 -2
  219. package/r-bridge/lang-4.x/ast/model/nodes/r-number.js +5 -0
  220. package/r-bridge/lang-4.x/ast/model/nodes/r-string.d.ts +3 -2
  221. package/r-bridge/lang-4.x/ast/model/nodes/r-string.js +5 -0
  222. package/r-bridge/lang-4.x/ast/model/processing/decorate.d.ts +1 -1
  223. package/r-bridge/lang-4.x/ast/model/processing/decorate.js +1 -1
  224. package/r-bridge/lang-4.x/ast/model/processing/fold.js +3 -1
  225. package/r-bridge/lang-4.x/ast/model/processing/stateful-fold.d.ts +1 -1
  226. package/r-bridge/lang-4.x/ast/parser/main/internal/expression/normalize-expression.js +1 -1
  227. package/r-bridge/lang-4.x/ast/parser/main/internal/functions/normalize-argument.js +1 -1
  228. package/r-bridge/lang-4.x/ast/parser/main/internal/functions/normalize-call.js +1 -1
  229. package/r-bridge/lang-4.x/ast/parser/main/internal/functions/normalize-definition.js +1 -1
  230. package/r-bridge/lang-4.x/ast/parser/main/internal/normalize-access.js +1 -1
  231. package/r-bridge/lang-4.x/ast/parser/main/internal/operators/normalize-binary.js +1 -1
  232. package/r-bridge/lang-4.x/ast/parser/main/internal/structure/normalize-root.js +1 -1
  233. package/r-bridge/lang-4.x/ast/parser/main/internal/values/normalize-symbol.js +1 -1
  234. package/r-bridge/lang-4.x/tree-sitter/tree-sitter-executor.d.ts +2 -2
  235. package/r-bridge/lang-4.x/tree-sitter/tree-sitter-executor.js +4 -4
  236. package/r-bridge/lang-4.x/tree-sitter/tree-sitter-normalize.js +26 -8
  237. package/r-bridge/retriever.js +1 -1
  238. package/search/search-executor/search-generators.d.ts +1 -1
  239. package/search/search-executor/search-transformer.d.ts +1 -1
  240. package/slicing/criterion/collect-all.js +1 -1
  241. package/slicing/static/slice-call.js +13 -3
  242. package/statistics/features/supported/assignments/post-process.js +1 -1
  243. package/statistics/features/supported/defined-functions/post-process.js +2 -2
  244. package/statistics/features/supported/used-functions/post-process.js +1 -1
  245. package/statistics/features/supported/used-packages/post-process.js +2 -2
  246. package/statistics/features/supported/values/post-process.js +2 -2
  247. package/statistics/output/print-stats.js +2 -2
  248. package/statistics/summarizer/post-process/clusterer.d.ts +1 -1
  249. package/statistics/summarizer/post-process/clusterer.js +1 -1
  250. package/statistics/summarizer/post-process/histogram.js +3 -3
  251. package/statistics/summarizer/post-process/post-process-output.js +3 -3
  252. package/statistics/summarizer/second-phase/process.js +2 -2
  253. package/statistics/summarizer/summarizer.js +2 -2
  254. package/util/assert.js +36 -1
  255. package/util/cfg/cfg.d.ts +0 -80
  256. package/util/cfg/cfg.js +0 -549
  257. package/util/{arrays.d.ts → collections/arrays.d.ts} +24 -1
  258. package/util/{arrays.js → collections/arrays.js} +44 -3
  259. package/util/collections/set.js +17 -0
  260. package/util/{list-access.d.ts → containers.d.ts} +24 -4
  261. package/util/{list-access.js → containers.js} +42 -12
  262. package/util/diff-graph.d.ts +47 -0
  263. package/util/diff-graph.js +61 -0
  264. package/util/diff.d.ts +6 -6
  265. package/util/diff.js +1 -1
  266. package/util/mermaid/ast.js +12 -1
  267. package/util/mermaid/cfg.d.ts +9 -2
  268. package/util/mermaid/cfg.js +65 -13
  269. package/util/mermaid/dfg.d.ts +2 -1
  270. package/util/mermaid/dfg.js +26 -10
  271. package/util/mermaid/mermaid.d.ts +2 -0
  272. package/util/mermaid/mermaid.js +6 -0
  273. package/util/parallel.d.ts +2 -1
  274. package/util/parallel.js +11 -2
  275. package/util/prefix.d.ts +13 -0
  276. package/util/prefix.js +34 -0
  277. package/util/quads.js +1 -1
  278. package/util/schema.d.ts +1 -1
  279. package/util/schema.js +1 -1
  280. package/util/summarizer.js +1 -1
  281. package/util/{text.js → text/text.js} +1 -1
  282. package/util/{time.js → text/time.js} +1 -1
  283. package/util/version.js +1 -1
  284. package/dataflow/graph/diff.d.ts +0 -36
  285. package/util/cfg/happens-before.d.ts +0 -7
  286. package/util/cfg/visitor.d.ts +0 -9
  287. package/util/cfg/visitor.js +0 -30
  288. package/util/set.js +0 -31
  289. /package/util/{bimap.d.ts → collections/bimap.d.ts} +0 -0
  290. /package/util/{bimap.js → collections/bimap.js} +0 -0
  291. /package/util/{defaultmap.d.ts → collections/defaultmap.d.ts} +0 -0
  292. /package/util/{defaultmap.js → collections/defaultmap.js} +0 -0
  293. /package/util/{set.d.ts → collections/set.d.ts} +0 -0
  294. /package/util/{ansi.d.ts → text/ansi.d.ts} +0 -0
  295. /package/util/{ansi.js → text/ansi.js} +0 -0
  296. /package/util/{args.d.ts → text/args.d.ts} +0 -0
  297. /package/util/{args.js → text/args.js} +0 -0
  298. /package/util/{strings.d.ts → text/strings.d.ts} +0 -0
  299. /package/util/{strings.js → text/strings.js} +0 -0
  300. /package/util/{text.d.ts → text/text.d.ts} +0 -0
  301. /package/util/{time.d.ts → text/time.d.ts} +0 -0
@@ -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
@@ -2,6 +2,7 @@ import type { MergeableRecord } from './util/objects';
2
2
  import Joi from 'joi';
3
3
  import type { BuiltInDefinitions } from './dataflow/environments/built-in-config';
4
4
  import type { KnownParser } from './r-bridge/parser';
5
+ import type { DeepPartial } from 'ts-essentials';
5
6
  export declare enum VariableResolve {
6
7
  /** Don't resolve constants at all */
7
8
  Disabled = "disabled",
@@ -34,6 +35,52 @@ export declare enum DropPathsOption {
34
35
  /** try to drop every folder of the path */
35
36
  All = "all"
36
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
+ }
37
84
  export interface FlowrConfigOptions extends MergeableRecord {
38
85
  /**
39
86
  * Whether source calls should be ignored, causing {@link processSourceCall}'s behavior to be skipped
@@ -67,36 +114,27 @@ export interface FlowrConfigOptions extends MergeableRecord {
67
114
  * How to resolve variables and their values
68
115
  */
69
116
  readonly variables: VariableResolve;
117
+ /**
118
+ * Should we include eval(parse(text="...")) calls in the dataflow graph?
119
+ */
120
+ readonly evalStrings: boolean;
70
121
  /**
71
122
  * Whether to track pointers in the dataflow graph,
72
123
  * if not, the graph will be over-approximated wrt.
73
124
  * containers and accesses
74
125
  */
75
- readonly pointerTracking: boolean;
126
+ readonly pointerTracking: boolean | {
127
+ /**
128
+ * The maximum number of indices tracked per obj with the pointer analysis (currently this focuses on initialization)
129
+ */
130
+ readonly maxIndexCount: number;
131
+ };
76
132
  /**
77
133
  * If lax source calls are active, flowR searches for sourced files much more freely,
78
134
  * based on the configurations you give it.
79
135
  * This option is only in effect if {@link ignoreSourceCalls} is set to false.
80
136
  */
81
- readonly resolveSource?: {
82
- /**
83
- * search for filenames matching in the lowercase
84
- */
85
- readonly ignoreCapitalization: boolean;
86
- /**
87
- * try to infer the working directory from the main or any script to analyze.
88
- */
89
- readonly inferWorkingDirectory: InferWorkingDirectory;
90
- /**
91
- * Additionally search in these paths
92
- */
93
- readonly searchPath: readonly string[];
94
- /**
95
- * Allow to drop the first or all parts of the sourced path,
96
- * if it is relative.
97
- */
98
- readonly dropPaths: DropPathsOption;
99
- };
137
+ readonly resolveSource?: FlowrLaxSourcingOptions;
100
138
  /**
101
139
  * The configuration for flowR's slicer
102
140
  */
@@ -139,8 +177,9 @@ export declare const flowrConfigFileSchema: Joi.ObjectSchema<any>;
139
177
  export declare function setConfigFile(file: string | undefined, workingDirectory?: string, forceLoad?: boolean): void;
140
178
  export declare function parseConfig(jsonString: string): FlowrConfigOptions | undefined;
141
179
  export declare function setConfig(config: FlowrConfigOptions): void;
142
- export declare function amendConfig(amendment: Partial<FlowrConfigOptions>): void;
180
+ export declare function amendConfig(amendment: DeepPartial<FlowrConfigOptions>): void;
143
181
  export declare function getConfig(): FlowrConfigOptions;
144
182
  export declare function getEngineConfig<T extends EngineConfig['type']>(engine: T): EngineConfig & {
145
183
  type: T;
146
184
  } | undefined;
185
+ export declare function isOverPointerAnalysisThreshold(count: number): boolean;
package/config.js CHANGED
@@ -10,6 +10,7 @@ exports.setConfig = setConfig;
10
10
  exports.amendConfig = amendConfig;
11
11
  exports.getConfig = getConfig;
12
12
  exports.getEngineConfig = getEngineConfig;
13
+ exports.isOverPointerAnalysisThreshold = isOverPointerAnalysisThreshold;
13
14
  const objects_1 = require("./util/objects");
14
15
  const path_1 = __importDefault(require("path"));
15
16
  const fs_1 = __importDefault(require("fs"));
@@ -51,7 +52,6 @@ var DropPathsOption;
51
52
  /** try to drop every folder of the path */
52
53
  DropPathsOption["All"] = "all";
53
54
  })(DropPathsOption || (exports.DropPathsOption = DropPathsOption = {}));
54
- ;
55
55
  const defaultEngineConfigs = {
56
56
  'tree-sitter': { type: 'tree-sitter' },
57
57
  'r-shell': { type: 'r-shell' }
@@ -70,12 +70,14 @@ exports.defaultConfigOptions = {
70
70
  defaultEngine: 'r-shell',
71
71
  solver: {
72
72
  variables: VariableResolve.Alias,
73
+ evalStrings: true,
73
74
  pointerTracking: false,
74
75
  resolveSource: {
75
76
  dropPaths: DropPathsOption.No,
76
77
  ignoreCapitalization: true,
77
78
  inferWorkingDirectory: InferWorkingDirectory.ActiveScript,
78
- searchPath: []
79
+ searchPath: [],
80
+ repeatedSourceLimit: 2
79
81
  },
80
82
  slicer: {
81
83
  threshold: 50
@@ -104,12 +106,17 @@ exports.flowrConfigFileSchema = joi_1.default.object({
104
106
  defaultEngine: joi_1.default.string().optional().valid('tree-sitter', 'r-shell').description('The default engine to use for interacting with R code. If this is undefined, an arbitrary engine from the specified list will be used.'),
105
107
  solver: joi_1.default.object({
106
108
  variables: joi_1.default.string().valid(...Object.values(VariableResolve)).description('How to resolve variables and their values.'),
107
- pointerTracking: joi_1.default.boolean().description('Whether to track pointers in the dataflow graph, if not, the graph will be over-approximated wrt. containers and accesses.'),
109
+ evalStrings: joi_1.default.boolean().description('Should we include eval(parse(text="...")) calls in the dataflow graph?'),
110
+ pointerTracking: joi_1.default.alternatives(joi_1.default.boolean(), joi_1.default.object({
111
+ maxIndexCount: joi_1.default.number().required().description('The maximum number of indices tracked per object with the pointer analysis.')
112
+ })).description('Whether to track pointers in the dataflow graph, if not, the graph will be over-approximated wrt. containers and accesses.'),
108
113
  resolveSource: joi_1.default.object({
109
114
  dropPaths: joi_1.default.string().valid(...Object.values(DropPathsOption)).description('Allow to drop the first or all parts of the sourced path, if it is relative.'),
110
115
  ignoreCapitalization: joi_1.default.boolean().description('Search for filenames matching in the lowercase.'),
111
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.'),
112
- searchPath: joi_1.default.array().items(joi_1.default.string()).description('Additionally search in these paths.')
117
+ searchPath: joi_1.default.array().items(joi_1.default.string()).description('Additionally search in these paths.'),
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')
113
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.'),
114
121
  slicer: joi_1.default.object({
115
122
  threshold: joi_1.default.number().optional().description('The maximum number of iterations to perform on a single function call during slicing.')
@@ -175,6 +182,19 @@ function getEngineConfig(engine) {
175
182
  return config.find(e => e.type == engine);
176
183
  }
177
184
  }
185
+ function getPointerAnalysisThreshold() {
186
+ const config = getConfig().solver.pointerTracking;
187
+ if (typeof config === 'object') {
188
+ return config.maxIndexCount;
189
+ }
190
+ else {
191
+ return config ? 'unlimited' : 'disabled';
192
+ }
193
+ }
194
+ function isOverPointerAnalysisThreshold(count) {
195
+ const threshold = getPointerAnalysisThreshold();
196
+ return threshold !== 'unlimited' && (threshold === 'disabled' || count > threshold);
197
+ }
178
198
  function loadConfigFromFile(configFile, workingDirectory) {
179
199
  if (configFile !== undefined) {
180
200
  if (path_1.default.isAbsolute(configFile) && fs_1.default.existsSync(configFile)) {
@@ -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