@eagleoutice/flowr 2.9.12 → 2.9.14

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (233) hide show
  1. package/README.md +35 -23
  2. package/abstract-interpretation/absint-visitor.d.ts +1 -1
  3. package/abstract-interpretation/absint-visitor.js +20 -20
  4. package/abstract-interpretation/data-frame/mappers/replacement-mapper.js +2 -2
  5. package/benchmark/slicer.d.ts +5 -3
  6. package/benchmark/slicer.js +26 -10
  7. package/benchmark/stats/print.js +12 -0
  8. package/benchmark/stats/stats.d.ts +3 -2
  9. package/benchmark/stats/stats.js +1 -1
  10. package/benchmark/summarizer/data.d.ts +1 -0
  11. package/benchmark/summarizer/second-phase/process.js +5 -0
  12. package/cli/benchmark-app.d.ts +1 -0
  13. package/cli/benchmark-app.js +1 -0
  14. package/cli/benchmark-helper-app.d.ts +2 -1
  15. package/cli/benchmark-helper-app.js +6 -3
  16. package/cli/common/options.d.ts +8 -0
  17. package/cli/common/options.js +3 -1
  18. package/cli/common/scripts-info.d.ts +8 -0
  19. package/cli/export-quads-app.js +1 -1
  20. package/cli/flowr.js +3 -3
  21. package/cli/repl/commands/repl-dataflow.js +5 -5
  22. package/cli/repl/core.d.ts +3 -3
  23. package/cli/repl/parser/slice-query-parser.d.ts +1 -1
  24. package/cli/repl/parser/slice-query-parser.js +2 -2
  25. package/cli/repl/server/connection.d.ts +2 -2
  26. package/cli/repl/server/connection.js +2 -2
  27. package/cli/repl/server/messages/message-slice.d.ts +1 -1
  28. package/cli/repl/server/messages/message-slice.js +2 -2
  29. package/cli/repl/server/server.d.ts +2 -2
  30. package/cli/script-core/statistics-core.d.ts +2 -2
  31. package/cli/script-core/statistics-helper-core.d.ts +2 -2
  32. package/cli/script-core/statistics-helper-core.js +1 -1
  33. package/cli/slicer-app.js +2 -2
  34. package/cli/statistics-app.js +1 -1
  35. package/cli/statistics-helper-app.js +1 -1
  36. package/cli/wiki.js +2 -2
  37. package/config.d.ts +65 -24
  38. package/config.js +197 -161
  39. package/control-flow/extract-cfg.js +7 -10
  40. package/control-flow/semantic-cfg-guided-visitor.d.ts +1 -1
  41. package/control-flow/semantic-cfg-guided-visitor.js +43 -43
  42. package/control-flow/useless-loop.d.ts +1 -1
  43. package/control-flow/useless-loop.js +3 -3
  44. package/core/print/dataflow-printer.d.ts +0 -14
  45. package/core/print/dataflow-printer.js +0 -21
  46. package/core/steps/all/core/20-dataflow.d.ts +3 -3
  47. package/core/steps/all/core/20-dataflow.js +3 -2
  48. package/core/steps/all/static-slicing/00-slice.d.ts +2 -5
  49. package/core/steps/all/static-slicing/00-slice.js +6 -8
  50. package/core/steps/pipeline/default-pipelines.d.ts +89 -89
  51. package/core/steps/pipeline-step.d.ts +2 -2
  52. package/dataflow/environments/built-in-proc-name.d.ts +83 -0
  53. package/dataflow/environments/built-in-proc-name.js +88 -0
  54. package/dataflow/environments/built-in.d.ts +1 -83
  55. package/dataflow/environments/built-in.js +37 -120
  56. package/dataflow/environments/default-builtin-config.d.ts +1 -1
  57. package/dataflow/environments/default-builtin-config.js +75 -75
  58. package/dataflow/environments/identifier.d.ts +1 -0
  59. package/dataflow/environments/identifier.js +1 -0
  60. package/dataflow/eval/resolve/alias-tracking.js +12 -15
  61. package/dataflow/eval/resolve/resolve.js +2 -2
  62. package/dataflow/fn/exceptions-of-function.d.ts +1 -1
  63. package/dataflow/fn/exceptions-of-function.js +2 -2
  64. package/dataflow/graph/call-graph.d.ts +49 -19
  65. package/dataflow/graph/call-graph.js +117 -114
  66. package/dataflow/graph/dataflowgraph-builder.d.ts +1 -1
  67. package/dataflow/graph/dataflowgraph-builder.js +2 -2
  68. package/dataflow/graph/df-helper.d.ts +132 -0
  69. package/dataflow/graph/df-helper.js +131 -0
  70. package/dataflow/graph/diff-dataflow-graph.d.ts +5 -10
  71. package/dataflow/graph/diff-dataflow-graph.js +3 -28
  72. package/dataflow/graph/edge.d.ts +1 -0
  73. package/dataflow/graph/edge.js +1 -0
  74. package/dataflow/graph/graph-helper.d.ts +55 -0
  75. package/dataflow/graph/graph-helper.js +105 -0
  76. package/dataflow/graph/graph.d.ts +6 -1
  77. package/dataflow/graph/graph.js +14 -9
  78. package/dataflow/graph/vertex.d.ts +1 -1
  79. package/dataflow/info.d.ts +14 -4
  80. package/dataflow/info.js +28 -16
  81. package/dataflow/internal/linker.d.ts +14 -10
  82. package/dataflow/internal/linker.js +29 -32
  83. package/dataflow/internal/process/functions/call/built-in/built-in-access.js +5 -5
  84. package/dataflow/internal/process/functions/call/built-in/built-in-apply.js +4 -4
  85. package/dataflow/internal/process/functions/call/built-in/built-in-assignment.js +7 -6
  86. package/dataflow/internal/process/functions/call/built-in/built-in-eval.d.ts +1 -1
  87. package/dataflow/internal/process/functions/call/built-in/built-in-eval.js +5 -5
  88. package/dataflow/internal/process/functions/call/built-in/built-in-expression-list.js +2 -2
  89. package/dataflow/internal/process/functions/call/built-in/built-in-for-loop.js +2 -2
  90. package/dataflow/internal/process/functions/call/built-in/built-in-function-definition.js +4 -4
  91. package/dataflow/internal/process/functions/call/built-in/built-in-get.js +2 -2
  92. package/dataflow/internal/process/functions/call/built-in/built-in-if-then-else.js +3 -3
  93. package/dataflow/internal/process/functions/call/built-in/built-in-library.js +2 -2
  94. package/dataflow/internal/process/functions/call/built-in/built-in-list.js +2 -2
  95. package/dataflow/internal/process/functions/call/built-in/built-in-local.d.ts +1 -1
  96. package/dataflow/internal/process/functions/call/built-in/built-in-local.js +5 -5
  97. package/dataflow/internal/process/functions/call/built-in/built-in-pipe.js +2 -2
  98. package/dataflow/internal/process/functions/call/built-in/built-in-quote.js +2 -2
  99. package/dataflow/internal/process/functions/call/built-in/built-in-recall.js +2 -2
  100. package/dataflow/internal/process/functions/call/built-in/built-in-register-hook.js +5 -5
  101. package/dataflow/internal/process/functions/call/built-in/built-in-repeat-loop.js +2 -2
  102. package/dataflow/internal/process/functions/call/built-in/built-in-replacement.d.ts +1 -1
  103. package/dataflow/internal/process/functions/call/built-in/built-in-replacement.js +5 -4
  104. package/dataflow/internal/process/functions/call/built-in/built-in-rm.js +2 -2
  105. package/dataflow/internal/process/functions/call/built-in/built-in-s-seven-dispatch.js +3 -3
  106. package/dataflow/internal/process/functions/call/built-in/built-in-s-seven-new-generic.js +3 -3
  107. package/dataflow/internal/process/functions/call/built-in/built-in-s-three-dispatch.d.ts +1 -1
  108. package/dataflow/internal/process/functions/call/built-in/built-in-s-three-dispatch.js +7 -7
  109. package/dataflow/internal/process/functions/call/built-in/built-in-source.d.ts +2 -2
  110. package/dataflow/internal/process/functions/call/built-in/built-in-source.js +23 -12
  111. package/dataflow/internal/process/functions/call/built-in/built-in-special-bin-op.js +3 -3
  112. package/dataflow/internal/process/functions/call/built-in/built-in-stop-if-not.js +2 -2
  113. package/dataflow/internal/process/functions/call/built-in/built-in-try-catch.js +6 -9
  114. package/dataflow/internal/process/functions/call/built-in/built-in-vector.js +2 -2
  115. package/dataflow/internal/process/functions/call/built-in/built-in-while-loop.js +2 -2
  116. package/dataflow/internal/process/functions/call/known-call-handling.js +2 -2
  117. package/dataflow/internal/process/functions/call/named-call-handling.d.ts +1 -1
  118. package/dataflow/internal/process/functions/call/named-call-handling.js +1 -1
  119. package/dataflow/internal/process/functions/call/unnamed-call-handling.js +2 -2
  120. package/dataflow/internal/process/process-uninteresting-leaf.d.ts +1 -1
  121. package/dataflow/internal/process/process-uninteresting-leaf.js +1 -1
  122. package/dataflow/origin/dfg-get-origin.d.ts +1 -1
  123. package/dataflow/origin/dfg-get-symbol-refs.js +6 -6
  124. package/documentation/doc-readme.js +2 -2
  125. package/documentation/doc-util/doc-dfg.d.ts +3 -0
  126. package/documentation/doc-util/doc-dfg.js +5 -7
  127. package/documentation/doc-util/doc-normalized-ast.d.ts +0 -6
  128. package/documentation/doc-util/doc-normalized-ast.js +0 -23
  129. package/documentation/doc-util/doc-structure.js +3 -3
  130. package/documentation/doc-util/doc-types.js +3 -3
  131. package/documentation/wiki-analyzer.js +7 -5
  132. package/documentation/wiki-core.js +6 -7
  133. package/documentation/wiki-dataflow-graph.js +15 -13
  134. package/documentation/wiki-interface.js +8 -6
  135. package/documentation/wiki-linter.js +6 -5
  136. package/documentation/wiki-mk/doc-context.js +3 -4
  137. package/documentation/wiki-normalized-ast.js +5 -4
  138. package/documentation/wiki-query.js +28 -3
  139. package/engines.d.ts +2 -2
  140. package/engines.js +4 -4
  141. package/linter/linter-rules.d.ts +24 -1
  142. package/linter/linter-rules.js +3 -1
  143. package/linter/rules/dataframe-access-validation.js +5 -5
  144. package/linter/rules/naming-convention.d.ts +1 -1
  145. package/linter/rules/naming-convention.js +7 -3
  146. package/linter/rules/seeded-randomness.js +2 -2
  147. package/linter/rules/stop-with-call-arg.d.ts +35 -0
  148. package/linter/rules/stop-with-call-arg.js +72 -0
  149. package/linter/rules/useless-loop.d.ts +1 -1
  150. package/package.json +3 -1
  151. package/project/cache/flowr-analyzer-cache.d.ts +1 -1
  152. package/project/cache/flowr-analyzer-cache.js +1 -1
  153. package/project/context/flowr-analyzer-context.d.ts +6 -6
  154. package/project/context/flowr-analyzer-context.js +2 -2
  155. package/project/context/flowr-analyzer-files-context.d.ts +2 -2
  156. package/project/context/flowr-analyzer-files-context.js +28 -8
  157. package/project/flowr-analyzer-builder.d.ts +13 -6
  158. package/project/flowr-analyzer-builder.js +12 -3
  159. package/project/flowr-analyzer.d.ts +4 -4
  160. package/queries/catalog/call-context-query/identify-link-to-nested-call-relation.js +2 -2
  161. package/queries/catalog/call-graph-query/call-graph-query-format.d.ts +1 -1
  162. package/queries/catalog/call-graph-query/call-graph-query-format.js +2 -2
  163. package/queries/catalog/cluster-query/cluster-query-format.js +2 -2
  164. package/queries/catalog/config-query/config-query-format.d.ts +5 -5
  165. package/queries/catalog/dataflow-lens-query/dataflow-lens-query-format.js +2 -2
  166. package/queries/catalog/dataflow-query/dataflow-query-format.js +2 -2
  167. package/queries/catalog/df-shape-query/df-shape-query-executor.js +1 -2
  168. package/queries/catalog/df-shape-query/df-shape-query-format.d.ts +2 -2
  169. package/queries/catalog/does-call-query/does-call-query-executor.js +2 -2
  170. package/queries/catalog/does-call-query/does-call-query-format.d.ts +2 -2
  171. package/queries/catalog/files-query/files-query-format.d.ts +3 -3
  172. package/queries/catalog/happens-before-query/happens-before-query-executor.js +2 -2
  173. package/queries/catalog/inspect-exceptions-query/inspect-exception-query-executor.d.ts +1 -1
  174. package/queries/catalog/inspect-exceptions-query/inspect-exception-query-executor.js +1 -1
  175. package/queries/catalog/inspect-exceptions-query/inspect-exception-query-format.d.ts +2 -2
  176. package/queries/catalog/inspect-higher-order-query/inspect-higher-order-query-executor.js +3 -3
  177. package/queries/catalog/inspect-higher-order-query/inspect-higher-order-query-format.d.ts +2 -2
  178. package/queries/catalog/inspect-recursion-query/inspect-recursion-query-format.d.ts +2 -2
  179. package/queries/catalog/linter-query/linter-query-format.d.ts +3 -3
  180. package/queries/catalog/location-map-query/location-map-query-executor.js +2 -2
  181. package/queries/catalog/location-map-query/location-map-query-format.d.ts +2 -2
  182. package/queries/catalog/origin-query/origin-query-executor.d.ts +1 -1
  183. package/queries/catalog/origin-query/origin-query-executor.js +3 -3
  184. package/queries/catalog/origin-query/origin-query-format.d.ts +2 -2
  185. package/queries/catalog/provenance-query/provenance-query-executor.d.ts +9 -0
  186. package/queries/catalog/provenance-query/provenance-query-executor.js +37 -0
  187. package/queries/catalog/provenance-query/provenance-query-format.d.ts +35 -0
  188. package/queries/catalog/provenance-query/provenance-query-format.js +62 -0
  189. package/queries/catalog/resolve-value-query/resolve-value-query-executor.js +4 -4
  190. package/queries/catalog/resolve-value-query/resolve-value-query-format.d.ts +2 -2
  191. package/queries/catalog/resolve-value-query/resolve-value-query-format.js +4 -0
  192. package/queries/catalog/search-query/search-query-format.js +1 -1
  193. package/queries/catalog/static-slice-query/static-slice-query-executor.js +4 -2
  194. package/queries/catalog/static-slice-query/static-slice-query-format.d.ts +4 -4
  195. package/queries/catalog/static-slice-query/static-slice-query-format.js +3 -3
  196. package/queries/query.d.ts +27 -19
  197. package/queries/query.js +2 -0
  198. package/r-bridge/lang-4.x/ast/model/model.d.ts +13 -2
  199. package/r-bridge/lang-4.x/ast/model/model.js +20 -1
  200. package/r-bridge/lang-4.x/ast/model/nodes/r-function-definition.d.ts +8 -1
  201. package/r-bridge/lang-4.x/ast/model/nodes/r-function-definition.js +13 -0
  202. package/r-bridge/lang-4.x/ast/parser/json/parser.d.ts +2 -2
  203. package/r-bridge/lang-4.x/ast/parser/json/parser.js +2 -2
  204. package/r-bridge/lang-4.x/tree-sitter/tree-sitter-normalize.js +6 -2
  205. package/search/flowr-search-filters.d.ts +1 -1
  206. package/search/flowr-search-printer.js +3 -3
  207. package/search/search-executor/search-enrichers.js +2 -2
  208. package/search/search-executor/search-generators.js +1 -1
  209. package/slicing/criterion/parse.d.ts +40 -16
  210. package/slicing/criterion/parse.js +67 -63
  211. package/slicing/static/slicer-types.d.ts +2 -3
  212. package/slicing/static/static-slicer.d.ts +3 -4
  213. package/slicing/static/static-slicer.js +9 -12
  214. package/statistics/statistics.d.ts +2 -2
  215. package/util/diff.d.ts +2 -2
  216. package/util/mermaid/ast.js +4 -4
  217. package/util/mermaid/cfg.js +5 -5
  218. package/util/mermaid/dfg.d.ts +33 -18
  219. package/util/mermaid/dfg.js +46 -31
  220. package/util/mermaid/mermaid.d.ts +57 -12
  221. package/util/mermaid/mermaid.js +74 -67
  222. package/util/objects.d.ts +12 -0
  223. package/util/objects.js +28 -0
  224. package/util/range.d.ts +8 -0
  225. package/util/range.js +13 -1
  226. package/util/slice-direction.d.ts +7 -0
  227. package/util/slice-direction.js +12 -0
  228. package/util/summarizer.js +1 -1
  229. package/util/version.js +1 -1
  230. package/dataflow/graph/invert-dfg.d.ts +0 -6
  231. package/dataflow/graph/invert-dfg.js +0 -20
  232. package/dataflow/graph/resolve-graph.d.ts +0 -8
  233. package/dataflow/graph/resolve-graph.js +0 -59
