@eagleoutice/flowr 2.2.7 → 2.2.9

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 (61) hide show
  1. package/README.md +7 -5
  2. package/cli/flowr-main-options.js +6 -0
  3. package/cli/flowr.d.ts +1 -0
  4. package/cli/flowr.js +2 -1
  5. package/cli/repl/server/compact.d.ts +2 -0
  6. package/cli/repl/server/compact.js +13 -0
  7. package/cli/repl/server/connection.js +10 -0
  8. package/cli/repl/server/messages/message-analysis.d.ts +21 -5
  9. package/cli/repl/server/messages/message-analysis.js +9 -2
  10. package/config.d.ts +53 -1
  11. package/config.js +45 -5
  12. package/dataflow/environments/built-in.js +1 -1
  13. package/dataflow/environments/environment.d.ts +4 -0
  14. package/dataflow/environments/environment.js +3 -3
  15. package/dataflow/environments/resolve-by-name.js +1 -1
  16. package/dataflow/extractor.js +12 -10
  17. package/dataflow/graph/dataflowgraph-builder.js +7 -7
  18. package/dataflow/graph/diff.js +1 -1
  19. package/dataflow/graph/graph.d.ts +3 -3
  20. package/dataflow/graph/graph.js +4 -4
  21. package/dataflow/graph/vertex.d.ts +1 -1
  22. package/dataflow/internal/process/functions/call/built-in/built-in-access.js +1 -1
  23. package/dataflow/internal/process/functions/call/built-in/built-in-apply.js +1 -1
  24. package/dataflow/internal/process/functions/call/built-in/built-in-expression-list.js +1 -1
  25. package/dataflow/internal/process/functions/call/built-in/built-in-function-definition.js +2 -2
  26. package/dataflow/internal/process/functions/call/built-in/built-in-pipe.js +10 -3
  27. package/dataflow/internal/process/functions/call/built-in/built-in-source.d.ts +11 -1
  28. package/dataflow/internal/process/functions/call/built-in/built-in-source.js +94 -16
  29. package/dataflow/internal/process/functions/call/common.js +1 -1
  30. package/dataflow/internal/process/functions/call/known-call-handling.js +1 -1
  31. package/dataflow/internal/process/functions/call/unnamed-call-handling.js +2 -3
  32. package/dataflow/internal/process/functions/process-argument.js +1 -1
  33. package/dataflow/internal/process/process-symbol.js +1 -1
  34. package/dataflow/internal/process/process-value.d.ts +1 -1
  35. package/dataflow/internal/process/process-value.js +6 -6
  36. package/dataflow/processor.d.ts +2 -2
  37. package/documentation/data/server/doc-data-server-messages.js +31 -0
  38. package/documentation/doc-util/doc-dfg.js +4 -7
  39. package/documentation/print-engines-wiki.js +1 -0
  40. package/documentation/print-interface-wiki.js +7 -1
  41. package/documentation/print-normalized-ast-wiki.js +3 -3
  42. package/documentation/print-readme.js +1 -1
  43. package/package.json +4 -3
  44. package/queries/catalog/dataflow-lens-query/dataflow-lens-query-executor.d.ts +3 -0
  45. package/queries/catalog/dataflow-lens-query/dataflow-lens-query-executor.js +29 -0
  46. package/queries/catalog/dataflow-lens-query/dataflow-lens-query-format.d.ts +72 -0
  47. package/queries/catalog/dataflow-lens-query/dataflow-lens-query-format.js +24 -0
  48. package/queries/query.d.ts +60 -1
  49. package/queries/query.js +2 -0
  50. package/r-bridge/lang-4.x/tree-sitter/tree-sitter-normalize.d.ts +5 -0
  51. package/r-bridge/lang-4.x/tree-sitter/tree-sitter-normalize.js +28 -7
  52. package/r-bridge/retriever.d.ts +3 -2
  53. package/r-bridge/retriever.js +26 -7
  54. package/slicing/static/static-slicer.js +2 -2
  55. package/util/mermaid/cfg.js +1 -1
  56. package/util/mermaid/dfg.d.ts +4 -3
  57. package/util/mermaid/dfg.js +13 -10
  58. package/util/objects.d.ts +2 -2
  59. package/util/simple-df/dfg-view.d.ts +16 -0
  60. package/util/simple-df/dfg-view.js +64 -0
  61. package/util/version.js +1 -1
@@ -51,7 +51,7 @@ function processNextExpression(currentElement, environment, listEnvironments, re
51
51
  }
52
52
  function updateSideEffectsForCalledFunctions(calledEnvs, inputEnvironment, nextGraph) {
53
53
  for (const { functionCall, called } of calledEnvs) {
54
- const callDependencies = nextGraph.getVertex(functionCall, true)?.controlDependencies;
54
+ const callDependencies = nextGraph.getVertex(functionCall, true)?.cds;
55
55
  for (const calledFn of called) {
56
56
  (0, assert_1.guard)(calledFn.tag === vertex_1.VertexType.FunctionDefinition, 'called function must be a function definition');
57
57
  // only merge the environments they have in common
@@ -68,7 +68,7 @@ function processFunctionDefinition(name, args, rootId, data) {
68
68
  tag: vertex_1.VertexType.Use,
69
69
  id: read.nodeId,
70
70
  environment: undefined,
71
- controlDependencies: undefined
71
+ cds: undefined
72
72
  });
73
73
  }
74
74
  }
