@eagleoutice/flowr 2.2.16 → 2.4.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 (147) hide show
  1. package/README.md +48 -20
  2. package/abstract-interpretation/data-frame/absint-info.d.ts +109 -0
  3. package/abstract-interpretation/data-frame/absint-info.js +31 -0
  4. package/abstract-interpretation/data-frame/absint-visitor.d.ts +58 -0
  5. package/abstract-interpretation/data-frame/absint-visitor.js +171 -0
  6. package/abstract-interpretation/data-frame/domain.d.ts +107 -0
  7. package/abstract-interpretation/data-frame/domain.js +315 -0
  8. package/abstract-interpretation/data-frame/mappers/access-mapper.d.ts +17 -0
  9. package/abstract-interpretation/data-frame/mappers/access-mapper.js +166 -0
  10. package/abstract-interpretation/data-frame/mappers/arguments.d.ts +117 -0
  11. package/abstract-interpretation/data-frame/mappers/arguments.js +188 -0
  12. package/abstract-interpretation/data-frame/mappers/assignment-mapper.d.ts +20 -0
  13. package/abstract-interpretation/data-frame/mappers/assignment-mapper.js +34 -0
  14. package/abstract-interpretation/data-frame/mappers/function-mapper.d.ts +261 -0
  15. package/abstract-interpretation/data-frame/mappers/function-mapper.js +1219 -0
  16. package/abstract-interpretation/data-frame/mappers/replacement-mapper.d.ts +12 -0
  17. package/abstract-interpretation/data-frame/mappers/replacement-mapper.js +206 -0
  18. package/abstract-interpretation/data-frame/resolve-args.d.ts +42 -0
  19. package/abstract-interpretation/data-frame/resolve-args.js +118 -0
  20. package/abstract-interpretation/data-frame/semantics.d.ts +213 -0
  21. package/abstract-interpretation/data-frame/semantics.js +363 -0
  22. package/abstract-interpretation/data-frame/shape-inference.d.ts +38 -0
  23. package/abstract-interpretation/data-frame/shape-inference.js +111 -0
  24. package/benchmark/slicer.d.ts +15 -1
  25. package/benchmark/slicer.js +137 -0
  26. package/benchmark/stats/print.js +123 -45
  27. package/benchmark/stats/size-of.d.ts +7 -0
  28. package/benchmark/stats/size-of.js +1 -0
  29. package/benchmark/stats/stats.d.ts +30 -1
  30. package/benchmark/stats/stats.js +4 -2
  31. package/benchmark/summarizer/data.d.ts +33 -2
  32. package/benchmark/summarizer/first-phase/input.js +5 -1
  33. package/benchmark/summarizer/first-phase/process.js +47 -1
  34. package/benchmark/summarizer/second-phase/graph.js +1 -1
  35. package/benchmark/summarizer/second-phase/process.js +102 -4
  36. package/cli/benchmark-app.d.ts +2 -0
  37. package/cli/benchmark-app.js +2 -0
  38. package/cli/benchmark-helper-app.d.ts +2 -0
  39. package/cli/benchmark-helper-app.js +10 -3
  40. package/cli/common/options.js +4 -0
  41. package/cli/repl/commands/repl-query.js +1 -1
  42. package/cli/repl/server/connection.js +14 -5
  43. package/config.d.ts +31 -0
  44. package/config.js +21 -1
  45. package/control-flow/basic-cfg-guided-visitor.d.ts +1 -2
  46. package/control-flow/basic-cfg-guided-visitor.js +0 -6
  47. package/control-flow/cfg-simplification.d.ts +6 -0
  48. package/control-flow/cfg-simplification.js +18 -9
  49. package/control-flow/control-flow-graph.d.ts +3 -8
  50. package/control-flow/control-flow-graph.js +5 -6
  51. package/control-flow/dfg-cfg-guided-visitor.js +1 -1
  52. package/control-flow/extract-cfg.d.ts +2 -2
  53. package/control-flow/extract-cfg.js +52 -63
  54. package/control-flow/semantic-cfg-guided-visitor.d.ts +1 -1
  55. package/control-flow/semantic-cfg-guided-visitor.js +1 -1
  56. package/core/steps/all/static-slicing/00-slice.d.ts +7 -1
  57. package/core/steps/all/static-slicing/00-slice.js +9 -3
  58. package/core/steps/pipeline/default-pipelines.d.ts +74 -74
  59. package/dataflow/environments/built-in.d.ts +7 -5
  60. package/dataflow/environments/built-in.js +16 -13
  61. package/dataflow/eval/resolve/alias-tracking.js +2 -2
  62. package/dataflow/eval/resolve/resolve.d.ts +53 -9
  63. package/dataflow/eval/resolve/resolve.js +132 -38
  64. package/dataflow/graph/dataflowgraph-builder.js +2 -2
  65. package/dataflow/graph/graph.js +1 -1
  66. package/dataflow/graph/invert-dfg.d.ts +2 -0
  67. package/dataflow/graph/invert-dfg.js +17 -0
  68. package/dataflow/internal/process/functions/call/built-in/built-in-source.d.ts +1 -0
  69. package/dataflow/internal/process/functions/call/built-in/built-in-source.js +4 -0
  70. package/documentation/doc-util/doc-query.js +11 -1
  71. package/documentation/doc-util/doc-search.js +2 -2
  72. package/documentation/print-cfg-wiki.js +3 -4
  73. package/documentation/print-core-wiki.js +2 -2
  74. package/documentation/print-dataflow-graph-wiki.js +7 -0
  75. package/documentation/print-faq-wiki.js +4 -0
  76. package/documentation/print-interface-wiki.js +11 -0
  77. package/documentation/print-linter-wiki.js +36 -4
  78. package/documentation/print-linting-and-testing-wiki.js +13 -1
  79. package/documentation/print-onboarding-wiki.js +4 -0
  80. package/documentation/print-query-wiki.js +29 -3
  81. package/linter/linter-executor.js +1 -2
  82. package/linter/linter-format.d.ts +26 -4
  83. package/linter/linter-format.js +25 -6
  84. package/linter/linter-rules.d.ts +63 -12
  85. package/linter/linter-rules.js +5 -1
  86. package/linter/rules/absolute-path.d.ts +4 -7
  87. package/linter/rules/absolute-path.js +9 -6
  88. package/linter/rules/dataframe-access-validation.d.ts +55 -0
  89. package/linter/rules/dataframe-access-validation.js +118 -0
  90. package/linter/rules/dead-code.d.ts +43 -0
  91. package/linter/rules/dead-code.js +50 -0
  92. package/linter/rules/deprecated-functions.d.ts +3 -2
  93. package/linter/rules/deprecated-functions.js +3 -1
  94. package/linter/rules/file-path-validity.d.ts +4 -4
  95. package/linter/rules/file-path-validity.js +8 -6
  96. package/linter/rules/naming-convention.d.ts +5 -4
  97. package/linter/rules/naming-convention.js +8 -2
  98. package/linter/rules/seeded-randomness.d.ts +4 -3
  99. package/linter/rules/seeded-randomness.js +3 -1
  100. package/linter/rules/unused-definition.d.ts +2 -0
  101. package/linter/rules/unused-definition.js +3 -1
  102. package/package.json +2 -2
  103. package/queries/catalog/dependencies-query/dependencies-query-executor.js +6 -1
  104. package/queries/catalog/dependencies-query/function-info/read-functions.js +1 -0
  105. package/queries/catalog/dependencies-query/function-info/write-functions.js +1 -0
  106. package/queries/catalog/df-shape-query/df-shape-query-executor.d.ts +3 -0
  107. package/queries/catalog/df-shape-query/df-shape-query-executor.js +46 -0
  108. package/queries/catalog/df-shape-query/df-shape-query-format.d.ts +72 -0
  109. package/queries/catalog/df-shape-query/df-shape-query-format.js +31 -0
  110. package/queries/catalog/linter-query/linter-query-format.js +1 -1
  111. package/queries/catalog/location-map-query/location-map-query-executor.js +7 -5
  112. package/queries/catalog/location-map-query/location-map-query-format.d.ts +3 -0
  113. package/queries/catalog/location-map-query/location-map-query-format.js +1 -0
  114. package/queries/catalog/search-query/search-query-executor.js +1 -1
  115. package/queries/catalog/static-slice-query/static-slice-query-executor.js +2 -1
  116. package/queries/catalog/static-slice-query/static-slice-query-format.d.ts +3 -0
  117. package/queries/catalog/static-slice-query/static-slice-query-format.js +3 -1
  118. package/queries/query-print.d.ts +1 -1
  119. package/queries/query-print.js +0 -1
  120. package/queries/query.d.ts +77 -6
  121. package/queries/query.js +26 -11
  122. package/search/flowr-search-builder.d.ts +6 -6
  123. package/search/flowr-search-executor.d.ts +2 -2
  124. package/search/flowr-search-executor.js +1 -1
  125. package/search/flowr-search.d.ts +13 -8
  126. package/search/flowr-search.js +21 -0
  127. package/search/search-executor/search-enrichers.d.ts +87 -20
  128. package/search/search-executor/search-enrichers.js +44 -5
  129. package/search/search-executor/search-generators.d.ts +4 -4
  130. package/search/search-executor/search-generators.js +12 -7
  131. package/search/search-executor/search-mappers.js +3 -2
  132. package/search/search-executor/search-transformer.d.ts +3 -3
  133. package/search/search-executor/search-transformer.js +2 -2
  134. package/slicing/static/static-slicer.d.ts +4 -2
  135. package/slicing/static/static-slicer.js +10 -4
  136. package/util/collections/arrays.d.ts +2 -0
  137. package/util/collections/arrays.js +9 -0
  138. package/util/files.d.ts +8 -2
  139. package/util/files.js +22 -4
  140. package/util/mermaid/dfg.js +4 -2
  141. package/util/r-value.d.ts +23 -0
  142. package/util/r-value.js +113 -0
  143. package/util/range.d.ts +1 -0
  144. package/util/range.js +5 -1
  145. package/util/version.js +1 -1
  146. package/util/cfg/cfg.d.ts +0 -0
  147. package/util/cfg/cfg.js +0 -2