package/config.js CHANGED
@@ -3,18 +3,14 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
3
3
  return (mod && mod.__esModule) ? mod : { "default": mod };
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.flowrConfigFileSchema = exports.defaultConfigOptions = exports.DropPathsOption = exports.InferWorkingDirectory = exports.VariableResolve = void 0;
7
- exports.parseConfig = parseConfig;
8
- exports.amendConfig = amendConfig;
9
- exports.cloneConfig = cloneConfig;
10
- exports.getConfig = getConfig;
11
- exports.getEngineConfig = getEngineConfig;
6
+ exports.FlowrConfig = exports.DropPathsOption = exports.InferWorkingDirectory = exports.VariableResolve = void 0;
12
7
  const objects_1 = require("./util/objects");
13
8
  const path_1 = __importDefault(require("path"));
14
9
  const fs_1 = __importDefault(require("fs"));
15
10
  const log_1 = require("./util/log");
16
11
  const files_1 = require("./util/files");
17
12
  const joi_1 = __importDefault(require("joi"));
13
+ const object_path_1 = __importDefault(require("object-path"));
18
14
  var VariableResolve;
19
15
  (function (VariableResolve) {
20
16
  /** Don't resolve constants at all */
@@ -54,173 +50,213 @@ const defaultEngineConfigs = {
54
50
  'tree-sitter': { type: 'tree-sitter' },
55
51
  'r-shell': { type: 'r-shell' }
56
52
  };
57
- exports.defaultConfigOptions = {
58
- ignoreSourceCalls: false,
59
- semantics: {
60
- environment: {
61
- overwriteBuiltIns: {
62
- loadDefaults: true,
63
- definitions: []
53
+ /**
54
+ * Helper Object to work with {@link FlowrConfig}, provides the default config and the Joi schema for validation.
55
+ */
56
+ exports.FlowrConfig = {
57
+ name: 'FlowrConfig',
58
+ /**
59
+ * The default configuration for flowR, used when no config file is found or when a config file is missing some options.
60
+ * You can use this as a base for your own config and only specify the options you want to change.
61
+ */
62
+ default() {
63
+ return {
64
+ ignoreSourceCalls: false,
65
+ semantics: {
66
+ environment: {
67
+ overwriteBuiltIns: {
68
+ loadDefaults: true,
69
+ definitions: []
70
+ }
71
+ }
72
+ },
73
+ repl: {
74
+ quickStats: false,
75
+ dfProcessorHeat: false
76
+ },
77
+ project: {
78
+ resolveUnknownPathsOnDisk: true
79
+ },
80
+ engines: [],
81
+ defaultEngine: 'tree-sitter',
82
+ solver: {
83
+ variables: VariableResolve.Alias,
84
+ evalStrings: true,
85
+ resolveSource: {
86
+ dropPaths: DropPathsOption.No,
87
+ ignoreCapitalization: true,
88
+ inferWorkingDirectory: InferWorkingDirectory.ActiveScript,
89
+ searchPath: [],
90
+ repeatedSourceLimit: 2
91
+ },
92
+ instrument: {
93
+ dataflowExtractors: undefined
94
+ },
95
+ slicer: {
96
+ threshold: 50
97
+ }
98
+ },
99
+ abstractInterpretation: {
100
+ wideningThreshold: 4,
101
+ dataFrame: {
102
+ maxColNames: 50,
103
+ readLoadedData: {
104
+ readExternalFiles: true,
105
+ maxReadLines: 1e6
106
+ }
107
+ }
64
108
  }
109
+ };
110
+ },
111
+ /**
112
+ * The Joi schema for validating a config file, use this to validate your config file before using it. You can also use this to generate documentation for the config file format.
113
+ */
114
+ Schema: joi_1.default.object({
115
+ ignoreSourceCalls: joi_1.default.boolean().optional().description('Whether source calls should be ignored, causing {@link processSourceCall}\'s behavior to be skipped.'),
116
+ semantics: joi_1.default.object({
117
+ environment: joi_1.default.object({
118
+ overwriteBuiltIns: joi_1.default.object({
119
+ loadDefaults: joi_1.default.boolean().optional().description('Should the default configuration still be loaded?'),
120
+ definitions: joi_1.default.array().items(joi_1.default.object()).optional().description('The definitions to load/overwrite.')
121
+ }).optional().description('Do you want to overwrite (parts) of the builtin definition?')
122
+ }).optional().description('Semantics regarding how to handle the R environment.')
123
+ }).description('Configure language semantics and how flowR handles them.'),
124
+ repl: joi_1.default.object({
125
+ quickStats: joi_1.default.boolean().optional().description('Whether to show quick stats in the REPL after each evaluation.'),
126
+ dfProcessorHeat: joi_1.default.boolean().optional().description('This instruments the dataflow processors to count how often each processor is called.')
127
+ }).description('Configuration options for the REPL.'),
128
+ project: joi_1.default.object({
129
+ resolveUnknownPathsOnDisk: joi_1.default.boolean().optional().description('Whether to resolve unknown paths loaded by the r project disk when trying to source/analyze files.')
130
+ }).description('Project specific configuration options.'),
131
+ engines: joi_1.default.array().items(joi_1.default.alternatives(joi_1.default.object({
132
+ type: joi_1.default.string().required().valid('tree-sitter').description('Use the tree sitter engine.'),
133
+ wasmPath: joi_1.default.string().optional().description('The path to the tree-sitter-r WASM binary to use. If this is undefined, this uses the default path.'),
134
+ treeSitterWasmPath: joi_1.default.string().optional().description('The path to the tree-sitter WASM binary to use. If this is undefined, this uses the default path.'),
135
+ lax: joi_1.default.boolean().optional().description('Whether to use the lax parser for parsing R code (allowing for syntax errors). If this is undefined, the strict parser will be used.')
136
+ }).description('The configuration for the tree sitter engine.'), joi_1.default.object({
137
+ type: joi_1.default.string().required().valid('r-shell').description('Use the R shell engine.'),
138
+ rPath: joi_1.default.string().optional().description('The path to the R executable to use. If this is undefined, this uses the default path.')
139
+ }).description('The configuration for the R shell engine.'))).description('The engine or set of engines to use for interacting with R code. An empty array means all available engines will be used.'),
140
+ 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.'),
141
+ solver: joi_1.default.object({
142
+ variables: joi_1.default.string().valid(...Object.values(VariableResolve)).description('How to resolve variables and their values.'),
143
+ evalStrings: joi_1.default.boolean().description('Should we include eval(parse(text="...")) calls in the dataflow graph?'),
144
+ instrument: joi_1.default.object({
145
+ dataflowExtractors: joi_1.default.any().optional().description('These keys are only intended for use within code, allowing to instrument the dataflow analyzer!')
146
+ }),
147
+ resolveSource: joi_1.default.object({
148
+ 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.'),
149
+ ignoreCapitalization: joi_1.default.boolean().description('Search for filenames matching in the lowercase.'),
150
+ inferWorkingDirectory: joi_1.default.string().valid(...Object.values(InferWorkingDirectory)).description('Try to infer the working directory from the main or any script to analyze.'),
151
+ searchPath: joi_1.default.array().items(joi_1.default.string()).description('Additionally search in these paths.'),
152
+ 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.'),
153
+ applyReplacements: joi_1.default.array().items(joi_1.default.object()).description('Provide name replacements for loaded files')
154
+ }).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.'),
155
+ slicer: joi_1.default.object({
156
+ threshold: joi_1.default.number().optional().description('The maximum number of iterations to perform on a single function call during slicing.')
157
+ }).optional().description('The configuration for the slicer.')
158
+ }).description('How to resolve constants, constraints, cells, ...'),
159
+ abstractInterpretation: joi_1.default.object({
160
+ wideningThreshold: joi_1.default.number().min(1).description('The threshold for the number of visitations of a node at which widening should be performed to ensure the termination of the fixpoint iteration.'),
161
+ dataFrame: joi_1.default.object({
162
+ maxColNames: joi_1.default.number().min(0).description('The maximum number of columns names to infer for data frames before over-approximating the column names to top.'),
163
+ readLoadedData: joi_1.default.object({
164
+ readExternalFiles: joi_1.default.boolean().description('Whether data frame shapes should be extracted from loaded external files, such as CSV files.'),
165
+ maxReadLines: joi_1.default.number().min(1).description('The maximum number of lines to read when extracting data frame shapes from loaded files, such as CSV files.')
166
+ }).description('Configuration options for reading data frame shapes from loaded external data files, such as CSV files.')
167
+ }).description('The configuration of the shape inference for data frames.')
168
+ }).description('The configuration options for abstract interpretation.')
169
+ }).description('The configuration file format for flowR.'),
170
+ /**
171
+ * Parses the given JSON string as a flowR config file, returning the resulting config object if the parsing and validation were successful, or `undefined` if there was an error.
172
+ */
173
+ parse(jsonString) {
174
+ try {
175
+ const parsed = JSON.parse(jsonString);
176
+ const validate = exports.FlowrConfig.Schema.validate(parsed);
177
+ if (!validate.error) {
178
+ // assign default values to all config options except for the specified ones
179
+ return (0, objects_1.deepMergeObject)(exports.FlowrConfig.default(), parsed);
180
+ }
181
+ else {
182
+ log_1.log.error(`Failed to validate config ${jsonString}: ${validate.error.message}`);
183
+ return undefined;
184
+ }
185
+ }
186
+ catch (e) {
187
+ log_1.log.error(`Failed to parse config ${jsonString}: ${e.message}`);
65
188
  }
66
189
  },
67
- repl: {
68
- quickStats: false,
69
- dfProcessorHeat: false
190
+ /**
191
+ * Creates a new flowr config that has the updated values.
192
+ */
193
+ // eslint-disable-next-line @typescript-eslint/no-invalid-void-type
194
+ amend(config, amendmentFunc) {
195
+ const newConfig = exports.FlowrConfig.clone(config);
196
+ return amendmentFunc(newConfig) ?? newConfig;
70
197
  },
71
- project: {
72
- resolveUnknownPathsOnDisk: true
198
+ /**
199
+ * Clones the given flowr config object.
200
+ */
201
+ clone(config) {
202
+ return (0, objects_1.deepClonePreserveUnclonable)(config);
73
203
  },
74
- engines: [],
75
- defaultEngine: 'tree-sitter',
76
- solver: {
77
- variables: VariableResolve.Alias,
78
- evalStrings: true,
79
- resolveSource: {
80
- dropPaths: DropPathsOption.No,
81
- ignoreCapitalization: true,
82
- inferWorkingDirectory: InferWorkingDirectory.ActiveScript,
83
- searchPath: [],
84
- repeatedSourceLimit: 2
85
- },
86
- instrument: {
87
- dataflowExtractors: undefined
88
- },
89
- slicer: {
90
- threshold: 50
204
+ /**
205
+ * Loads the flowr config from the given file or the default locations.
206
+ * Please note that you can also use this without a path parameter to
207
+ * infer the config from flowR's default locations.
208
+ * This is mostly useful for user-facing features.
209
+ */
210
+ fromFile(configFile, configWorkingDirectory = process.cwd()) {
211
+ try {
212
+ return loadConfigFromFile(configFile, configWorkingDirectory);
91
213
  }
92
- },
93
- abstractInterpretation: {
94
- wideningThreshold: 4,
95
- dataFrame: {
96
- maxColNames: 50,
97
- readLoadedData: {
98
- readExternalFiles: true,
99
- maxReadLines: 1e6
100
- }
214
+ catch (e) {
215
+ log_1.log.error(`Failed to load config: ${e.message}`);
216
+ return exports.FlowrConfig.default();
101
217
  }
102
- }
103
- };
104
- exports.flowrConfigFileSchema = joi_1.default.object({
105
- ignoreSourceCalls: joi_1.default.boolean().optional().description('Whether source calls should be ignored, causing {@link processSourceCall}\'s behavior to be skipped.'),
106
- semantics: joi_1.default.object({
107
- environment: joi_1.default.object({
108
- overwriteBuiltIns: joi_1.default.object({
109
- loadDefaults: joi_1.default.boolean().optional().description('Should the default configuration still be loaded?'),
110
- definitions: joi_1.default.array().items(joi_1.default.object()).optional().description('The definitions to load/overwrite.')
111
- }).optional().description('Do you want to overwrite (parts) of the builtin definition?')
112
- }).optional().description('Semantics regarding how to handle the R environment.')
113
- }).description('Configure language semantics and how flowR handles them.'),
114
- repl: joi_1.default.object({
115
- quickStats: joi_1.default.boolean().optional().description('Whether to show quick stats in the REPL after each evaluation.'),
116
- dfProcessorHeat: joi_1.default.boolean().optional().description('This instruments the dataflow processors to count how often each processor is called.')
117
- }).description('Configuration options for the REPL.'),
118
- project: joi_1.default.object({
119
- resolveUnknownPathsOnDisk: joi_1.default.boolean().optional().description('Whether to resolve unknown paths loaded by the r project disk when trying to source/analyze files.')
120
- }).description('Project specific configuration options.'),
121
- engines: joi_1.default.array().items(joi_1.default.alternatives(joi_1.default.object({
122
- type: joi_1.default.string().required().valid('tree-sitter').description('Use the tree sitter engine.'),
123
- wasmPath: joi_1.default.string().optional().description('The path to the tree-sitter-r WASM binary to use. If this is undefined, this uses the default path.'),
124
- treeSitterWasmPath: joi_1.default.string().optional().description('The path to the tree-sitter WASM binary to use. If this is undefined, this uses the default path.'),
125
- lax: joi_1.default.boolean().optional().description('Whether to use the lax parser for parsing R code (allowing for syntax errors). If this is undefined, the strict parser will be used.')
126
- }).description('The configuration for the tree sitter engine.'), joi_1.default.object({
127
- type: joi_1.default.string().required().valid('r-shell').description('Use the R shell engine.'),
128
- rPath: joi_1.default.string().optional().description('The path to the R executable to use. If this is undefined, this uses the default path.')
129
- }).description('The configuration for the R shell engine.'))).min(1).description('The engine or set of engines to use for interacting with R code. An empty array means all available engines will be used.'),
130
- 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.'),
131
- solver: joi_1.default.object({
132
- variables: joi_1.default.string().valid(...Object.values(VariableResolve)).description('How to resolve variables and their values.'),
133
- evalStrings: joi_1.default.boolean().description('Should we include eval(parse(text="...")) calls in the dataflow graph?'),
134
- instrument: joi_1.default.object({
135
- dataflowExtractors: joi_1.default.any().optional().description('These keys are only intended for use within code, allowing to instrument the dataflow analyzer!')
136
- }),
137
- resolveSource: joi_1.default.object({
138
- 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.'),
139
- ignoreCapitalization: joi_1.default.boolean().description('Search for filenames matching in the lowercase.'),
140
- inferWorkingDirectory: joi_1.default.string().valid(...Object.values(InferWorkingDirectory)).description('Try to infer the working directory from the main or any script to analyze.'),
141
- searchPath: joi_1.default.array().items(joi_1.default.string()).description('Additionally search in these paths.'),
142
- 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.'),
143
- applyReplacements: joi_1.default.array().items(joi_1.default.object()).description('Provide name replacements for loaded files')
144
- }).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.'),
145
- slicer: joi_1.default.object({
146
- threshold: joi_1.default.number().optional().description('The maximum number of iterations to perform on a single function call during slicing.')
147
- }).optional().description('The configuration for the slicer.')
148
- }).description('How to resolve constants, constraints, cells, ...'),
149
- abstractInterpretation: joi_1.default.object({
150
- dataFrame: joi_1.default.object({
151
- maxColNames: joi_1.default.number().min(0).description('The maximum number of columns names to infer for data frames before over-approximating the column names to top.'),
152
- wideningThreshold: joi_1.default.number().min(1).description('The threshold for the number of visitations of a node at which widening should be performed to ensure the termination of the fixpoint iteration.'),
153
- readLoadedData: joi_1.default.object({
154
- readExternalFiles: joi_1.default.boolean().description('Whether data frame shapes should be extracted from loaded external files, such as CSV files.'),
155
- maxReadLines: joi_1.default.number().min(1).description('The maximum number of lines to read when extracting data frame shapes from loaded files, such as CSV files.')
156
- }).description('Configuration options for reading data frame shapes from loaded external data files, such as CSV files.')
157
- }).description('The configuration of the shape inference for data frames.')
158
- }).description('The configuration options for abstract interpretation.')
159
- }).description('The configuration file format for flowR.');
160
- /**
161
- * Parses the given JSON string as a flowR config file.
162
- */
163
- function parseConfig(jsonString) {
164
- try {
165
- const parsed = JSON.parse(jsonString);
166
- const validate = exports.flowrConfigFileSchema.validate(parsed);
167
- if (!validate.error) {
168
- // assign default values to all config options except for the specified ones
169
- return (0, objects_1.deepMergeObject)(exports.defaultConfigOptions, parsed);
218
+ },
219
+ /**
220
+ * Gets the configuration for the given engine type from the config.
221
+ */
222
+ getForEngine(config, engine) {
223
+ const engines = config.engines;
224
+ if (engines.length > 0) {
225
+ return engines.find(e => e.type === engine);
170
226
  }
171
227
  else {
172
- log_1.log.error(`Failed to validate config ${jsonString}: ${validate.error.message}`);
173
- return undefined;
228
+ return defaultEngineConfigs[engine];
174
229
  }
230
+ },
231
+ /**
232
+ * Returns a new config object with the given value set at the given key, where the key is a dot-separated path to the value in the config object.
233
+ * @see {@link setInConfigInPlace} for a version that modifies the config object in place instead of returning a new one.
234
+ * @example
235
+ * ```ts
236
+ * const config = FlowrConfig.default();
237
+ * const newConfig = FlowrConfig.setInConfig(config, 'solver.variables', VariableResolve.Builtin);
238
+ * console.log(config.solver.variables); // Output: "alias"
239
+ * console.log(newConfig.solver.variables); // Output: "builtin"
240
+ * ```
241
+ */
242
+ setInConfig(config, key, value) {
243
+ const clone = exports.FlowrConfig.clone(config);
244
+ object_path_1.default.set(clone, key, value);
245
+ return clone;
246
+ },
247
+ /**
248
+ * Modifies the given config object in place by setting the given value at the given key, where the key is a dot-separated path to the value in the config object.
249
+ * @see {@link setInConfig} for a version that returns a new config object instead of modifying the given one in place.
250
+ */
251
+ setInConfigInPlace(config, key, value) {
252
+ object_path_1.default.set(config, key, value);
175
253
  }
176
- catch (e) {
177
- log_1.log.error(`Failed to parse config ${jsonString}: ${e.message}`);
178
- }
179
- }
180
- /**
181
- * Creates a new flowr config that has the updated values.
182
- */
183
- // eslint-disable-next-line @typescript-eslint/no-invalid-void-type
184
- function amendConfig(config, amendmentFunc) {
185
- const newConfig = cloneConfig(config);
186
- amendmentFunc(newConfig);
187
- return newConfig;
188
- }
189
- /**
190
- * Clones the given flowr config object.
191
- */
192
- function cloneConfig(config) {
193
- return JSON.parse(JSON.stringify(config));
194
- }
195
- /**
196
- * Loads the flowr config from the given file or the default locations.
197
- */
198
- function getConfig(configFile, configWorkingDirectory = process.cwd()) {
199
- try {
200
- return loadConfigFromFile(configFile, configWorkingDirectory);
201
- }
202
- catch (e) {
203
- log_1.log.error(`Failed to load config: ${e.message}`);
204
- return exports.defaultConfigOptions;
205
- }
206
- }
207
- /**
208
- * Gets the configuration for the given engine type from the config.
209
- */
210
- function getEngineConfig(config, engine) {
211
- const engines = config.engines;
212
- if (!engines.length) {
213
- return defaultEngineConfigs[engine];
214
- }
215
- else {
216
- return engines.find(e => e.type === engine);
217
- }
218
- }
254
+ };
219
255
  function loadConfigFromFile(configFile, workingDirectory) {
220
256
  if (configFile !== undefined) {
221
257
  if (path_1.default.isAbsolute(configFile) && fs_1.default.existsSync(configFile)) {
222
258
  log_1.log.trace(`Found config at ${configFile} (absolute)`);
223
- const ret = parseConfig(fs_1.default.readFileSync(configFile, { encoding: 'utf-8' }));
259
+ const ret = exports.FlowrConfig.parse(fs_1.default.readFileSync(configFile, { encoding: 'utf-8' }));
224
260
  if (ret) {
225
261
  log_1.log.info(`Using config ${JSON.stringify(ret)}`);
226
262
  return ret;
@@ -231,7 +267,7 @@ function loadConfigFromFile(configFile, workingDirectory) {
231
267
  const configPath = path_1.default.join(searchPath, configFile);
232
268
  if (fs_1.default.existsSync(configPath)) {
233
269
  log_1.log.trace(`Found config at ${configPath}`);
234
- const ret = parseConfig(fs_1.default.readFileSync(configPath, { encoding: 'utf-8' }));
270
+ const ret = exports.FlowrConfig.parse(fs_1.default.readFileSync(configPath, { encoding: 'utf-8' }));
235
271
  if (ret) {
236
272
  log_1.log.info(`Using config ${JSON.stringify(ret)}`);
237
273
  return ret;
@@ -241,7 +277,7 @@ function loadConfigFromFile(configFile, workingDirectory) {
241
277
  searchPath = (0, files_1.getParentDirectory)(searchPath);
242
278
  } while (fs_1.default.existsSync(searchPath));
243
279
  }
244
- log_1.log.info(`Using default config ${JSON.stringify(exports.defaultConfigOptions)}`);
245
- return exports.defaultConfigOptions;
280
+ log_1.log.info('Using default config');
281
+ return exports.FlowrConfig.default();
246
282
  }
247
283
  //# sourceMappingURL=config.js.map
@@ -13,9 +13,9 @@ const vertex_1 = require("../dataflow/graph/vertex");
13
13
  const control_flow_graph_1 = require("./control-flow-graph");
14
14
  const cfg_simplification_1 = require("./cfg-simplification");
15
15
  const assert_1 = require("../util/assert");
16
- const built_in_1 = require("../dataflow/environments/built-in");
17
16
  const stateful_fold_1 = require("../r-bridge/lang-4.x/ast/model/processing/stateful-fold");
18
17
  const model_1 = require("../r-bridge/lang-4.x/ast/model/model");
18
+ const built_in_proc_name_1 = require("../dataflow/environments/built-in-proc-name");
19
19
  const cfgFolds = {
20
20
  down: (n, down) => {
21
21
  if (r_function_definition_1.RFunctionDefinition.is(n)) {
@@ -292,14 +292,11 @@ function cfgFor(forLoop, variable, vector, body) {
292
292
  for (const breakPoint of body.breaks) {
293
293
  graph.addEdge(control_flow_graph_1.CfgVertex.toExitId(forLoopId), breakPoint, control_flow_graph_1.CfgEdge.makeFd());
294
294
  }
295
- const isNotEndless = body.exitPoints.length > 0 || body.breaks.length > 0;
296
- if (isNotEndless) {
297
- graph.addVertex(control_flow_graph_1.CfgVertex.makeExitMarker(forLoopId));
298
- for (const e of variable.exitPoints) {
299
- graph.addEdge(control_flow_graph_1.CfgVertex.toExitId(forLoopId), e, control_flow_graph_1.CfgEdge.makeCdFalse(forLoopId));
300
- }
295
+ graph.addVertex(control_flow_graph_1.CfgVertex.makeExitMarker(forLoopId));
296
+ for (const e of variable.exitPoints) {
297
+ graph.addEdge(control_flow_graph_1.CfgVertex.toExitId(forLoopId), e, control_flow_graph_1.CfgEdge.makeCdFalse(forLoopId));
301
298
  }
302
- return { graph, breaks: [], nexts: [], returns: body.returns, exitPoints: isNotEndless ? [control_flow_graph_1.CfgVertex.toExitId(forLoopId)] : [], entryPoints: [forLoopId] };
299
+ return { graph, breaks: [], nexts: [], returns: body.returns, exitPoints: [control_flow_graph_1.CfgVertex.toExitId(forLoopId)], entryPoints: [forLoopId] };
303
300
  }
304
301
  function cfgFunctionDefinition(fn, params, body) {
305
302
  const fnId = fn.info.id;
@@ -336,7 +333,7 @@ function cfgFunctionDefinition(fn, params, body) {
336
333
  return { graph: graph, breaks: [], nexts: [], returns: [], exitPoints: [fnId], entryPoints: [fnId] };
337
334
  }
338
335
  function cfgFunctionCall(call, name, args, down) {
339
- if (call.named && call.functionName.content === 'ifelse') {
336
+ if (call.named && call.functionName.content === 'ifelse' && args.length > 1) {
340
337
  // special built-in handling for ifelse as it is an expression that does not short-circuit
341
338
  return cfgIfThenElse(call, args[0] === r_function_call_1.EmptyArgument ? (0, control_flow_graph_1.emptyControlFlowInformation)() : args[0], args[1] === r_function_call_1.EmptyArgument ? (0, control_flow_graph_1.emptyControlFlowInformation)() : args[1], args[2] === r_function_call_1.EmptyArgument ? (0, control_flow_graph_1.emptyControlFlowInformation)() : args[2]);
342
339
  }
@@ -385,7 +382,7 @@ function cfgFunctionCall(call, name, args, down) {
385
382
  }
386
383
  exports.ResolvedCallSuffix = control_flow_graph_1.CfgVertex.toExitId('-resolved-call');
387
384
  const OriginToFoldTypeMap = {
388
- [built_in_1.BuiltInProcName.IfThenElse]: (folds, call, args, down) => {
385
+ [built_in_proc_name_1.BuiltInProcName.IfThenElse]: (folds, call, args, down) => {
389
386
  // arguments are in order!
390
387
  return folds.foldIfThenElse(call, // we will have to this more sophisticated if we rewrite the dfg based generation
391
388
  args[0] === r_function_call_1.EmptyArgument ? (0, control_flow_graph_1.emptyControlFlowInformation)() : args[0], args[1] === r_function_call_1.EmptyArgument ? (0, control_flow_graph_1.emptyControlFlowInformation)() : args[1], args[2] === r_function_call_1.EmptyArgument ? (0, control_flow_graph_1.emptyControlFlowInformation)() : args[2], down);
@@ -11,10 +11,10 @@ import type { RLogical } from '../r-bridge/lang-4.x/ast/model/nodes/r-logical';
11
11
  import type { DataflowGraph, FunctionArgument } from '../dataflow/graph/graph';
12
12
  import type { NoInfo, RNode } from '../r-bridge/lang-4.x/ast/model/model';
13
13
  import type { RSymbol } from '../r-bridge/lang-4.x/ast/model/nodes/r-symbol';
14
- import { BuiltInProcName } from '../dataflow/environments/built-in';
15
14
  import type { RExpressionList } from '../r-bridge/lang-4.x/ast/model/nodes/r-expression-list';
16
15
  import type { ReadOnlyFlowrAnalyzerContext } from '../project/context/flowr-analyzer-context';
17
16
  import { RNull } from '../r-bridge/lang-4.x/convert-values';
17
+ import { BuiltInProcName } from '../dataflow/environments/built-in-proc-name';
18
18
  export interface SemanticCfgGuidedVisitorConfiguration<OtherInfo = NoInfo, ControlFlow extends ControlFlowInformation = ControlFlowInformation, Ast extends NormalizedAst<OtherInfo> = NormalizedAst<OtherInfo>, Dfg extends DataflowGraph = DataflowGraph> extends DataflowCfgGuidedVisitorConfiguration<ControlFlow, Dfg>, SyntaxCfgGuidedVisitorConfiguration<OtherInfo, ControlFlow, Ast> {
19
19
  readonly ctx: ReadOnlyFlowrAnalyzerContext;
20
20
  }