@@ -87,7 +87,7 @@ function processFunctionDefinition(name, args, rootId, data) {
87
87
  tag: vertex_1.VertexType.FunctionDefinition,
88
88
  id: name.info.id,
89
89
  environment: (0, scoping_1.popLocalEnvironment)(outEnvironment),
90
- controlDependencies: data.controlDependencies,
90
+ cds: data.controlDependencies,
91
91
  subflow: flow,
92
92
  exitPoints: exitPoints?.filter(e => e.type === 1 /* ExitPointType.Return */ || e.type === 0 /* ExitPointType.Default */).map(e => e.nodeId) ?? []
93
93
  });
@@ -10,7 +10,7 @@ const vertex_1 = require("../../../../../graph/vertex");
10
10
  const edge_1 = require("../../../../../graph/edge");
11
11
  const identifier_1 = require("../../../../../environments/identifier");
12
12
  function processPipe(name, args, rootId, data) {
13
- const { information } = (0, known_call_handling_1.processKnownFunctionCall)({ name, args, rootId, data });
13
+ const { information, processedArguments } = (0, known_call_handling_1.processKnownFunctionCall)({ name, args, rootId, data });
14
14
  if (args.length !== 2) {
15
15
  logger_1.dataflowLogger.warn(`Pipe ${name.content} has something else than 2 arguments, skipping`);
16
16
  return information;
@@ -32,8 +32,15 @@ function processPipe(name, args, rootId, data) {
32
32
  controlDependencies: data.controlDependencies,
33
33
  type: identifier_1.ReferenceType.Function
34
34
  });
35
- information.graph.addEdge(functionCallNode.id, argId, edge_1.EdgeType.Argument);
35
+ information.graph.addEdge(functionCallNode.id, argId, edge_1.EdgeType.Argument | edge_1.EdgeType.Reads);
36
36
  }
37
- return information;
37
+ const firstArgument = processedArguments[0];
38
+ return {
39
+ ...information,
40
+ in: [...information.in, ...firstArgument.in],
41
+ out: [...information.out, ...firstArgument.out],
42
+ unknownReferences: [...information.unknownReferences, ...firstArgument.unknownReferences],
43
+ entryPoint: rootId
44
+ };
38
45
  }
39
46
  //# sourceMappingURL=built-in-pipe.js.map
@@ -1,12 +1,22 @@
1
1
  import { type DataflowProcessorInformation } from '../../../../../processor';
2
2
  import type { DataflowInformation } from '../../../../../info';
3
- import type { RParseRequestProvider, RParseRequest } from '../../../../../../r-bridge/retriever';
3
+ import { InferWorkingDirectory } from '../../../../../../config';
4
+ import type { RParseRequest, RParseRequestProvider } from '../../../../../../r-bridge/retriever';
4
5
  import type { IdGenerator, ParentInformation } from '../../../../../../r-bridge/lang-4.x/ast/model/processing/decorate';
5
6
  import type { RFunctionArgument } from '../../../../../../r-bridge/lang-4.x/ast/model/nodes/r-function-call';
6
7
  import type { RSymbol } from '../../../../../../r-bridge/lang-4.x/ast/model/nodes/r-symbol';
7
8
  import type { NodeId } from '../../../../../../r-bridge/lang-4.x/ast/model/processing/node-id';
8
9
  import type { NoInfo } from '../../../../../../r-bridge/lang-4.x/ast/model/model';
9
10
  export declare function setSourceProvider(provider: RParseRequestProvider): void;
