@eagleoutice/flowr 2.0.25 → 2.1.0

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 (381) hide show
  1. package/benchmark/slicer.js +2 -1
  2. package/benchmark/stats/print.js +3 -4
  3. package/benchmark/stats/size-of.js +9 -7
  4. package/benchmark/summarizer/first-phase/input.d.ts +0 -1
  5. package/benchmark/summarizer/first-phase/input.js +2 -3
  6. package/benchmark/summarizer/first-phase/process.js +7 -7
  7. package/benchmark/summarizer/second-phase/graph.js +1 -2
  8. package/benchmark/summarizer/second-phase/process.d.ts +0 -1
  9. package/benchmark/summarizer/second-phase/process.js +4 -5
  10. package/benchmark/summarizer/summarizer.js +7 -1
  11. package/cli/benchmark-app.js +6 -1
  12. package/cli/common/features.js +2 -3
  13. package/cli/common/script.js +2 -3
  14. package/cli/common/scripts-info.d.ts +69 -1
  15. package/cli/common/scripts-info.js +6 -6
  16. package/cli/flowr-main-options.d.ts +4 -0
  17. package/cli/flowr-main-options.js +88 -0
  18. package/cli/flowr.d.ts +3 -3
  19. package/cli/flowr.js +22 -31
  20. package/cli/repl/commands/{cfg.d.ts → repl-cfg.d.ts} +1 -1
  21. package/cli/repl/commands/{cfg.js → repl-cfg.js} +3 -3
  22. package/cli/repl/commands/{commands.d.ts → repl-commands.d.ts} +3 -1
  23. package/cli/repl/commands/{commands.js → repl-commands.js} +56 -35
  24. package/cli/repl/commands/{dataflow.d.ts → repl-dataflow.d.ts} +1 -1
  25. package/cli/repl/commands/{dataflow.js → repl-dataflow.js} +2 -2
  26. package/cli/repl/commands/{execute.d.ts → repl-execute.d.ts} +1 -1
  27. package/cli/repl/commands/{execute.js → repl-execute.js} +3 -3
  28. package/cli/repl/commands/repl-lineage.d.ts +15 -0
  29. package/cli/repl/commands/{lineage.js → repl-lineage.js} +14 -12
  30. package/cli/repl/commands/{main.js → repl-main.js} +1 -1
  31. package/cli/repl/commands/{normalize.d.ts → repl-normalize.d.ts} +1 -1
  32. package/cli/repl/commands/{normalize.js → repl-normalize.js} +3 -3
  33. package/cli/repl/commands/{parse.d.ts → repl-parse.d.ts} +1 -1
  34. package/cli/repl/commands/{parse.js → repl-parse.js} +3 -2
  35. package/cli/repl/commands/repl-query.d.ts +8 -0
  36. package/cli/repl/commands/repl-query.js +155 -0
  37. package/cli/repl/commands/repl-quit.d.ts +2 -0
  38. package/cli/repl/commands/{quit.js → repl-quit.js} +1 -1
  39. package/cli/repl/commands/{version.d.ts → repl-version.d.ts} +1 -1
  40. package/cli/repl/commands/{version.js → repl-version.js} +4 -4
  41. package/cli/repl/core.d.ts +1 -2
  42. package/cli/repl/core.js +13 -13
  43. package/cli/repl/execute.d.ts +1 -2
  44. package/cli/repl/execute.js +2 -3
  45. package/cli/repl/print-version.js +3 -4
  46. package/cli/repl/server/connection.d.ts +1 -0
  47. package/cli/repl/server/connection.js +45 -12
  48. package/cli/repl/server/messages/{messages.d.ts → all-messages.d.ts} +8 -7
  49. package/cli/repl/server/messages/{messages.js → all-messages.js} +1 -1
  50. package/cli/repl/server/messages/{analysis.d.ts → message-analysis.d.ts} +2 -1
  51. package/cli/repl/server/messages/message-analysis.js +39 -0
  52. package/cli/repl/server/messages/{error.d.ts → message-error.d.ts} +1 -1
  53. package/cli/repl/server/messages/{error.js → message-error.js} +1 -1
  54. package/cli/repl/server/messages/{hello.d.ts → message-hello.d.ts} +4 -3
  55. package/cli/repl/server/messages/message-hello.js +20 -0
  56. package/cli/repl/server/messages/{lineage.d.ts → message-lineage.d.ts} +2 -1
  57. package/cli/repl/server/messages/message-lineage.js +25 -0
  58. package/cli/repl/server/messages/message-query.d.ts +16 -0
  59. package/cli/repl/server/messages/message-query.js +26 -0
  60. package/cli/repl/server/messages/{repl.d.ts → message-repl.d.ts} +3 -1
  61. package/cli/repl/server/messages/message-repl.js +53 -0
  62. package/cli/repl/server/messages/{slice.d.ts → message-slice.d.ts} +2 -1
  63. package/cli/repl/server/messages/{slice.js → message-slice.js} +14 -6
  64. package/cli/repl/server/net.d.ts +0 -1
  65. package/cli/repl/server/send.d.ts +1 -1
  66. package/cli/repl/server/send.js +2 -3
  67. package/cli/repl/server/server.js +2 -2
  68. package/cli/repl/server/validate.d.ts +1 -1
  69. package/cli/repl/server/validate.js +5 -6
  70. package/cli/run-script.d.ts +8 -0
  71. package/cli/run-script.js +18 -0
  72. package/cli/script-core/statistics-core.d.ts +2 -0
  73. package/cli/script-core/statistics-core.js +100 -0
  74. package/cli/script-core/statistics-helper-core.d.ts +2 -0
  75. package/cli/script-core/statistics-helper-core.js +81 -0
  76. package/cli/script-core/summarizer-core.d.ts +2 -0
  77. package/cli/script-core/summarizer-core.js +51 -0
  78. package/cli/statistics-app.js +3 -87
  79. package/cli/statistics-helper-app.js +3 -77
  80. package/cli/summarizer-app.js +2 -48
  81. package/config.d.ts +20 -4
  82. package/config.js +62 -36
  83. package/core/pipeline-executor.js +11 -1
  84. package/core/print/dataflow-printer.js +4 -5
  85. package/core/print/normalize-printer.js +4 -5
  86. package/core/print/parse-printer.js +1 -2
  87. package/core/print/print.js +2 -3
  88. package/core/print/slice-diff-ansi.js +1 -2
  89. package/core/steps/pipeline/create-pipeline.js +1 -2
  90. package/core/steps/pipeline/default-pipelines.d.ts +18 -18
  91. package/core/steps/pipeline/pipeline.js +1 -2
  92. package/dataflow/environments/append.js +1 -2
  93. package/dataflow/environments/built-in-config.d.ts +47 -0
  94. package/dataflow/environments/built-in-config.js +83 -0
  95. package/dataflow/environments/built-in.d.ts +49 -6
  96. package/dataflow/environments/built-in.js +29 -97
  97. package/dataflow/environments/clone.js +2 -2
  98. package/dataflow/environments/default-builtin-config.d.ts +5 -0
  99. package/dataflow/environments/default-builtin-config.js +83 -0
  100. package/dataflow/environments/define.js +1 -2
  101. package/dataflow/environments/diff.js +5 -6
  102. package/dataflow/environments/environment.js +8 -7
  103. package/dataflow/environments/identifier.d.ts +39 -8
  104. package/dataflow/environments/identifier.js +33 -0
  105. package/dataflow/environments/overwrite.d.ts +6 -5
  106. package/dataflow/environments/overwrite.js +16 -9
  107. package/dataflow/environments/resolve-by-name.d.ts +3 -1
  108. package/dataflow/environments/resolve-by-name.js +40 -8
  109. package/dataflow/environments/scoping.js +2 -3
  110. package/dataflow/extractor.js +25 -24
  111. package/dataflow/graph/dataflowgraph-builder.d.ts +139 -0
  112. package/dataflow/graph/dataflowgraph-builder.js +247 -0
  113. package/dataflow/graph/diff.js +12 -11
  114. package/dataflow/graph/edge.d.ts +2 -2
  115. package/dataflow/graph/edge.js +46 -20
  116. package/dataflow/graph/graph.d.ts +14 -6
  117. package/dataflow/graph/graph.js +25 -21
  118. package/dataflow/graph/quads.js +1 -2
  119. package/dataflow/graph/resolve-graph.d.ts +7 -0
  120. package/dataflow/graph/resolve-graph.js +51 -0
  121. package/dataflow/graph/vertex.d.ts +12 -4
  122. package/dataflow/graph/vertex.js +19 -11
  123. package/dataflow/info.d.ts +3 -7
  124. package/dataflow/info.js +7 -8
  125. package/dataflow/internal/linker.d.ts +3 -1
  126. package/dataflow/internal/linker.js +77 -32
  127. package/dataflow/internal/process/functions/call/argument/make-argument.js +5 -5
  128. package/dataflow/internal/process/functions/call/argument/unpack-argument.js +1 -2
  129. package/dataflow/internal/process/functions/call/built-in/built-in-access.js +10 -8
  130. package/dataflow/internal/process/functions/call/built-in/built-in-apply.d.ts +5 -1
  131. package/dataflow/internal/process/functions/call/built-in/built-in-apply.js +27 -10
  132. package/dataflow/internal/process/functions/call/built-in/built-in-assignment.js +40 -26
  133. package/dataflow/internal/process/functions/call/built-in/built-in-expression-list.js +30 -20
  134. package/dataflow/internal/process/functions/call/built-in/built-in-for-loop.js +10 -9
  135. package/dataflow/internal/process/functions/call/built-in/built-in-function-definition.js +12 -11
  136. package/dataflow/internal/process/functions/call/built-in/built-in-get.js +6 -5
  137. package/dataflow/internal/process/functions/call/built-in/built-in-if-then-else.js +7 -6
  138. package/dataflow/internal/process/functions/call/built-in/built-in-library.js +4 -4
  139. package/dataflow/internal/process/functions/call/built-in/built-in-pipe.js +10 -6
  140. package/dataflow/internal/process/functions/call/built-in/built-in-quote.js +7 -3
  141. package/dataflow/internal/process/functions/call/built-in/built-in-repeat-loop.js +2 -3
  142. package/dataflow/internal/process/functions/call/built-in/built-in-replacement.js +5 -4
  143. package/dataflow/internal/process/functions/call/built-in/built-in-source.js +6 -6
  144. package/dataflow/internal/process/functions/call/built-in/built-in-special-bin-op.js +3 -3
  145. package/dataflow/internal/process/functions/call/built-in/built-in-while-loop.js +6 -5
  146. package/dataflow/internal/process/functions/call/common.js +30 -19
  147. package/dataflow/internal/process/functions/call/default-call-handling.js +1 -2
  148. package/dataflow/internal/process/functions/call/known-call-handling.js +8 -6
  149. package/dataflow/internal/process/functions/call/named-call-handling.js +7 -6
  150. package/dataflow/internal/process/functions/call/unnamed-call-handling.js +11 -7
  151. package/dataflow/internal/process/functions/process-argument.js +10 -8
  152. package/dataflow/internal/process/functions/process-parameter.js +8 -6
  153. package/dataflow/internal/process/process-named-call.js +3 -3
  154. package/dataflow/internal/process/process-symbol.js +5 -4
  155. package/dataflow/internal/process/process-uninteresting-leaf.js +1 -2
  156. package/dataflow/internal/process/process-value.js +5 -4
  157. package/dataflow/processor.js +1 -2
  158. package/documentation/data/dfg/doc-data-dfg-util.d.ts +20 -0
  159. package/documentation/data/dfg/doc-data-dfg-util.js +13 -0
  160. package/documentation/data/query/example-query-code.d.ts +1 -0
  161. package/documentation/data/query/example-query-code.js +25 -0
  162. package/documentation/data/server/doc-data-server-messages.d.ts +1 -0
  163. package/documentation/data/server/doc-data-server-messages.js +508 -0
  164. package/documentation/doc-util/doc-auto-gen.d.ts +7 -0
  165. package/documentation/doc-util/doc-auto-gen.js +9 -0
  166. package/documentation/doc-util/doc-cfg.d.ts +7 -0
  167. package/documentation/doc-util/doc-cfg.js +18 -0
  168. package/documentation/doc-util/doc-cli-option.d.ts +8 -0
  169. package/documentation/doc-util/doc-cli-option.js +36 -0
  170. package/documentation/doc-util/doc-code.d.ts +1 -0
  171. package/documentation/doc-util/doc-code.js +7 -0
  172. package/documentation/doc-util/doc-dfg.d.ts +21 -0
  173. package/documentation/doc-util/doc-dfg.js +93 -0
  174. package/documentation/doc-util/doc-docker.d.ts +1 -0
  175. package/documentation/doc-util/doc-docker.js +5 -0
  176. package/documentation/doc-util/doc-env.d.ts +2 -0
  177. package/documentation/doc-util/doc-env.js +20 -0
  178. package/documentation/doc-util/doc-files.d.ts +6 -0
  179. package/documentation/doc-util/doc-files.js +25 -0
  180. package/documentation/doc-util/doc-general.d.ts +2 -0
  181. package/documentation/doc-util/doc-general.js +16 -0
  182. package/documentation/doc-util/doc-hover-over.d.ts +1 -0
  183. package/documentation/doc-util/doc-hover-over.js +7 -0
  184. package/documentation/doc-util/doc-issue.d.ts +1 -0
  185. package/documentation/doc-util/doc-issue.js +6 -0
  186. package/documentation/doc-util/doc-ms.d.ts +1 -0
  187. package/documentation/doc-util/doc-ms.js +8 -0
  188. package/documentation/doc-util/doc-normalized-ast.d.ts +11 -0
  189. package/documentation/doc-util/doc-normalized-ast.js +71 -0
  190. package/documentation/doc-util/doc-query.d.ts +24 -0
  191. package/documentation/doc-util/doc-query.js +113 -0
  192. package/documentation/doc-util/doc-repl.d.ts +13 -0
  193. package/documentation/doc-util/doc-repl.js +79 -0
  194. package/documentation/doc-util/doc-server-message.d.ts +37 -0
  195. package/documentation/doc-util/doc-server-message.js +153 -0
  196. package/documentation/doc-util/doc-structure.d.ts +12 -0
  197. package/documentation/doc-util/doc-structure.js +21 -0
  198. package/documentation/doc-util/doc-types.d.ts +38 -0
  199. package/documentation/doc-util/doc-types.js +276 -0
  200. package/{r-bridge/data/print.js → documentation/print-capabilities-markdown.js} +8 -4
  201. package/documentation/print-dataflow-graph-wiki.d.ts +1 -0
  202. package/documentation/print-dataflow-graph-wiki.js +849 -0
  203. package/documentation/print-interface-wiki.d.ts +1 -0
  204. package/documentation/print-interface-wiki.js +401 -0
  205. package/documentation/print-normalized-ast-wiki.d.ts +1 -0
  206. package/documentation/print-normalized-ast-wiki.js +98 -0
  207. package/documentation/print-query-wiki.d.ts +1 -0
  208. package/documentation/print-query-wiki.js +215 -0
  209. package/package.json +29 -33
  210. package/queries/base-query-format.d.ts +11 -0
  211. package/{cli/repl/server/messages/hello.js → queries/base-query-format.js} +1 -1
  212. package/queries/call-context-query/call-context-query-executor.d.ts +11 -0
  213. package/queries/call-context-query/call-context-query-executor.js +255 -0
  214. package/queries/call-context-query/call-context-query-format.d.ts +72 -0
  215. package/queries/call-context-query/call-context-query-format.js +17 -0
  216. package/queries/query-schema.d.ts +7 -0
  217. package/queries/query-schema.js +31 -0
  218. package/queries/query.d.ts +35 -0
  219. package/queries/query.js +57 -0
  220. package/queries/two-layer-collector.d.ts +8 -0
  221. package/queries/two-layer-collector.js +31 -0
  222. package/queries/virtual-query/compound-query.d.ts +24 -0
  223. package/queries/virtual-query/compound-query.js +18 -0
  224. package/queries/virtual-query/virtual-queries.d.ts +15 -0
  225. package/queries/virtual-query/virtual-queries.js +8 -0
  226. package/r-bridge/data/data.d.ts +5 -0
  227. package/r-bridge/data/data.js +6 -0
  228. package/r-bridge/data/get.js +2 -3
  229. package/r-bridge/init.js +2 -2
  230. package/r-bridge/lang-4.x/ast/model/collect.js +1 -2
  231. package/r-bridge/lang-4.x/ast/model/model.d.ts +1 -2
  232. package/r-bridge/lang-4.x/ast/model/nodes/r-access.d.ts +3 -0
  233. package/r-bridge/lang-4.x/ast/model/nodes/r-binary-op.d.ts +3 -0
  234. package/r-bridge/lang-4.x/ast/model/nodes/r-break.d.ts +3 -0
  235. package/r-bridge/lang-4.x/ast/model/nodes/r-comment.d.ts +5 -0
  236. package/r-bridge/lang-4.x/ast/model/nodes/r-expression-list.d.ts +4 -0
  237. package/r-bridge/lang-4.x/ast/model/nodes/r-for-loop.d.ts +1 -1
  238. package/r-bridge/lang-4.x/ast/model/nodes/r-function-definition.d.ts +10 -1
  239. package/r-bridge/lang-4.x/ast/model/nodes/r-if-then-else.d.ts +5 -0
  240. package/r-bridge/lang-4.x/ast/model/nodes/r-line-directive.d.ts +3 -0
  241. package/r-bridge/lang-4.x/ast/model/nodes/r-logical.d.ts +3 -0
  242. package/r-bridge/lang-4.x/ast/model/nodes/r-next.d.ts +3 -0
  243. package/r-bridge/lang-4.x/ast/model/nodes/r-pipe.d.ts +3 -0
  244. package/r-bridge/lang-4.x/ast/model/nodes/r-repeat-loop.d.ts +1 -1
  245. package/r-bridge/lang-4.x/ast/model/nodes/r-string.d.ts +3 -0
  246. package/r-bridge/lang-4.x/ast/model/nodes/r-symbol.d.ts +3 -0
  247. package/r-bridge/lang-4.x/ast/model/nodes/r-symbol.js +1 -2
  248. package/r-bridge/lang-4.x/ast/model/nodes/r-unary-op.d.ts +3 -0
  249. package/r-bridge/lang-4.x/ast/model/nodes/r-while-loop.d.ts +2 -2
  250. package/r-bridge/lang-4.x/ast/model/operators.js +27 -26
  251. package/r-bridge/lang-4.x/ast/model/processing/decorate.js +9 -9
  252. package/r-bridge/lang-4.x/ast/model/processing/fold.js +1 -2
  253. package/r-bridge/lang-4.x/ast/model/processing/node-id.d.ts +5 -0
  254. package/r-bridge/lang-4.x/ast/model/processing/node-id.js +26 -3
  255. package/r-bridge/lang-4.x/ast/model/processing/role.js +1 -2
  256. package/r-bridge/lang-4.x/ast/model/processing/stateful-fold.js +23 -23
  257. package/r-bridge/lang-4.x/ast/model/processing/visitor.js +23 -23
  258. package/r-bridge/lang-4.x/ast/model/type.d.ts +2 -2
  259. package/r-bridge/lang-4.x/ast/model/type.js +221 -12
  260. package/r-bridge/lang-4.x/ast/parser/json/format.js +2 -2
  261. package/r-bridge/lang-4.x/ast/parser/json/parser.js +6 -5
  262. package/r-bridge/lang-4.x/ast/parser/xml/input-format.js +3 -3
  263. package/r-bridge/lang-4.x/ast/parser/xml/internal/control/normalize-if-then-else.js +4 -4
  264. package/r-bridge/lang-4.x/ast/parser/xml/internal/control/normalize-if-then.js +7 -7
  265. package/r-bridge/lang-4.x/ast/parser/xml/internal/expression/normalize-expression.js +4 -4
  266. package/r-bridge/lang-4.x/ast/parser/xml/internal/functions/normalize-argument.js +10 -10
  267. package/r-bridge/lang-4.x/ast/parser/xml/internal/functions/normalize-call.js +18 -18
  268. package/r-bridge/lang-4.x/ast/parser/xml/internal/functions/normalize-definition.js +8 -8
  269. package/r-bridge/lang-4.x/ast/parser/xml/internal/functions/normalize-parameter.js +9 -9
  270. package/r-bridge/lang-4.x/ast/parser/xml/internal/loops/normalize-break.js +3 -3
  271. package/r-bridge/lang-4.x/ast/parser/xml/internal/loops/normalize-for.js +10 -10
  272. package/r-bridge/lang-4.x/ast/parser/xml/internal/loops/normalize-next.js +3 -3
  273. package/r-bridge/lang-4.x/ast/parser/xml/internal/loops/normalize-repeat.js +5 -5
  274. package/r-bridge/lang-4.x/ast/parser/xml/internal/loops/normalize-while.js +7 -7
  275. package/r-bridge/lang-4.x/ast/parser/xml/internal/normalize-access.js +12 -12
  276. package/r-bridge/lang-4.x/ast/parser/xml/internal/operators/normalize-binary.js +14 -14
  277. package/r-bridge/lang-4.x/ast/parser/xml/internal/operators/normalize-unary.js +4 -4
  278. package/r-bridge/lang-4.x/ast/parser/xml/internal/other/normalize-comment.js +3 -3
  279. package/r-bridge/lang-4.x/ast/parser/xml/internal/other/normalize-line-directive.js +4 -4
  280. package/r-bridge/lang-4.x/ast/parser/xml/internal/structure/normalize-delimiter.js +3 -3
  281. package/r-bridge/lang-4.x/ast/parser/xml/internal/structure/normalize-expressions.js +13 -13
  282. package/r-bridge/lang-4.x/ast/parser/xml/internal/structure/normalize-root.js +6 -6
  283. package/r-bridge/lang-4.x/ast/parser/xml/internal/structure/normalize-single-node.js +19 -19
  284. package/r-bridge/lang-4.x/ast/parser/xml/internal/values/normalize-number.js +5 -5
  285. package/r-bridge/lang-4.x/ast/parser/xml/internal/values/normalize-string.js +3 -3
  286. package/r-bridge/lang-4.x/ast/parser/xml/internal/values/normalize-symbol.js +2 -3
  287. package/r-bridge/lang-4.x/ast/parser/xml/normalize-meta.js +12 -12
  288. package/r-bridge/lang-4.x/convert-values.js +7 -7
  289. package/r-bridge/retriever.js +12 -11
  290. package/r-bridge/shell.d.ts +0 -1
  291. package/r-bridge/shell.js +6 -1
  292. package/reconstruct/auto-select/auto-select-defaults.js +1 -2
  293. package/reconstruct/auto-select/magic-comments.js +3 -3
  294. package/reconstruct/reconstruct.js +4 -3
  295. package/slicing/criterion/collect-all.js +1 -2
  296. package/slicing/criterion/parse.d.ts +1 -1
  297. package/slicing/criterion/parse.js +6 -5
  298. package/slicing/static/fingerprint.js +2 -3
  299. package/slicing/static/slice-call.js +9 -9
  300. package/slicing/static/static-slicer.js +5 -4
  301. package/statistics/features/common-syntax-probability.js +13 -13
  302. package/statistics/features/feature.d.ts +5 -9
  303. package/statistics/features/feature.js +2 -2
  304. package/statistics/features/post-processing.js +2 -3
  305. package/statistics/features/supported/assignments/assignments.js +3 -2
  306. package/statistics/features/supported/assignments/post-process.js +1 -2
  307. package/statistics/features/supported/comments/post-process.js +1 -2
  308. package/statistics/features/supported/control-flow/control-flow.js +4 -3
  309. package/statistics/features/supported/control-flow/post-process.js +1 -2
  310. package/statistics/features/supported/data-access/data-access.d.ts +2 -2
  311. package/statistics/features/supported/data-access/data-access.js +3 -2
  312. package/statistics/features/supported/data-access/post-process.js +1 -2
  313. package/statistics/features/supported/defined-functions/defined-functions.js +9 -7
  314. package/statistics/features/supported/defined-functions/post-process.d.ts +1 -1
  315. package/statistics/features/supported/defined-functions/post-process.js +2 -3
  316. package/statistics/features/supported/expression-list/post-process.js +1 -2
  317. package/statistics/features/supported/expression-list/{expression-list.js → statistics-expression-list.js} +4 -3
  318. package/statistics/features/supported/loops/loops.js +8 -7
  319. package/statistics/features/supported/loops/post-process.js +1 -2
  320. package/statistics/features/supported/used-functions/post-process.js +2 -3
  321. package/statistics/features/supported/used-functions/used-functions.d.ts +1 -1
  322. package/statistics/features/supported/used-functions/used-functions.js +4 -3
  323. package/statistics/features/supported/used-packages/post-process.js +1 -2
  324. package/statistics/features/supported/values/post-process.js +1 -2
  325. package/statistics/features/supported/variables/post-process.js +2 -3
  326. package/statistics/features/supported/variables/variables.js +2 -1
  327. package/statistics/meta-statistics.js +1 -2
  328. package/statistics/output/print-stats.js +4 -5
  329. package/statistics/output/statistics-file.js +5 -5
  330. package/statistics/statistics.js +2 -3
  331. package/statistics/summarizer/auto-detect.js +1 -2
  332. package/statistics/summarizer/post-process/clusterer.js +1 -2
  333. package/statistics/summarizer/post-process/file-based-count.js +2 -3
  334. package/statistics/summarizer/post-process/histogram.js +3 -4
  335. package/statistics/summarizer/post-process/post-process-output.js +2 -3
  336. package/statistics/summarizer/second-phase/process.d.ts +2 -0
  337. package/statistics/summarizer/second-phase/process.js +2 -2
  338. package/statistics/summarizer/summarizer.js +8 -1
  339. package/util/ansi.d.ts +1 -0
  340. package/util/ansi.js +27 -4
  341. package/util/args.js +2 -3
  342. package/util/arrays.js +8 -9
  343. package/util/assert.js +5 -6
  344. package/util/bimap.d.ts +4 -4
  345. package/util/cfg/cfg.d.ts +1 -0
  346. package/util/cfg/cfg.js +8 -5
  347. package/util/cfg/visitor.d.ts +8 -13
  348. package/util/cfg/visitor.js +22 -56
  349. package/util/diff.js +1 -2
  350. package/util/files.d.ts +0 -1
  351. package/util/files.js +11 -8
  352. package/util/json.js +2 -3
  353. package/util/mermaid/ast.js +7 -7
  354. package/util/mermaid/cfg.js +2 -3
  355. package/util/mermaid/dfg.d.ts +12 -4
  356. package/util/mermaid/dfg.js +28 -16
  357. package/util/mermaid/mermaid.js +5 -4
  358. package/util/numbers.js +1 -2
  359. package/util/objects.d.ts +7 -0
  360. package/util/objects.js +13 -3
  361. package/util/os.js +1 -2
  362. package/util/quads.js +5 -5
  363. package/util/random.js +2 -2
  364. package/util/range.js +8 -9
  365. package/util/schema.d.ts +11 -0
  366. package/util/schema.js +75 -0
  367. package/util/set.js +2 -3
  368. package/util/strings.js +3 -4
  369. package/util/summarizer.js +4 -4
  370. package/util/text.d.ts +1 -0
  371. package/util/text.js +20 -0
  372. package/util/time.js +1 -2
  373. package/util/version.js +2 -3
  374. package/cli/repl/commands/lineage.d.ts +0 -15
  375. package/cli/repl/commands/quit.d.ts +0 -2
  376. package/cli/repl/server/messages/analysis.js +0 -21
  377. package/cli/repl/server/messages/lineage.js +0 -17
  378. package/cli/repl/server/messages/repl.js +0 -37
  379. /package/cli/repl/commands/{main.d.ts → repl-main.d.ts} +0 -0
  380. /package/{r-bridge/data/print.d.ts → documentation/print-capabilities-markdown.d.ts} +0 -0
  381. /package/statistics/features/supported/expression-list/{expression-list.d.ts → statistics-expression-list.d.ts} +0 -0