@@ -41,30 +41,31 @@ function builtInId(name) {
41
41
  function isBuiltIn(name) {
42
42
  return String(name).startsWith('built-in:');
43
43
  }
44
- function defaultBuiltInProcessor(name, args, rootId, data, config) {
45
- const { information: res, processedArguments } = (0, known_call_handling_1.processKnownFunctionCall)({ name, args, rootId, data, forceArgs: config.forceArgs, origin: config.useAsProcessor ?? 'builtin:default' });
46
- if (config.returnsNthArgument !== undefined) {
47
- const arg = config.returnsNthArgument === 'last' ? processedArguments[args.length - 1] : processedArguments[config.returnsNthArgument];
44
+ function defaultBuiltInProcessor(name, args, rootId, data, { returnsNthArgument, useAsProcessor, forceArgs, readAllArguments, cfg, hasUnknownSideEffects, treatAsFnCall }) {
45
+ const activeProcessor = useAsProcessor ?? 'builtin:default';
46
+ const { information: res, processedArguments } = (0, known_call_handling_1.processKnownFunctionCall)({ name, args, rootId, data, forceArgs, origin: activeProcessor });
47
+ if (returnsNthArgument !== undefined) {
48
+ const arg = returnsNthArgument === 'last' ? processedArguments[args.length - 1] : processedArguments[returnsNthArgument];
48
49
  if (arg !== undefined) {
49
50
  res.graph.addEdge(rootId, arg.entryPoint, edge_1.EdgeType.Returns);
50
51
  }
51
52
  }
52
- if (config.readAllArguments) {
53
+ if (readAllArguments) {
53
54
  for (const arg of processedArguments) {
54
55
  if (arg) {
55
56
  res.graph.addEdge(rootId, arg.entryPoint, edge_1.EdgeType.Reads);
56
57
  }
57
58
  }
58
59
  }
59
- if (config.hasUnknownSideEffects) {
60
- if (typeof config.hasUnknownSideEffects !== 'boolean') {
61
- (0, unknown_side_effect_1.handleUnknownSideEffect)(res.graph, res.environment, rootId, config.hasUnknownSideEffects);
60
+ if (hasUnknownSideEffects) {
61
+ if (typeof hasUnknownSideEffects !== 'boolean') {
62
+ (0, unknown_side_effect_1.handleUnknownSideEffect)(res.graph, res.environment, rootId, hasUnknownSideEffects);
62
63
  }
63
64
  else {
64
65
  (0, unknown_side_effect_1.handleUnknownSideEffect)(res.graph, res.environment, rootId);
65
66
  }
66
67
  }
67
- const fnCallNames = config.treatAsFnCall?.[name.content];
68
+ const fnCallNames = treatAsFnCall?.[name.content];
68
69
  if (fnCallNames) {
69
70
  for (const arg of args) {
70
71
  if (arg !== r_function_call_1.EmptyArgument && arg.value && fnCallNames.includes(arg.name?.content)) {
@@ -90,13 +91,13 @@ function defaultBuiltInProcessor(name, args, rootId, data, config) {
90
91
  environment: data.environment,
91
92
  onlyBuiltin: false,
92
93
  cds: data.controlDependencies,
93
- origin: [config.useAsProcessor ?? 'builtin:default']
94
+ origin: [activeProcessor]
94
95
  });
95
96
  }
96
97
  }
97
98
  }
98
- if (config.cfg !== undefined) {
99
- res.exitPoints = [...res.exitPoints, { type: config.cfg, nodeId: rootId, controlDependencies: data.controlDependencies }];
99
+ if (cfg !== undefined) {
100
+ res.exitPoints.push({ type: cfg, nodeId: rootId, controlDependencies: data.controlDependencies });
100
101
  }
101
102
  return res;
102
103
  }
@@ -144,7 +145,9 @@ exports.BuiltInProcessorMapper = {
144
145
  };
145
146
  exports.BuiltInEvalHandlerMapper = {
146
147
  'built-in:c': resolve_1.resolveAsVector,
147
- 'builtin:vector': resolve_1.resolveAsVector
148
+ 'built-in::': resolve_1.resolveAsSeq,
149
+ 'built-in:+': resolve_1.resolveAsPlus,
150
+ 'built-in:-': resolve_1.resolveAsMinus
148
151
  };
149
152
  exports.BuiltInMemory = new Map();
150
153
  exports.EmptyBuiltInMemory = new Map();
@@ -139,6 +139,8 @@ function resolveIdToValue(id, { environment, graph, idMap, full = true, resolve
139
139
  return r_value_1.Top;
140
140
  }
141
141
  case type_1.RType.FunctionCall:
142
+ case type_1.RType.BinaryOp:
143
+ case type_1.RType.UnaryOp:
142
144
  return (0, set_constants_1.setFrom)((0, resolve_1.resolveNode)(resolve, node, environment, graph, idMap));
143
145
  case type_1.RType.String:
144
146
  case type_1.RType.Number:
@@ -261,8 +263,6 @@ function isNestedInLoop(node, ast) {
261
263
  function trackAliasesInGraph(id, graph, idMap) {
262
264
  idMap ??= graph.idMap;
263
265
  (0, assert_1.guard)(idMap !== undefined, 'The ID map is required to get the lineage of a node');
264
- const start = graph.getVertex(id);
265
- (0, assert_1.guard)(start !== undefined, 'Unable to find start for alias tracking');
266
266
  const queue = new visiting_queue_1.VisitingQueue(25);
267
267
  const clean = (0, environment_1.initializeCleanEnvironments)();
268
268
  const cleanFingerprint = (0, fingerprint_1.envFingerprint)(clean);
@@ -1,7 +1,8 @@
1
1
  import type { AstIdMap, RNodeWithParent } from '../../../r-bridge/lang-4.x/ast/model/processing/decorate';
2
2
  import type { REnvironmentInformation } from '../../environments/environment';
3
3
  import type { DataflowGraph } from '../../graph/graph';
4
- import type { Value } from '../values/r-value';
4
+ import type { Lift, Value, ValueNumber, ValueVector } from '../values/r-value';
5
+ import { Top } from '../values/r-value';
5
6
  import type { VariableResolve } from '../../../config';
6
7
  /**
7
8
  * Helper function used by {@link resolveIdToValue}, please use that instead, if
@@ -22,16 +23,59 @@ export declare function resolveNode(resolve: VariableResolve, a: RNodeWithParent
22
23
  * Helper function used by {@link resolveIdToValue}, please use that instead, if
23
24
  * you want to resolve the value of an identifier / node
24
25
  *
25
- * This function converts an r-node to a Value Vector {@link vectorFrom}
26
- * It also recursively resolves any symbols, values, function calls (only c), in
27
- * order to construct the value of the vector to resolve by calling {@link resolveIdToValue}
28
- * or {@link resolveNode}
26
+ * This function resolves a vector function call `c` to a {@link ValueVector}
27
+ * by recursively resolving the values of the arguments by calling {@link resolveIdToValue}
29
28
  *
30
- * @param a - Node of the vector to resolve
31
- * @param env - Environment to use
32
29
  * @param resolve - Variable resolve mode
30
+ * @param node - Node of the vector function to resolve
31
+ * @param env - Environment to use
33
32
  * @param graph - Dataflow graph
34
- * @param map - Idmap of Dataflow Graph
33
+ * @param map - Id map of the dataflow graph
35
34
  * @returns ValueVector or Top
36
35
  */
37
- export declare function resolveAsVector(resolve: VariableResolve, a: RNodeWithParent, env: REnvironmentInformation, graph?: DataflowGraph, map?: AstIdMap): Value;
36
+ export declare function resolveAsVector(resolve: VariableResolve, node: RNodeWithParent, environment?: REnvironmentInformation, graph?: DataflowGraph, idMap?: AstIdMap): ValueVector<Lift<Value[]>> | typeof Top;
37
+ /**
38
+ * Helper function used by {@link resolveIdToValue}, please use that instead, if
39
+ * you want to resolve the value of an identifier / node
40
+ *
41
+ * This function resolves a binary sequence operator `:` to a {@link ValueVector} of {@link ValueNumber}s
42
+ * by recursively resolving the values of the arguments by calling {@link resolveIdToValue}
43
+ *
44
+ * @param resolve - Variable resolve mode
45
+ * @param operator - Node of the sequence operator to resolve
46
+ * @param env - Environment to use
47
+ * @param graph - Dataflow graph
48
+ * @param map - Id map of the dataflow graph
49
+ * @returns ValueVector of ValueNumbers or Top
50
+ */
51
+ export declare function resolveAsSeq(resolve: VariableResolve, operator: RNodeWithParent, environment?: REnvironmentInformation, graph?: DataflowGraph, idMap?: AstIdMap): ValueVector<Lift<ValueNumber[]>> | typeof Top;
52
+ /**
53
+ * Helper function used by {@link resolveIdToValue}, please use that instead, if
54
+ * you want to resolve the value of an identifier / node
55
+ *
56
+ * This function resolves a unary plus operator `+` to a {@link ValueNumber} or {@link ValueVector} of ValueNumbers
57
+ * by recursively resolving the values of the arguments by calling {@link resolveIdToValue}
58
+ *
59
+ * @param resolve - Variable resolve mode
60
+ * @param operator - Node of the plus operator to resolve
61
+ * @param env - Environment to use
62
+ * @param graph - Dataflow graph
63
+ * @param map - Id map of the dataflow graph
64
+ * @returns ValueNumber, ValueVector of ValueNumbers, or Top
65
+ */
66
+ export declare function resolveAsPlus(resolve: VariableResolve, operator: RNodeWithParent, environment?: REnvironmentInformation, graph?: DataflowGraph, idMap?: AstIdMap): ValueNumber | ValueVector<Lift<ValueNumber[]>> | typeof Top;
67
+ /**
68
+ * Helper function used by {@link resolveIdToValue}, please use that instead, if
69
+ * you want to resolve the value of an identifier / node
70
+ *
71
+ * This function resolves a unary minus operator `-` to a {@link ValueNumber} or {@link ValueVector} of ValueNumbers
72
+ * by recursively resolving the values of the arguments by calling {@link resolveIdToValue}
73
+ *
74
+ * @param resolve - Variable resolve mode
75
+ * @param operator - Node of the minus operator to resolve
76
+ * @param env - Environment to use
77
+ * @param graph - Dataflow graph
78
+ * @param map - Id map of the dataflow graph
79
+ * @returns ValueNumber, ValueVector of ValueNumbers, or Top
80
+ */
81
+ export declare function resolveAsMinus(resolve: VariableResolve, operator: RNodeWithParent, environment?: REnvironmentInformation, graph?: DataflowGraph, idMap?: AstIdMap): ValueNumber | ValueVector<Lift<ValueNumber[]>> | typeof Top;
@@ -2,17 +2,21 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.resolveNode = resolveNode;
4
4
  exports.resolveAsVector = resolveAsVector;
5
+ exports.resolveAsSeq = resolveAsSeq;
6
+ exports.resolveAsPlus = resolveAsPlus;
7
+ exports.resolveAsMinus = resolveAsMinus;
5
8
  const r_function_call_1 = require("../../../r-bridge/lang-4.x/ast/model/nodes/r-function-call");
6
9
  const type_1 = require("../../../r-bridge/lang-4.x/ast/model/type");
7
- const assert_1 = require("../../../util/assert");
10
+ const r_value_1 = require("../../../util/r-value");
8
11
  const built_in_1 = require("../../environments/built-in");
9
12
  const dfg_get_origin_1 = require("../../origin/dfg-get-origin");
10
13
  const interval_constants_1 = require("../values/intervals/interval-constants");
11
14
  const logical_constants_1 = require("../values/logical/logical-constants");
12
- const r_value_1 = require("../values/r-value");
15
+ const r_value_2 = require("../values/r-value");
13
16
  const string_constants_1 = require("../values/string/string-constants");
14
17
  const vector_constants_1 = require("../values/vectors/vector-constants");
15
18
  const alias_tracking_1 = require("./alias-tracking");
19
+ const scalar_consatnts_1 = require("../values/scalar/scalar-consatnts");
16
20
  /**
17
21
  * Helper function used by {@link resolveIdToValue}, please use that instead, if
18
22
  * you want to resolve the value of an identifier / node
@@ -37,59 +41,149 @@ function resolveNode(resolve, a, env, graph, map) {
37
41
  else if (a.type === type_1.RType.Logical) {
38
42
  return a.content.valueOf() ? logical_constants_1.ValueLogicalTrue : logical_constants_1.ValueLogicalFalse;
39
43
  }
40
- else if (a.type === type_1.RType.FunctionCall && env && graph) {
44
+ else if ((a.type === type_1.RType.FunctionCall || a.type === type_1.RType.BinaryOp || a.type === type_1.RType.UnaryOp) && graph) {
41
45
  const origin = (0, dfg_get_origin_1.getOriginInDfg)(graph, a.info.id)?.[0];
42
46
  if (origin === undefined || origin.type !== 3 /* OriginType.BuiltInFunctionOrigin */) {
43
- return r_value_1.Top;
47
+ return r_value_2.Top;
44
48
  }
45
- if (origin.proc in built_in_1.BuiltInEvalHandlerMapper) {
46
- const handler = built_in_1.BuiltInEvalHandlerMapper[origin.proc];
49
+ let builtInName;
50
+ if ((0, built_in_1.isBuiltIn)(origin.proc)) {
51
+ builtInName = origin.proc;
52
+ }
53
+ else if (a.type === type_1.RType.FunctionCall && a.named) {
54
+ builtInName = (0, built_in_1.builtInId)(a.functionName.content);
55
+ }
56
+ else if (a.type === type_1.RType.BinaryOp || a.type === type_1.RType.UnaryOp) {
57
+ builtInName = (0, built_in_1.builtInId)(a.operator);
58
+ }
59
+ else {
60
+ return r_value_2.Top;
61
+ }
62
+ if (Object.prototype.hasOwnProperty.call(built_in_1.BuiltInEvalHandlerMapper, builtInName)) {
63
+ const handler = built_in_1.BuiltInEvalHandlerMapper[builtInName];
47
64
  return handler(resolve, a, env, graph, map);
48
65
  }
49
66
  }
50
- return r_value_1.Top;
67
+ return r_value_2.Top;
51
68
  }
52
69
  /**
53
70
  * Helper function used by {@link resolveIdToValue}, please use that instead, if
54
71
  * you want to resolve the value of an identifier / node
55
72
  *
56
- * This function converts an r-node to a Value Vector {@link vectorFrom}
57
- * It also recursively resolves any symbols, values, function calls (only c), in
58
- * order to construct the value of the vector to resolve by calling {@link resolveIdToValue}
59
- * or {@link resolveNode}
73
+ * This function resolves a vector function call `c` to a {@link ValueVector}
74
+ * by recursively resolving the values of the arguments by calling {@link resolveIdToValue}
60
75
  *
61
- * @param a - Node of the vector to resolve
62
- * @param env - Environment to use
63
76
  * @param resolve - Variable resolve mode
77
+ * @param node - Node of the vector function to resolve
78
+ * @param env - Environment to use
64
79
  * @param graph - Dataflow graph
65
- * @param map - Idmap of Dataflow Graph
80
+ * @param map - Id map of the dataflow graph
66
81
  * @returns ValueVector or Top
67
82
  */
68
- function resolveAsVector(resolve, a, env, graph, map) {
69
- (0, assert_1.guard)(a.type === type_1.RType.FunctionCall);
70
- const values = [];
71
- for (const arg of a.arguments) {
72
- if (arg === r_function_call_1.EmptyArgument) {
73
- continue;
74
- }
75
- if (arg.value === undefined) {
76
- return r_value_1.Top;
77
- }
78
- if (arg.value.type === type_1.RType.Symbol) {
79
- const value = (0, alias_tracking_1.resolveIdToValue)(arg.info.id, { environment: env, idMap: map, graph: graph, full: true, resolve });
80
- if ((0, r_value_1.isTop)(value)) {
81
- return r_value_1.Top;
82
- }
83
- values.push(value);
84
- }
85
- else {
86
- const val = resolveNode(resolve, arg.value, env, graph, map);
87
- if ((0, r_value_1.isTop)(val)) {
88
- return r_value_1.Top;
89
- }
90
- values.push(val);
91
- }
83
+ function resolveAsVector(resolve, node, environment, graph, idMap) {
84
+ if (node.type !== type_1.RType.FunctionCall) {
85
+ return r_value_2.Top;
92
86
  }
87
+ const resolveInfo = { environment, graph, idMap, full: true, resolve };
88
+ const values = node.arguments.map(arg => arg !== r_function_call_1.EmptyArgument ? (0, alias_tracking_1.resolveIdToValue)(arg.value, resolveInfo) : r_value_2.Top);
93
89
  return (0, vector_constants_1.vectorFrom)((0, vector_constants_1.flattenVectorElements)(values));
94
90
  }
91
+ /**
92
+ * Helper function used by {@link resolveIdToValue}, please use that instead, if
93
+ * you want to resolve the value of an identifier / node
94
+ *
95
+ * This function resolves a binary sequence operator `:` to a {@link ValueVector} of {@link ValueNumber}s
96
+ * by recursively resolving the values of the arguments by calling {@link resolveIdToValue}
97
+ *
98
+ * @param resolve - Variable resolve mode
99
+ * @param operator - Node of the sequence operator to resolve
100
+ * @param env - Environment to use
101
+ * @param graph - Dataflow graph
102
+ * @param map - Id map of the dataflow graph
103
+ * @returns ValueVector of ValueNumbers or Top
104
+ */
105
+ function resolveAsSeq(resolve, operator, environment, graph, idMap) {
106
+ if (operator.type !== type_1.RType.BinaryOp) {
107
+ return r_value_2.Top;
108
+ }
109
+ const resolveInfo = { environment, graph, idMap, full: true, resolve };
110
+ const leftArg = (0, alias_tracking_1.resolveIdToValue)(operator.lhs, resolveInfo);
111
+ const rightArg = (0, alias_tracking_1.resolveIdToValue)(operator.rhs, resolveInfo);
112
+ const leftValue = (0, r_value_1.unliftRValue)(leftArg);
113
+ const rightValue = (0, r_value_1.unliftRValue)(rightArg);
114
+ if ((0, r_value_1.isRNumberValue)(leftValue) && (0, r_value_1.isRNumberValue)(rightValue)) {
115
+ return (0, vector_constants_1.vectorFrom)(createNumberSequence(leftValue, rightValue).map(scalar_consatnts_1.liftScalar));
116
+ }
117
+ return r_value_2.Top;
118
+ }
119
+ /**
120
+ * Helper function used by {@link resolveIdToValue}, please use that instead, if
121
+ * you want to resolve the value of an identifier / node
122
+ *
123
+ * This function resolves a unary plus operator `+` to a {@link ValueNumber} or {@link ValueVector} of ValueNumbers
124
+ * by recursively resolving the values of the arguments by calling {@link resolveIdToValue}
125
+ *
126
+ * @param resolve - Variable resolve mode
127
+ * @param operator - Node of the plus operator to resolve
128
+ * @param env - Environment to use
129
+ * @param graph - Dataflow graph
130
+ * @param map - Id map of the dataflow graph
131
+ * @returns ValueNumber, ValueVector of ValueNumbers, or Top
132
+ */
133
+ function resolveAsPlus(resolve, operator, environment, graph, idMap) {
134
+ if (operator.type !== type_1.RType.UnaryOp) {
135
+ return r_value_2.Top;
136
+ }
137
+ const resolveInfo = { environment, graph, idMap, full: true, resolve };
138
+ const arg = (0, alias_tracking_1.resolveIdToValue)(operator.operand, resolveInfo);
139
+ const argValue = (0, r_value_1.unliftRValue)(arg);
140
+ if ((0, r_value_1.isRNumberValue)(argValue)) {
141
+ return (0, scalar_consatnts_1.liftScalar)(argValue);
142
+ }
143
+ else if (Array.isArray(argValue) && argValue.every(r_value_1.isRNumberValue)) {
144
+ return (0, vector_constants_1.vectorFrom)(argValue.map(scalar_consatnts_1.liftScalar));
145
+ }
146
+ return r_value_2.Top;
147
+ }
148
+ /**
149
+ * Helper function used by {@link resolveIdToValue}, please use that instead, if
150
+ * you want to resolve the value of an identifier / node
151
+ *
152
+ * This function resolves a unary minus operator `-` to a {@link ValueNumber} or {@link ValueVector} of ValueNumbers
153
+ * by recursively resolving the values of the arguments by calling {@link resolveIdToValue}
154
+ *
155
+ * @param resolve - Variable resolve mode
156
+ * @param operator - Node of the minus operator to resolve
157
+ * @param env - Environment to use
158
+ * @param graph - Dataflow graph
159
+ * @param map - Id map of the dataflow graph
160
+ * @returns ValueNumber, ValueVector of ValueNumbers, or Top
161
+ */
162
+ function resolveAsMinus(resolve, operator, environment, graph, idMap) {
163
+ if (operator.type !== type_1.RType.UnaryOp) {
164
+ return r_value_2.Top;
165
+ }
166
+ const resolveInfo = { environment, graph, idMap, full: true, resolve };
167
+ const arg = (0, alias_tracking_1.resolveIdToValue)(operator.operand, resolveInfo);
168
+ const argValue = (0, r_value_1.unliftRValue)(arg);
169
+ if ((0, r_value_1.isRNumberValue)(argValue)) {
170
+ return (0, scalar_consatnts_1.liftScalar)({ ...argValue, num: -argValue.num });
171
+ }
172
+ else if (Array.isArray(argValue) && argValue.every(r_value_1.isRNumberValue)) {
173
+ return (0, vector_constants_1.vectorFrom)(argValue.map(element => (0, scalar_consatnts_1.liftScalar)({ ...element, num: -element.num })));
174
+ }
175
+ return r_value_2.Top;
176
+ }
177
+ function createNumberSequence(start, end) {
178
+ const sequence = [];
179
+ const min = Math.min(start.num, end.num);
180
+ const max = Math.max(start.num, end.num);
181
+ for (let i = min; i <= max; i++) {
182
+ sequence.push({ ...start, num: i });
183
+ }
184
+ if (start > end) {
185
+ sequence.reverse();
186
+ }
187
+ return sequence;
188
+ }
95
189
  //# sourceMappingURL=resolve.js.map
@@ -180,7 +180,7 @@ class DataflowGraphBuilder extends graph_1.DataflowGraph {
180
180
  fromId = from.nodeId;
181
181
  }
182
182
  else {
183
- const result = (0, flowr_search_executor_1.runSearch)(from.query, data);
183
+ const result = (0, flowr_search_executor_1.runSearch)(from.query, data).getElements();
184
184
  (0, assert_1.guard)(result.length === 1, `from query result should yield exactly one node, but yielded ${result.length}`);
185
185
  fromId = result[0].node.info.id;
186
186
  }
@@ -189,7 +189,7 @@ class DataflowGraphBuilder extends graph_1.DataflowGraph {
189
189
  toIds = to.target;
190
190
  }
191
191
  else {
192
- const result = (0, flowr_search_executor_1.runSearch)(to.query, data);
192
+ const result = (0, flowr_search_executor_1.runSearch)(to.query, data).getElements();
193
193
  toIds = result.map(r => r.node.info.id);
194
194
  }
195
195
  return this.edgeHelper(fromId, toIds, type);
@@ -376,7 +376,7 @@ function mergeNodeInfos(current, next) {
376
376
  }
377
377
  else if (current.tag === vertex_1.VertexType.FunctionDefinition) {
378
378
  (0, assert_1.guard)(current.scope === next.scope, 'nodes to be joined for the same id must have the same scope');
379
- (0, assert_1.guard)((0, arrays_1.arrayEqual)(current.exitPoints, next.exitPoints), 'nodes to be joined must have same exist points');
379
+ current.exitPoints = (0, arrays_1.uniqueArrayMerge)(current.exitPoints, next.exitPoints);
380
380
  }
381
381
  return current;
382
382
  }
@@ -0,0 +1,2 @@
1
+ import { DataflowGraph } from './graph';
2
+ export declare function invertDfg(graph: DataflowGraph): DataflowGraph;
@@ -0,0 +1,17 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.invertDfg = invertDfg;
4
+ const graph_1 = require("./graph");
5
+ function invertDfg(graph) {
6
+ const invertedGraph = new graph_1.DataflowGraph(graph.idMap);
7
+ for (const [, v] of graph.vertices(true)) {
8
+ invertedGraph.addVertex(v);
9
+ }
10
+ for (const [from, targets] of graph.edges()) {
11
+ for (const [to, { types }] of targets) {
12
+ invertedGraph.addEdge(to, from, types);
13
+ }
14
+ }
15
+ return invertedGraph;
16
+ }
17
+ //# sourceMappingURL=invert-dfg.js.map
@@ -8,6 +8,7 @@ import type { RFunctionArgument } from '../../../../../../r-bridge/lang-4.x/ast/
8
8
  import type { RSymbol } from '../../../../../../r-bridge/lang-4.x/ast/model/nodes/r-symbol';
9
9
  import type { NodeId } from '../../../../../../r-bridge/lang-4.x/ast/model/processing/node-id';
10
10
  import type { NoInfo } from '../../../../../../r-bridge/lang-4.x/ast/model/model';
11
+ export declare function getSourceProvider(): RParseRequestProvider;
11
12
  export declare function setSourceProvider(provider: RParseRequestProvider): void;
12
13
  export declare function inferWdFromScript(option: InferWorkingDirectory, referenceChain: readonly RParseRequest[]): string[];
13
14
  /**
@@ -3,6 +3,7 @@ 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.getSourceProvider = getSourceProvider;
6
7
  exports.setSourceProvider = setSourceProvider;
7
8
  exports.inferWdFromScript = inferWdFromScript;
8
9
  exports.findSource = findSource;
@@ -30,6 +31,9 @@ const r_value_1 = require("../../../../../eval/values/r-value");
30
31
  const unknown_side_effect_1 = require("../../../../../graph/unknown-side-effect");
31
32
  const alias_tracking_1 = require("../../../../../eval/resolve/alias-tracking");
32
33
  let sourceProvider = (0, retriever_1.requestProviderFromFile)();
34
+ function getSourceProvider() {
35
+ return sourceProvider;
36
+ }
33
37
  function setSourceProvider(provider) {
34
38
  sourceProvider = provider;
35
39
  }
@@ -17,6 +17,7 @@ const doc_dfg_1 = require("./doc-dfg");
17
17
  const doc_code_1 = require("./doc-code");
18
18
  const time_1 = require("../../util/text/time");
19
19
  const query_print_1 = require("../../queries/query-print");
20
+ const doc_cli_option_1 = require("./doc-cli-option");
20
21
  const config_1 = require("../../config");
21
22
  async function showQuery(shell, code, queries, { showCode, collapseResult, collapseQuery, addOutput = () => '' } = {}) {
22
23
  const now = performance.now();
@@ -24,7 +25,7 @@ async function showQuery(shell, code, queries, { showCode, collapseResult, colla
24
25
  parser: shell,
25
26
  request: (0, retriever_1.requestFromInput)(code)
26
27
  }, config_1.defaultConfigOptions).allRemainingSteps();
27
- const results = (0, query_1.executeQueries)({ dataflow: analysis.dataflow, ast: analysis.normalize, config: config_1.defaultConfigOptions }, queries);
28
+ const results = await Promise.resolve((0, query_1.executeQueries)({ dataflow: analysis.dataflow, ast: analysis.normalize, config: config_1.defaultConfigOptions }, queries));
28
29
  const duration = performance.now() - now;
29
30
  const metaInfo = `
30
31
  The analysis required _${(0, time_1.printAsMs)(duration)}_ (including parsing and normalization and the query) within the generation environment.
@@ -34,6 +35,15 @@ The analysis required _${(0, time_1.printAsMs)(duration)}_ (including parsing an
34
35
 
35
36
  ${(0, doc_code_1.codeBlock)('json', collapseQuery ? str.split('\n').join(' ').replace(/([{[])\s{2,}/g, '$1 ').replace(/\s{2,}([\]}])/g, ' $1') : str)}
36
37
 
38
+ ${(function () {
39
+ if (queries.length === 1 && Object.keys(queries[0]).length === 1) {
40
+ return `(This query can be shortened to \`@${queries[0].type}\` when used within the REPL command ${(0, doc_cli_option_1.getReplCommand)('query')}).`;
41
+ }
42
+ else {
43
+ return '';
44
+ }
45
+ })()}
46
+
37
47
  ${collapseResult ? ' <details> <summary style="color:gray">Show Results</summary>' : ''}
38
48
 
39
49
  _Results (prettified and summarized):_
@@ -53,13 +53,13 @@ ${(0, doc_code_1.codeBlock)('json', JSON.stringify(search, null, 2))}
53
53
  ${collapseResult ? ' <details> <summary style="color:gray">Show Results</summary>' : ''}
54
54
 
55
55
  The query returns the following vetices (all references to \`x\` in the code):
56
- ${result.map(({ node }) => `<b>${node.info.id} ('${(0, node_id_1.recoverContent)(node.info.id, analysis.dataflow.graph)}')</b> at L${(0, dfg_1.formatRange)(node.location)}`).join(', ')}
56
+ ${result.getElements().map(({ node }) => `<b>${node.info.id} ('${(0, node_id_1.recoverContent)(node.info.id, analysis.dataflow.graph)}')</b> at L${(0, dfg_1.formatRange)(node.location)}`).join(', ')}
57
57
 
58
58
  ${metaInfo}
59
59
 
60
60
  The returned results are highlighted thick and blue within the dataflow graph:
61
61
 
62
- ${await (0, doc_dfg_1.printDfGraphForCode)(shell, code, { showCode: false, switchCodeAndGraph: false, mark: new Set(result.map(({ node }) => node.info.id)) })}
62
+ ${await (0, doc_dfg_1.printDfGraphForCode)(shell, code, { showCode: false, switchCodeAndGraph: false, mark: new Set(result.getElements().map(({ node }) => node.info.id)) })}
63
63
 
64
64
 
65
65
  ${collapseResult ? '</details>' : ''}
@@ -224,8 +224,7 @@ ${Object.entries(control_flow_graph_1.CfgVertexType).map(([key, value]) => `- \`
224
224
  We use the ${(0, doc_types_1.shortLink)('CfgBasicBlockVertex', types.info)} to represent [basic blocks](#cfg-basic-blocks) and separate
225
225
  expressions (${(0, doc_types_1.shortLink)('CfgExpressionVertex', types.info)}) and statements (${(0, doc_types_1.shortLink)('CfgStatementVertex', types.info)})
226
226
  as control flow units with and without side effects (if you want to, you can see view statements as effectful expressions).
227
- The markers (${(0, doc_types_1.shortLink)('CfgMidMarkerVertex', types.info)} and ${(0, doc_types_1.shortLink)('CfgEndMarkerVertex', types.info)})
228
- indicate specific segments of larger expressions/statements (e.g., an \`if\` which has a condition and its branches).
227
+ The markers (${(0, doc_types_1.shortLink)('CfgEndMarkerVertex', types.info)}) indicate the end of larger expressions/statements.
229
228
 
230
229
  To signal these links, the expressions and statements contain information about the attached markers:
231
230
 
@@ -235,7 +234,7 @@ Similarly, the markers contain a link to their root:
235
234
 
236
235
  ${(0, doc_types_1.printHierarchy)({ info: types.info, root: 'CfgWithRoot', program: types.program, openTop: true })}
237
236
 
238
- In mermaid visualizations, we use rectangles for statements, rounded rectangles for expressions, circles for exit markers and double-lined rectangles for mid markers.
237
+ In mermaid visualizations, we use rectangles for statements, rounded rectangles for expressions and circles for exit markers.
239
238
  Blocks are visualized as boxes around the contained vertices.
240
239
 
241
240
  ${(0, doc_structure_1.block)({
@@ -554,7 +553,7 @@ Hence, you may rely on the corresponding exit point(s) to identify all exits of
554
553
 
555
554
  ${(0, doc_structure_1.block)({
556
555
  type: 'WARNING',
557
- content: 'Using basic blocks, this works just the same. However please keep in mind that the corresponding exit markers do not (and for control statements usually will not) be part of the same basic block.'
556
+ content: 'Using basic blocks, this works just the same. However, please keep in mind that the corresponding exit markers do not (and for control statements usually will not) be part of the same basic block.'
558
557
  })}
559
558
 
560
559
  `;
@@ -28,7 +28,6 @@ const built_in_access_1 = require("../dataflow/internal/process/functions/call/b
28
28
  const built_in_for_loop_1 = require("../dataflow/internal/process/functions/call/built-in/built-in-for-loop");
29
29
  const built_in_repeat_loop_1 = require("../dataflow/internal/process/functions/call/built-in/built-in-repeat-loop");
30
30
  const linker_1 = require("../dataflow/internal/linker");
31
- const static_slicer_1 = require("../slicing/static/static-slicer");
32
31
  const info_1 = require("../dataflow/info");
33
32
  const processor_1 = require("../dataflow/processor");
34
33
  const default_pipelines_1 = require("../core/steps/pipeline/default-pipelines");
@@ -42,6 +41,7 @@ const normalize_for_1 = require("../r-bridge/lang-4.x/ast/parser/main/internal/l
42
41
  const doc_issue_1 = require("./doc-util/doc-issue");
43
42
  const pipeline_executor_1 = require("../core/pipeline-executor");
44
43
  const pipeline_1 = require("../core/steps/pipeline/pipeline");
44
+ const static_slicer_1 = require("../slicing/static/static-slicer");
45
45
  const config_1 = require("../config");
46
46
  async function getText(shell) {
47
47
  const rversion = (await shell.usedRVersion())?.format() ?? 'unknown';
@@ -373,7 +373,7 @@ Of course, all of these endeavors work not just with the ${(0, doc_types_1.short
373
373
  The slicing is available as an extra step as you can see by inspecting he ${(0, doc_types_1.shortLink)('DEFAULT_SLICING_PIPELINE', info)}.
374
374
  Besides ${(0, doc_types_1.shortLink)('STATIC_SLICE', info)} it contains a ${(0, doc_types_1.shortLink)('NAIVE_RECONSTRUCT', info)} to print the slice as (executable) R code.
375
375
 
376
- Your main point of interesting here is the ${(0, doc_types_1.shortLink)(static_slicer_1.staticSlicing.name, info)} function which relies on a modified
376
+ Your main point of interesting here is the ${(0, doc_types_1.shortLink)(static_slicer_1.staticSlice.name, info)} function which relies on a modified
377
377
  breadth-first search to collect all nodes which are part of the slice.
378
378
  For more information on how the slicing works, please refer to the [tool demonstration (Section 3.2)](https://doi.org/10.1145/3691620.3695359),
379
379
  or the [original master's thesis (Chapter 4)](https://doi.org/10.18725/OPARU-50107).
@@ -835,6 +835,13 @@ The following sections present details on the different types of vertices and ed
835
835
  ${(0, doc_general_1.prefixLines)((0, doc_code_1.codeBlock)('ts', 'const node = graph.idMap.get(id);'), '> ')}
836
836
  > In case you just need the name (\`lexeme\`) of the respective vertex, ${(0, doc_types_1.shortLink)(node_id_1.recoverName.name, vertexType.info)} can help you out:
837
837
  ${(0, doc_general_1.prefixLines)((0, doc_code_1.codeBlock)('ts', `const name = ${node_id_1.recoverName.name}(id, graph.idMap);`), '> ')}
838
+ >
839
+ > Please note that not every node in the normalized AST is represented in the dataflow graph.
840
+ > For example, if the node is unreachable in a way that can be detected during the analysis and flowR
841
+ > is configured to ignore dead code. Likewise, empty argument wrappers do not have a corresponding
842
+ > dataflow graph vertex (as they are not relevant for the dataflow graph). It depends on the scenario what to do in such a case.
843
+ > For argument wrappers you can access the dataflow information for their value. For dead code, however, flowR currently contains
844
+ > some core heuristics that remove it which cannot be reversed easily. So please open [an issue](${doc_issue_1.NewIssueUrl}) if you encounter such a case and require the node to be present in the dataflow graph.
838
845
 
839
846
  ${(0, doc_structure_1.section)('Vertices', 2, 'vertices')}
840
847
 
@@ -39,6 +39,10 @@ With \`npm\` you have to pass arguments in a specific way. The \`--\` operator i
39
39
  ${(0, doc_code_1.codeBlock)('shell', 'npm run flowR -- --help')}
40
40
  `)}
41
41
 
42
+ ${qAndA('How to do logging in flowR?', `
43
+ Check out the [Logging Section in the Linting and Testing wiki page](${doc_files_1.FlowrWikiBaseRef}/Linting-and-Testing#logging) for more information on how to do logging in *flowR*.
44
+ `)}
45
+
42
46
  ## 🇷 R FAQ
43
47
 
44
48
  ### 📦 R Packages
@@ -182,6 +182,7 @@ The following summarizes the configuration options:
182
182
  - \`solver\`: allows to configure how _flowR_ resolves variables and their values (currently we support: ${Object.values(config_1.VariableResolve).map(v => `\`${v}\``).join(', ')}), as well as if pointer analysis should be active.
183
183
  - \`engines\`: allows to configure the engines used by _flowR_ to interact with R code. See the [Engines wiki page](${doc_files_1.FlowrWikiBaseRef}/Engines) for more information.
184
184
  - \`defaultEngine\`: allows to specify the default engine to use for interacting with R code. If not set, an arbitrary engine from the specified list will be used.
185
+ - \`abstractInterpretation\`: allows to configure how _flowR_ performs abstract interpretation, although we currently only support data frame shape inference through abstract interpretation.
185
186
 
186
187
  So you can configure _flowR_ by adding a file like the following:
187
188
 
@@ -214,6 +215,16 @@ ${(0, doc_code_1.codeBlock)('json', JSON.stringify({
214
215
  slicer: {
215
216
  threshold: 50
216
217
  }
218
+ },
219
+ abstractInterpretation: {
220
+ dataFrame: {
221
+ maxColNames: 20,
222
+ wideningThreshold: 4,
223
+ readLoadedData: {
224
+ readExternalFiles: true,
225
+ maxReadLines: 1_000_000
226
+ }
227
+ }
217
228
  }
218
229
  }, null, 2))}
219
230