11
+ export declare function inferWdFromScript(option: InferWorkingDirectory, referenceChain: readonly RParseRequest[]): string[];
12
+ /**
13
+ * Tries to find sourced by a source request and returns the first path that exists
14
+ * @param seed - the path originally requested in the `source` call
15
+ * @param data - more information on the loading context
16
+ */
17
+ export declare function findSource(seed: string, data: {
18
+ referenceChain: readonly RParseRequest[];
19
+ }): string[] | undefined;
10
20
  export declare function processSourceCall<OtherInfo>(name: RSymbol<OtherInfo & ParentInformation>, args: readonly RFunctionArgument<OtherInfo & ParentInformation>[], rootId: NodeId, data: DataflowProcessorInformation<OtherInfo & ParentInformation>, config: {
11
21
  /** should this produce an explicit source function call in the graph? */
12
22
  includeFunctionCall?: boolean;
@@ -4,6 +4,8 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.setSourceProvider = setSourceProvider;
7
+ exports.inferWdFromScript = inferWdFromScript;
8
+ exports.findSource = findSource;
7
9
  exports.processSourceCall = processSourceCall;
8
10
  exports.sourceRequest = sourceRequest;
9
11
  exports.standaloneSourceFile = standaloneSourceFile;
@@ -23,10 +25,83 @@ const parser_1 = require("../../../../../../r-bridge/lang-4.x/ast/parser/json/pa
23
25
  const shell_executor_1 = require("../../../../../../r-bridge/shell-executor");
24
26
  const resolve_by_name_1 = require("../../../../../environments/resolve-by-name");
25
27
  const assert_1 = require("../../../../../../util/assert");
28
+ const path_1 = __importDefault(require("path"));
26
29
  let sourceProvider = (0, retriever_1.requestProviderFromFile)();
27
30
  function setSourceProvider(provider) {
28
31
  sourceProvider = provider;
29
32
  }
33
+ function inferWdFromScript(option, referenceChain) {
34
+ switch (option) {
35
+ case config_1.InferWorkingDirectory.MainScript:
36
+ return referenceChain[0]?.request === 'file' ? [platformDirname(referenceChain[0].content)] : [];
37
+ case config_1.InferWorkingDirectory.ActiveScript:
38
+ return referenceChain[referenceChain.length - 1] ? [platformDirname(referenceChain[referenceChain.length - 1].content)] : [];
39
+ case config_1.InferWorkingDirectory.AnyScript:
40
+ return referenceChain.filter(e => e.request === 'file').map(e => platformDirname(e.content));
41
+ case config_1.InferWorkingDirectory.No:
42
+ default:
43
+ return [];
44
+ }
45
+ }
46
+ const AnyPathSeparator = /[/\\]/g;
47
+ function platformBasename(p) {
48
+ const normalized = p.replaceAll(path_1.default.win32.sep, path_1.default.posix.sep);
49
+ return path_1.default.posix.basename(normalized);
50
+ }
51
+ function platformDirname(p) {
52
+ const normalized = p.replaceAll(path_1.default.win32.sep, path_1.default.posix.sep);
53
+ return path_1.default.posix.dirname(normalized);
54
+ }
55
+ function returnPlatformPath(p) {
56
+ return p.replaceAll(AnyPathSeparator, path_1.default.sep);
57
+ }
58
+ /**
59
+ * Tries to find sourced by a source request and returns the first path that exists
60
+ * @param seed - the path originally requested in the `source` call
61
+ * @param data - more information on the loading context
62
+ */
63
+ function findSource(seed, data) {
64
+ const config = (0, config_1.getConfig)().solver.resolveSource;
65
+ const capitalization = config?.ignoreCapitalization ?? false;
66
+ const explorePaths = [
67
+ ...(config?.searchPath ?? []),
68
+ ...(inferWdFromScript(config?.inferWorkingDirectory ?? config_1.InferWorkingDirectory.No, data.referenceChain))
69
+ ];
70
+ const tryPaths = [seed];
71
+ switch (config?.dropPaths ?? config_1.DropPathsOption.No) {
72
+ case config_1.DropPathsOption.Once: {
73
+ const first = platformBasename(seed);
74
+ tryPaths.push(first);
75
+ break;
76
+ }
77
+ case config_1.DropPathsOption.All: {
78
+ const paths = platformDirname(seed).split(AnyPathSeparator);
79
+ const basename = platformBasename(seed);
80
+ if (paths.length === 1 && paths[0] === '.') {
81
+ break;
82
+ }
83
+ for (let i = 0; i < paths.length; i++) {
84
+ tryPaths.push(path_1.default.join(...paths.slice(i), basename));
85
+ }
86
+ break;
87
+ }
88
+ default:
89
+ case config_1.DropPathsOption.No:
90
+ break;
91
+ }
92
+ const found = [];
93
+ for (const explore of [undefined, ...explorePaths]) {
94
+ for (const tryPath of tryPaths) {
95
+ const effectivePath = explore ? path_1.default.join(explore, tryPath) : tryPath;
96
+ const get = sourceProvider.exists(effectivePath, capitalization) ?? sourceProvider.exists(returnPlatformPath(effectivePath), capitalization);
97
+ if (get && !found.includes(effectivePath)) {
98
+ found.push(returnPlatformPath(effectivePath));
99
+ }
100
+ }
101
+ }
102
+ log_1.log.info(`Found sourced file ${JSON.stringify(seed)} at ${JSON.stringify(found)}`);
103
+ return found;
104
+ }
30
105
  function processSourceCall(name, args, rootId, data, config) {
31
106
  const information = config.includeFunctionCall ?
32
107
  (0, known_call_handling_1.processKnownFunctionCall)({ name, args, rootId, data }).information
@@ -53,20 +128,24 @@ function processSourceCall(name, args, rootId, data, config) {
53
128
  }
54
129
  if (sourceFile && sourceFile.length === 1) {
55
130
  const path = (0, retriever_1.removeRQuotes)(sourceFile[0]);
56
- const request = sourceProvider.createRequest(path);
57
- // check if the sourced file has already been dataflow analyzed, and if so, skip it
58
- if (data.referenceChain.includes((0, retriever_1.requestFingerprint)(request))) {
59
- (0, log_1.expensiveTrace)(logger_1.dataflowLogger, () => `Found loop in dataflow analysis for ${JSON.stringify(request)}: ${JSON.stringify(data.referenceChain)}, skipping further dataflow analysis`);
60
- information.graph.markIdForUnknownSideEffects(rootId);
61
- return information;
131
+ let filepath = path ? findSource(path, data) : path;
132
+ if (Array.isArray(filepath)) {
133
+ filepath = filepath?.[0];
134
+ }
135
+ if (filepath !== undefined) {
136
+ const request = sourceProvider.createRequest(filepath);
137
+ // check if the sourced file has already been dataflow analyzed, and if so, skip it
138
+ if (data.referenceChain.find(e => e.request === request.request && e.content === request.content)) {
139
+ (0, log_1.expensiveTrace)(logger_1.dataflowLogger, () => `Found loop in dataflow analysis for ${JSON.stringify(request)}: ${JSON.stringify(data.referenceChain)}, skipping further dataflow analysis`);
140
+ information.graph.markIdForUnknownSideEffects(rootId);
141
+ return information;
142
+ }
143
+ return sourceRequest(rootId, request, data, information, (0, decorate_1.sourcedDeterministicCountingIdGenerator)(path, name.location));
62
144
  }
63
- return sourceRequest(rootId, request, data, information, (0, decorate_1.sourcedDeterministicCountingIdGenerator)(path, name.location));
64
- }
65
- else {
66
- (0, log_1.expensiveTrace)(logger_1.dataflowLogger, () => `Non-constant argument ${JSON.stringify(sourceFile)} for source is currently not supported, skipping`);
67
- information.graph.markIdForUnknownSideEffects(rootId);
68
- return information;
69
145
  }
146
+ (0, log_1.expensiveTrace)(logger_1.dataflowLogger, () => `Non-constant argument ${JSON.stringify(sourceFile)} for source is currently not supported, skipping`);
147
+ information.graph.markIdForUnknownSideEffects(rootId);
148
+ return information;
70
149
  }
71
150
  function sourceRequest(rootId, request, data, information, getId) {
72
151
  if (request.request === 'file') {
@@ -89,7 +168,7 @@ function sourceRequest(rootId, request, data, information, getId) {
89
168
  ...data,
90
169
  currentRequest: request,
91
170
  environment: information.environment,
92
- referenceChain: [...data.referenceChain, (0, retriever_1.requestFingerprint)(request)]
171
+ referenceChain: [...data.referenceChain, request]
93
172
  });
94
173
  }
95
174
  catch (e) {
@@ -118,9 +197,8 @@ function standaloneSourceFile(inputRequest, data, uniqueSourceId, information) {
118
197
  const path = inputRequest.request === 'file' ? inputRequest.content : '-inline-';
119
198
  /* this way we can still pass content */
120
199
  const request = inputRequest.request === 'file' ? sourceProvider.createRequest(inputRequest.content) : inputRequest;
121
- const fingerprint = (0, retriever_1.requestFingerprint)(request);
122
200
  // check if the sourced file has already been dataflow analyzed, and if so, skip it
123
- if (data.referenceChain.includes(fingerprint)) {
201
+ if (data.referenceChain.find(e => e.request === request.request && e.content === request.content)) {
124
202
  logger_1.dataflowLogger.info(`Found loop in dataflow analysis for ${JSON.stringify(request)}: ${JSON.stringify(data.referenceChain)}, skipping further dataflow analysis`);
125
203
  information.graph.markIdForUnknownSideEffects(uniqueSourceId);
126
204
  return information;
@@ -129,7 +207,7 @@ function standaloneSourceFile(inputRequest, data, uniqueSourceId, information) {
129
207
  ...data,
130
208
  currentRequest: request,
131
209
  environment: information.environment,
132
- referenceChain: [...data.referenceChain, fingerprint]
210
+ referenceChain: [...data.referenceChain, inputRequest]
133
211
  }, information, (0, decorate_1.deterministicPrefixIdGenerator)(path + '@' + uniqueSourceId));
134
212
  }
135
213
  //# sourceMappingURL=built-in-source.js.map
@@ -109,7 +109,7 @@ function patchFunctionCall({ nextGraph, rootId, name, data, argumentProcessResul
109
109
  environment: data.environment,
110
110
  /* will be overwritten accordingly */
111
111
  onlyBuiltin: false,
112
- controlDependencies: data.controlDependencies,
112
+ cds: data.controlDependencies,
113
113
  args: argumentProcessResult.map(arg => arg === undefined ? r_function_call_1.EmptyArgument : { nodeId: arg.entryPoint, controlDependencies: undefined, call: undefined, type: identifier_1.ReferenceType.Argument }),
114
114
  });
115
115
  for (const arg of argumentProcessResult) {
@@ -40,7 +40,7 @@ function processKnownFunctionCall({ name, args, rootId, data, reverseOrder = fal
40
40
  name: functionCallName,
41
41
  /* will be overwritten accordingly */
42
42
  onlyBuiltin: false,
43
- controlDependencies: data.controlDependencies,
43
+ cds: data.controlDependencies,
44
44
  args: reverseOrder ? [...callArgs].reverse() : callArgs,
45
45
  indicesCollection: indicesCollection,
46
46
  });
@@ -20,8 +20,7 @@ function processUnnamedFunctionCall(functionCall, data) {
20
20
  const functionCallName = `${exports.UnnamedFunctionCallPrefix}${functionRootId}`;
21
21
  logger_1.dataflowLogger.debug(`Using ${functionRootId} as root for the unnamed function call`);
22
22
  // we know that it calls the toplevel:
23
- finalGraph.addEdge(functionRootId, calledRootId, edge_1.EdgeType.Calls);
24
- finalGraph.addEdge(functionRootId, calledRootId, edge_1.EdgeType.Reads);
23
+ finalGraph.addEdge(functionRootId, calledRootId, edge_1.EdgeType.Calls | edge_1.EdgeType.Reads);
25
24
  // keep the defined function
26
25
  finalGraph.mergeWith(calledFunction.graph);
27
26
  const { finalEnv, callArgs, remainingReadInArgs } = (0, common_1.processAllArguments)({
@@ -39,7 +38,7 @@ function processUnnamedFunctionCall(functionCall, data) {
39
38
  name: functionCallName,
40
39
  /* can never be a direct built-in-call */
41
40
  onlyBuiltin: false,
42
- controlDependencies: data.controlDependencies,
41
+ cds: data.controlDependencies,
43
42
  args: callArgs // same reference
44
43
  });
45
44
  const inIds = remainingReadInArgs;
@@ -27,7 +27,7 @@ function processFunctionArgument(argument, data) {
27
27
  graph.addVertex({
28
28
  tag: vertex_1.VertexType.Use,
29
29
  id: argument.info.id,
30
- controlDependencies: data.controlDependencies
30
+ cds: data.controlDependencies
31
31
  });
32
32
  entryPoint = argument.info.id;
33
33
  }
@@ -18,7 +18,7 @@ function processSymbol(symbol, data) {
18
18
  graph: new graph_1.DataflowGraph(data.completeAst.idMap).addVertex({
19
19
  tag: vertex_1.VertexType.Use,
20
20
  id: symbol.info.id,
21
- controlDependencies: data.controlDependencies
21
+ cds: data.controlDependencies
22
22
  }),
23
23
  entryPoint: symbol.info.id,
24
24
  exitPoints: [{ nodeId: symbol.info.id, type: 0 /* ExitPointType.Default */, controlDependencies: data.controlDependencies }]
@@ -1,4 +1,4 @@
1
1
  import { type DataflowInformation } from '../../info';
2
2
  import type { DataflowProcessorInformation } from '../../processor';
3
3
  import type { RNodeWithParent } from '../../../r-bridge/lang-4.x/ast/model/processing/decorate';
4
- export declare function processValue<OtherInfo>(value: RNodeWithParent, data: DataflowProcessorInformation<OtherInfo>): DataflowInformation;
4
+ export declare function processValue<OtherInfo>({ info: { id } }: RNodeWithParent, data: DataflowProcessorInformation<OtherInfo>): DataflowInformation;
@@ -4,19 +4,19 @@ exports.processValue = processValue;
4
4
  const graph_1 = require("../../graph/graph");
5
5
  const vertex_1 = require("../../graph/vertex");
6
6
  const identifier_1 = require("../../environments/identifier");
7
- function processValue(value, data) {
7
+ function processValue({ info: { id } }, data) {
8
8
  return {
9
9
  unknownReferences: [],
10
- in: [{ nodeId: value.info.id, name: undefined, controlDependencies: data.controlDependencies, type: identifier_1.ReferenceType.Constant }],
10
+ in: [{ nodeId: id, name: undefined, controlDependencies: data.controlDependencies, type: identifier_1.ReferenceType.Constant }],
11
11
  out: [],
12
12
  environment: data.environment,
13
13
  graph: new graph_1.DataflowGraph(data.completeAst.idMap).addVertex({
14
14
  tag: vertex_1.VertexType.Value,
15
- id: value.info.id,
16
- controlDependencies: data.controlDependencies
15
+ id: id,
16
+ cds: data.controlDependencies
17
17
  }),
18
- exitPoints: [{ nodeId: value.info.id, type: 0 /* ExitPointType.Default */, controlDependencies: data.controlDependencies }],
19
- entryPoint: value.info.id
18
+ exitPoints: [{ nodeId: id, type: 0 /* ExitPointType.Default */, controlDependencies: data.controlDependencies }],
19
+ entryPoint: id
20
20
  };
21
21
  }
22
22
  //# sourceMappingURL=process-value.js.map
@@ -27,10 +27,10 @@ export interface DataflowProcessorInformation<OtherInfo> {
27
27
  */
28
28
  readonly currentRequest: RParseRequest;
29
29
  /**
30
- * The chain of {@link RParseRequests} fingerprints ({@link requestFingerprint}) that lead to the {@link currentRequest}.
30
+ * The chain of {@link RParseRequests} that lead to the {@link currentRequest}.
31
31
  * The most recent (last) entry is expected to always be the {@link currentRequest}.
32
32
  */
33
- readonly referenceChain: string[];
33
+ readonly referenceChain: RParseRequest[];
34
34
  /**
35
35
  * The chain of control-flow {@link NodeId}s that lead to the current node (e.g., of known ifs).
36
36
  */
@@ -195,6 +195,37 @@ ${await (0, doc_server_message_1.documentServerMessageResponse)({
195
195
  Please note, that the base message format is still JSON. Only the individual results get converted.
196
196
  While the context is derived from the \`filename\`, we currently offer no way to customize other parts of the quads
197
197
  (please open a [new issue](${doc_issue_1.NewIssueUrl}) if you require this).
198
+
199
+ `
200
+ }]
201
+ })}
202
+
203
+ <a id="analysis-format-compact"></a>
204
+ **Retrieve the Output in a compactedForm**
205
+
206
+ The default response is formatted as JSON. But this can get very big quickly.
207
+ By specifying \`format: "compact"\`, you can retrieve the results heavily compacted (using [msgpack](https://www.npmjs.com/package/@msgpack/msgpack)).
208
+ This works with and without the control flow graph as described [above](#analysis-include-cfg).
209
+
210
+ ${await (0, doc_server_message_1.documentServerMessageResponse)({
211
+ shell,
212
+ title: 'Requesting Compacted Results',
213
+ messages: [{
214
+ type: 'request',
215
+ message: {
216
+ type: 'request-file-analysis',
217
+ id: '1',
218
+ filetoken: 'x',
219
+ content: 'x <- 1\nx + 1',
220
+ format: 'compact',
221
+ cfg: true
222
+ },
223
+ mark: true
224
+ }, {
225
+ type: 'response',
226
+ expectedType: 'response-file-analysis',
227
+ description: `
228
+ Please note, that the base message format is still JSON. Only the individual results are printed as binary objects.
198
229
  `
199
230
  }]
200
231
  })}
@@ -14,16 +14,15 @@ const diff_1 = require("../../dataflow/graph/diff");
14
14
  const assert_1 = require("../../util/assert");
15
15
  const time_1 = require("../../util/time");
16
16
  const doc_files_1 = require("./doc-files");
17
+ const doc_code_1 = require("./doc-code");
17
18
  function printDfGraph(graph, mark, simplified = false) {
18
19
  return `
19
- \`\`\`mermaid
20
- ${(0, dfg_1.graphToMermaid)({
20
+ ${(0, doc_code_1.codeBlock)('mermaid', (0, dfg_1.graphToMermaid)({
21
21
  graph,
22
22
  prefix: 'flowchart LR',
23
23
  mark,
24
24
  simplified
25
- }).string}
26
- \`\`\`
25
+ }).string)}
27
26
  `;
28
27
  }
29
28
  function formatSideEffect(ef) {
@@ -48,9 +47,7 @@ async function printDfGraphForCode(parser, code, { simplified = false, mark, sho
48
47
  const simplyText = simplified ? '(simplified) ' : '';
49
48
  let resultText = '\n\n';
50
49
  if (showCode) {
51
- const codeText = `\`\`\`r
52
- ${code}
53
- \`\`\``;
50
+ const codeText = (0, doc_code_1.codeBlock)('r', code);
54
51
  resultText += switchCodeAndGraph ? codeText : dfGraph;
55
52
  resultText += `
56
53
  <details${codeOpen ? ' open' : ''}>
@@ -39,6 +39,7 @@ are exposed with some command line options (e.g., when using the docker image of
39
39
  - ${(0, doc_cli_option_1.getCliLongOptionOf)('flowr', 'engine.r-shell.disabled', false)} to disable the ${(0, doc_types_1.shortLink)(shell_1.RShell.name, types.info)} engine
40
40
  - ${(0, doc_cli_option_1.getCliLongOptionOf)('flowr', 'engine.r-shell.r-path', false)} (which is the canonical version of ${(0, doc_cli_option_1.getCliLongOptionOf)('flowr', 'r-path')})
41
41
  - ${(0, doc_cli_option_1.getCliLongOptionOf)('flowr', 'engine.tree-sitter.disabled', false)} to disable the ${(0, doc_types_1.shortLink)(tree_sitter_executor_1.TreeSitterExecutor.name, types.info)} engine
42
+ - ${(0, doc_cli_option_1.getCliLongOptionOf)('flowr', 'engine.tree-sitter.lax', false)} to use lax parsing with tree-sitter
42
43
  - ${(0, doc_cli_option_1.getCliLongOptionOf)('flowr', 'engine.tree-sitter.wasm-path', false)} pass the path to the wasm of the r grammar of tree-sitter (see [below](#tree-sitter))
43
44
  - ${(0, doc_cli_option_1.getCliLongOptionOf)('flowr', 'engine.tree-sitter.tree-sitter-wasm-path', false)} pass the path to the wasm of tree-sitter (see [below](#tree-sitter))
44
45
  - ${(0, doc_cli_option_1.getCliLongOptionOf)('flowr', 'default-engine', false)} to set the default engine to use
@@ -203,7 +203,13 @@ ${(0, doc_code_1.codeBlock)('json', JSON.stringify({
203
203
  engines: [{ type: 'r-shell' }],
204
204
  solver: {
205
205
  variables: config_1.VariableResolve.Alias,
206
- pointerTracking: true
206
+ pointerTracking: true,
207
+ resolveSource: {
208
+ dropPaths: config_1.DropPathsOption.No,
209
+ ignoreCapitalization: true,
210
+ inferWorkingDirectory: config_1.InferWorkingDirectory.ActiveScript,
211
+ searchPath: []
212
+ }
207
213
  }
208
214
  }, null, 2))}
209
215
 
@@ -86,10 +86,10 @@ ${(0, doc_structure_1.details)('Normalized AST Node Types', (0, doc_types_1.prin
86
86
 
87
87
  The following segments intend to give you an overview of how to work with the normalized AST:
88
88
 
89
- * [How to get a normalized AST](#how-get-a-normalized-ast)
89
+ * [How to get a Normalized AST](#how-to-get-a-normalized-ast)
90
90
  * [Visitors and Folds](#visitors-and-folds)
91
91
 
92
- ## How Get a Normalized AST
92
+ ## How to Get a Normalized AST
93
93
 
94
94
  As explained alongside the [Interface](${doc_files_1.FlowrWikiBaseRef}/Interface#the-pipeline-executor) wiki page, you can use the
95
95
  ${(0, doc_types_1.shortLink)(pipeline_executor_1.PipelineExecutor.name, types.info)} to get the ${(0, doc_types_1.shortLink)('NormalizedAst', types.info)}. If you are only interested in the normalization,
@@ -115,7 +115,7 @@ We provide two ways to traverse the normalized AST: [Visitors](#visitors) and [F
115
115
  If you want a simple visitor which traverses the AST, the ${(0, doc_types_1.shortLink)(visitor_1.visitAst.name, types.info)} function is a good starting point.
116
116
  You may specify functions to be called whenever you enter and exit a node during the traversal, and any
117
117
  computation is to be done by side effects.
118
- For example, if you want to collect all the \`id\`s present within a normalized (sub-)ast,
118
+ For example, if you want to collect all the \`id\`s present within a normalized (sub-)AST,
119
119
  as it is done by the ${(0, doc_types_1.shortLink)(collect_1.collectAllIds.name, types.info)} function, you can use the following visitor:
120
120
 
121
121
  ${(0, doc_code_1.codeBlock)('ts', `
@@ -65,7 +65,7 @@ The following showcases the dependency view of the [Visual Studio Code extension
65
65
  `), ' ')}
66
66
 
67
67
  * 🚀 **fast data- and control-flow graphs**\\
68
- Within just ${'<i>' + (0, html_hover_over_1.textWithTooltip)((0, numbers_1.roundToDecimals)(await (0, doc_benchmarks_1.getLatestDfAnalysisTime)('"social-science" Benchmark Suite (tree-sitter)'), 1) + ' ms</i>', 'This measurement is automatically fetched from the latest benchmark!')} (as of ${new Date(await (0, doc_benchmarks_1.getLastBenchmarkUpdate)()).toLocaleDateString('en-US', dateOptions)}),
68
+ Within just ${'<i>' + (0, html_hover_over_1.textWithTooltip)((0, numbers_1.roundToDecimals)(await (0, doc_benchmarks_1.getLatestDfAnalysisTime)('"social-science" Benchmark Suite (tree-sitter)'), 1) + ' ms', 'This measurement is automatically fetched from the latest benchmark!') + '</i>'} (as of ${new Date(await (0, doc_benchmarks_1.getLastBenchmarkUpdate)()).toLocaleDateString('en-US', dateOptions)}),
69
69
  _flowR_ can analyze the data- and control-flow of the average real-world R script. See the [benchmarks](https://flowr-analysis.github.io/flowr/wiki/stats/benchmark) for more information,
70
70
  and consult the [wiki pages](${doc_files_1.FlowrWikiBaseRef}/Dataflow-Graph) for more details on the dataflow graph.
71
71
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@eagleoutice/flowr",
3
- "version": "2.2.7",
3
+ "version": "2.2.9",
4
4
  "description": "Static Dataflow Analyzer and Program Slicer for the R Programming Language",
5
5
  "types": "dist/src/index.d.ts",
6
6
  "repository": {
@@ -184,7 +184,7 @@
184
184
  "@types/tmp": "^0.2.6",
185
185
  "@types/ws": "^8.5.14",
186
186
  "@typescript-eslint/eslint-plugin": "^8.24.0",
187
- "@vitest/coverage-v8": "^3.0.5",
187
+ "@vitest/coverage-v8": "^3.0.6",
188
188
  "esbuild": "^0.25.0",
189
189
  "eslint": "^9.20.1",
190
190
  "license-checker": "^25.0.1",
@@ -196,9 +196,10 @@
196
196
  "typedoc-theme-hierarchy": "^5.0.4",
197
197
  "typedoc-umlclass": "^0.10.1",
198
198
  "typescript": "^5.7.3",
199
- "vitest": "^3.0.5"
199
+ "vitest": "^3.0.6"
200
200
  },
201
201
  "dependencies": {
202
+ "@msgpack/msgpack": "^3.0.1",
202
203
  "@xmldom/xmldom": "^0.9.7",
203
204
  "clipboardy": "^4.0.0",
204
205
  "command-line-args": "^6.0.1",
@@ -0,0 +1,3 @@
1
+ import type { DataflowLensQuery, DataflowLensQueryResult } from './dataflow-lens-query-format';
2
+ import type { BasicQueryData } from '../../base-query-format';
3
+ export declare function executeDataflowLensQuery({ dataflow: { graph } }: BasicQueryData, queries: readonly DataflowLensQuery[]): DataflowLensQueryResult;
@@ -0,0 +1,29 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.executeDataflowLensQuery = executeDataflowLensQuery;
4
+ const log_1 = require("../../../util/log");
5
+ const dfg_view_1 = require("../../../util/simple-df/dfg-view");
6
+ const vertex_1 = require("../../../dataflow/graph/vertex");
7
+ function executeDataflowLensQuery({ dataflow: { graph } }, queries) {
8
+ if (queries.length !== 1) {
9
+ log_1.log.warn('Dataflow query expects only up to one query, but got', queries.length);
10
+ }
11
+ const now = Date.now();
12
+ const simplifiedGraph = (0, dfg_view_1.reduceDfg)(graph, {
13
+ vertices: {
14
+ keepEnv: false,
15
+ keepCd: true,
16
+ tags: [vertex_1.VertexType.Use, vertex_1.VertexType.VariableDefinition, vertex_1.VertexType.FunctionDefinition, vertex_1.VertexType.FunctionCall],
17
+ nameRegex: '<-|<<-|->|->>|=|+|-|*|/|\\|>|function|repeat|if|next|break',
18
+ blacklistWithName: true
19
+ }
20
+ });
21
+ const timing = Date.now() - now;
22
+ return {
23
+ '.meta': {
24
+ timing
25
+ },
26
+ simplifiedGraph
27
+ };
28
+ }
29
+ //# sourceMappingURL=dataflow-lens-query-executor.js.map
@@ -0,0 +1,72 @@
1
+ import type { BaseQueryFormat, BaseQueryResult } from '../../base-query-format';
2
+ import type { DataflowGraph } from '../../../dataflow/graph/graph';
3
+ import { executeDataflowLensQuery } from './dataflow-lens-query-executor';
4
+ import Joi from 'joi';
5
+ /**
6
+ * Returns a simplified view on the dataflow graph of the analysis
7
+ */
8
+ export interface DataflowLensQuery extends BaseQueryFormat {
9
+ readonly type: 'dataflow-lens';
10
+ }
11
+ export interface DataflowLensQueryResult extends BaseQueryResult {
12
+ /** This is the simplified dataflow graph */
13
+ readonly simplifiedGraph: DataflowGraph;
14
+ }
15
+ export declare const DataflowLensQueryDefinition: {
16
+ readonly executor: typeof executeDataflowLensQuery;
17
+ readonly asciiSummarizer: (formatter: import("../../../util/ansi").OutputFormatter, _processed: import("../../../core/steps/pipeline/pipeline").PipelineOutput<import("../../../core/steps/pipeline/pipeline").Pipeline<{
18
+ readonly name: "parse";
19
+ readonly humanReadableName: "parse with R shell";
20
+ readonly description: "Parse the given R code into an AST";
21
+ readonly processor: (_results: unknown, input: Partial<import("../../../r-bridge/parser").ParseRequiredInput<string>>) => Promise<import("../../../r-bridge/parser").ParseStepOutput<string>>;
22
+ readonly executed: import("../../../core/steps/pipeline-step").PipelineStepStage.OncePerFile;
23
+ readonly printer: {
24
+ readonly 0: typeof import("../../../core/print/print").internalPrinter;
25
+ readonly 2: {
26
+ (value: any, replacer?: (this: any, key: string, value: any) => any, space?: string | number): string;
27
+ (value: any, replacer?: (number | string)[] | null, space?: string | number): string;
28
+ };
29
+ readonly 5: ({ parsed }: import("../../../r-bridge/parser").ParseStepOutput<string>, config: import("../../../util/quads").QuadSerializationConfiguration) => string;
30
+ };
31
+ readonly dependencies: readonly [];
32
+ readonly requiredInput: import("../../../r-bridge/parser").ParseRequiredInput<string>;
33
+ } | {
34
+ readonly name: "normalize";
35
+ readonly humanReadableName: "normalize";
36
+ readonly description: "Normalize the AST to flowR's AST";
37
+ readonly processor: (results: {
38
+ parse?: import("../../../r-bridge/parser").ParseStepOutput<string>;
39
+ }, input: Partial<import("../../../core/steps/all/core/10-normalize").NormalizeRequiredInput>) => import("../../../r-bridge/lang-4.x/ast/model/processing/decorate").NormalizedAst<import("../../../r-bridge/lang-4.x/ast/model/processing/decorate").ParentInformation, import("../../../r-bridge/lang-4.x/ast/model/model").RNode<import("../../../r-bridge/lang-4.x/ast/model/processing/decorate").ParentInformation>>;
40
+ readonly executed: import("../../../core/steps/pipeline-step").PipelineStepStage.OncePerFile;
41
+ readonly printer: {
42
+ readonly 0: typeof import("../../../core/print/print").internalPrinter;
43
+ readonly 2: typeof import("../../../core/print/normalize-printer").normalizedAstToJson;
44
+ readonly 5: typeof import("../../../core/print/normalize-printer").normalizedAstToQuads;
45
+ readonly 3: typeof import("../../../core/print/normalize-printer").printNormalizedAstToMermaid;
46
+ readonly 4: typeof import("../../../core/print/normalize-printer").printNormalizedAstToMermaidUrl;
47
+ };
48
+ readonly dependencies: readonly ["parse"];
49
+ readonly requiredInput: import("../../../core/steps/all/core/10-normalize").NormalizeRequiredInput;
50
+ } | {
51
+ readonly humanReadableName: "dataflow";
52
+ readonly processor: (results: {
53
+ normalize?: import("../../../r-bridge/lang-4.x/ast/model/processing/decorate").NormalizedAst;
54
+ }, input: {
55
+ request?: import("../../../r-bridge/retriever").RParseRequests;
56
+ parser?: import("../../../r-bridge/parser").Parser<import("../../../r-bridge/parser").KnownParserType>;
57
+ }) => import("../../../dataflow/info").DataflowInformation;
58
+ readonly requiredInput: {};
59
+ readonly name: "dataflow";
60
+ readonly description: "Construct the dataflow graph";
61
+ readonly executed: import("../../../core/steps/pipeline-step").PipelineStepStage.OncePerFile;
62
+ readonly printer: {
63
+ readonly 0: typeof import("../../../core/print/print").internalPrinter;
64
+ readonly 2: typeof import("../../../core/print/dataflow-printer").dataflowGraphToJson;
65
+ readonly 5: typeof import("../../../core/print/dataflow-printer").dataflowGraphToQuads;
66
+ readonly 3: typeof import("../../../core/print/dataflow-printer").dataflowGraphToMermaid;
67
+ readonly 4: typeof import("../../../core/print/dataflow-printer").dataflowGraphToMermaidUrl;
68
+ };
69
+ readonly dependencies: readonly ["normalize"];
70
+ }>>, queryResults: BaseQueryResult, result: string[]) => true;
71
+ readonly schema: Joi.ObjectSchema<any>;
72
+ };