@eagleoutice/flowr 2.1.12 → 2.2.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 (93) hide show
  1. package/README.md +0 -1
  2. package/benchmark/slicer.d.ts +5 -12
  3. package/benchmark/slicer.js +46 -28
  4. package/cli/benchmark-app.d.ts +2 -0
  5. package/cli/benchmark-app.js +2 -1
  6. package/cli/benchmark-helper-app.d.ts +2 -0
  7. package/cli/benchmark-helper-app.js +2 -2
  8. package/cli/common/options.js +3 -1
  9. package/cli/flowr-main-options.js +36 -2
  10. package/cli/flowr.d.ts +6 -0
  11. package/cli/flowr.js +51 -24
  12. package/cli/repl/commands/repl-cfg.js +2 -4
  13. package/cli/repl/commands/repl-dataflow.js +2 -4
  14. package/cli/repl/commands/repl-execute.d.ts +2 -2
  15. package/cli/repl/commands/repl-execute.js +15 -5
  16. package/cli/repl/commands/repl-lineage.js +2 -4
  17. package/cli/repl/commands/repl-main.d.ts +2 -2
  18. package/cli/repl/commands/repl-normalize.js +2 -4
  19. package/cli/repl/commands/repl-parse.js +2 -4
  20. package/cli/repl/commands/repl-query.js +6 -8
  21. package/cli/repl/commands/repl-version.d.ts +5 -4
  22. package/cli/repl/commands/repl-version.js +10 -9
  23. package/cli/repl/core.d.ts +5 -5
  24. package/cli/repl/core.js +8 -12
  25. package/cli/repl/print-version.d.ts +2 -2
  26. package/cli/repl/print-version.js +3 -3
  27. package/cli/repl/server/connection.d.ts +3 -3
  28. package/cli/repl/server/connection.js +5 -7
  29. package/cli/repl/server/messages/message-hello.js +2 -1
  30. package/cli/repl/server/server.d.ts +4 -3
  31. package/cli/repl/server/server.js +7 -5
  32. package/cli/slicer-app.js +1 -1
  33. package/config.d.ts +36 -4
  34. package/config.js +30 -1
  35. package/core/pipeline-executor.d.ts +1 -1
  36. package/core/pipeline-executor.js +1 -1
  37. package/core/steps/all/core/00-parse.d.ts +4 -18
  38. package/core/steps/all/core/00-parse.js +2 -11
  39. package/core/steps/all/core/01-parse-tree-sitter.d.ts +23 -0
  40. package/core/steps/all/core/01-parse-tree-sitter.js +19 -0
  41. package/core/steps/all/core/10-normalize.d.ts +3 -2
  42. package/core/steps/all/core/10-normalize.js +1 -0
  43. package/core/steps/all/core/11-normalize-tree-sitter.d.ts +25 -0
  44. package/core/steps/all/core/11-normalize-tree-sitter.js +27 -0
  45. package/core/steps/all/core/20-dataflow.d.ts +2 -0
  46. package/core/steps/all/core/20-dataflow.js +1 -1
  47. package/core/steps/pipeline/default-pipelines.d.ts +368 -23
  48. package/core/steps/pipeline/default-pipelines.js +42 -4
  49. package/dataflow/extractor.d.ts +2 -1
  50. package/dataflow/extractor.js +2 -1
  51. package/dataflow/internal/process/functions/call/built-in/built-in-source.js +6 -5
  52. package/dataflow/processor.d.ts +2 -0
  53. package/documentation/doc-util/doc-auto-gen.js +2 -1
  54. package/documentation/doc-util/doc-cfg.js +1 -1
  55. package/documentation/doc-util/doc-dfg.js +2 -2
  56. package/documentation/doc-util/doc-files.d.ts +1 -0
  57. package/documentation/doc-util/doc-files.js +4 -0
  58. package/documentation/doc-util/doc-normalized-ast.js +2 -3
  59. package/documentation/doc-util/doc-query.js +1 -1
  60. package/documentation/doc-util/doc-search.js +1 -1
  61. package/documentation/doc-util/doc-types.js +2 -2
  62. package/documentation/print-dataflow-graph-wiki.js +15 -15
  63. package/documentation/print-engines-wiki.d.ts +1 -0
  64. package/documentation/print-engines-wiki.js +82 -0
  65. package/documentation/print-interface-wiki.js +6 -7
  66. package/documentation/print-normalized-ast-wiki.js +1 -1
  67. package/package.json +9 -5
  68. package/queries/catalog/cluster-query/cluster-query-format.d.ts +5 -4
  69. package/queries/catalog/dataflow-query/dataflow-query-format.d.ts +5 -4
  70. package/queries/catalog/dependencies-query/dependencies-query-format.d.ts +5 -4
  71. package/queries/catalog/id-map-query/id-map-query-format.d.ts +5 -4
  72. package/queries/catalog/lineage-query/lineage-query-format.d.ts +5 -4
  73. package/queries/catalog/normalized-ast-query/normalized-ast-query-format.d.ts +5 -4
  74. package/queries/catalog/search-query/search-query-format.d.ts +5 -4
  75. package/queries/catalog/static-slice-query/static-slice-query-format.d.ts +5 -4
  76. package/queries/query.d.ts +40 -32
  77. package/r-bridge/lang-4.x/ast/parser/json/parser.d.ts +4 -2
  78. package/r-bridge/lang-4.x/ast/parser/json/parser.js +5 -0
  79. package/r-bridge/lang-4.x/tree-sitter/tree-sitter-executor.d.ts +18 -0
  80. package/r-bridge/lang-4.x/tree-sitter/tree-sitter-executor.js +57 -0
  81. package/r-bridge/lang-4.x/tree-sitter/tree-sitter-normalize.d.ts +3 -0
  82. package/r-bridge/lang-4.x/tree-sitter/tree-sitter-normalize.js +541 -0
  83. package/r-bridge/lang-4.x/tree-sitter/tree-sitter-types.d.ts +35 -0
  84. package/r-bridge/lang-4.x/tree-sitter/tree-sitter-types.js +40 -0
  85. package/r-bridge/parser.d.ts +32 -0
  86. package/r-bridge/parser.js +14 -0
  87. package/r-bridge/shell-executor.d.ts +37 -1
  88. package/r-bridge/shell-executor.js +39 -0
  89. package/r-bridge/shell.d.ts +12 -6
  90. package/r-bridge/shell.js +15 -6
  91. package/search/search-optimizer/search-optimizer.js +1 -1
  92. package/statistics/statistics.js +1 -1
  93. package/util/version.js +1 -1
