@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
package/README.md CHANGED
@@ -48,7 +48,7 @@ It offers a wide variety of features, for example:
48
48
 
49
49
  ```shell
50
50
  $ docker run -it --rm eagleoutice/flowr # or npm run flowr
51
- flowR repl using flowR v2.2.5, R v4.4.0 (r-shell engine)
51
+ flowR repl using flowR v2.2.8, R v4.4.0 (r-shell engine)
52
52
  R> :slicer test/testfiles/example.R --criterion "11@sum"
53
53
  ```
54
54
 
@@ -95,7 +95,7 @@ It offers a wide variety of features, for example:
95
95
 
96
96
 
97
97
  * 🚀 **fast data- and control-flow graphs**\
98
- Within just <i><span title="This measurement is automatically fetched from the latest benchmark!">117.7 ms</i></span> (as of Feb 17, 2025),
98
+ Within just <i><span title="This measurement is automatically fetched from the latest benchmark!">120.8 ms</span></i> (as of Feb 19, 2025),
99
99
  _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,
100
100
  and consult the [wiki pages](https://github.com/flowr-analysis/flowr/wiki/Dataflow-Graph) for more details on the dataflow graph.
101
101
 
@@ -131,7 +131,7 @@ It offers a wide variety of features, for example:
131
131
 
132
132
  ```shell
133
133
  $ docker run -it --rm eagleoutice/flowr # or npm run flowr
134
- flowR repl using flowR v2.2.5, R v4.4.0 (r-shell engine)
134
+ flowR repl using flowR v2.2.8, R v4.4.0 (r-shell engine)
135
135
  R> :dataflow* test/testfiles/example.R
136
136
  ```
137
137
 
@@ -140,7 +140,7 @@ It offers a wide variety of features, for example:
140
140
 
141
141
 
142
142
  ```text
143
- https://mermaid.live/view#base64:eyJjb2RlIjoiZmxvd2NoYXJ0IFREXG4gICAgMChbXCJgIzkxO1JTeW1ib2wjOTM7IHRlc3RcbiAgICAgICgwKVxuICAgICAgKjEuMS00KmBcIl0pXG4gICAgMShbXCJgIzkxO1JTeW1ib2wjOTM7IHRlc3RmaWxlc1xuICAgICAgKDEpXG4gICAgICAqMS42LTE0KmBcIl0pXG4gICAgMltbXCJgIzkxO1JCaW5hcnlPcCM5MzsgL1xuICAgICAgKDIpXG4gICAgICAqMS4xLTE0KlxuICAgICgwLCAxKWBcIl1dXG4gICAgMyhbXCJgIzkxO1JTeW1ib2wjOTM7IGV4YW1wbGUuUlxuICAgICAgKDMpXG4gICAgICAqMS4xNi0yNCpgXCJdKVxuICAgIDRbW1wiYCM5MTtSQmluYXJ5T3AjOTM7IC9cbiAgICAgICg0KVxuICAgICAgKjEuMS0yNCpcbiAgICAoMiwgMylgXCJdXVxuICAgIDIgLS0+fFwicmVhZHMsIGFyZ3VtZW50XCJ8IDBcbiAgICAyIC0tPnxcInJlYWRzLCBhcmd1bWVudFwifCAxXG4gICAgNCAtLT58XCJyZWFkcywgYXJndW1lbnRcInwgMlxuICAgIDQgLS0+fFwicmVhZHMsIGFyZ3VtZW50XCJ8IDMiLCJtZXJtYWlkIjp7ImF1dG9TeW5jIjp0cnVlfX0=
143
+ https://mermaid.live/view#base64:eyJjb2RlIjoiZmxvd2NoYXJ0IEJUXG4gICAgMChbXCJgIzkxO1JTeW1ib2wjOTM7IHRlc3RcbiAgICAgICgwKVxuICAgICAgKjEuMS00KmBcIl0pXG4gICAgMShbXCJgIzkxO1JTeW1ib2wjOTM7IHRlc3RmaWxlc1xuICAgICAgKDEpXG4gICAgICAqMS42LTE0KmBcIl0pXG4gICAgMltbXCJgIzkxO1JCaW5hcnlPcCM5MzsgL1xuICAgICAgKDIpXG4gICAgICAqMS4xLTE0KlxuICAgICgwLCAxKWBcIl1dXG4gICAgMyhbXCJgIzkxO1JTeW1ib2wjOTM7IGV4YW1wbGUuUlxuICAgICAgKDMpXG4gICAgICAqMS4xNi0yNCpgXCJdKVxuICAgIDRbW1wiYCM5MTtSQmluYXJ5T3AjOTM7IC9cbiAgICAgICg0KVxuICAgICAgKjEuMS0yNCpcbiAgICAoMiwgMylgXCJdXVxuICAgIDIgLS0+fFwicmVhZHMsIGFyZ3VtZW50XCJ8IDBcbiAgICAyIC0tPnxcInJlYWRzLCBhcmd1bWVudFwifCAxXG4gICAgNCAtLT58XCJyZWFkcywgYXJndW1lbnRcInwgMlxuICAgIDQgLS0+fFwicmVhZHMsIGFyZ3VtZW50XCJ8IDMiLCJtZXJtYWlkIjp7ImF1dG9TeW5jIjp0cnVlfX0=
144
144
  ```
145
145
 
146
146
 
@@ -149,6 +149,7 @@ It offers a wide variety of features, for example:
149
149
 
150
150
 
151
151
 
152
+
152
153
  ```mermaid
153
154
  flowchart LR
154
155
  1{{"`#91;RNumber#93; 0
@@ -374,8 +375,9 @@ It offers a wide variety of features, for example:
374
375
  52 -->|"reads, argument"| 48
375
376
  52 -->|"argument"| 50
376
377
  ```
378
+
377
379
 
378
- (The analysis required _24.34 ms_ (including parse and normalize, using the [r-shell](https://github.com/flowr-analysis/flowr/wiki/Engines) engine) within the generation environment.)
380
+ (The analysis required _22.72 ms_ (including parse and normalize, using the [r-shell](https://github.com/flowr-analysis/flowr/wiki/Engines) engine) within the generation environment.)
379
381
 
380
382
 
381
383
 
@@ -111,6 +111,12 @@ exports.flowrMainOptionDefinitions = [
111
111
  description: 'The path to the tree-sitter WASM binary to use. Defaults to the path specified by the tree-sitter package.',
112
112
  multiple: false
113
113
  },
114
+ {
115
+ name: 'engine.tree-sitter.lax',
116
+ type: Boolean,
117
+ description: 'Use the lax parser for parsing R code (allowing for syntax errors).',
118
+ multiple: false
119
+ },
114
120
  {
115
121
  name: 'default-engine',
116
122
  type: String,
package/cli/flowr.d.ts CHANGED
@@ -20,6 +20,7 @@ export interface FlowrCliOptions {
20
20
  'engine.tree-sitter.disabled': boolean;
21
21
  'engine.tree-sitter.wasm-path': string | undefined;
22
22
  'engine.tree-sitter.tree-sitter-wasm-path': string | undefined;
23
+ 'engine.tree-sitter.lax': boolean;
23
24
  }
24
25
  export declare const optionHelp: ({
25
26
  header: string;
package/cli/flowr.js CHANGED
@@ -79,7 +79,8 @@ if (!options['engine.tree-sitter.disabled']) {
79
79
  (0, config_1.amendConfig)({ engines: [{
80
80
  type: 'tree-sitter',
81
81
  wasmPath: options['engine.tree-sitter.wasm-path'],
82
- treeSitterWasmPath: options['engine.tree-sitter.tree-sitter-wasm-path']
82
+ treeSitterWasmPath: options['engine.tree-sitter.tree-sitter-wasm-path'],
83
+ lax: options['engine.tree-sitter.lax']
83
84
  }] });
84
85
  }
85
86
  if (options['default-engine']) {
@@ -0,0 +1,2 @@
1
+ export declare function compact(obj: unknown): Buffer;
2
+ export declare function uncompact(buf: Buffer | Uint8Array): unknown;
@@ -0,0 +1,13 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.compact = compact;
4
+ exports.uncompact = uncompact;
5
+ const json_1 = require("../../../util/json");
6
+ const msgpack_1 = require("@msgpack/msgpack");
7
+ function compact(obj) {
8
+ return Buffer.from((0, msgpack_1.encode)(JSON.parse(JSON.stringify(obj, json_1.jsonReplacer))));
9
+ }
10
+ function uncompact(buf) {
11
+ return (0, msgpack_1.decode)(new Uint8Array(Buffer.from(buf)));
12
+ }
13
+ //# sourceMappingURL=compact.js.map
@@ -60,6 +60,7 @@ const assert_1 = require("../../../util/assert");
60
60
  const auto_select_defaults_1 = require("../../../reconstruct/auto-select/auto-select-defaults");
61
61
  const message_query_1 = require("./messages/message-query");
62
62
  const query_1 = require("../../../queries/query");
63
+ const compact_1 = require("./compact");
63
64
  /**
64
65
  * Each connection handles a single client, answering to its requests.
65
66
  * There is no need to construct this class manually, {@link FlowRServer} will do it for you.
@@ -181,6 +182,15 @@ class FlowRServerConnection {
181
182
  }
182
183
  });
183
184
  }
185
+ else if (message.format === 'compact') {
186
+ (0, send_1.sendMessage)(this.socket, {
187
+ type: 'response-file-analysis',
188
+ format: 'compact',
189
+ id: message.id,
190
+ cfg: cfg ? (0, compact_1.compact)(cfg) : undefined,
191
+ results: (0, compact_1.compact)(sanitizedResults)
192
+ });
193
+ }
184
194
  else {
185
195
  (0, send_1.sendMessage)(this.socket, {
186
196
  type: 'response-file-analysis',
@@ -1,6 +1,6 @@
1
1
  import type { IdMessageBase, MessageDefinition } from './all-messages';
2
2
  import type { ControlFlowInformation } from '../../../../util/cfg/cfg';
3
- import type { DEFAULT_DATAFLOW_PIPELINE, DEFAULT_SLICING_PIPELINE } from '../../../../core/steps/pipeline/default-pipelines';
3
+ import type { DEFAULT_DATAFLOW_PIPELINE } from '../../../../core/steps/pipeline/default-pipelines';
4
4
  import type { PipelineOutput } from '../../../../core/steps/pipeline/pipeline';
5
5
  /**
6
6
  * Send by the client to request an analysis of a given file.
@@ -33,7 +33,7 @@ export interface FileAnalysisRequestMessage extends IdMessageBase {
33
33
  /** Can be used to additionally extract the {@link ControlFlowInformation} of the file, which is not exposed (and not fully calculated) by default. */
34
34
  cfg?: boolean;
35
35
  /** Controls the serialization of the `results` (and the {@link ControlFlowGraph} if the corresponding flag is set). If missing, we assume _json_. */
36
- format?: 'json' | 'n-quads';
36
+ format?: 'compact' | 'json' | 'n-quads';
37
37
  }
38
38
  export declare const requestAnalysisMessage: MessageDefinition<FileAnalysisRequestMessage>;
39
39
  /**
@@ -45,20 +45,36 @@ export declare const requestAnalysisMessage: MessageDefinition<FileAnalysisReque
45
45
  *
46
46
  * @note The serialization of maps and sets is controlled by the {@link jsonReplacer} as part of {@link sendMessage}.
47
47
  *
48
- * @see FileAnalysisResponseMessageNQuads
48
+ * @see {@link FileAnalysisResponseMessageNQuads}
49
+ * @see {@link FileAnalysisResponseMessageCompact}
49
50
  */
50
51
  export interface FileAnalysisResponseMessageJson extends IdMessageBase {
51
52
  type: 'response-file-analysis';
52
53
  format: 'json';
53
54
  /**
54
- * See the {@link SteppingSlicer} and {@link StepResults} for details on the results.
55
+ * See the {@link PipelineExecutor} and {@link DEFAULT_DATAFLOW_PIPELINE} for details on the results.
55
56
  */
56
- results: PipelineOutput<typeof DEFAULT_SLICING_PIPELINE>;
57
+ results: PipelineOutput<typeof DEFAULT_DATAFLOW_PIPELINE>;
57
58
  /**
58
59
  * Only if the {@link FileAnalysisRequestMessage} contained a `cfg: true` this will contain the {@link ControlFlowInformation} of the file.
59
60
  */
60
61
  cfg?: ControlFlowInformation;
61
62
  }
63
+ /**
64
+ * Similar to {@link FileAnalysisResponseMessageJson} but using a compact serialization format.
65
+ */
66
+ export interface FileAnalysisResponseMessageCompact extends IdMessageBase {
67
+ type: 'response-file-analysis';
68
+ format: 'compact';
69
+ /**
70
+ * See the {@link PipelineExecutor} and {@link DEFAULT_DATAFLOW_PIPELINE} for details on the results.
71
+ */
72
+ results: Buffer;
73
+ /**
74
+ * Only if the {@link FileAnalysisRequestMessage} contained a `cfg: true` this will contain the {@link ControlFlowInformation} of the file.
75
+ */
76
+ cfg?: Buffer;
77
+ }
62
78
  /**
63
79
  * Similar to {@link FileAnalysisResponseMessageJson} but using n-quads as serialization format.
64
80
  */
@@ -15,7 +15,7 @@ exports.requestAnalysisMessage = {
15
15
  content: joi_1.default.string().optional().description('The content of the file or an R expression (either give this or the filepath).'),
16
16
  filepath: joi_1.default.alternatives(joi_1.default.string(), joi_1.default.array().items(joi_1.default.string())).optional().description('The path to the file(s) on the local machine (either give this or the content).'),
17
17
  cfg: joi_1.default.boolean().optional().description('If you want to extract the control flow information of the file.'),
18
- format: joi_1.default.string().valid('json', 'n-quads').optional().description('The format of the results, if missing we assume json.')
18
+ format: joi_1.default.string().valid('json', 'n-quads', 'compact').optional().description('The format of the results, if missing we assume json.')
19
19
  }).xor('content', 'filepath')
20
20
  };
21
21
  const jsonSchema = joi_1.default.object({
@@ -25,6 +25,13 @@ const jsonSchema = joi_1.default.object({
25
25
  results: joi_1.default.object().required().description('The results of the analysis (one field per step).'),
26
26
  cfg: joi_1.default.object().optional().description('The control flow information of the file, only present if requested.')
27
27
  }).description('The response in JSON format.');
28
+ const compactSchema = joi_1.default.object({
29
+ type: joi_1.default.string().valid('response-file-analysis').required().description('The type of the message.'),
30
+ id: joi_1.default.string().optional().description('The id of the message, if you passed one in the request.'),
31
+ format: joi_1.default.string().valid('bson').required().description('The format of the results in bson format.'),
32
+ results: joi_1.default.binary().required().description('The results of the analysis (one field per step).'),
33
+ cfg: joi_1.default.binary().optional().description('The control flow information of the file, only present if requested.')
34
+ });
28
35
  const nquadsSchema = joi_1.default.object({
29
36
  type: joi_1.default.string().valid('response-file-analysis').required().description('The type of the message.'),
30
37
  id: joi_1.default.string().optional().description('The id of the message, if you passed one in the request.'),
@@ -34,6 +41,6 @@ const nquadsSchema = joi_1.default.object({
34
41
  }).description('The response as n-quads.');
35
42
  exports.analysisResponseMessage = {
36
43
  type: 'response-file-analysis',
37
- schema: joi_1.default.alternatives(jsonSchema, nquadsSchema).required().description('The response to a file analysis request (based on the `format` field).')
44
+ schema: joi_1.default.alternatives(jsonSchema, nquadsSchema, compactSchema).required().description('The response to a file analysis request (based on the `format` field).')
38
45
  };
39
46
  //# sourceMappingURL=message-analysis.js.map
package/config.d.ts CHANGED
@@ -10,6 +10,30 @@ export declare enum VariableResolve {
10
10
  /** Only resolve directly assigned builtin constants */
11
11
  Builtin = "builtin"
12
12
  }
13
+ /**
14
+ * How to infer the working directory from a script
15
+ */
16
+ export declare enum InferWorkingDirectory {
17
+ /** Don't infer the working directory */
18
+ No = "no",
19
+ /** Infer the working directory from the main script */
20
+ MainScript = "main-script",
21
+ /** Infer the working directory from the active script */
22
+ ActiveScript = "active-script",
23
+ /** Infer the working directory from any script */
24
+ AnyScript = "any-script"
25
+ }
26
+ /**
27
+ * How to handle fixed strings in a source path
28
+ */
29
+ export declare enum DropPathsOption {
30
+ /** Don't drop any parts of the sourced path */
31
+ No = "no",
32
+ /** try to drop everything but the filename */
33
+ Once = "once",
34
+ /** try to drop every folder of the path */
35
+ All = "all"
36
+ }
13
37
  export interface FlowrConfigOptions extends MergeableRecord {
14
38
  /**
15
39
  * Whether source calls should be ignored, causing {@link processSourceCall}'s behavior to be skipped
@@ -17,7 +41,7 @@ export interface FlowrConfigOptions extends MergeableRecord {
17
41
  readonly ignoreSourceCalls: boolean;
18
42
  /** Configure language semantics and how flowR handles them */
19
43
  readonly semantics: {
20
- /** Semantics regarding the handlings of the environment */
44
+ /** Semantics regarding the handling of the environment */
21
45
  readonly environment: {
22
46
  /** Do you want to overwrite (parts) of the builtin definition? */
23
47
  readonly overwriteBuiltIns: {
@@ -49,6 +73,30 @@ export interface FlowrConfigOptions extends MergeableRecord {
49
73
  * containers and accesses
50
74
  */
51
75
  readonly pointerTracking: boolean;
76
+ /**
77
+ * If lax source calls are active, flowR searches for sourced files much more freely,
78
+ * based on the configurations you give it.
79
+ * This option is only in effect if {@link ignoreSourceCalls} is set to false.
80
+ */
81
+ readonly resolveSource?: {
82
+ /**
83
+ * search for filenames matching in the lowercase
84
+ */
85
+ readonly ignoreCapitalization: boolean;
86
+ /**
87
+ * try to infer the working directory from the main or any script to analyze.
88
+ */
89
+ readonly inferWorkingDirectory: InferWorkingDirectory;
90
+ /**
91
+ * Additionally search in these paths
92
+ */
93
+ readonly searchPath: readonly string[];
94
+ /**
95
+ * Allow to drop the first or all parts of the sourced path,
96
+ * if it is relative.
97
+ */
98
+ readonly dropPaths: DropPathsOption;
99
+ };
52
100
  };
53
101
  }
54
102
  export interface TreeSitterEngineConfig extends MergeableRecord {
@@ -61,6 +109,10 @@ export interface TreeSitterEngineConfig extends MergeableRecord {
61
109
  * The path to the tree-sitter WASM binary to use. If this is undefined, the path specified by the tree-sitter package will be used.
62
110
  */
63
111
  readonly treeSitterWasmPath?: string;
112
+ /**
113
+ * Whether to use the lax parser for parsing R code (allowing for syntax errors). If this is undefined, the strict parser will be used.
114
+ */
115
+ readonly lax?: boolean;
64
116
  }
65
117
  export interface RShellEngineConfig extends MergeableRecord {
66
118
  readonly type: 'r-shell';
package/config.js CHANGED
@@ -3,7 +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.flowrConfigFileSchema = exports.defaultConfigOptions = exports.VariableResolve = void 0;
6
+ exports.flowrConfigFileSchema = exports.defaultConfigOptions = exports.DropPathsOption = exports.InferWorkingDirectory = exports.VariableResolve = void 0;
7
7
  exports.setConfigFile = setConfigFile;
8
8
  exports.parseConfig = parseConfig;
9
9
  exports.setConfig = setConfig;
@@ -25,6 +25,33 @@ var VariableResolve;
25
25
  /** Only resolve directly assigned builtin constants */
26
26
  VariableResolve["Builtin"] = "builtin";
27
27
  })(VariableResolve || (exports.VariableResolve = VariableResolve = {}));
28
+ /**
29
+ * How to infer the working directory from a script
30
+ */
31
+ var InferWorkingDirectory;
32
+ (function (InferWorkingDirectory) {
33
+ /** Don't infer the working directory */
34
+ InferWorkingDirectory["No"] = "no";
35
+ /** Infer the working directory from the main script */
36
+ InferWorkingDirectory["MainScript"] = "main-script";
37
+ /** Infer the working directory from the active script */
38
+ InferWorkingDirectory["ActiveScript"] = "active-script";
39
+ /** Infer the working directory from any script */
40
+ InferWorkingDirectory["AnyScript"] = "any-script";
41
+ })(InferWorkingDirectory || (exports.InferWorkingDirectory = InferWorkingDirectory = {}));
42
+ /**
43
+ * How to handle fixed strings in a source path
44
+ */
45
+ var DropPathsOption;
46
+ (function (DropPathsOption) {
47
+ /** Don't drop any parts of the sourced path */
48
+ DropPathsOption["No"] = "no";
49
+ /** try to drop everything but the filename */
50
+ DropPathsOption["Once"] = "once";
51
+ /** try to drop every folder of the path */
52
+ DropPathsOption["All"] = "all";
53
+ })(DropPathsOption || (exports.DropPathsOption = DropPathsOption = {}));
54
+ ;
28
55
  const defaultEngineConfigs = {
29
56
  'tree-sitter': { type: 'tree-sitter' },
30
57
  'r-shell': { type: 'r-shell' }
@@ -43,7 +70,13 @@ exports.defaultConfigOptions = {
43
70
  defaultEngine: 'r-shell',
44
71
  solver: {
45
72
  variables: VariableResolve.Alias,
46
- pointerTracking: true
73
+ pointerTracking: true,
74
+ resolveSource: {
75
+ dropPaths: DropPathsOption.No,
76
+ ignoreCapitalization: true,
77
+ inferWorkingDirectory: InferWorkingDirectory.ActiveScript,
78
+ searchPath: []
79
+ }
47
80
  }
48
81
  };
49
82
  exports.flowrConfigFileSchema = joi_1.default.object({
@@ -54,12 +87,13 @@ exports.flowrConfigFileSchema = joi_1.default.object({
54
87
  loadDefaults: joi_1.default.boolean().optional().description('Should the default configuration still be loaded?'),
55
88
  definitions: joi_1.default.array().items(joi_1.default.object()).optional().description('The definitions to load/overwrite.')
56
89
  }).optional().description('Do you want to overwrite (parts) of the builtin definition?')
57
- }).optional().description('Semantics regarding the handlings of the environment.')
90
+ }).optional().description('Semantics regarding how to handle the R environment.')
58
91
  }).description('Configure language semantics and how flowR handles them.'),
59
92
  engines: joi_1.default.array().items(joi_1.default.alternatives(joi_1.default.object({
60
93
  type: joi_1.default.string().required().valid('tree-sitter').description('Use the tree sitter engine.'),
61
94
  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.'),
62
- 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.')
95
+ 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.'),
96
+ 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.')
63
97
  }).description('The configuration for the tree sitter engine.'), joi_1.default.object({
64
98
  type: joi_1.default.string().required().valid('r-shell').description('Use the R shell engine.'),
65
99
  rPath: joi_1.default.string().optional().description('The path to the R executable to use. If this is undefined, this uses the default path.')
@@ -67,7 +101,13 @@ exports.flowrConfigFileSchema = joi_1.default.object({
67
101
  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.'),
68
102
  solver: joi_1.default.object({
69
103
  variables: joi_1.default.string().valid(...Object.values(VariableResolve)).description('How to resolve variables and their values.'),
70
- pointerTracking: joi_1.default.boolean().description('Whether to track pointers in the dataflow graph, if not, the graph will be over-approximated wrt. containers and accesses.')
104
+ pointerTracking: joi_1.default.boolean().description('Whether to track pointers in the dataflow graph, if not, the graph will be over-approximated wrt. containers and accesses.'),
105
+ resolveSource: joi_1.default.object({
106
+ 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.'),
107
+ ignoreCapitalization: joi_1.default.boolean().description('Search for filenames matching in the lowercase.'),
108
+ inferWorkingDirectory: joi_1.default.string().valid(...Object.values(InferWorkingDirectory)).description('Try to infer the working directory from the main or any script to analyze.'),
109
+ searchPath: joi_1.default.array().items(joi_1.default.string()).description('Additionally search in these paths.')
110
+ }).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.')
71
111
  }).description('How to resolve constants, constraints, cells, ...')
72
112
  }).description('The configuration file format for flowR.');
73
113
  // we don't load from a config file at all by default unless setConfigFile is called
@@ -89,7 +89,7 @@ exports.BuiltInProcessorMapper = {
89
89
  'builtin:repeat-loop': built_in_repeat_loop_1.processRepeatLoop,
90
90
  'builtin:while-loop': built_in_while_loop_1.processWhileLoop,
91
91
  'builtin:replacement': built_in_replacement_1.processReplacementFunction,
92
- 'builtin:list': built_in_list_1.processList,
92
+ 'builtin:list': built_in_list_1.processList
93
93
  };
94
94
  exports.BuiltInMemory = new Map();
95
95
  exports.EmptyBuiltInMemory = new Map();
@@ -29,6 +29,10 @@ export declare class Environment implements IEnvironment {
29
29
  memory: Map<Identifier, IdentifierDefinition[]>;
30
30
  constructor(parent: IEnvironment);
31
31
  }
32
+ export interface WorkingDirectoryReference {
33
+ readonly path: string;
34
+ readonly controlDependencies: ControlDependency[] | undefined;
35
+ }
32
36
  /**
33
37
  * An environment describes a ({@link IEnvironment#parent|scoped}) mapping of names to their definitions ({@link EnvironmentMemory}).
34
38
  *
@@ -29,11 +29,11 @@ function makeReferenceMaybe(ref, graph, environments, includeDefs, defaultCd = u
29
29
  }
30
30
  if (node) {
31
31
  const [fst] = node;
32
- if (fst.controlDependencies && defaultCd && !fst.controlDependencies.includes(defaultCd)) {
33
- fst.controlDependencies.push(defaultCd);
32
+ if (fst.cds && defaultCd && !fst.cds.includes(defaultCd)) {
33
+ fst.cds.push(defaultCd);
34
34
  }
35
35
  else {
36
- fst.controlDependencies = defaultCd ? [defaultCd] : [];
36
+ fst.cds = defaultCd ? [defaultCd] : [];
37
37
  }
38
38
  }
39
39
  return { ...ref, controlDependencies: [...ref.controlDependencies ?? [], ...(defaultCd ? [defaultCd] : [])] };
@@ -221,7 +221,7 @@ function trackAliasesInGraph(id, graph, idMap) {
221
221
  continue;
222
222
  }
223
223
  const [vertex, outgoingEdges] = res;
224
- const cds = vertex.controlDependencies;
224
+ const cds = vertex.cds;
225
225
  for (const cd of cds ?? []) {
226
226
  const target = graph.idMap?.get(cd.id);
227
227
  if (target === undefined) {
@@ -14,7 +14,6 @@ const named_call_handling_1 = require("./internal/process/functions/call/named-c
14
14
  const make_argument_1 = require("./internal/process/functions/call/argument/make-argument");
15
15
  const range_1 = require("../util/range");
16
16
  const type_1 = require("../r-bridge/lang-4.x/ast/model/type");
17
- const retriever_1 = require("../r-bridge/retriever");
18
17
  const environment_1 = require("./environments/environment");
19
18
  const built_in_source_1 = require("./internal/process/functions/call/built-in/built-in-source");
20
19
  const cfg_1 = require("../util/cfg/cfg");
@@ -46,14 +45,17 @@ exports.processors = {
46
45
  [type_1.RType.FunctionDefinition]: (n, d) => (0, process_named_call_1.processAsNamedCall)(n, d, n.lexeme, [...n.parameters, n.body]),
47
46
  [type_1.RType.Parameter]: process_parameter_1.processFunctionParameter,
48
47
  [type_1.RType.Argument]: process_argument_1.processFunctionArgument,
49
- [type_1.RType.ExpressionList]: (n, d) => (0, named_call_handling_1.processNamedCall)({
50
- type: type_1.RType.Symbol,
51
- info: n.info,
52
- content: n.grouping?.[0].content ?? '{',
53
- lexeme: n.grouping?.[0].lexeme ?? '{',
54
- location: n.location ?? (0, range_1.rangeFrom)(-1, -1, -1, -1),
55
- namespace: n.grouping?.[0].content ? undefined : 'base'
56
- }, (0, make_argument_1.wrapArgumentsUnnamed)(n.children, d.completeAst.idMap), n.info.id, d)
48
+ [type_1.RType.ExpressionList]: ({ grouping, info, children, location }, d) => {
49
+ const groupStart = grouping?.[0];
50
+ return (0, named_call_handling_1.processNamedCall)({
51
+ type: type_1.RType.Symbol,
52
+ info: info,
53
+ content: groupStart?.content ?? '{',
54
+ lexeme: groupStart?.lexeme ?? '{',
55
+ location: location ?? (0, range_1.rangeFrom)(-1, -1, -1, -1),
56
+ namespace: groupStart?.content ? undefined : 'base'
57
+ }, (0, make_argument_1.wrapArgumentsUnnamed)(children, d.completeAst.idMap), info.id, d);
58
+ }
57
59
  };
58
60
  function resolveLinkToSideEffects(ast, graph) {
59
61
  let cfg = undefined;
@@ -94,7 +96,7 @@ function produceDataFlowGraph(parser, request, ast) {
94
96
  processors: exports.processors,
95
97
  currentRequest: firstRequest,
96
98
  controlDependencies: undefined,
97
- referenceChain: [(0, retriever_1.requestFingerprint)(firstRequest)]
99
+ referenceChain: [firstRequest],
98
100
  };
99
101
  let df = (0, processor_1.processDataflowFor)(ast.ast, dfData);
100
102
  if (multifile) {
@@ -44,7 +44,7 @@ class DataflowGraphBuilder extends graph_1.DataflowGraph {
44
44
  unknownReferences: subflow.unknownReferences.map(o => ({ ...o, nodeId: (0, node_id_1.normalizeIdToNumberIfPossible)(o.nodeId), controlDependencies: o.controlDependencies?.map(c => ({ ...c, id: (0, node_id_1.normalizeIdToNumberIfPossible)(c.id) })) }))
45
45
  },
46
46
  exitPoints: exitPoints.map(node_id_1.normalizeIdToNumberIfPossible),
47
- controlDependencies: info?.controlDependencies?.map(c => ({ ...c, id: (0, node_id_1.normalizeIdToNumberIfPossible)(c.id) })),
47
+ cds: info?.controlDependencies?.map(c => ({ ...c, id: (0, node_id_1.normalizeIdToNumberIfPossible)(c.id) })),
48
48
  environment: info?.environment
49
49
  }, asRoot);
50
50
  }
@@ -66,7 +66,7 @@ class DataflowGraphBuilder extends graph_1.DataflowGraph {
66
66
  name,
67
67
  args: args.map(a => a === r_function_call_1.EmptyArgument ? r_function_call_1.EmptyArgument : { ...a, nodeId: (0, node_id_1.normalizeIdToNumberIfPossible)(a.nodeId), controlDependencies: undefined }),
68
68
  environment: (info?.onlyBuiltIn || onlyBuiltInAuto) ? undefined : info?.environment ?? (0, environment_1.initializeCleanEnvironments)(),
69
- controlDependencies: info?.controlDependencies?.map(c => ({ ...c, id: (0, node_id_1.normalizeIdToNumberIfPossible)(c.id) })),
69
+ cds: info?.controlDependencies?.map(c => ({ ...c, id: (0, node_id_1.normalizeIdToNumberIfPossible)(c.id) })),
70
70
  onlyBuiltin: info?.onlyBuiltIn ?? onlyBuiltInAuto ?? false
71
71
  }, asRoot);
72
72
  this.addArgumentLinks(id, args);
@@ -96,7 +96,7 @@ class DataflowGraphBuilder extends graph_1.DataflowGraph {
96
96
  }
97
97
  }
98
98
  else if (!this.hasVertex(arg.nodeId, true)) {
99
- this.use(arg.nodeId, arg.name, { controlDependencies: arg.controlDependencies });
99
+ this.use(arg.nodeId, arg.name, { cds: arg.controlDependencies });
100
100
  this.argument(id, arg.nodeId);
101
101
  }
102
102
  }
@@ -115,7 +115,7 @@ class DataflowGraphBuilder extends graph_1.DataflowGraph {
115
115
  tag: vertex_1.VertexType.VariableDefinition,
116
116
  id: (0, node_id_1.normalizeIdToNumberIfPossible)(id),
117
117
  name,
118
- controlDependencies: info?.controlDependencies?.map(c => ({ ...c, id: (0, node_id_1.normalizeIdToNumberIfPossible)(c.id) })),
118
+ cds: info?.controlDependencies?.map(c => ({ ...c, id: (0, node_id_1.normalizeIdToNumberIfPossible)(c.id) })),
119
119
  }, asRoot);
120
120
  if (info?.definedBy) {
121
121
  for (const def of info.definedBy) {
@@ -138,11 +138,11 @@ class DataflowGraphBuilder extends graph_1.DataflowGraph {
138
138
  tag: vertex_1.VertexType.Use,
139
139
  id: (0, node_id_1.normalizeIdToNumberIfPossible)(id),
140
140
  name,
141
- controlDependencies: undefined,
141
+ cds: undefined,
142
142
  environment: undefined
143
143
  }, {
144
144
  ...info,
145
- controlDependencies: info?.controlDependencies?.map(c => ({ ...c, id: (0, node_id_1.normalizeIdToNumberIfPossible)(c.id) }))
145
+ cds: info?.cds?.map(c => ({ ...c, id: (0, node_id_1.normalizeIdToNumberIfPossible)(c.id) }))
146
146
  }), asRoot);
147
147
  }
148
148
  /**
@@ -157,7 +157,7 @@ class DataflowGraphBuilder extends graph_1.DataflowGraph {
157
157
  return this.addVertex({
158
158
  tag: vertex_1.VertexType.Value,
159
159
  id: (0, node_id_1.normalizeIdToNumberIfPossible)(id),
160
- controlDependencies: options?.controlDependencies?.map(c => ({ ...c, id: (0, node_id_1.normalizeIdToNumberIfPossible)(c.id) })),
160
+ cds: options?.controlDependencies?.map(c => ({ ...c, id: (0, node_id_1.normalizeIdToNumberIfPossible)(c.id) })),
161
161
  environment: undefined
162
162
  }, asRoot);
163
163
  }
@@ -199,7 +199,7 @@ function diffVertices(ctx) {
199
199
  });
200
200
  }
201
201
  }
202
- (0, info_1.diffControlDependencies)(lInfo.controlDependencies, rInfo.controlDependencies, { ...ctx, position: `Vertex ${id} differs in controlDependencies. ` });
202
+ (0, info_1.diffControlDependencies)(lInfo.cds, rInfo.cds, { ...ctx, position: `Vertex ${id} differs in controlDependencies. ` });
203
203
  if ((lInfo.environment === undefined && rInfo.environment !== undefined && !ctx.config.leftIsSubgraph)
204
204
  || (lInfo.environment !== undefined && rInfo.environment === undefined && !ctx.config.rightIsSubgraph)) {
205
205
  /* only diff them if specified at all */
@@ -178,11 +178,11 @@ export declare class DataflowGraph<Vertex extends DataflowGraphVertexInfo = Data
178
178
  */
179
179
  addVertex(vertex: DataflowGraphVertexArgument & Omit<Vertex, keyof DataflowGraphVertexArgument>, asRoot?: boolean): this;
180
180
  /** {@inheritDoc} */
181
- addEdge(from: NodeId, to: NodeId, type: EdgeType): this;
181
+ addEdge(from: NodeId, to: NodeId, type: EdgeType | number): this;
182
182
  /** {@inheritDoc} */
183
- addEdge(from: ReferenceForEdge, to: ReferenceForEdge, type: EdgeType): this;
183
+ addEdge(from: ReferenceForEdge, to: ReferenceForEdge, type: EdgeType | number): this;
184
184
  /** {@inheritDoc} */
185
- addEdge(from: NodeId | ReferenceForEdge, to: NodeId | ReferenceForEdge, type: EdgeType): this;
185
+ addEdge(from: NodeId | ReferenceForEdge, to: NodeId | ReferenceForEdge, type: EdgeType | number): this;
186
186
  /**
187
187
  * Merges the other graph into *this* one (in-place). The return value is only for convenience.
188
188
  *
@@ -272,7 +272,7 @@ class DataflowGraph {
272
272
  const vertex = this.getVertex(reference.nodeId, true);
273
273
  (0, assert_1.guard)(vertex !== undefined, () => `node must be defined for ${JSON.stringify(reference)} to set reference`);
274
274
  if (vertex.tag === vertex_1.VertexType.FunctionDefinition || vertex.tag === vertex_1.VertexType.VariableDefinition) {
275
- vertex.controlDependencies = reference.controlDependencies;
275
+ vertex.cds = reference.controlDependencies;
276
276
  }
277
277
  else {
278
278
  this.vertexInformation.set(reference.nodeId, { ...vertex, tag: vertex_1.VertexType.VariableDefinition });
@@ -292,17 +292,17 @@ class DataflowGraph {
292
292
  to = to ? (0, node_id_1.normalizeIdToNumberIfPossible)(to) : undefined;
293
293
  const vertex = this.getVertex(from, true);
294
294
  (0, assert_1.guard)(vertex !== undefined, () => `node must be defined for ${from} to add control dependency`);
295
- vertex.controlDependencies ??= [];
295
+ vertex.cds ??= [];
296
296
  if (to) {
297
297
  let hasControlDependency = false;
298
- for (const { id, when: cond } of vertex.controlDependencies) {
298
+ for (const { id, when: cond } of vertex.cds) {
299
299
  if (id === to && when !== cond) {
300
300
  hasControlDependency = true;
301
301
  break;
302
302
  }
303
303
  }
304
304
  if (!hasControlDependency) {
305
- vertex.controlDependencies.push({ id: to, when });
305
+ vertex.cds.push({ id: to, when });
306
306
  }
307
307
  }
308
308
  return this;
@@ -90,7 +90,7 @@ interface DataflowGraphVertexBase extends MergeableRecord {
90
90
  /**
91
91
  * @see {@link ControlDependency} - the collection of control dependencies which have an influence on whether the vertex is executed.
92
92
  */
93
- controlDependencies: ControlDependency[] | undefined;
93
+ cds: ControlDependency[] | undefined;
94
94
  /**
95
95
  * this attribute links a vertex to indices (pointer links) it may be affected by or related to
96
96
  */
@@ -53,7 +53,7 @@ function processAccess(name, args, rootId, data, config) {
53
53
  }
54
54
  /* access always reads all of its indices */
55
55
  for (const arg of fnCall.processedArguments) {
56
- if (arg !== undefined) {
56
+ if (arg) {
57
57
  info.graph.addEdge(name.info.id, arg.entryPoint, edge_1.EdgeType.Reads);
58
58
  }
59
59
  /* we include the read edges to the constant arguments as well so that they are included if necessary */
@@ -70,7 +70,7 @@ function processApply(name, args, rootId, data, { indexOfFunction = 1, nameOfFun
70
70
  args: allOtherArguments,
71
71
  environment: data.environment,
72
72
  onlyBuiltin: false,
73
- controlDependencies: data.controlDependencies
73
+ cds: data.controlDependencies
74
74
  });
75
75
  for (const arg of processedArguments) {
76
76
  if (arg) {