@@ -0,0 +1,849 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ const graph_1 = require("../dataflow/graph/graph");
7
+ const shell_1 = require("../r-bridge/shell");
8
+ const vertex_1 = require("../dataflow/graph/vertex");
9
+ const edge_1 = require("../dataflow/graph/edge");
10
+ const dataflowgraph_builder_1 = require("../dataflow/graph/dataflowgraph-builder");
11
+ const assert_1 = require("../util/assert");
12
+ const doc_dfg_1 = require("./doc-util/doc-dfg");
13
+ const doc_files_1 = require("./doc-util/doc-files");
14
+ const pipeline_executor_1 = require("../core/pipeline-executor");
15
+ const retriever_1 = require("../r-bridge/retriever");
16
+ const json_1 = require("../util/json");
17
+ const doc_env_1 = require("./doc-util/doc-env");
18
+ const doc_data_dfg_util_1 = require("./data/dfg/doc-data-dfg-util");
19
+ const doc_cli_option_1 = require("./doc-util/doc-cli-option");
20
+ const doc_types_1 = require("./doc-util/doc-types");
21
+ const doc_structure_1 = require("./doc-util/doc-structure");
22
+ const doc_code_1 = require("./doc-util/doc-code");
23
+ const path_1 = __importDefault(require("path"));
24
+ const doc_general_1 = require("./doc-util/doc-general");
25
+ const node_id_1 = require("../r-bridge/lang-4.x/ast/model/processing/node-id");
26
+ const identifier_1 = require("../dataflow/environments/identifier");
27
+ const r_function_call_1 = require("../r-bridge/lang-4.x/ast/model/nodes/r-function-call");
28
+ const resolve_by_name_1 = require("../dataflow/environments/resolve-by-name");
29
+ const environment_builder_1 = require("../../test/functionality/_helper/dataflow/environment-builder");
30
+ const default_pipelines_1 = require("../core/steps/pipeline/default-pipelines");
31
+ const doc_auto_gen_1 = require("./doc-util/doc-auto-gen");
32
+ const text_1 = require("../util/text");
33
+ const log_1 = require("../../test/functionality/_helper/log");
34
+ const linker_1 = require("../dataflow/internal/linker");
35
+ const doc_normalized_ast_1 = require("./doc-util/doc-normalized-ast");
36
+ async function subExplanation(shell, { description, code, expectedSubgraph }) {
37
+ expectedSubgraph = await (0, doc_dfg_1.verifyExpectedSubgraph)(shell, code, expectedSubgraph);
38
+ const marks = [];
39
+ for (const [id] of expectedSubgraph.vertices(true)) {
40
+ marks.push(id);
41
+ }
42
+ for (const [from, targets] of expectedSubgraph.edges()) {
43
+ for (const [to] of targets) {
44
+ marks.push(`${from}->${to}`);
45
+ }
46
+ }
47
+ return `
48
+ ${await (0, doc_dfg_1.printDfGraphForCode)(shell, code, { mark: new Set(marks) })}
49
+
50
+ ${description}`;
51
+ }
52
+ async function printAllSubExplanations(shell, expls) {
53
+ let result = `
54
+ <details>
55
+
56
+ <summary>Additional Case${expls.length > 1 ? 's' : ''}</summary>
57
+
58
+ `;
59
+ for (const sub of expls) {
60
+ result += `#### ${sub.name}\n`;
61
+ result += await subExplanation(shell, sub) + '\n';
62
+ }
63
+ return result + '\n\n</details>';
64
+ }
65
+ async function explanation({ shell, name, type, description, code, expectedSubgraph }, index, ...subExplanations) {
66
+ await (0, doc_dfg_1.verifyExpectedSubgraph)(shell, code, expectedSubgraph);
67
+ return `
68
+ <a id='${name.toLowerCase().replaceAll(' ', '-')}'> </a>
69
+ ### ${index}) ${name}
70
+
71
+ Type: \`${type}\`
72
+
73
+ ${await subExplanation(shell, { name, description, code, expectedSubgraph })}
74
+
75
+ ${subExplanations.length > 0 ? await printAllSubExplanations(shell, subExplanations) : ''}
76
+ `;
77
+ }
78
+ function edgeTypeToId(edgeType) {
79
+ return (0, edge_1.edgeTypeToName)(edgeType).toLowerCase().replaceAll(' ', '-');
80
+ }
81
+ function linkEdgeName(edgeType) {
82
+ return `[\`${(0, edge_1.edgeTypeToName)(edgeType)}\`](#${edgeTypeToId(edgeType)})`;
83
+ }
84
+ async function getVertexExplanations(shell, vertexType) {
85
+ /* we use the map to ensure order easily :D */
86
+ const vertexExplanations = new Map();
87
+ vertexExplanations.set(vertex_1.VertexType.Value, [{
88
+ shell: shell,
89
+ name: 'Value Vertex',
90
+ type: vertex_1.VertexType.Value,
91
+ description: `
92
+ Describes a constant value (numbers, booleans/logicals, strings, ...).
93
+ In general, the respective vertex is more or less a dummy vertex as you can see from its implementation.
94
+
95
+ ${(0, doc_types_1.printHierarchy)({ program: vertexType.program, hierarchy: vertexType.info, root: 'DataflowGraphVertexValue' })}
96
+
97
+ ${(0, doc_structure_1.block)({
98
+ type: 'NOTE',
99
+ content: `
100
+ The value is not stored in the vertex itself, but in the normalized AST.
101
+ To access the value, you can use the \`id\` of the vertex to access the respective node in the [normalized AST](${doc_files_1.FlowrWikiBaseRef}/Normalized%20AST)
102
+ and ask for the value associated with it.
103
+ `
104
+ })}
105
+
106
+ Please be aware that such nodes may be the result from language semantics as well, and not just from constants directly in the source.
107
+ For example, an access operation like \`df$column\` will treat the column name as a constant value.
108
+
109
+ ${(0, doc_structure_1.details)('Example: Semantics Create a Value', `In the following graph, the original type printed by mermaid is still \`RSymbol\` (from the [normalized AST](${doc_files_1.FlowrWikiBaseRef}/Normalized%20AST)), however, the shape of the vertex signals to you that the symbol is in-fact treated as a constant! If you do not know what \`df$column\` even means, please refer to the [R topic](https://rdrr.io/r/base/Extract.html).\n` +
110
+ await (0, doc_dfg_1.printDfGraphForCode)(shell, 'df$column', { mark: new Set([1]) }))}
111
+ `,
112
+ code: '42',
113
+ expectedSubgraph: (0, dataflowgraph_builder_1.emptyGraph)().constant('0')
114
+ }, []]);
115
+ vertexExplanations.set(vertex_1.VertexType.Use, [{
116
+ shell: shell,
117
+ name: 'Use Vertex',
118
+ type: vertex_1.VertexType.Use,
119
+ description: `
120
+
121
+ Describes symbol/variable references which are read (or potentially read at a given position).
122
+ Similar to the [value vertex](#value-vertex) described above, this is more a marker vertex as
123
+ you can see from the implementation.
124
+
125
+ ${(0, doc_types_1.printHierarchy)({ program: vertexType.program, hierarchy: vertexType.info, root: 'DataflowGraphVertexUse' })}
126
+
127
+ ${(0, doc_structure_1.block)({
128
+ type: 'NOTE',
129
+ content: `
130
+ The name of the symbol is not actually part of what we store in the dataflow graph,
131
+ as we have it within the normalized AST.
132
+ To access the name, you can use the \`id\` of the vertex:
133
+
134
+ ${(0, doc_code_1.codeBlock)('ts', `const name = ${node_id_1.recoverName.name}(id, graph.idMap);`)}
135
+ `
136
+ })}
137
+
138
+ Most often, you will see the _use_ vertex whenever a variable is read.
139
+ However, similar to the [value vertex](#value-vertex), the _use_ vertex can also be the result of language semantics.
140
+ Consider a case, in which we refer to a variable with a string, as in \`get("x")\`.
141
+
142
+ ${(0, doc_structure_1.details)('Example: Semantics Create a Symbol', `In the following graph, the original type printed by mermaid is still \`RString\` (from the [normalized AST](${doc_files_1.FlowrWikiBaseRef}/Normalized%20AST)), however, the shape of the vertex signals to you that the symbol is in-fact treated as a variable use! ` +
143
+ 'If you are unsure what `get` does, refer to the [documentation](https://www.rdocumentation.org/packages/base/versions/3.6.2/topics/get). ' +
144
+ 'Please note, that the lexeme being printed as `"x"` may be misleading (after all it is recovered from the AST), the quotes are not part of the reference.\n' +
145
+ await (0, doc_dfg_1.printDfGraphForCode)(shell, 'get("x")', { mark: new Set([1]) }))}
146
+
147
+ But now to the interesting stuff: how do we actually know which values are read by the respective variable use?
148
+ This usually involves a [variable definition](#variable-definition-vertex) and a [reads edge](#reads-edge) linking the two.
149
+
150
+ ${(0, doc_structure_1.details)('Example: Reads Edge Identifying a Single Definition', 'In the following graph, the `x` is read from the definition `x <- 1`.\n' +
151
+ await (0, doc_dfg_1.printDfGraphForCode)(shell, 'x <- 1\nprint(x)', { mark: new Set([3, '0->3']), codeOpen: true }))}
152
+
153
+ In general, there may be many such edges, identifying every possible definition of the variable.
154
+
155
+ ${(0, doc_structure_1.details)('Example: Reads Edge Identifying Multiple Definitions (conditional)', await (0, doc_dfg_1.printDfGraphForCode)(shell, 'x <- 1\nif(u) x <- 2\nprint(x)', { mark: new Set([10, '10->0', '10->4']), codeOpen: true }))}
156
+ ${(0, doc_structure_1.details)('Example: Reads Edge Identifying Multiple Definitions (loop)', await (0, doc_dfg_1.printDfGraphForCode)(shell, 'x <- 1\nfor(i in v) x <- 2\nprint(x)', { mark: new Set([11, '11->0', '11->5']), codeOpen: true }))}
157
+ ${(0, doc_structure_1.details)('Example: Reads Edge Identifying Multiple Definitions (side-effect)', await (0, doc_dfg_1.printDfGraphForCode)(shell, 'f <- function() x <<- 2\nx <- 2\nif(u) f()\nprint(x)', { mark: new Set([16, '16->1', '16->7']), codeOpen: true }))}
158
+ `,
159
+ code: 'x',
160
+ expectedSubgraph: (0, dataflowgraph_builder_1.emptyGraph)().use('1@x', 'x')
161
+ }, []]);
162
+ vertexExplanations.set(vertex_1.VertexType.FunctionCall, [{
163
+ shell: shell,
164
+ name: 'Function Call Vertex',
165
+ type: vertex_1.VertexType.FunctionCall,
166
+ description: `
167
+ Describes any kind of function call, including unnamed calls and those that happen implicitly!
168
+ In general the vertex provides you with information about
169
+ the _name_ of the called function, the passed _arguments_, and the _environment_ in which the call happens (if it is of importance).
170
+
171
+ However, the implementation reveals that it may hold an additional \`onlyBuiltin\` flag to indicate that the call is only calling builtin functions &mdash; however, this is only a flag to improve performance
172
+ and it should not be relied on as it may under-approximate the actual calling targets (e.g., being \`false\` even though all calls resolve to builtins).
173
+
174
+ ${(0, doc_types_1.printHierarchy)({ program: vertexType.program, hierarchy: vertexType.info, root: 'DataflowGraphVertexFunctionCall' })}
175
+ The related function argument references are defined like this:
176
+ ${(0, doc_types_1.printHierarchy)({ program: vertexType.program, hierarchy: vertexType.info, root: 'FunctionArgument' })}
177
+
178
+
179
+ ${(0, doc_structure_1.details)('Example: Simple Function Call (unresolved)', await (async () => {
180
+ const code = 'foo(x,3,y=3,)';
181
+ const [text, info] = await (0, doc_dfg_1.printDfGraphForCode)(shell, code, { mark: new Set([8]), exposeResult: true });
182
+ const callInfo = [...info.dataflow.graph.vertices(true)].find(([, vertex]) => vertex.tag === vertex_1.VertexType.FunctionCall && vertex.name === 'foo');
183
+ (0, assert_1.guard)(callInfo !== undefined, () => `Could not find call vertex for ${code}`);
184
+ const [callId, callVert] = callInfo;
185
+ const inverseMapReferenceTypes = Object.fromEntries(Object.entries(identifier_1.ReferenceType).map(([k, v]) => [v, k]));
186
+ const identifierType = (0, doc_types_1.getTypesFromFolderAsMermaid)({
187
+ files: [path_1.default.resolve('./src/dataflow/environments/identifier.ts')],
188
+ typeName: 'IdentifierReference',
189
+ inlineTypes: ['ControlDependency']
190
+ });
191
+ return `
192
+ To get a better understanding, let's look at a simple function call without any known call target, like \`${code}\`:
193
+
194
+ ${text}
195
+
196
+ In this case, we have a function call vertex with id \`${callId}\` and the following arguments:
197
+
198
+ ${(0, doc_code_1.codeBlock)('json', JSON.stringify(callVert.args, json_1.jsonReplacer, 2))}
199
+
200
+ Of course now, this is hard to read in this form (although the ids of the arguments can be mapped pretty easily to the visualization),
201
+ as the \`type\` of these references is a bit-mask, encoding one of the following reference types:
202
+
203
+ | Value | Reference Type |
204
+ |------:|----------------|
205
+ ${Object.values(identifier_1.ReferenceType).filter(k => typeof k === 'string').map(k => `| ${identifier_1.ReferenceType[k]} | ${k} |`).join('\n')}
206
+
207
+ In other words, we classify the references as ${(0, doc_general_1.lastJoin)(callVert.args.map(a => {
208
+ if (a === r_function_call_1.EmptyArgument) {
209
+ return `the (special) empty argument type (\`${r_function_call_1.EmptyArgument}\`)`;
210
+ }
211
+ else {
212
+ return inverseMapReferenceTypes[a.type];
213
+ }
214
+ }), ', ', ', and ')}.
215
+ For more information on the types of references, please consult the implementation.
216
+
217
+ ${(0, doc_types_1.printHierarchy)({ program: identifierType.program, hierarchy: identifierType.info, root: 'ReferenceType' })}
218
+ `;
219
+ })())}
220
+
221
+ ${(0, doc_structure_1.block)({
222
+ type: 'NOTE',
223
+ content: `
224
+ But how do you know which definitions are actually called by the function?
225
+
226
+ So first of all, some frontends of _flowR_ (like the ${(0, doc_cli_option_1.getReplCommand)('slicer')} and ${(0, doc_cli_option_1.getReplCommand)('query')} with the [Query API](${doc_files_1.FlowrWikiBaseRef}/Query%20API)) already provide you with this information.
227
+ In general there are three scenarios you may be interested in:
228
+
229
+ ${(0, doc_structure_1.details)('1) the function resolves only to builtin definitions (like <code><-</code>)', `
230
+
231
+ Let's have a look at a simple assignment:
232
+
233
+ ${await (0, doc_dfg_1.printDfGraphForCode)(shell, 'x <- 2')}
234
+
235
+ In this case, the call does not have a single ${linkEdgeName(edge_1.EdgeType.Calls)} edge, which in general means (i.e., if the analysis is done and you are not looking at an intermediate result) it is bound to anything
236
+ global beyond the scope of the given script. _flowR_ generally (theoretically at least) does not know if the call really refers to a built-in variable or function,
237
+ as any code that is not part of the analysis could cause the semantics to change.
238
+ However, it is (in most cases) safe to assume we call a builtin if there is a builtin function with the given name and if there is no ${linkEdgeName(edge_1.EdgeType.Calls)} edge attached to a call.
239
+ If you want to check the resolve targets, refer to \`${resolve_by_name_1.resolveByName.name}\` which is defined in ${(0, doc_files_1.getFilePathMd)('../dataflow/environments/resolve-by-name')}.
240
+ `)}
241
+
242
+ ${(0, doc_structure_1.details)('2) the function only resolves to definitions that are present in the program', `
243
+
244
+ Let's have a look at a call to a function named \`foo\` which is defined in the same script:
245
+
246
+ ${await (async () => {
247
+ const code = 'foo <- function() 3\nfoo()';
248
+ const [text, info] = await (0, doc_dfg_1.printDfGraphForCode)(shell, code, { exposeResult: true, mark: new Set([6, '6->0', '6->1', '6->3']) });
249
+ const numberOfEdges = [...info.dataflow.graph.edges()].flatMap(e => [...e[1].keys()]).length;
250
+ const callVertex = [...info.dataflow.graph.vertices(true)].find(([, vertex]) => vertex.tag === vertex_1.VertexType.FunctionCall && vertex.name === 'foo');
251
+ (0, assert_1.guard)(callVertex !== undefined, () => `Could not find call vertex for ${code}`);
252
+ const [callId] = callVertex;
253
+ return `
254
+ ${text}
255
+
256
+ Now, there are several edges, ${numberOfEdges} to be precise, although we are primarily interested in the ${info.dataflow.graph.outgoingEdges(callId)?.size ?? 0}
257
+ edges going out from the call vertex \`${callId}\`.
258
+ The ${linkEdgeName(edge_1.EdgeType.Reads)} edge signals all definitions which are read by the \`foo\` identifier (similar to a [use vertex](#use-vertex)).
259
+ While it seems to be somewhat redundant given the ${linkEdgeName(edge_1.EdgeType.Calls)} edge that identifies the called [function definition](#function-definition-vertex),
260
+ you have to consider cases in which aliases are involved in the call resolution (e.g., with higher order functions).
261
+
262
+ ${(0, doc_structure_1.details)('Example: Alias in Call Resolution', `In the following example, \`g\` ${linkEdgeName(edge_1.EdgeType.Reads)} the previous definition, but ${linkEdgeName(edge_1.EdgeType.Calls)} the function assigned to \`f\`.\n`
263
+ + await (0, doc_dfg_1.printDfGraphForCode)(shell, 'f <- function() 3\ng <- f\ng()', { mark: new Set(['9', '9->5', '9->3']) }))}
264
+
265
+ Lastly, the ${linkEdgeName(edge_1.EdgeType.Returns)} edge links the call to the return vertices(s) of the function.
266
+ Please be aware, that these multiple exit points may be counter intuitive as they often appear with a nested call (usually a call to the built-in \`{\` function).
267
+
268
+ ${(0, doc_structure_1.details)('(Advanced) Example: Multiple Exit Points May Still Reflect As One', await (0, doc_dfg_1.printDfGraphForCode)(shell, `
269
+ f <- function() {
270
+ if(u) return(3)
271
+ if(v) return(2)
272
+ 1
273
+ }
274
+ f()`.trim(), { mark: new Set([22, '22->18']) }) +
275
+ `
276
+ In this case the call of \`f\` still only has one ${linkEdgeName(edge_1.EdgeType.Returns)} edge, although the function _looks_ as if it would have multiple exit points!
277
+ But you have to beware that \`{\` is a function call as well (see below) and it may be redefined, or at least affect the actual returns of the function.
278
+ In this scenario we show two types of such returns (or exit points): _explicit_ returns with the \`return\` function and _implicit_ returns (the result of the last evaluated expression).
279
+ However, they are actually linked with the call of the built-in function \`{\` (and, in fact, they are highlighted in the mermaid graph).
280
+ `)}
281
+
282
+ `;
283
+ })()}
284
+
285
+
286
+
287
+ `)}
288
+
289
+
290
+ ${(0, doc_structure_1.details)('3) the function resolves to a mix of both', `
291
+
292
+ Users may write... interesting pieces of code - for reasons we should not be interested in!
293
+ Consider a case in which you have a built-in function (like the assignment operator \`<-\`) and a user that wants to redefine the meaning of the function call _sometimes_:
294
+
295
+ ${await (async () => {
296
+ const [text, info] = await (0, doc_dfg_1.printDfGraphForCode)(shell, 'x <- 2\nif(u) `<-` <- `*`\nx <- 3', { switchCodeAndGraph: true, mark: new Set([9, '9->0', '9->10']), exposeResult: true });
297
+ const interestingUseOfAssignment = [...info.dataflow.graph.vertices(true)].find(([, vertex]) => vertex.id === 11);
298
+ (0, assert_1.guard)(interestingUseOfAssignment !== undefined, () => 'Could not find interesting assignment vertex for the code');
299
+ const [id, interestingVertex] = interestingUseOfAssignment;
300
+ const env = interestingVertex.environment;
301
+ (0, assert_1.guard)(env !== undefined, () => 'Could not find environment for interesting assignment vertex');
302
+ const name = interestingVertex.name;
303
+ (0, assert_1.guard)(name !== undefined, () => 'Could not find name for interesting assignment vertex');
304
+ return `
305
+ ${text}
306
+
307
+ Interesting program, right? Running this with \`u <- TRUE\` will cause the last line to evaluate to \`6\` because we redefined the assignment
308
+ operator to mean multiplication, while with \`u <- FALSE\` causes \`x\` to be assigned to \`3\`.
309
+ In short: the last line may either refer to a definition or to a use of \`x\`, and we are not fully equipped to visualize this (this causes a warning).
310
+ First of all how can you spot that something weird is happening? Well, this definition has a ${linkEdgeName(edge_1.EdgeType.Reads)} and a ${linkEdgeName(edge_1.EdgeType.DefinedBy)} edge,
311
+ but this of course does not apply to the general case.
312
+
313
+ For starters, let's have a look at the environment of the call to \`<-\` in the last line:
314
+
315
+ ${(0, doc_env_1.printEnvironmentToMarkdown)(env.current)}
316
+
317
+ Great, you should see a definition of \`<-\` which is constraint by the [control dependency](#control-dependencies) to the \`if\`.
318
+ Hence, trying to re-resolve the call using \`${linker_1.getAllFunctionCallTargets.name}\` (defined in ${(0, doc_files_1.getFilePathMd)('../dataflow/internal/linker.ts')}) with the id \`${id}\` of the call as starting point will present you with
319
+ the following target ids: { \`${[...(0, linker_1.getAllFunctionCallTargets)(id, info.dataflow.graph)].join('`, `')}\` }.
320
+ This way we know that the call may refer to the built-in assignment operator or to the multiplication.
321
+ Similarly, trying to resolve the name with \`${resolve_by_name_1.resolveByName.name}\` using the environment attached to the call vertex (filtering for any reference type) returns (in a similar fashion):
322
+ { \`${(0, resolve_by_name_1.resolveByName)(name, env)?.map(d => d.nodeId).join('`, `')}\` } (however, the latter will not trace aliases).
323
+
324
+ `;
325
+ })()}
326
+
327
+ `)}
328
+
329
+ `
330
+ })}
331
+
332
+ Function calls are the most complicated mechanism in R as essentially everything is a function call.
333
+ Even **control structures** like \`if(p) a else b\` are desugared into function calls (e.g., as \`if\`(p, a, b)).
334
+ ${(0, doc_structure_1.details)('Example: <code>if</code> as a Function Call', await (0, doc_dfg_1.printDfGraphForCode)(shell, 'if(p) a else b'))}
335
+
336
+ Similarly you should be aware of calls to **anonymous functions**, which may appear given directly (e.g. as \`(function() 1)()\`) or indirectly, with code
337
+ directly calling the return of another function call: \`foo()()\`.
338
+ ${(0, doc_structure_1.details)('Example: Anonymous Function Call (given directly)', await (0, doc_dfg_1.printDfGraphForCode)(shell, '(function() 1)()', { mark: new Set([6, '6->4']) }))}
339
+
340
+ ${(0, doc_structure_1.details)('Example: Anonymous Function Call (given indirectly)', await (0, doc_dfg_1.printDfGraphForCode)(shell, 'foo <- function() return(function() 3)\nfoo()()', { mark: new Set([12, '12->4']) }))}
341
+
342
+ Another interesting case is a function with **side effects**, most prominently with the super-assignment \`<<-\`.
343
+ In this case, you may encounter the ${linkEdgeName(edge_1.EdgeType.SideEffectOnCall)} as exemplified below.
344
+ ${(0, doc_structure_1.details)('Example: Function Call with a Side-Effect', await (0, doc_dfg_1.printDfGraphForCode)(shell, 'f <- function() x <<- 3\n f()', { mark: new Set([8, '1->8']) }))}
345
+
346
+ `,
347
+ code: 'foo()',
348
+ expectedSubgraph: (0, dataflowgraph_builder_1.emptyGraph)().call('1@foo', 'foo', [])
349
+ }, []]);
350
+ vertexExplanations.set(vertex_1.VertexType.VariableDefinition, [{
351
+ shell: shell,
352
+ name: 'Variable Definition Vertex',
353
+ type: vertex_1.VertexType.VariableDefinition,
354
+ description: `
355
+ Defined variables most commonly occur in the context of an assignment, for example, with the \`<-\` operator as shown above.
356
+
357
+ ${(0, doc_structure_1.details)('Example: Super Definition (<code><<-</code>)', await (0, doc_dfg_1.printDfGraphForCode)(shell, 'x <<- 1', { mark: new Set([0]) }))}
358
+
359
+ The implementation is relatively sparse and similar to the other marker vertices:
360
+
361
+ ${(0, doc_types_1.printHierarchy)({ program: vertexType.program, hierarchy: vertexType.info, root: 'DataflowGraphVertexVariableDefinition' })}
362
+
363
+ Of course, there are not just operators that define variables, but also functions, like \`assign\`.
364
+
365
+ ${(0, doc_structure_1.details)('Example: Using <code>assign</code>', await (0, doc_dfg_1.printDfGraphForCode)(shell, 'assign("x", 1)\nx', { mark: new Set([1]) })
366
+ + `\nThe example may be misleading as the visualization uses \`${node_id_1.recoverName.name}\` to print the lexeme of the variable. However, this actually defines the variable \`x\` (without the quotes) as you can see with the ${linkEdgeName(edge_1.EdgeType.Reads)} edge.`)}
367
+
368
+ Please be aware, that the name of the symbol defined may differ from what you read in the program as R allows the assignments to strings, escaped names, and more:
369
+
370
+ ${(0, doc_structure_1.details)('Example: Assigning with an Escaped Name', await (0, doc_dfg_1.printDfGraphForCode)(shell, '`x` <- 1\nx', { mark: new Set([0]) }))}
371
+ ${(0, doc_structure_1.details)('Example: Assigning with a String', await (0, doc_dfg_1.printDfGraphForCode)(shell, '"x" <- 1\nx', { mark: new Set([0]) }))}
372
+
373
+ Definitions may be constrained by conditionals (_flowR_ takes care of calculating the dominating front for you).
374
+
375
+ ${(0, doc_structure_1.details)('Conditional Assignments', await (async () => {
376
+ const constrainedDefinitions = await (0, doc_dfg_1.printDfGraphForCode)(shell, 'x <- 0\nif(u) x <- 1 else x <- 2\nx', { exposeResult: true });
377
+ const [text, info] = constrainedDefinitions;
378
+ const finalEnvironment = (0, doc_env_1.printEnvironmentToMarkdown)(info.dataflow.environment.current);
379
+ return `
380
+ ${text}
381
+
382
+ In this case, the definition of \`x\` is constrained by the conditional, which is reflected in the environment at the end of the analysis:
383
+
384
+ ${finalEnvironment}
385
+
386
+ As you can see, _flowR_ is able to recognize that the initial definition of \`x\` has no influence on the final value of the variable.
387
+ `;
388
+ })())}
389
+
390
+ `,
391
+ code: 'x <- 1',
392
+ expectedSubgraph: (0, dataflowgraph_builder_1.emptyGraph)().defineVariable('1@x', 'x')
393
+ }, []]);
394
+ vertexExplanations.set(vertex_1.VertexType.FunctionDefinition, [{
395
+ shell: shell,
396
+ name: 'Function Definition Vertex',
397
+ type: vertex_1.VertexType.FunctionDefinition,
398
+ description: `
399
+ Defining a function does do a lot of things: 1) it creates a new scope, 2) it may introduce parameters which act as promises and which are only evaluated if they are actually required in the body, 3) it may access the enclosing environments and the callstack.
400
+ The vertex object in the dataflow graph stores multiple things, including all exit points, the enclosing environment if necessary, and the information of the subflow (the "body" of the function).
401
+
402
+ ${(0, doc_types_1.printHierarchy)({ program: vertexType.program, hierarchy: vertexType.info, root: 'DataflowGraphVertexFunctionDefinition' })}
403
+ The subflow is defined like this:
404
+ ${(0, doc_types_1.printHierarchy)({ program: vertexType.program, hierarchy: vertexType.info, root: 'DataflowFunctionFlowInformation' })}
405
+ And if you are interested in the exit points, they are defined like this:
406
+ ${(0, doc_types_1.printHierarchy)({ program: vertexType.program, hierarchy: vertexType.info, root: 'ExitPoint' })}
407
+
408
+
409
+ Whenever we visualize a function definition, we use a dedicated node to represent the anonymous function object,
410
+ and a subgraph (usually with the name \`"function <id>"\`) to encompass the body of the function (they are linked with a dotted line).
411
+
412
+ ${(0, doc_structure_1.block)({
413
+ type: 'NOTE',
414
+ content: `
415
+ You may ask yourself: How can I know which vertices are part of the function body? how do i know the parameters?
416
+ All vertices that are part of the graph are present in the \`graph\` property of the function definition &mdash; it contains a set of all ids of the contained vertices:
417
+ the actual dataflow graph is flat, and you can query all root vertices (i.e., those not part of any function definition) using
418
+ \`${new graph_1.DataflowGraph(undefined).rootIds.name}\`. Additionally, most functions that you can call on the dataflow graph offer a flag whether you want to include
419
+ vertices of function definitions or not (e.g., \`${new graph_1.DataflowGraph(undefined).vertices.name}\`)
420
+
421
+ ${(0, doc_structure_1.details)('Example: Nested Function Definitions', await (async () => {
422
+ const [text, info] = await (0, doc_dfg_1.printDfGraphForCode)(shell, 'f <- function() { g <- function() 3 }', { mark: new Set([9, 6]), exposeResult: true });
423
+ const definitions = [...info.dataflow.graph.vertices(true)]
424
+ .filter(([, vertex]) => vertex.tag === vertex_1.VertexType.FunctionDefinition)
425
+ .map(([id, vertex]) => `| \`${id}\` | { \`${[...vertex.subflow.graph].join('`, `')}\` } |`);
426
+ return `
427
+ ${text}
428
+
429
+ As you can see, the vertex ids of the subflow do not contain those of nested function definitions but again only those which are part of the respective scope (creating a tree-like structure):
430
+
431
+ | Id | Vertex Ids in Subflow |
432
+ |---:|-----------------------|
433
+ ${definitions.join('\n')}
434
+
435
+ `;
436
+ })())}
437
+
438
+ But now there is still an open question: how do you know which vertices are the parameters?
439
+ In short: there is no direct way to infer this from the dataflow graph (as parameters are handled as open references which are promises).
440
+ However, you can use the [normalized AST](${doc_files_1.FlowrWikiBaseRef}/Normalized%20AST) to get the parameters used.
441
+
442
+ ${(0, doc_structure_1.details)('Example: Parameters of a Function', await (async () => {
443
+ const code = 'f <- function(x, y = 3) x + y';
444
+ const [text, info] = await (0, doc_dfg_1.printDfGraphForCode)(shell, code, { mark: new Set([10, 1, 3]), exposeResult: true });
445
+ const ast = await (0, doc_normalized_ast_1.printNormalizedAstForCode)(shell, code, { prefix: 'flowchart LR\n', showCode: false });
446
+ const functionDefinition = [...info.dataflow.graph.vertices(true)].find(([, vertex]) => vertex.tag === vertex_1.VertexType.FunctionDefinition);
447
+ (0, assert_1.guard)(functionDefinition !== undefined, () => `Could not find function definition for ${code}`);
448
+ const [id] = functionDefinition;
449
+ const normalized = info.normalize.idMap.get(id);
450
+ return `
451
+ Let's first consider the following dataflow graph (of \`${code}\`):
452
+
453
+ ${text}
454
+
455
+ The function definition we are interested in has the id \`${id}\`. Looking at the [normalized AST](${doc_files_1.FlowrWikiBaseRef}/Normalized%20AST) of the code,
456
+ we can get the parameters simply be requesting the \`parameters\` property of the function definition (yielding the names: [${normalized.parameters.map(p => `\`${p.name.content}\``).join(', ')}]):
457
+
458
+ ${ast}
459
+ `;
460
+ })())}
461
+ `
462
+ })}
463
+
464
+ Last but not least, please keep in mind that R offers another way of writing anonymous functions (using the backslash):
465
+
466
+ ${await (0, doc_dfg_1.printDfGraphForCode)(shell, '\\(x) x + 1', { switchCodeAndGraph: true })}
467
+
468
+ Besides this being a theoretically "shorter" way of defining a function, this behaves similarly to the use of \`function\`.
469
+
470
+ `,
471
+ code: 'function() 1',
472
+ expectedSubgraph: (0, dataflowgraph_builder_1.emptyGraph)().defineFunction('1@function', [0], { graph: new Set('0'), in: [], out: [], unknownReferences: [], entryPoint: 0, environment: (0, environment_builder_1.defaultEnv)() })
473
+ }, []]);
474
+ const results = [];
475
+ let i = 0;
476
+ for (const [, vertex] of (0, doc_data_dfg_util_1.getAllVertices)()) {
477
+ const get = vertexExplanations.get(vertex);
478
+ (0, assert_1.guard)(get !== undefined, () => `No explanation for vertex type ${vertex}`);
479
+ const [expl, subExplanations] = get;
480
+ results.push(await explanation(expl, ++i, ...subExplanations));
481
+ }
482
+ return results.join('\n');
483
+ }
484
+ async function getEdgesExplanations(shell) {
485
+ const edgeExplanations = new Map();
486
+ edgeExplanations.set(edge_1.EdgeType.Reads, [{
487
+ shell: shell,
488
+ name: 'Reads Edge',
489
+ type: edge_1.EdgeType.Reads,
490
+ description: `
491
+ Reads edges mark that the source vertex (usually a [use vertex](#use-vertex)) reads whatever is defined by the target vertex (usually a [variable definition](#variable-definition-vertex)).
492
+
493
+ ${(0, doc_structure_1.block)({
494
+ type: 'NOTE',
495
+ content: `
496
+ A ${linkEdgeName(edge_1.EdgeType.Reads)} edge is not a transitive closure and only links the "directly read" definition(s).
497
+ Our abstract domains resolving transitive ${linkEdgeName(edge_1.EdgeType.Reads)} edges (and for that matter, following ${linkEdgeName(edge_1.EdgeType.Returns)} as well)
498
+ are currently tailored to what we need in _flowR_. Hence we offer a function like \`${linker_1.getAllFunctionCallTargets.name}\` (defined in ${(0, doc_files_1.getFilePathMd)('../dataflow/internal/linker.ts')}),
499
+ as well as \`${resolve_by_name_1.resolvesToBuiltInConstant.name}\` (defined in ${(0, doc_files_1.getFilePathMd)('../dataflow/environments/resolve-by-name.ts')}) which do this for specific cases.
500
+
501
+ ${(0, doc_structure_1.details)('Example: Multi-Level Reads', await (0, doc_dfg_1.printDfGraphForCode)(shell, 'x <- 3\ny <- x\nprint(y)', { mark: new Set(['9->7', '7->3', '4->0']) }))}
502
+
503
+ Similarly, ${linkEdgeName(edge_1.EdgeType.Reads)} can be cyclic, for example in the context of loops:
504
+
505
+ ${(0, doc_structure_1.details)('Example: Cyclic Reads', await (0, doc_dfg_1.printDfGraphForCode)(shell, 'for(i in v) x <- x + 1', { mark: new Set(['3->2']) }))}
506
+ `
507
+ })}
508
+
509
+ Please refer to the explanation of the respective vertices for more information.
510
+ `,
511
+ code: 'x <- 2\nprint(x)',
512
+ expectedSubgraph: (0, dataflowgraph_builder_1.emptyGraph)().reads('2@x', '1@x')
513
+ }, [{
514
+ name: 'Reads Edge (Call)',
515
+ description: 'Named calls are resolved too, linking to the symbol that holds the anonymous function definition (indirectly or directly)',
516
+ code: 'foo <- function() {}\nfoo()',
517
+ expectedSubgraph: (0, dataflowgraph_builder_1.emptyGraph)().reads('2@foo', '1@foo')
518
+ }, {
519
+ name: 'Reads Edge (Parameter)',
520
+ description: 'Parameters can read from each other as well.',
521
+ code: 'f <- function(x, y=x) {}',
522
+ expectedSubgraph: (0, dataflowgraph_builder_1.emptyGraph)().reads('1:20', '1@x')
523
+ }]]);
524
+ edgeExplanations.set(edge_1.EdgeType.DefinedBy, [{
525
+ shell: shell,
526
+ name: 'DefinedBy Edge', /* concat for link generation */
527
+ type: edge_1.EdgeType.DefinedBy,
528
+ description: `
529
+ The source vertex is usually a [\`define variable vertex\`](#variable-definition-vertex) linking the defined symbol to the entry point of the resulting side.
530
+ ${(0, doc_structure_1.details)('In general, this does not have to be the right hand side of the operator.', await (0, doc_dfg_1.printDfGraphForCode)(shell, '3 -> x', { mark: new Set([0]) }))}
531
+
532
+ However, nested definitions can carry it (in the nested case, \`x\` is defined by the return value of <code>\\\`<-\\\`(y, z)</code>). Additionally, we link the assignment function.
533
+
534
+ `,
535
+ code: 'x <- y',
536
+ expectedSubgraph: (0, dataflowgraph_builder_1.emptyGraph)().definedBy('1@x', '1@y').definedBy('1@x', '1:3')
537
+ }, [{
538
+ name: 'DefinedBy Edge (Nested)',
539
+ description: `Nested definitions can carry the ${linkEdgeName(edge_1.EdgeType.DefinedBy)} edge as well.`,
540
+ code: 'x <- y <- z',
541
+ expectedSubgraph: (0, dataflowgraph_builder_1.emptyGraph)().definedBy('1@x', '1:3').definedBy('1@x', '1:8').definedBy('1@y', '1:8')
542
+ }, {
543
+ name: 'DefinedBy Edge (Expression)',
544
+ description: 'Here, we define by the result of the `+` expression.',
545
+ code: 'x <- y + z',
546
+ expectedSubgraph: (0, dataflowgraph_builder_1.emptyGraph)().definedBy('1@x', '1:8')
547
+ }]]);
548
+ edgeExplanations.set(edge_1.EdgeType.Calls, [{
549
+ shell: shell,
550
+ name: 'Calls Edge',
551
+ type: edge_1.EdgeType.Calls,
552
+ description: 'Link the [function call](#function-call-vertex) to the [function definition](#function-definition-vertex) that is called.',
553
+ code: 'foo <- function() {}\nfoo()',
554
+ expectedSubgraph: (0, dataflowgraph_builder_1.emptyGraph)().calls('2@foo', '1@function')
555
+ }, []]);
556
+ edgeExplanations.set(edge_1.EdgeType.Returns, [{
557
+ shell: shell,
558
+ name: 'Returns Edge',
559
+ type: edge_1.EdgeType.Returns,
560
+ description: 'Link the [function call](#function-call-vertex) to the exit points of the target definition (this may incorporate the call-context).',
561
+ code: 'foo <- function() x\nfoo()',
562
+ expectedSubgraph: (0, dataflowgraph_builder_1.emptyGraph)().returns('2@foo', '1@x')
563
+ }, []]);
564
+ edgeExplanations.set(edge_1.EdgeType.DefinesOnCall, [{
565
+ shell: shell,
566
+ name: 'DefinesOnCall Edge',
567
+ type: edge_1.EdgeType.DefinesOnCall,
568
+ description: `**This edge is automatically joined with ${linkEdgeName(edge_1.EdgeType.DefinedByOnCall)}!**
569
+
570
+ Link an Argument to whichever parameter they cause to be defined if the related function call is invoked.`,
571
+ code: 'f <- function(x) {}\nf(x=1)',
572
+ // here we use the ids as the argument wrappers are not easily selected with slicing criteria
573
+ expectedSubgraph: (0, dataflowgraph_builder_1.emptyGraph)().definesOnCall('$11', '$1')
574
+ }, []]);
575
+ edgeExplanations.set(edge_1.EdgeType.DefinedByOnCall, [{
576
+ shell: shell,
577
+ name: 'DefinedByOnCall Edge',
578
+ type: edge_1.EdgeType.DefinedByOnCall,
579
+ description: `**This edge is automatically joined with ${linkEdgeName(edge_1.EdgeType.DefinesOnCall)}!**
580
+
581
+ This represents the other direction of ${linkEdgeName(edge_1.EdgeType.DefinesOnCall)} (i.e., links the parameter to the argument). This is just for completeness.`,
582
+ code: 'f <- function(x) {}\nf(x=1)',
583
+ expectedSubgraph: (0, dataflowgraph_builder_1.emptyGraph)().definesOnCall('$11', '$1')
584
+ }, []]);
585
+ edgeExplanations.set(edge_1.EdgeType.Argument, [{
586
+ shell: shell,
587
+ name: 'Argument Edge',
588
+ type: edge_1.EdgeType.Argument,
589
+ description: `Links a [function call](#function-call-vertex) to the entry point of its arguments. If we do not know the target of such a call, we automatically assume that all arguments are read by the call as well!
590
+
591
+ The exception to this is the [function definition](#function-definition-vertex) which does no longer hold these argument relationships (as they are no implicit in the structure).
592
+ `,
593
+ code: 'f(x,y)',
594
+ expectedSubgraph: (0, dataflowgraph_builder_1.emptyGraph)().argument('1@f', '1@x').reads('1@f', '1@x').argument('1@f', '1@y').reads('1@f', '1@y')
595
+ }, []]);
596
+ edgeExplanations.set(edge_1.EdgeType.SideEffectOnCall, [{
597
+ shell: shell,
598
+ name: 'SideEffectOnCall Edge',
599
+ type: edge_1.EdgeType.SideEffectOnCall,
600
+ description: 'Links a global side effect to an affected function call (e.g., a super definition within the function body)',
601
+ code: 'f <- function() { x <<- 2 }\nf()',
602
+ expectedSubgraph: (0, dataflowgraph_builder_1.emptyGraph)().sideEffectOnCall('1@x', '2@f')
603
+ }, []]);
604
+ edgeExplanations.set(edge_1.EdgeType.NonStandardEvaluation, [{
605
+ shell: shell,
606
+ name: 'NonStandardEvaluation Edge',
607
+ type: edge_1.EdgeType.NonStandardEvaluation,
608
+ description: `
609
+ Marks cases in which R's non-standard evaluation mechanisms cause the default semantics to deviate (see the case below for multiple vertices)
610
+
611
+ ${(0, doc_structure_1.block)({
612
+ type: 'NOTE',
613
+ content: `
614
+ What to do if you encounter this vertex?
615
+
616
+ This depends on your analysis. To handle many real-world sources correctly you are probably fine with just ignoring it.
617
+ Yet, you may choose to follow these references for other queries. For now, _flowR's_ support for non-standard evaluation is limited.
618
+ `
619
+ })}
620
+ `,
621
+ code: 'quote(x)',
622
+ expectedSubgraph: (0, dataflowgraph_builder_1.emptyGraph)().argument('1@quote', '1@x').nse('1@quote', '1@x')
623
+ }, [{
624
+ name: 'Complete Expressions',
625
+ description: 'This works, even if we have a larger expression in `quote`.',
626
+ code: 'quote(x + y)',
627
+ expectedSubgraph: (0, dataflowgraph_builder_1.emptyGraph)()
628
+ .argument('1@quote', '1@+').nse('1@quote', '1@+')
629
+ .nse('1@quote', '1@x')
630
+ .nse('1@quote', '1@y')
631
+ }]]);
632
+ const results = [];
633
+ let i = 0;
634
+ for (const [, edge] of (0, doc_data_dfg_util_1.getAllEdges)()) {
635
+ const get = edgeExplanations.get(edge);
636
+ (0, assert_1.guard)(get !== undefined, () => `No explanation for edge type ${edge}`);
637
+ const [expl, subExplanations] = get;
638
+ results.push(`<a id='${edgeTypeToId(edge)}'></a>` + await explanation(expl, ++i, ...subExplanations));
639
+ }
640
+ return results.join('\n');
641
+ }
642
+ async function dummyDataflow() {
643
+ const shell = new shell_1.RShell();
644
+ const result = await new pipeline_executor_1.PipelineExecutor(default_pipelines_1.DEFAULT_DATAFLOW_PIPELINE, {
645
+ shell,
646
+ request: (0, retriever_1.requestFromInput)('x <- 1\nx + 1')
647
+ }).allRemainingSteps();
648
+ shell.close();
649
+ return result;
650
+ }
651
+ async function getText(shell) {
652
+ const rversion = (await shell.usedRVersion())?.format() ?? 'unknown';
653
+ /* we collect type information on the graph */
654
+ const vertexType = (0, doc_types_1.getTypesFromFolderAsMermaid)({
655
+ files: [path_1.default.resolve('./src/dataflow/graph/vertex.ts'), path_1.default.resolve('./src/dataflow/graph/graph.ts'), path_1.default.resolve('./src/dataflow/environments/identifier.ts'), path_1.default.resolve('./src/dataflow/info.ts')],
656
+ typeName: 'DataflowGraphVertexInfo',
657
+ inlineTypes: ['MergeableRecord']
658
+ });
659
+ const edgeType = (0, doc_types_1.getTypesFromFolderAsMermaid)({
660
+ files: [path_1.default.resolve('./src/dataflow/graph/edge.ts'), path_1.default.resolve('./src/dataflow/graph/graph.ts'), path_1.default.resolve('./src/dataflow/environments/identifier.ts'), path_1.default.resolve('./src/dataflow/info.ts')],
661
+ typeName: 'EdgeType',
662
+ inlineTypes: ['MergeableRecord']
663
+ });
664
+ return `${(0, doc_auto_gen_1.autoGenHeader)({ filename: module.filename, purpose: 'dataflow graph', rVersion: rversion })}
665
+
666
+ This page briefly summarizes flowR's dataflow graph, represented by ${graph_1.DataflowGraph.name} in ${(0, doc_files_1.getFilePathMd)('../dataflow/graph/graph.ts')}.
667
+ In case you want to manually build such a graph (e.g., for testing), you can use the builder in ${(0, doc_files_1.getFilePathMd)('../dataflow/graph/dataflowgraph-builder.ts')}.
668
+ This wiki page focuses on explaining what such a dataflow graph looks like!
669
+
670
+ Please be aware that the accompanied [dataflow information](#dataflow-information) returned by _flowR_ contains things besides the graph,
671
+ like the entry and exit points of the subgraphs, and currently active references (see [below](#dataflow-information)).
672
+ Additionally, you may be interested in the set of [Unknown Side Effects](#unknown-side-effects) marking calls which _flowR_ is unable to handle correctly.
673
+
674
+ > [!TIP]
675
+ > If you want to investigate the dataflow graph,
676
+ > you can either use the [Visual Studio Code extension](${doc_files_1.FlowrGithubBaseRef}/vscode-flowr) or the ${(0, doc_cli_option_1.getReplCommand)('dataflow*')}
677
+ > command in the REPL (see the [Interface wiki page](${doc_files_1.FlowrWikiBaseRef}/Interface) for more information).
678
+
679
+ ${await (0, doc_dfg_1.printDfGraphForCode)(shell, 'x <- 3\ny <- x + 1\ny')}
680
+
681
+
682
+ The above dataflow graph showcases the general gist. We define a dataflow graph as a directed graph G = (V, E), differentiating between ${(0, doc_data_dfg_util_1.getAllVertices)().length} types of vertices V and
683
+ ${(0, doc_data_dfg_util_1.getAllEdges)().length} types of edges E allowing each vertex to have a single, and each edge to have multiple distinct types.
684
+ Additionally, every node may have links to its [control dependencies](#control-dependencies) (which you may view as a ${(0, text_1.nth)((0, doc_data_dfg_util_1.getAllEdges)().length + 1)} edge type, although they are explicitly no data dependency).
685
+
686
+ <details open>
687
+
688
+ <summary>Vertex Types</summary>
689
+
690
+ The following vertices types exist:
691
+
692
+ 1. ${(0, doc_data_dfg_util_1.getAllVertices)().map(([k, v], index) => `[\`${k}\`](#${index + 1}-${v.toLowerCase().replace(/\s/g, '-')}-vertex)`).join('\n1. ')}
693
+
694
+ ${vertexType.text.trim().length > 0 ? (0, doc_structure_1.details)('Class Diagram', 'All boxes should link to their respective implementation:\n' + (0, doc_code_1.codeBlock)('mermaid', vertexType.text)) : ''}
695
+
696
+ </details>
697
+
698
+ <details open>
699
+
700
+ <summary>Edge Types</summary>
701
+
702
+ The following edges types exist, internally we use bitmasks to represent multiple types in a compact form:
703
+
704
+ 1. ${(0, doc_data_dfg_util_1.getAllEdges)().map(([k, v], index) => `[\`${k}\` (${v})](#${index + 1}-${k.toLowerCase().replace(/\s/g, '-')}-edge)`).join('\n1. ')}
705
+
706
+ ${edgeType.text.trim().length > 0 ? (0, doc_structure_1.details)('Class Diagram', 'All boxes should link to their respective implementation:\n' + (0, doc_code_1.codeBlock)('mermaid', edgeType.text)) : ''}
707
+
708
+ </details>
709
+
710
+
711
+ From an implementation perspective all of these types are represented by respective interfaces, see ${(0, doc_files_1.getFilePathMd)('../dataflow/graph/vertex.ts')} and ${(0, doc_files_1.getFilePathMd)('../dataflow/graph/edge.ts')}.
712
+
713
+ The following sections present details on the different types of vertices and edges, including examples and explanations.
714
+
715
+ > [!NOTE]
716
+ > Every dataflow vertex holds an \`id\` which links it to the respective node in the [normalized AST](${doc_files_1.FlowrWikiBaseRef}/Normalized%20AST).
717
+ > So if you want more information about the respective vertex, you can usually access more information
718
+ > using the \`${graph_1.DataflowGraph.name}::idMap\` linked to the dataflow graph:
719
+ ${(0, doc_general_1.prefixLines)((0, doc_code_1.codeBlock)('ts', 'const node = graph.idMap.get(id);'), '> ')}
720
+ > In case you just need the name (\`lexeme\`) of the respective vertex, ${node_id_1.recoverName.name} (defined in ${(0, doc_files_1.getFilePathMd)('../r-bridge/lang-4.x/ast/model/processing/node-id.ts')}) can help you out:
721
+ ${(0, doc_general_1.prefixLines)((0, doc_code_1.codeBlock)('ts', `const name = ${node_id_1.recoverName.name}(id, graph.idMap);`), '> ')}
722
+
723
+ ## Vertices
724
+
725
+ ${await getVertexExplanations(shell, vertexType)}
726
+
727
+ ## Edges
728
+
729
+ ${await getEdgesExplanations(shell)}
730
+
731
+ ## Control Dependencies
732
+
733
+ Each vertex may have a list of active control dependencies.
734
+ They hold the \`id\` of all nodes that effect if the current vertex is part of the execution or not,
735
+ and a boolean flag \`when\` to indicate if the control dependency is active when the condition is \`true\` or \`false\`.
736
+
737
+ As an example, consider the following dataflow graph:
738
+
739
+ ${await (0, doc_dfg_1.printDfGraphForCode)(shell, 'if(p) a else b')}
740
+
741
+ Whenever we visualize a graph, we represent the control dependencies as grayed out edges with a \`CD\` prefix, followed
742
+ by the \`when\` flag.
743
+ In the above example, both \`a\` and \`b\` depend on the \`if\`. Please note that they are _not_ linked to the result of
744
+ the condition itself as this is the more general linkage point (and harmonizes with other control structures, especially those which are user-defined).
745
+
746
+ ${(0, doc_structure_1.details)('Example: Multiple Vertices (Assignment)', await (0, doc_dfg_1.printDfGraphForCode)(shell, 'if(p) a <- 1'))}
747
+ ${(0, doc_structure_1.details)('Example: Multiple Vertices (Arithmetic Expression)', await (0, doc_dfg_1.printDfGraphForCode)(shell, 'if(p) 3 + 2'))}
748
+ ${(0, doc_structure_1.details)('Example: Nested Conditionals', await (0, doc_dfg_1.printDfGraphForCode)(shell, 'if(x) { if(y) a else b } else c'))}
749
+
750
+ ## Dataflow Information
751
+
752
+ Using _flowR's_ code interface (see the [Interface](${doc_files_1.FlowrWikiBaseRef}/Interface) wiki page for more), you can generate the dataflow information
753
+ for a given piece of R code (in this case \`x <- 1; x + 1\`) as follows:
754
+
755
+ ${(0, doc_code_1.codeBlock)('ts', `
756
+ const shell = new ${shell_1.RShell.name}()
757
+ const result = await new ${pipeline_executor_1.PipelineExecutor.name}(DEFAULT_DATAFLOW_PIPELINE, {
758
+ shell,
759
+ request: ${retriever_1.requestFromInput.name}('x <- 1; x + 1')
760
+ }).allRemainingSteps();
761
+ shell.close();
762
+ `)}
763
+
764
+ <details>
765
+
766
+ <summary style="color:gray">Transpiled Code</summary>
767
+
768
+ The actual code we are using in case the example above gets oudated:
769
+
770
+ ${(0, doc_code_1.codeBlock)('ts', dummyDataflow.toString())}
771
+
772
+ </details>
773
+
774
+
775
+ Now, you can find the dataflow _information_ with \`result.dataflow\`. More specifically, the graph is stored in \`result.dataflow.graph\` and looks like this:
776
+
777
+ ${await (async () => {
778
+ const result = await dummyDataflow();
779
+ const dfGraphString = (0, doc_dfg_1.printDfGraph)(result.dataflow.graph);
780
+ return `
781
+ ${dfGraphString}
782
+
783
+ However, the dataflow information contains more, quite a lot of information in fact.
784
+
785
+ <details>
786
+
787
+ <summary style="color:gray">Dataflow Information as Json</summary>
788
+
789
+ _As the information is pretty long, we inhibit pretty printing and syntax highlighting:_
790
+ ${(0, doc_code_1.codeBlock)('text', JSON.stringify(result.dataflow, json_1.jsonReplacer))}
791
+
792
+ </details>
793
+
794
+ You may be interested in its implementation:
795
+
796
+ ${(0, doc_types_1.printHierarchy)({ program: vertexType.program, hierarchy: vertexType.info, root: 'DataflowInformation' })}
797
+
798
+ Let's start by looking at the properties of the dataflow information object: ${Object.keys(result.dataflow).map(k => `\`${k}\``).join(', ')}.
799
+
800
+ ${(() => {
801
+ (0, assert_1.guard)(Object.keys(result.dataflow).length === 7, () => 'Update Dataflow Documentation!');
802
+ return '';
803
+ })()}
804
+
805
+ There are three sets of references.
806
+ **in** (ids: ${JSON.stringify(new Set(result.dataflow.in.map(n => n.nodeId)), json_1.jsonReplacer)}) and **out** (ids: ${JSON.stringify(new Set(result.dataflow.out.map(n => n.nodeId)), json_1.jsonReplacer)}) contain the
807
+ ingoing and outgoing references of the subgraph at hand (in this case, the whole code, as we are at the end of the dataflow analysis).
808
+ Besides the Ids, they also contain important meta-information (e.g., what is to be read).
809
+ The third set, **unknownReferences**, contains all references that are not yet identified as read or written
810
+ (the example does not have any, but, for example, \`x\` (with id 0) would first be unknown and then later classified as a definition).
811
+
812
+ The **environment** property contains the active environment information of the subgraph.
813
+ In other words, this is a linked list of tables (scopes), mapping identifiers to their respective definitions.
814
+ A summarized version of the produced environment looks like this:
815
+
816
+ ${(0, doc_env_1.printEnvironmentToMarkdown)(result.dataflow.environment.current)}
817
+
818
+ This shows us that the local environment contains a single definition for \`x\` (with id 0) and that the parent environment is the built-in environment.
819
+ Additionally, we get the information that the node with the id 2 was responsible for the definition of \`x\`.
820
+
821
+ Last but not least, the information contains the single **entry point** (${JSON.stringify(result.dataflow.entryPoint)}) and a set of **exit points** (${JSON.stringify(result.dataflow.exitPoints.map(e => e.nodeId))}).
822
+ Besides marking potential exits, the exit points also provide information about why the exit occurs and which control dependencies affect the exit.
823
+
824
+ ### Unknown Side Effects
825
+
826
+ In case _flowR_ encounters a function call that it cannot handle, it marks the call as an unknown side effect.
827
+ You can find these as part of the dataflow graph, specifically as \`unknownSideEffects\` (with a leading underscore if sesrialized as JSON).
828
+ In the following graph, _flowR_ realizes that it is unable to correctly handle the impacts of the \`load\` call and therefore marks it as such (marked in bright red):
829
+
830
+ ${await (0, doc_dfg_1.printDfGraphForCode)(shell, 'load("file")\nprint(x + y)')}
831
+
832
+ In general, as we cannot handle these correctly, we leave it up to other analyses (and [queries](${doc_files_1.FlowrWikiBaseRef}/Query%20API)) to handle these cases
833
+ as they see fit.
834
+ `;
835
+ })()}
836
+
837
+ `;
838
+ }
839
+ /** if we run this script, we want a Markdown representation of the capabilities */
840
+ if (require.main === module) {
841
+ (0, log_1.setMinLevelOfAllLogs)(6 /* LogLevel.Fatal */);
842
+ const shell = new shell_1.RShell();
843
+ void getText(shell).then(str => {
844
+ console.log(str);
845
+ }).finally(() => {
846
+ shell.close();
847
+ });
848
+ }
849
+ //# sourceMappingURL=print-dataflow-graph-wiki.js.map