@@ -1,7 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.queryStarCommand = exports.queryCommand = void 0;
4
- const pipeline_executor_1 = require("../../../core/pipeline-executor");
5
4
  const default_pipelines_1 = require("../../../core/steps/pipeline/default-pipelines");
6
5
  const retriever_1 = require("../../../r-bridge/retriever");
7
6
  const args_1 = require("../../../util/args");
@@ -10,9 +9,8 @@ const schema_1 = require("../../../util/schema");
10
9
  const query_1 = require("../../../queries/query");
11
10
  const json_1 = require("../../../util/json");
12
11
  const query_print_1 = require("../../../queries/query-print");
13
- async function getDataflow(shell, remainingLine) {
14
- return await new pipeline_executor_1.PipelineExecutor(default_pipelines_1.DEFAULT_DATAFLOW_PIPELINE, {
15
- shell,
12
+ async function getDataflow(parser, remainingLine) {
13
+ return await (0, default_pipelines_1.createDataflowPipeline)(parser, {
16
14
  request: (0, retriever_1.requestFromInput)(remainingLine.trim())
17
15
  }).allRemainingSteps();
18
16
  }
@@ -26,7 +24,7 @@ function printHelp(output) {
26
24
  output.stdout(`Similarly, '@<type>' is interpreted as a query of the given type.`);
27
25
  output.stdout(`With this, ${(0, ansi_1.italic)(':query @config', output.formatter)} prints the result of the config query.`);
28
26
  }
29
- async function processQueryArgs(line, shell, output) {
27
+ async function processQueryArgs(line, parser, output) {
30
28
  const args = (0, args_1.splitAtEscapeSensitive)(line);
31
29
  const query = args.shift();
32
30
  if (!query) {
@@ -59,7 +57,7 @@ async function processQueryArgs(line, shell, output) {
59
57
  else {
60
58
  parsedQuery = [{ type: 'call-context', callName: query }];
61
59
  }
62
- const processed = await getDataflow(shell, args.join(' '));
60
+ const processed = await getDataflow(parser, args.join(' '));
63
61
  return {
64
62
  query: (0, query_1.executeQueries)({ dataflow: processed.dataflow, ast: processed.normalize }, parsedQuery),
65
63
  processed
@@ -70,9 +68,9 @@ exports.queryCommand = {
70
68
  usageExample: ':query "<query>" <code>',
71
69
  aliases: [],
72
70
  script: false,
73
- fn: async (output, shell, remainingLine) => {
71
+ fn: async (output, parser, remainingLine) => {
74
72
  const totalStart = Date.now();
75
- const results = await processQueryArgs(remainingLine, shell, output);
73
+ const results = await processQueryArgs(remainingLine, parser, output);
76
74
  const totalEnd = Date.now();
77
75
  if (results) {
78
76
  output.stdout((0, query_print_1.asciiSummaryOfQueryResult)(ansi_1.ansiFormatter, totalEnd - totalStart, results.query, results.processed));
@@ -1,5 +1,5 @@
1
1
  import type { ReplCommand, ReplOutput } from './repl-main';
2
- import type { RShell } from '../../../r-bridge/shell';
2
+ import type { KnownParser } from '../../../r-bridge/parser';
3
3
  type Version = `${number}.${number}.${number}`;
4
4
  /**
5
5
  * Describes the version of flowR and the used R interpreter.
@@ -8,9 +8,10 @@ export interface VersionInformation {
8
8
  /** The version of flowR */
9
9
  flowr: Version;
10
10
  /** The version of R identified by the underlying {@link RShell} */
11
- r: Version | 'unknown';
11
+ r: Version | 'unknown' | 'none';
12
+ engine: string;
12
13
  }
13
- export declare function retrieveVersionInformation(shell: RShell): Promise<VersionInformation>;
14
- export declare function printVersionInformation(output: ReplOutput, shell: RShell): Promise<void>;
14
+ export declare function retrieveVersionInformation(parser: KnownParser): Promise<VersionInformation>;
15
+ export declare function printVersionInformation(output: ReplOutput, parser: KnownParser): Promise<void>;
15
16
  export declare const versionCommand: ReplCommand;
16
17
  export {};
@@ -6,23 +6,24 @@ exports.printVersionInformation = printVersionInformation;
6
6
  const version_1 = require("../../../util/version");
7
7
  const assert_1 = require("../../../util/assert");
8
8
  const versionRegex = /^\d+\.\d+\.\d+/m;
9
- async function retrieveVersionInformation(shell) {
9
+ async function retrieveVersionInformation(parser) {
10
10
  const flowr = (0, version_1.flowrVersion)().toString();
11
- const r = (await shell.usedRVersion())?.format() ?? 'unknown';
11
+ const r = await parser.rVersion();
12
12
  (0, assert_1.guard)(versionRegex.test(flowr), `flowR version ${flowr} does not match the expected format!`);
13
- (0, assert_1.guard)(r === 'unknown' || versionRegex.test(r), `R version ${r} does not match the expected format!`);
14
- return { flowr: flowr, r: r };
13
+ (0, assert_1.guard)(r === 'unknown' || r === 'none' || versionRegex.test(r), `R version ${r} does not match the expected format!`);
14
+ return { flowr: flowr, r: r, engine: parser.name };
15
15
  }
16
- async function printVersionInformation(output, shell) {
17
- const { flowr, r } = await retrieveVersionInformation(shell);
18
- output.stdout(`flowR: ${flowr}`);
19
- output.stdout(`R: ${r}`);
16
+ async function printVersionInformation(output, parser) {
17
+ const { flowr, r, engine } = await retrieveVersionInformation(parser);
18
+ output.stdout(`Engine: ${engine}`);
19
+ output.stdout(` flowR: ${flowr}`);
20
+ output.stdout(` R: ${r}`);
20
21
  }
21
22
  exports.versionCommand = {
22
23
  description: 'Prints the version of flowR as well as the current version of R',
23
24
  aliases: [],
24
25
  usageExample: ':version',
25
26
  script: false,
26
- fn: (output, shell) => printVersionInformation(output, shell)
27
+ fn: (output, parser) => printVersionInformation(output, parser)
27
28
  };
28
29
  //# sourceMappingURL=repl-version.js.map
@@ -1,7 +1,7 @@
1
1
  import * as readline from 'readline';
2
2
  import type { ReplOutput } from './commands/repl-main';
3
- import { RShell } from '../../r-bridge/shell';
4
3
  import type { MergeableRecord } from '../../util/objects';
4
+ import type { KnownParser } from '../../r-bridge/parser';
5
5
  /**
6
6
  * Used by the repl to provide automatic completions for a given (partial) input line
7
7
  */
@@ -12,16 +12,16 @@ export declare const DEFAULT_REPL_READLINE_CONFIGURATION: readline.ReadLineOptio
12
12
  *
13
13
  * @param output - Defines two methods that every function in the repl uses to output its data.
14
14
  * @param expr - The expression to process.
15
- * @param shell - The {@link RShell} to use (see {@link repl}).
15
+ * @param parser - The {@link RShell} or {@link TreeSitterExecutor} to use (see {@link repl}).
16
16
  * @param allowRSessionAccess - If true, allows the execution of arbitrary R code.
17
17
  */
18
- export declare function replProcessAnswer(output: ReplOutput, expr: string, shell: RShell, allowRSessionAccess: boolean): Promise<void>;
18
+ export declare function replProcessAnswer(output: ReplOutput, expr: string, parser: KnownParser, allowRSessionAccess: boolean): Promise<void>;
19
19
  /**
20
20
  * Options for the {@link repl} function.
21
21
  */
22
22
  export interface FlowrReplOptions extends MergeableRecord {
23
23
  /** The shell to use, if you do not pass one it will automatically create a new one with the `revive` option set to 'always'. */
24
- readonly shell?: RShell;
24
+ readonly parser?: KnownParser;
25
25
  /**
26
26
  * A potentially customized readline interface to be used for the repl to *read* from the user, we write the output with the {@link ReplOutput | `output` } interface.
27
27
  * If you want to provide a custom one but use the same `completer`, refer to {@link replCompleter}.
@@ -47,5 +47,5 @@ export interface FlowrReplOptions extends MergeableRecord {
47
47
  * For the execution, this function makes use of {@link replProcessAnswer}.
48
48
  *
49
49
  */
50
- export declare function repl({ shell, rl, output, historyFile, allowRSessionAccess }: FlowrReplOptions): Promise<void>;
50
+ export declare function repl({ parser, rl, output, historyFile, allowRSessionAccess }: FlowrReplOptions): Promise<void>;
51
51
  export declare function loadReplHistory(historyFile: string): string[] | undefined;
package/cli/repl/core.js CHANGED
@@ -43,7 +43,6 @@ const os_1 = __importDefault(require("os"));
43
43
  const path_1 = __importDefault(require("path"));
44
44
  const fs_1 = __importDefault(require("fs"));
45
45
  const args_1 = require("../../util/args");
46
- const ansi_1 = require("../../util/ansi");
47
46
  const repl_commands_1 = require("./commands/repl-commands");
48
47
  const scripts_info_1 = require("../common/scripts-info");
49
48
  const retriever_1 = require("../../r-bridge/retriever");
@@ -97,14 +96,14 @@ exports.DEFAULT_REPL_READLINE_CONFIGURATION = {
97
96
  removeHistoryDuplicates: true,
98
97
  completer: replCompleter
99
98
  };
100
- async function replProcessStatement(output, statement, shell, allowRSessionAccess) {
99
+ async function replProcessStatement(output, statement, parser, allowRSessionAccess) {
101
100
  if (statement.startsWith(':')) {
102
101
  const command = statement.slice(1).split(' ')[0].toLowerCase();
103
102
  const processor = (0, repl_commands_1.getCommand)(command);
104
103
  const bold = (s) => output.formatter.format(s, { style: 1 /* FontStyles.Bold */ });
105
104
  if (processor) {
106
105
  try {
107
- await processor.fn(output, shell, statement.slice(command.length + 2).trim());
106
+ await processor.fn(output, parser, statement.slice(command.length + 2).trim(), allowRSessionAccess);
108
107
  }
109
108
  catch (e) {
110
109
  output.stdout(`${bold(`Failed to execute command ${command}`)}: ${e?.message}. Using the ${bold('--verbose')} flag on startup may provide additional information.\n`);
@@ -114,11 +113,8 @@ async function replProcessStatement(output, statement, shell, allowRSessionAcces
114
113
  output.stdout(`the command '${command}' is unknown, try ${bold(':help')} for more information\n`);
115
114
  }
116
115
  }
117
- else if (allowRSessionAccess) {
118
- await (0, repl_execute_1.executeRShellCommand)(output, shell, statement);
119
- }
120
116
  else {
121
- output.stderr(`${output.formatter.format('You are not allowed to execute arbitrary R code.', { style: 1 /* FontStyles.Bold */, color: 1 /* Colors.Red */, effect: ansi_1.ColorEffect.Foreground })}\nIf you want to do so, please restart flowR with the ${output.formatter.format('--r-session-access', { style: 1 /* FontStyles.Bold */ })} flag. Please be careful of the security implications of this action.`);
117
+ await (0, repl_execute_1.tryExecuteRShellCommand)(output, parser, statement, allowRSessionAccess);
122
118
  }
123
119
  }
124
120
  /**
@@ -126,13 +122,13 @@ async function replProcessStatement(output, statement, shell, allowRSessionAcces
126
122
  *
127
123
  * @param output - Defines two methods that every function in the repl uses to output its data.
128
124
  * @param expr - The expression to process.
129
- * @param shell - The {@link RShell} to use (see {@link repl}).
125
+ * @param parser - The {@link RShell} or {@link TreeSitterExecutor} to use (see {@link repl}).
130
126
  * @param allowRSessionAccess - If true, allows the execution of arbitrary R code.
131
127
  */
132
- async function replProcessAnswer(output, expr, shell, allowRSessionAccess) {
128
+ async function replProcessAnswer(output, expr, parser, allowRSessionAccess) {
133
129
  const statements = (0, args_1.splitAtEscapeSensitive)(expr, false, ';');
134
130
  for (const statement of statements) {
135
- await replProcessStatement(output, statement, shell, allowRSessionAccess);
131
+ await replProcessStatement(output, statement, parser, allowRSessionAccess);
136
132
  }
137
133
  }
138
134
  /**
@@ -147,7 +143,7 @@ async function replProcessAnswer(output, expr, shell, allowRSessionAccess) {
147
143
  * For the execution, this function makes use of {@link replProcessAnswer}.
148
144
  *
149
145
  */
150
- async function repl({ shell = new shell_1.RShell({ revive: 2 /* RShellReviveOptions.Always */ }), rl = readline.createInterface(exports.DEFAULT_REPL_READLINE_CONFIGURATION), output = repl_main_1.standardReplOutput, historyFile = defaultHistoryFile, allowRSessionAccess = false }) {
146
+ async function repl({ parser = new shell_1.RShell({ revive: 2 /* RShellReviveOptions.Always */ }), rl = readline.createInterface(exports.DEFAULT_REPL_READLINE_CONFIGURATION), output = repl_main_1.standardReplOutput, historyFile = defaultHistoryFile, allowRSessionAccess = false }) {
151
147
  if (historyFile) {
152
148
  rl.on('history', h => fs_1.default.writeFileSync(historyFile, h.join('\n'), { encoding: 'utf-8' }));
153
149
  }
@@ -157,7 +153,7 @@ async function repl({ shell = new shell_1.RShell({ revive: 2 /* RShellReviveOpti
157
153
  await new Promise((resolve, reject) => {
158
154
  rl.question((0, prompt_1.prompt)(), answer => {
159
155
  rl.pause();
160
- replProcessAnswer(output, answer, shell, allowRSessionAccess).then(() => {
156
+ replProcessAnswer(output, answer, parser, allowRSessionAccess).then(() => {
161
157
  rl.resume();
162
158
  resolve();
163
159
  }).catch(reject);
@@ -1,2 +1,2 @@
1
- import type { RShell } from '../../r-bridge/shell';
2
- export declare function printVersionRepl(shell: RShell): Promise<void>;
1
+ import type { KnownParser } from '../../r-bridge/parser';
2
+ export declare function printVersionRepl(parser: KnownParser): Promise<void>;
@@ -2,8 +2,8 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.printVersionRepl = printVersionRepl;
4
4
  const repl_version_1 = require("./commands/repl-version");
5
- async function printVersionRepl(shell) {
6
- const version = await (0, repl_version_1.retrieveVersionInformation)(shell);
7
- console.log(`flowR repl using flowR ${version.flowr}, R ${version.r}`);
5
+ async function printVersionRepl(parser) {
6
+ const version = await (0, repl_version_1.retrieveVersionInformation)(parser);
7
+ console.log(`flowR repl using flowR ${version.flowr}, R ${version.r}, engine ${version.engine}`);
8
8
  }
9
9
  //# sourceMappingURL=print-version.js.map
@@ -1,20 +1,20 @@
1
1
  import type { Socket } from './net';
2
2
  import { DEFAULT_SLICING_PIPELINE } from '../../../core/steps/pipeline/default-pipelines';
3
- import type { RShell } from '../../../r-bridge/shell';
4
3
  import type { PipelineOutput } from '../../../core/steps/pipeline/pipeline';
5
4
  import type { DeepPartial } from 'ts-essentials';
5
+ import type { KnownParser } from '../../../r-bridge/parser';
6
6
  /**
7
7
  * Each connection handles a single client, answering to its requests.
8
8
  * There is no need to construct this class manually, {@link FlowRServer} will do it for you.
9
9
  */
10
10
  export declare class FlowRServerConnection {
11
11
  private readonly socket;
12
- private readonly shell;
12
+ private readonly parser;
13
13
  private readonly name;
14
14
  private readonly logger;
15
15
  private readonly allowRSessionAccess;
16
16
  private readonly fileMap;
17
- constructor(socket: Socket, name: string, shell: RShell, allowRSessionAccess: boolean);
17
+ constructor(socket: Socket, name: string, parser: KnownParser, allowRSessionAccess: boolean);
18
18
  private currentMessageBuffer;
19
19
  private handleData;
20
20
  private handleFileAnalysisRequest;
@@ -35,7 +35,6 @@ const message_slice_1 = require("./messages/message-slice");
35
35
  const server_1 = require("./server");
36
36
  const message_repl_1 = require("./messages/message-repl");
37
37
  const core_1 = require("../core");
38
- const pipeline_executor_1 = require("../../../core/pipeline-executor");
39
38
  const cfg_1 = require("../../../util/cfg/cfg");
40
39
  const quads_1 = require("../../../util/quads");
41
40
  const print_1 = require("../../../core/print/print");
@@ -60,16 +59,16 @@ const query_1 = require("../../../queries/query");
60
59
  */
61
60
  class FlowRServerConnection {
62
61
  socket;
63
- shell;
62
+ parser;
64
63
  name;
65
64
  logger;
66
65
  allowRSessionAccess;
67
66
  // maps token to information
68
67
  fileMap = new Map();
69
68
  // we do not have to ensure synchronized shell-access as we are always running synchronized
70
- constructor(socket, name, shell, allowRSessionAccess) {
69
+ constructor(socket, name, parser, allowRSessionAccess) {
71
70
  this.socket = socket;
72
- this.shell = shell;
71
+ this.parser = parser;
73
72
  this.name = name;
74
73
  this.logger = server_1.serverLog.getSubLogger({ name });
75
74
  this.socket.on('data', data => this.handleData(String(data)));
@@ -198,8 +197,7 @@ class FlowRServerConnection {
198
197
  else {
199
198
  throw new Error('Either content or filepath must be defined.');
200
199
  }
201
- const slicer = new pipeline_executor_1.PipelineExecutor(default_pipelines_1.DEFAULT_SLICING_PIPELINE, {
202
- shell: this.shell,
200
+ const slicer = (0, default_pipelines_1.createSlicePipeline)(this.parser, {
203
201
  request,
204
202
  criterion: [] // currently unknown
205
203
  });
@@ -270,7 +268,7 @@ class FlowRServerConnection {
270
268
  formatter: request.ansi ? ansi_1.ansiFormatter : ansi_1.voidFormatter,
271
269
  stdout: msg => out('stdout', msg),
272
270
  stderr: msg => out('stderr', msg)
273
- }, request.expression, this.shell, this.allowRSessionAccess).then(() => {
271
+ }, request.expression, this.parser, this.allowRSessionAccess).then(() => {
274
272
  (0, send_1.sendMessage)(this.socket, {
275
273
  type: 'end-repl-execution',
276
274
  id: request.id
@@ -13,7 +13,8 @@ exports.helloMessageDefinition = {
13
13
  clientName: joi_1.default.string().required().description('A unique name that is assigned to each client. It has no semantic meaning and is only used/useful for debugging.'),
14
14
  versions: joi_1.default.object({
15
15
  flowr: joi_1.default.string().required().description('The version of the flowr server running in semver format.'),
16
- r: joi_1.default.string().required().description('The version of the underlying R shell running in semver format.')
16
+ r: joi_1.default.string().required().description('The version of the underlying R shell running in semver format.'),
17
+ engine: joi_1.default.string().required().description('The parser backend that is used to parse the R code.')
17
18
  }).required()
18
19
  }).required()
19
20
  };
@@ -1,6 +1,6 @@
1
1
  import type { Server } from './net';
2
2
  import { FlowrLogger } from '../../../util/log';
3
- import type { RShell } from '../../../r-bridge/shell';
3
+ import type { KnownEngines } from '../../../config';
4
4
  export declare const serverLog: FlowrLogger;
5
5
  /**
6
6
  * This class controls the TCP server, which can be started by calling {@link start}.
@@ -9,13 +9,14 @@ export declare const serverLog: FlowrLogger;
9
9
  */
10
10
  export declare class FlowRServer {
11
11
  private readonly server;
12
- private readonly shell;
12
+ private readonly engines;
13
+ private readonly defaultEngine;
13
14
  private versionInformation;
14
15
  private readonly allowRSessionAccess;
15
16
  /** maps names to the respective connection */
16
17
  private readonly connections;
17
18
  private nameCounter;
18
- constructor(shell: RShell, allowRSessionAccess: boolean, server?: Server);
19
+ constructor(engines: KnownEngines, defaultEngine: keyof KnownEngines, allowRSessionAccess: boolean, server?: Server);
19
20
  start(port: number): Promise<void>;
20
21
  private onConnect;
21
22
  }
@@ -15,20 +15,22 @@ exports.serverLog = new log_1.FlowrLogger({ name: 'server' });
15
15
  */
16
16
  class FlowRServer {
17
17
  server;
18
- shell;
18
+ engines;
19
+ defaultEngine;
19
20
  versionInformation;
20
21
  allowRSessionAccess;
21
22
  /** maps names to the respective connection */
22
23
  connections = new Map();
23
24
  nameCounter = 0;
24
- constructor(shell, allowRSessionAccess, server = new net_1.NetServer()) {
25
+ constructor(engines, defaultEngine, allowRSessionAccess, server = new net_1.NetServer()) {
25
26
  this.server = server;
26
27
  this.server.onConnect(c => this.onConnect(c));
27
- this.shell = shell;
28
+ this.engines = engines;
29
+ this.defaultEngine = defaultEngine;
28
30
  this.allowRSessionAccess = allowRSessionAccess;
29
31
  }
30
32
  async start(port) {
31
- this.versionInformation = await (0, repl_version_1.retrieveVersionInformation)(this.shell);
33
+ this.versionInformation = await (0, repl_version_1.retrieveVersionInformation)(this.engines[this.defaultEngine]);
32
34
  this.server.start(port);
33
35
  exports.serverLog.info(`Server listening on port ${port}`);
34
36
  }
@@ -39,7 +41,7 @@ class FlowRServer {
39
41
  }
40
42
  const name = `client-${this.nameCounter++}`;
41
43
  exports.serverLog.info(`Client connected: ${(0, send_1.getUnnamedSocketName)(c)} as "${name}"`);
42
- this.connections.set(name, new connection_1.FlowRServerConnection(c, name, this.shell, this.allowRSessionAccess));
44
+ this.connections.set(name, new connection_1.FlowRServerConnection(c, name, this.engines[this.defaultEngine], this.allowRSessionAccess));
43
45
  helloClient(c, name, this.versionInformation);
44
46
  c.on('close', () => {
45
47
  this.connections.delete(name);
package/cli/slicer-app.js CHANGED
@@ -25,7 +25,7 @@ const options = (0, script_1.processCommandLineArgs)('slicer', ['input', 'criter
25
25
  ]
26
26
  });
27
27
  async function getSlice() {
28
- const slicer = new slicer_1.BenchmarkSlicer();
28
+ const slicer = new slicer_1.BenchmarkSlicer('r-shell');
29
29
  (0, assert_1.guard)(options.input !== undefined, 'input must be given');
30
30
  (0, assert_1.guard)(options.criterion !== undefined, 'a slicing criterion must be given');
31
31
  await slicer.init(options['input-is-text']
package/config.d.ts CHANGED
@@ -1,6 +1,7 @@
1
1
  import type { MergeableRecord } from './util/objects';
2
2
  import Joi from 'joi';
3
3
  import type { BuiltInDefinitions } from './dataflow/environments/built-in-config';
4
+ import type { KnownParser } from './r-bridge/parser';
4
5
  export declare enum VariableResolve {
5
6
  /** Don't resolve constants at all */
6
7
  Disabled = "disabled",
@@ -14,10 +15,6 @@ export interface FlowrConfigOptions extends MergeableRecord {
14
15
  * Whether source calls should be ignored, causing {@link processSourceCall}'s behavior to be skipped
15
16
  */
16
17
  readonly ignoreSourceCalls: boolean;
17
- /**
18
- * The path to the R executable to use. If this is undefined, {@link DEFAULT_R_PATH} will be used.
19
- */
20
- readonly rPath: string | undefined;
21
18
  /** Configure language semantics and how flowR handles them */
22
19
  readonly semantics: {
23
20
  /** Semantics regarding the handlings of the environment */
@@ -31,6 +28,15 @@ export interface FlowrConfigOptions extends MergeableRecord {
31
28
  };
32
29
  };
33
30
  };
31
+ /**
32
+ * The engines to use for interacting with R code. Currently supports {@link TreeSitterEngineConfig} and {@link RShellEngineConfig}.
33
+ * An empty array means all available engines will be used.
34
+ */
35
+ readonly engines: readonly EngineConfig[];
36
+ /**
37
+ * The default engine to use for interacting with R code. If this is undefined, an arbitrary engine from {@link engines} will be used.
38
+ */
39
+ readonly defaultEngine?: EngineConfig['type'];
34
40
  /** How to resolve constants, constraints, cells, ... */
35
41
  readonly solver: {
36
42
  /**
@@ -45,9 +51,35 @@ export interface FlowrConfigOptions extends MergeableRecord {
45
51
  readonly pointerTracking: boolean;
46
52
  };
47
53
  }
54
+ export interface TreeSitterEngineConfig extends MergeableRecord {
55
+ readonly type: 'tree-sitter';
56
+ /**
57
+ * The path to the tree-sitter-r WASM binary to use. If this is undefined, {@link DEFAULT_TREE_SITTER_R_WASM_PATH} will be used.
58
+ */
59
+ readonly wasmPath?: string;
60
+ /**
61
+ * 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
+ */
63
+ readonly treeSitterWasmPath?: string;
64
+ }
65
+ export interface RShellEngineConfig extends MergeableRecord {
66
+ readonly type: 'r-shell';
67
+ /**
68
+ * The path to the R executable to use. If this is undefined, {@link DEFAULT_R_PATH} will be used.
69
+ */
70
+ readonly rPath?: string;
71
+ }
72
+ export type EngineConfig = TreeSitterEngineConfig | RShellEngineConfig;
73
+ export type KnownEngines = {
74
+ [T in EngineConfig['type']]?: KnownParser;
75
+ };
48
76
  export declare const defaultConfigOptions: FlowrConfigOptions;
49
77
  export declare const flowrConfigFileSchema: Joi.ObjectSchema<any>;
50
78
  export declare function setConfigFile(file: string | undefined, workingDirectory?: string, forceLoad?: boolean): void;
51
79
  export declare function parseConfig(jsonString: string): FlowrConfigOptions | undefined;
52
80
  export declare function setConfig(config: FlowrConfigOptions): void;
81
+ export declare function amendConfig(amendment: Partial<FlowrConfigOptions>): void;
53
82
  export declare function getConfig(): FlowrConfigOptions;
83
+ export declare function getEngineConfig<T extends EngineConfig['type']>(engine: T): EngineConfig & {
84
+ type: T;
85
+ } | undefined;
package/config.js CHANGED
@@ -7,7 +7,9 @@ exports.flowrConfigFileSchema = exports.defaultConfigOptions = exports.VariableR
7
7
  exports.setConfigFile = setConfigFile;
8
8
  exports.parseConfig = parseConfig;
9
9
  exports.setConfig = setConfig;
10
+ exports.amendConfig = amendConfig;
10
11
  exports.getConfig = getConfig;
12
+ exports.getEngineConfig = getEngineConfig;
11
13
  const objects_1 = require("./util/objects");
12
14
  const path_1 = __importDefault(require("path"));
13
15
  const fs_1 = __importDefault(require("fs"));
@@ -23,6 +25,10 @@ var VariableResolve;
23
25
  /** Only resolve directly assigned builtin constants */
24
26
  VariableResolve["Builtin"] = "builtin";
25
27
  })(VariableResolve || (exports.VariableResolve = VariableResolve = {}));
28
+ const defaultEngineConfigs = {
29
+ 'tree-sitter': { type: 'tree-sitter' },
30
+ 'r-shell': { type: 'r-shell' }
31
+ };
26
32
  exports.defaultConfigOptions = {
27
33
  ignoreSourceCalls: false,
28
34
  rPath: undefined,
@@ -34,6 +40,8 @@ exports.defaultConfigOptions = {
34
40
  }
35
41
  }
36
42
  },
43
+ engines: [],
44
+ defaultEngine: 'r-shell',
37
45
  solver: {
38
46
  variables: VariableResolve.Alias,
39
47
  pointerTracking: true
@@ -41,7 +49,6 @@ exports.defaultConfigOptions = {
41
49
  };
42
50
  exports.flowrConfigFileSchema = joi_1.default.object({
43
51
  ignoreSourceCalls: joi_1.default.boolean().optional().description('Whether source calls should be ignored, causing {@link processSourceCall}\'s behavior to be skipped.'),
44
- rPath: joi_1.default.string().optional().description('The path to the R executable to use. If this is undefined, this uses the default path.'),
45
52
  semantics: joi_1.default.object({
46
53
  environment: joi_1.default.object({
47
54
  overwriteBuiltIns: joi_1.default.object({
@@ -50,6 +57,15 @@ exports.flowrConfigFileSchema = joi_1.default.object({
50
57
  }).optional().description('Do you want to overwrite (parts) of the builtin definition?')
51
58
  }).optional().description('Semantics regarding the handlings of the environment.')
52
59
  }).description('Configure language semantics and how flowR handles them.'),
60
+ engines: joi_1.default.array().items(joi_1.default.alternatives(joi_1.default.object({
61
+ type: joi_1.default.string().required().valid('tree-sitter').description('Use the tree sitter engine.'),
62
+ 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.'),
63
+ 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.')
64
+ }).description('The configuration for the tree sitter engine.'), joi_1.default.object({
65
+ type: joi_1.default.string().required().valid('r-shell').description('Use the R shell engine.'),
66
+ 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
+ }).description('The configuration for the R shell engine.'))).min(1).description('The engine or set of engines to use for interacting with R code. An empty array means all available engines will be used.'),
68
+ 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.'),
53
69
  solver: joi_1.default.object({
54
70
  variables: joi_1.default.string().valid(...Object.values(VariableResolve)).description('How to resolve variables and their values.'),
55
71
  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.')
@@ -88,6 +104,10 @@ function parseConfig(jsonString) {
88
104
  function setConfig(config) {
89
105
  currentConfig = config;
90
106
  }
107
+ function amendConfig(amendment) {
108
+ setConfig((0, objects_1.deepMergeObject)(getConfig(), amendment));
109
+ log_1.log.trace(`Amending config with ${JSON.stringify(amendment)}, resulting in ${JSON.stringify(getConfig())}}`);
110
+ }
91
111
  function getConfig() {
92
112
  // lazy-load the config based on the current settings
93
113
  if (currentConfig === undefined) {
@@ -95,6 +115,15 @@ function getConfig() {
95
115
  }
96
116
  return currentConfig;
97
117
  }
118
+ function getEngineConfig(engine) {
119
+ const config = getConfig().engines;
120
+ if (!config.length) {
121
+ return defaultEngineConfigs[engine];
122
+ }
123
+ else {
124
+ return config.find(e => e.type == engine);
125
+ }
126
+ }
98
127
  function loadConfigFromFile(configFile, workingDirectory) {
99
128
  if (configFile !== undefined) {
100
129
  let searchPath = path_1.default.resolve(workingDirectory);
@@ -61,7 +61,7 @@ import type { Pipeline, PipelineInput, PipelineOutput, PipelinePerRequestInput,
61
61
  *
62
62
  * ```ts
63
63
  * const slicer = new PipelineExecutor(DEFAULT_SLICING_PIPELINE, {
64
- * shell: new RShell(),
64
+ * parser: new RShell(),
65
65
  * // of course, the criterion and request given here are just examples, you can use whatever you want to slice!
66
66
  * criterion: ['2@b'],
67
67
  * request: requestFromInput('b <- 3; x <- 5\ncat(b)'),
@@ -65,7 +65,7 @@ const built_in_config_1 = require("../dataflow/environments/built-in-config");
65
65
  *
66
66
  * ```ts
67
67
  * const slicer = new PipelineExecutor(DEFAULT_SLICING_PIPELINE, {
68
- * shell: new RShell(),
68
+ * parser: new RShell(),
69
69
  * // of course, the criterion and request given here are just examples, you can use whatever you want to slice!
70
70
  * criterion: ['2@b'],
71
71
  * request: requestFromInput('b <- 3; x <- 5\ncat(b)'),
@@ -1,25 +1,12 @@
1
1
  import { internalPrinter } from '../../../print/print';
2
2
  import { PipelineStepStage } from '../../pipeline-step';
3
- import type { RShellExecutor } from '../../../../r-bridge/shell-executor';
4
- import type { RShell } from '../../../../r-bridge/shell';
5
- import type { RParseRequests } from '../../../../r-bridge/retriever';
6
3
  import type { QuadSerializationConfiguration } from '../../../../util/quads';
7
- export interface ParseRequiredInput {
8
- /** This is the {@link RShell} or {@link RShellExecutor} connection to be used to obtain the original parses AST of the R code */
9
- readonly shell: RShell | RShellExecutor;
10
- /** The request which essentially indicates the input to extract the AST from */
11
- readonly request: RParseRequests;
12
- }
13
- export interface ParseStepOutput {
14
- /** The parsed AST of the R code as given by the R parse side */
15
- readonly parsed: string;
16
- }
17
- declare function processor(_results: unknown, input: Partial<ParseRequiredInput>): Promise<ParseStepOutput>;
4
+ import type { ParseRequiredInput } from '../../../../r-bridge/parser';
18
5
  export declare const PARSE_WITH_R_SHELL_STEP: {
19
6
  readonly name: "parse";
20
7
  readonly humanReadableName: "parse with R shell";
21
8
  readonly description: "Parse the given R code into an AST";
22
- readonly processor: typeof processor;
9
+ readonly processor: (_results: unknown, input: Partial<ParseRequiredInput<string>>) => Promise<import("../../../../r-bridge/parser").ParseStepOutput<string>>;
23
10
  readonly executed: PipelineStepStage.OncePerFile;
24
11
  readonly printer: {
25
12
  readonly 0: typeof internalPrinter;
@@ -27,9 +14,8 @@ export declare const PARSE_WITH_R_SHELL_STEP: {
27
14
  (value: any, replacer?: (this: any, key: string, value: any) => any, space?: string | number): string;
28
15
  (value: any, replacer?: (number | string)[] | null, space?: string | number): string;
29
16
  };
30
- readonly 5: ({ parsed }: ParseStepOutput, config: QuadSerializationConfiguration) => string;
17
+ readonly 5: ({ parsed }: import("../../../../r-bridge/parser").ParseStepOutput<string>, config: QuadSerializationConfiguration) => string;
31
18
  };
32
19
  readonly dependencies: readonly [];
33
- readonly requiredInput: ParseRequiredInput;
20
+ readonly requiredInput: ParseRequiredInput<string>;
34
21
  };
35
- export {};
@@ -3,21 +3,12 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.PARSE_WITH_R_SHELL_STEP = void 0;
4
4
  const print_1 = require("../../../print/print");
5
5
  const parse_printer_1 = require("../../../print/parse-printer");
6
- const retriever_1 = require("../../../../r-bridge/retriever");
7
- async function processor(_results, input) {
8
- /* in the future, we want to expose all cases */
9
- if (Array.isArray(input.request)) {
10
- return { parsed: await (0, retriever_1.retrieveParseDataFromRCode)(input.request[0], input.shell) };
11
- }
12
- else {
13
- return { parsed: await (0, retriever_1.retrieveParseDataFromRCode)(input.request, input.shell) };
14
- }
15
- }
6
+ const parser_1 = require("../../../../r-bridge/parser");
16
7
  exports.PARSE_WITH_R_SHELL_STEP = {
17
8
  name: 'parse',
18
9
  humanReadableName: 'parse with R shell',
19
10
  description: 'Parse the given R code into an AST',
20
- processor,
11
+ processor: (parser_1.parseRequests),
21
12
  executed: 0 /* PipelineStepStage.OncePerFile */,
22
13
  printer: {
23
14
  [0 /* StepOutputFormat.Internal */]: print_1.internalPrinter,