@eagleoutice/flowr 1.4.1 → 1.4.2

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 (133) hide show
  1. package/README.md +3 -3
  2. package/abstract-interpretation/processor.js +9 -3
  3. package/benchmark/slicer.d.ts +0 -3
  4. package/benchmark/slicer.js +4 -16
  5. package/benchmark/stats/print.js +0 -2
  6. package/benchmark/stats/stats.d.ts +2 -3
  7. package/benchmark/stats/stats.js +1 -1
  8. package/cli/benchmark-app.d.ts +1 -0
  9. package/cli/benchmark-app.js +21 -6
  10. package/cli/benchmark-helper-app.d.ts +2 -0
  11. package/cli/benchmark-helper-app.js +15 -6
  12. package/cli/common/options.js +4 -1
  13. package/cli/common/scripts-info.d.ts +1 -0
  14. package/cli/common/scripts-info.js +15 -1
  15. package/cli/export-quads-app.js +1 -5
  16. package/cli/repl/commands/cfg.js +2 -2
  17. package/cli/repl/commands/commands.d.ts +3 -1
  18. package/cli/repl/commands/commands.js +67 -28
  19. package/cli/repl/commands/dataflow.js +2 -2
  20. package/cli/repl/commands/normalize.js +2 -2
  21. package/cli/repl/commands/parse.js +12 -12
  22. package/cli/repl/commands/quit.js +4 -1
  23. package/cli/repl/core.d.ts +4 -2
  24. package/cli/repl/core.js +63 -7
  25. package/cli/repl/execute.d.ts +1 -1
  26. package/cli/repl/execute.js +3 -3
  27. package/cli/repl/server/connection.js +3 -8
  28. package/cli/repl/server/net.js +2 -2
  29. package/cli/statistics-helper-app.js +0 -1
  30. package/cli/summarizer-app.js +1 -2
  31. package/config.d.ts +16 -0
  32. package/config.js +75 -0
  33. package/core/input.d.ts +1 -1
  34. package/core/output.d.ts +1 -2
  35. package/core/print/parse-printer.d.ts +1 -2
  36. package/core/print/parse-printer.js +6 -4
  37. package/core/slicer.js +4 -8
  38. package/core/steps.d.ts +7 -24
  39. package/core/steps.js +5 -12
  40. package/dataflow/environments/environment.js +8 -0
  41. package/dataflow/environments/register.js +1 -0
  42. package/dataflow/extractor.d.ts +2 -2
  43. package/dataflow/extractor.js +10 -2
  44. package/dataflow/internal/process/functions/function-call.js +7 -1
  45. package/dataflow/internal/process/functions/source.d.ts +8 -0
  46. package/dataflow/internal/process/functions/source.js +81 -0
  47. package/dataflow/processor.d.ts +10 -1
  48. package/flowr.d.ts +2 -0
  49. package/flowr.js +14 -9
  50. package/package.json +41 -18
  51. package/r-bridge/lang-4.x/ast/index.d.ts +1 -0
  52. package/r-bridge/lang-4.x/ast/index.js +3 -0
  53. package/r-bridge/lang-4.x/ast/model/processing/decorate.d.ts +2 -0
  54. package/r-bridge/lang-4.x/ast/model/processing/decorate.js +6 -1
  55. package/r-bridge/lang-4.x/ast/parser/json/format.d.ts +14 -0
  56. package/r-bridge/lang-4.x/ast/parser/json/format.js +26 -0
  57. package/r-bridge/lang-4.x/ast/parser/json/parser.d.ts +7 -0
  58. package/r-bridge/lang-4.x/ast/parser/json/parser.js +57 -0
  59. package/r-bridge/lang-4.x/ast/parser/xml/data.d.ts +0 -3
  60. package/r-bridge/lang-4.x/ast/parser/xml/index.d.ts +0 -2
  61. package/r-bridge/lang-4.x/ast/parser/xml/index.js +0 -2
  62. package/r-bridge/lang-4.x/ast/parser/xml/input-format.d.ts +5 -1
  63. package/r-bridge/lang-4.x/ast/parser/xml/input-format.js +7 -10
  64. package/r-bridge/lang-4.x/ast/parser/xml/internal/access.js +2 -2
  65. package/r-bridge/lang-4.x/ast/parser/xml/internal/control/if-then-else.js +1 -1
  66. package/r-bridge/lang-4.x/ast/parser/xml/internal/control/if-then.js +2 -2
  67. package/r-bridge/lang-4.x/ast/parser/xml/internal/expression/expression.js +4 -4
  68. package/r-bridge/lang-4.x/ast/parser/xml/internal/functions/argument.js +2 -2
  69. package/r-bridge/lang-4.x/ast/parser/xml/internal/functions/call.js +4 -4
  70. package/r-bridge/lang-4.x/ast/parser/xml/internal/functions/definition.js +2 -2
  71. package/r-bridge/lang-4.x/ast/parser/xml/internal/functions/parameter.js +2 -2
  72. package/r-bridge/lang-4.x/ast/parser/xml/internal/index.d.ts +0 -1
  73. package/r-bridge/lang-4.x/ast/parser/xml/internal/index.js +0 -1
  74. package/r-bridge/lang-4.x/ast/parser/xml/internal/loops/break.js +2 -2
  75. package/r-bridge/lang-4.x/ast/parser/xml/internal/loops/for.js +3 -6
  76. package/r-bridge/lang-4.x/ast/parser/xml/internal/loops/next.js +2 -2
  77. package/r-bridge/lang-4.x/ast/parser/xml/internal/loops/repeat.js +2 -2
  78. package/r-bridge/lang-4.x/ast/parser/xml/internal/loops/while.js +2 -2
  79. package/r-bridge/lang-4.x/ast/parser/xml/internal/meta.d.ts +6 -11
  80. package/r-bridge/lang-4.x/ast/parser/xml/internal/meta.js +15 -23
  81. package/r-bridge/lang-4.x/ast/parser/xml/internal/operators/binary.js +6 -6
  82. package/r-bridge/lang-4.x/ast/parser/xml/internal/operators/unary.js +3 -3
  83. package/r-bridge/lang-4.x/ast/parser/xml/internal/other/comment.js +2 -2
  84. package/r-bridge/lang-4.x/ast/parser/xml/internal/other/line-directive.js +2 -2
  85. package/r-bridge/lang-4.x/ast/parser/xml/internal/structure/elements.js +3 -3
  86. package/r-bridge/lang-4.x/ast/parser/xml/internal/structure/root.js +3 -4
  87. package/r-bridge/lang-4.x/ast/parser/xml/internal/structure/single-element.js +2 -2
  88. package/r-bridge/lang-4.x/ast/parser/xml/internal/values/number.js +2 -2
  89. package/r-bridge/lang-4.x/ast/parser/xml/internal/values/string.js +2 -2
  90. package/r-bridge/lang-4.x/ast/parser/xml/internal/values/symbol.js +4 -4
  91. package/r-bridge/lang-4.x/values.d.ts +0 -1
  92. package/r-bridge/lang-4.x/values.js +14 -6
  93. package/r-bridge/retriever.d.ts +25 -21
  94. package/r-bridge/retriever.js +73 -23
  95. package/r-bridge/shell-executor.d.ts +3 -17
  96. package/r-bridge/shell-executor.js +9 -78
  97. package/r-bridge/shell.d.ts +5 -27
  98. package/r-bridge/shell.js +31 -92
  99. package/statistics/features/supported/assignments/post-process.js +6 -6
  100. package/statistics/features/supported/comments/post-process.js +2 -2
  101. package/statistics/features/supported/data-access/post-process.js +4 -4
  102. package/statistics/features/supported/defined-functions/post-process.js +4 -4
  103. package/statistics/features/supported/expression-list/post-process.js +3 -3
  104. package/statistics/features/supported/loops/post-process.js +3 -3
  105. package/statistics/features/supported/used-functions/post-process.js +5 -5
  106. package/statistics/features/supported/used-packages/post-process.js +5 -5
  107. package/statistics/features/supported/values/post-process.js +3 -3
  108. package/statistics/features/supported/variables/post-process.js +3 -3
  109. package/statistics/output/ansi.js +1 -1
  110. package/statistics/statistics.js +7 -8
  111. package/util/args.d.ts +8 -4
  112. package/util/args.js +11 -4
  113. package/util/cfg/visitor.js +1 -1
  114. package/util/files.d.ts +6 -0
  115. package/util/files.js +11 -1
  116. package/util/log.js +3 -0
  117. package/util/summarizer/benchmark/first-phase/input.d.ts +2 -1
  118. package/util/summarizer/benchmark/first-phase/input.js +20 -4
  119. package/util/summarizer/benchmark/first-phase/process.d.ts +2 -1
  120. package/util/summarizer/benchmark/first-phase/process.js +14 -5
  121. package/util/summarizer/benchmark/second-phase/graph.js +1 -1
  122. package/util/summarizer/benchmark/second-phase/process.d.ts +2 -0
  123. package/util/summarizer/benchmark/second-phase/process.js +48 -11
  124. package/util/summarizer/benchmark/summarizer.d.ts +0 -4
  125. package/util/summarizer/benchmark/summarizer.js +16 -7
  126. package/util/summarizer/statistics/first-phase/process.js +8 -8
  127. package/util/summarizer/statistics/post-process/post-process-output.js +4 -5
  128. package/r-bridge/lang-4.x/ast/parser/xml/config.d.ts +0 -25
  129. package/r-bridge/lang-4.x/ast/parser/xml/config.js +0 -16
  130. package/r-bridge/lang-4.x/ast/parser/xml/internal/xml-to-json.d.ts +0 -9
  131. package/r-bridge/lang-4.x/ast/parser/xml/internal/xml-to-json.js +0 -51
  132. package/r-bridge/lang-4.x/ast/parser/xml/parser.d.ts +0 -17
  133. package/r-bridge/lang-4.x/ast/parser/xml/parser.js +0 -30
@@ -7,6 +7,9 @@ exports.quitCommand = {
7
7
  aliases: ['q', 'exit'],
8
8
  usageExample: ':quit',
9
9
  script: false,
10
- fn: () => { log_1.log.info('bye'); process.exit(0); }
10
+ fn: () => {
11
+ log_1.log.info('bye');
12
+ process.exit(0);
13
+ }
11
14
  };
12
15
  //# sourceMappingURL=quit.js.map
@@ -6,7 +6,7 @@
6
6
  */
7
7
  import { RShell } from '../../r-bridge';
8
8
  import type { ReplOutput } from './commands';
9
- import * as readline from 'node:readline';
9
+ import * as readline from 'readline';
10
10
  /**
11
11
  * Used by the repl to provide automatic completions for a given (partial) input line
12
12
  */
@@ -32,8 +32,10 @@ export declare function replProcessAnswer(output: ReplOutput, expr: string, shel
32
32
  * If you want to provide a custom one but use the same `completer`, refer to {@link replCompleter}.
33
33
  * For the default arguments, see {@link DEFAULT_REPL_READLINE_CONFIGURATION}.
34
34
  * @param output - Defines two methods that every function in the repl uses to output its data.
35
+ * @param historyFile - The file to use for persisting the repl's history. Passing undefined causes history not to be saved.
35
36
  *
36
37
  * For the execution, this function makes use of {@link replProcessAnswer}
37
38
  *
38
39
  */
39
- export declare function repl(shell?: RShell, rl?: readline.Interface, output?: ReplOutput): Promise<void>;
40
+ export declare function repl(shell?: RShell, rl?: readline.Interface, output?: ReplOutput, historyFile?: string | undefined): Promise<void>;
41
+ export declare function loadReplHistory(historyFile: string): string[] | undefined;
package/cli/repl/core.js CHANGED
@@ -22,8 +22,11 @@ var __importStar = (this && this.__importStar) || function (mod) {
22
22
  __setModuleDefault(result, mod);
23
23
  return result;
24
24
  };
25
+ var __importDefault = (this && this.__importDefault) || function (mod) {
26
+ return (mod && mod.__esModule) ? mod : { "default": mod };
27
+ };
25
28
  Object.defineProperty(exports, "__esModule", { value: true });
26
- exports.repl = exports.replProcessAnswer = exports.DEFAULT_REPL_READLINE_CONFIGURATION = exports.replCompleter = void 0;
29
+ exports.loadReplHistory = exports.repl = exports.replProcessAnswer = exports.DEFAULT_REPL_READLINE_CONFIGURATION = exports.replCompleter = void 0;
27
30
  /**
28
31
  * Basically a helper file to allow the main 'flowr' script (located in the source root) to provide its repl
29
32
  *
@@ -33,15 +36,51 @@ const r_bridge_1 = require("../../r-bridge");
33
36
  const statistics_1 = require("../../statistics");
34
37
  const prompt_1 = require("./prompt");
35
38
  const commands_1 = require("./commands");
36
- const readline = __importStar(require("node:readline"));
39
+ const readline = __importStar(require("readline"));
37
40
  const args_1 = require("../../util/args");
38
41
  const execute_1 = require("./commands/execute");
39
- const replCompleterKeywords = Array.from(commands_1.commandNames, s => `:${s}`);
42
+ const os_1 = __importDefault(require("os"));
43
+ const path_1 = __importDefault(require("path"));
44
+ const fs_1 = __importDefault(require("fs"));
45
+ const common_1 = require("../common");
46
+ let _replCompleterKeywords = undefined;
47
+ function replCompleterKeywords() {
48
+ if (_replCompleterKeywords === undefined) {
49
+ _replCompleterKeywords = Array.from((0, commands_1.getCommandNames)(), s => `:${s}`);
50
+ }
51
+ return _replCompleterKeywords;
52
+ }
53
+ const defaultHistoryFile = path_1.default.join(os_1.default.tmpdir(), '.flowrhistory');
40
54
  /**
41
55
  * Used by the repl to provide automatic completions for a given (partial) input line
42
56
  */
43
57
  function replCompleter(line) {
44
- return [replCompleterKeywords.filter(k => k.startsWith(line)), line];
58
+ const splitLine = (0, args_1.splitAtEscapeSensitive)(line);
59
+ // did we just type a space (and are starting a new arg right now)?
60
+ const startingNewArg = line.endsWith(' ');
61
+ // if we typed a command fully already, autocomplete the arguments
62
+ if (splitLine.length > 1 || startingNewArg) {
63
+ const commandNameColon = replCompleterKeywords().find(k => splitLine[0] === k);
64
+ if (commandNameColon) {
65
+ const completions = [];
66
+ const commandName = commandNameColon.slice(1);
67
+ if ((0, commands_1.getCommand)(commandName)?.script === true) {
68
+ // autocomplete script arguments
69
+ const options = common_1.scripts[commandName].options;
70
+ completions.push(...(0, common_1.getValidOptionsForCompletion)(options, splitLine).map(o => `${o} `));
71
+ }
72
+ else {
73
+ // autocomplete command arguments (specifically, autocomplete the file:// protocol)
74
+ completions.push(r_bridge_1.fileProtocol);
75
+ }
76
+ // add an empty option so that it doesn't autocomplete the only defined option immediately
77
+ completions.push(' ');
78
+ const currentArg = startingNewArg ? '' : splitLine[splitLine.length - 1];
79
+ return [completions.filter(a => a.startsWith(currentArg)), currentArg];
80
+ }
81
+ }
82
+ // if no command is already typed, just return all commands that match
83
+ return [replCompleterKeywords().filter(k => k.startsWith(line)).map(k => `${k} `), line];
45
84
  }
46
85
  exports.replCompleter = replCompleter;
47
86
  exports.DEFAULT_REPL_READLINE_CONFIGURATION = {
@@ -49,6 +88,7 @@ exports.DEFAULT_REPL_READLINE_CONFIGURATION = {
49
88
  output: process.stdout,
50
89
  tabSize: 4,
51
90
  terminal: true,
91
+ history: loadReplHistory(defaultHistoryFile),
52
92
  removeHistoryDuplicates: true,
53
93
  completer: replCompleter
54
94
  };
@@ -57,7 +97,12 @@ async function replProcessStatement(output, statement, shell) {
57
97
  const command = statement.slice(1).split(' ')[0].toLowerCase();
58
98
  const processor = (0, commands_1.getCommand)(command);
59
99
  if (processor) {
60
- await processor.fn(output, shell, statement.slice(command.length + 2).trim());
100
+ try {
101
+ await processor.fn(output, shell, statement.slice(command.length + 2).trim());
102
+ }
103
+ catch (e) {
104
+ console.log(`${(0, statistics_1.bold)(`Failed to execute command ${command}`)}: ${e?.message}. Using the ${(0, statistics_1.bold)('--verbose')} flag on startup may provide additional information.`);
105
+ }
61
106
  }
62
107
  else {
63
108
  console.log(`the command '${command}' is unknown, try ${(0, statistics_1.bold)(':help')} for more information`);
@@ -75,7 +120,7 @@ async function replProcessStatement(output, statement, shell) {
75
120
  * @param shell - The {@link RShell} to use (see {@link repl}).
76
121
  */
77
122
  async function replProcessAnswer(output, expr, shell) {
78
- const statements = (0, args_1.splitAtEscapeSensitive)(expr, ';');
123
+ const statements = (0, args_1.splitAtEscapeSensitive)(expr, false, ';');
79
124
  for (const statement of statements) {
80
125
  await replProcessStatement(output, statement, shell);
81
126
  }
@@ -93,11 +138,15 @@ exports.replProcessAnswer = replProcessAnswer;
93
138
  * If you want to provide a custom one but use the same `completer`, refer to {@link replCompleter}.
94
139
  * For the default arguments, see {@link DEFAULT_REPL_READLINE_CONFIGURATION}.
95
140
  * @param output - Defines two methods that every function in the repl uses to output its data.
141
+ * @param historyFile - The file to use for persisting the repl's history. Passing undefined causes history not to be saved.
96
142
  *
97
143
  * For the execution, this function makes use of {@link replProcessAnswer}
98
144
  *
99
145
  */
100
- async function repl(shell = new r_bridge_1.RShell({ revive: 'always' }), rl = readline.createInterface(exports.DEFAULT_REPL_READLINE_CONFIGURATION), output = commands_1.standardReplOutput) {
146
+ async function repl(shell = new r_bridge_1.RShell({ revive: 'always' }), rl = readline.createInterface(exports.DEFAULT_REPL_READLINE_CONFIGURATION), output = commands_1.standardReplOutput, historyFile = defaultHistoryFile) {
147
+ if (historyFile) {
148
+ rl.on('history', h => fs_1.default.writeFileSync(historyFile, h.join('\n'), { encoding: 'utf-8' }));
149
+ }
101
150
  // the incredible repl :D, we kill it with ':quit'
102
151
  // eslint-disable-next-line no-constant-condition,@typescript-eslint/no-unnecessary-condition
103
152
  while (true) {
@@ -113,4 +162,11 @@ async function repl(shell = new r_bridge_1.RShell({ revive: 'always' }), rl = re
113
162
  }
114
163
  }
115
164
  exports.repl = repl;
165
+ function loadReplHistory(historyFile) {
166
+ if (!fs_1.default.existsSync(historyFile)) {
167
+ return undefined;
168
+ }
169
+ return fs_1.default.readFileSync(historyFile, { encoding: 'utf-8' }).split('\n');
170
+ }
171
+ exports.loadReplHistory = loadReplHistory;
116
172
  //# sourceMappingURL=core.js.map
@@ -1,5 +1,5 @@
1
1
  /// <reference types="node" />
2
- import type { Readable, Writable } from 'node:stream';
2
+ import type { Readable, Writable } from 'stream';
3
3
  type Stdio = [stdin: Writable | null, stdout: Readable | null, stderr: Readable | null, extra: Writable | Readable | null | undefined, extra: Writable | Readable | null | undefined];
4
4
  export type StdioProcessor = (stdio: Stdio) => void;
5
5
  /**
@@ -6,7 +6,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.waitOnScript = exports.stdioCaptureProcessor = void 0;
7
7
  const log_1 = require("../../util/log");
8
8
  const child_process_1 = __importDefault(require("child_process"));
9
- const node_readline_1 = __importDefault(require("node:readline"));
9
+ const readline_1 = __importDefault(require("readline"));
10
10
  const assert_1 = require("../../util/assert");
11
11
  /**
12
12
  * Simply captures the output of the script executed by {@link waitOnScript}.
@@ -17,12 +17,12 @@ const assert_1 = require("../../util/assert");
17
17
  */
18
18
  function stdioCaptureProcessor(stdio, onStdOutLine, onStdErrLine) {
19
19
  (0, assert_1.guard)(stdio[1] !== null, 'no stdout given in stdio!');
20
- const outRl = node_readline_1.default.createInterface({
20
+ const outRl = readline_1.default.createInterface({
21
21
  input: stdio[1],
22
22
  terminal: false
23
23
  });
24
24
  (0, assert_1.guard)(stdio[2] !== null, 'no stderr given in stdio!');
25
- const errRl = node_readline_1.default.createInterface({
25
+ const errRl = readline_1.default.createInterface({
26
26
  input: stdio[2],
27
27
  terminal: false
28
28
  });
@@ -2,7 +2,6 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.FlowRServerConnection = void 0;
4
4
  const core_1 = require("../../../core");
5
- const r_bridge_1 = require("../../../r-bridge");
6
5
  const send_1 = require("./send");
7
6
  const validate_1 = require("./validate");
8
7
  const analysis_1 = require("./messages/analysis");
@@ -11,7 +10,6 @@ const server_1 = require("./server");
11
10
  const repl_1 = require("./messages/repl");
12
11
  const core_2 = require("../core");
13
12
  const statistics_1 = require("../../../statistics");
14
- const objects_1 = require("../../../util/objects");
15
13
  const cfg_1 = require("../../../util/cfg/cfg");
16
14
  const quads_1 = require("../../../util/quads");
17
15
  /**
@@ -100,7 +98,6 @@ class FlowRServerConnection {
100
98
  cfg = (0, cfg_1.extractCFG)(results.normalize);
101
99
  }
102
100
  const config = () => ({ context: message.filename ?? 'unknown', getId: (0, quads_1.defaultQuadIdGenerator)() });
103
- const parseConfig = (0, objects_1.deepMergeObject)(r_bridge_1.DEFAULT_XML_PARSER_CONFIG, { tokenMap: await this.shell.tokenMap() });
104
101
  if (message.format === 'n-quads') {
105
102
  (0, send_1.sendMessage)(this.socket, {
106
103
  type: 'response-file-analysis',
@@ -108,10 +105,9 @@ class FlowRServerConnection {
108
105
  id: message.id,
109
106
  cfg: cfg ? (0, cfg_1.cfg2quads)(cfg, config()) : undefined,
110
107
  results: {
111
- parse: await (0, core_1.printStepResult)('parse', results.parse, 5 /* StepOutputFormat.RdfQuads */, config(), parseConfig),
108
+ parse: await (0, core_1.printStepResult)('parse', results.parse, 5 /* StepOutputFormat.RdfQuads */, config()),
112
109
  normalize: await (0, core_1.printStepResult)('normalize', results.normalize, 5 /* StepOutputFormat.RdfQuads */, config()),
113
- dataflow: await (0, core_1.printStepResult)('dataflow', results.dataflow, 5 /* StepOutputFormat.RdfQuads */, config()),
114
- ai: ''
110
+ dataflow: await (0, core_1.printStepResult)('dataflow', results.dataflow, 5 /* StepOutputFormat.RdfQuads */, config())
115
111
  }
116
112
  });
117
113
  }
@@ -138,8 +134,7 @@ class FlowRServerConnection {
138
134
  // we have to make sure, that the content is not interpreted as a file path if it starts with 'file://' therefore, we do it manually
139
135
  request: {
140
136
  request: message.content === undefined ? 'file' : 'text',
141
- content: message.content ?? message.filepath,
142
- ensurePackageInstalled: false
137
+ content: message.content ?? message.filepath
143
138
  },
144
139
  criterion: [] // currently unknown
145
140
  });
@@ -7,7 +7,7 @@ exports.NetServer = exports.WebSocketWrapper = exports.WebSocketServerWrapper =
7
7
  /**
8
8
  * This is just a simple layer to allow me to mock the server's behavior in tests.
9
9
  */
10
- const node_net_1 = __importDefault(require("node:net"));
10
+ const net_1 = __importDefault(require("net"));
11
11
  const ws_1 = require("ws");
12
12
  const server_1 = require("./server");
13
13
  class WebSocketServerWrapper {
@@ -50,7 +50,7 @@ exports.WebSocketWrapper = WebSocketWrapper;
50
50
  class NetServer {
51
51
  server;
52
52
  constructor() {
53
- this.server = node_net_1.default.createServer();
53
+ this.server = net_1.default.createServer();
54
54
  }
55
55
  onConnect(handler) {
56
56
  this.server.on('connection', handler);
@@ -37,7 +37,6 @@ if (options.compress) {
37
37
  // assume correct
38
38
  const processedFeatures = new Set(options.features);
39
39
  const shell = new r_bridge_1.RShell();
40
- shell.tryToInjectHomeLibPath();
41
40
  (0, statistics_1.initFileProvider)(options['output-dir']);
42
41
  function compressFolder(folder, target) {
43
42
  // eslint-disable-next-line @typescript-eslint/no-unsafe-call,@typescript-eslint/no-unsafe-member-access
@@ -25,9 +25,8 @@ function getBenchmarkSummarizer() {
25
25
  return new summarizer_1.BenchmarkSummarizer({
26
26
  graphOutputPath: options.graph ? `${outputBase}-graph.json` : undefined,
27
27
  inputPath: options.input,
28
- intermediateOutputPath: `${outputBase}.json`,
28
+ intermediateOutputPath: outputBase,
29
29
  outputPath: `${outputBase}-ultimate.json`,
30
- outputLogPath: `${outputBase}.log`,
31
30
  logger: console.log
32
31
  });
33
32
  }
package/config.d.ts ADDED
@@ -0,0 +1,16 @@
1
+ import type { MergeableRecord } from './util/objects';
2
+ export interface FlowrConfigOptions extends MergeableRecord {
3
+ /**
4
+ * Whether source calls should be ignored, causing {@link processSourceCall}'s behavior to be skipped
5
+ */
6
+ ignoreSourceCalls: boolean;
7
+ /**
8
+ * The path to the R executable to use. If this is undefined, {@link DEFAULT_R_PATH} will be used.
9
+ */
10
+ rPath: string | undefined;
11
+ }
12
+ export declare const defaultConfigOptions: FlowrConfigOptions;
13
+ export declare const defaultConfigFile = "flowr.json";
14
+ export declare function setConfigFile(workingDirectory?: string, file?: string, forceLoad?: boolean): void;
15
+ export declare function setConfig(config: FlowrConfigOptions): void;
16
+ export declare function getConfig(): FlowrConfigOptions;
package/config.js ADDED
@@ -0,0 +1,75 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.getConfig = exports.setConfig = exports.setConfigFile = exports.defaultConfigFile = exports.defaultConfigOptions = void 0;
7
+ const objects_1 = require("./util/objects");
8
+ const path_1 = __importDefault(require("path"));
9
+ const fs_1 = __importDefault(require("fs"));
10
+ const log_1 = require("./util/log");
11
+ const files_1 = require("./util/files");
12
+ const joi_1 = __importDefault(require("joi"));
13
+ exports.defaultConfigOptions = {
14
+ ignoreSourceCalls: false,
15
+ rPath: undefined
16
+ };
17
+ exports.defaultConfigFile = 'flowr.json';
18
+ const schema = joi_1.default.object({
19
+ ignoreSourceCalls: joi_1.default.boolean().optional()
20
+ });
21
+ let configWorkingDirectory = process.cwd();
22
+ let configFile = exports.defaultConfigFile;
23
+ let currentConfig;
24
+ function setConfigFile(workingDirectory = process.cwd(), file = exports.defaultConfigFile, forceLoad = false) {
25
+ configWorkingDirectory = workingDirectory;
26
+ configFile = file;
27
+ // reset the config so it gets reloaded
28
+ currentConfig = undefined;
29
+ if (forceLoad) {
30
+ getConfig();
31
+ }
32
+ }
33
+ exports.setConfigFile = setConfigFile;
34
+ function setConfig(config) {
35
+ currentConfig = config;
36
+ }
37
+ exports.setConfig = setConfig;
38
+ function getConfig() {
39
+ // lazy-load the config based on the current settings
40
+ if (currentConfig === undefined) {
41
+ setConfig(parseConfigOptions(configWorkingDirectory, configFile));
42
+ }
43
+ return currentConfig;
44
+ }
45
+ exports.getConfig = getConfig;
46
+ function parseConfigOptions(workingDirectory, configFile) {
47
+ let searchPath = path_1.default.resolve(workingDirectory);
48
+ do {
49
+ const configPath = path_1.default.join(searchPath, configFile);
50
+ if (fs_1.default.existsSync(configPath)) {
51
+ try {
52
+ const text = fs_1.default.readFileSync(configPath, { encoding: 'utf-8' });
53
+ const parsed = JSON.parse(text);
54
+ const validate = schema.validate(parsed);
55
+ if (!validate.error) {
56
+ // assign default values to all config options except for the specified ones
57
+ const ret = (0, objects_1.deepMergeObject)(exports.defaultConfigOptions, parsed);
58
+ log_1.log.info(`Using config ${JSON.stringify(ret)} from ${configPath}`);
59
+ return ret;
60
+ }
61
+ else {
62
+ log_1.log.error(`Failed to validate config file at ${configPath}: ${validate.error.message}`);
63
+ }
64
+ }
65
+ catch (e) {
66
+ log_1.log.error(`Failed to parse config file at ${configPath}: ${e.message}`);
67
+ }
68
+ }
69
+ // move up to parent directory
70
+ searchPath = (0, files_1.getParentDirectory)(searchPath);
71
+ } while (fs_1.default.existsSync(searchPath));
72
+ log_1.log.info(`Using default config ${JSON.stringify(exports.defaultConfigOptions)}`);
73
+ return exports.defaultConfigOptions;
74
+ }
75
+ //# sourceMappingURL=config.js.map
package/core/input.d.ts CHANGED
@@ -27,7 +27,7 @@ interface BaseSteppingSlicerInput<InterestedIn extends StepName | undefined> ext
27
27
  /** If you want to auto-select something in the reconstruction add it here, otherwise, it will use the default defined alongside {@link reconstructToCode}*/
28
28
  autoSelectIf?: AutoSelectPredicate;
29
29
  }
30
- interface NormalizeSteppingSlicerInput<InterestedIn extends 'ai' | 'dataflow' | 'normalize'> extends BaseSteppingSlicerInput<InterestedIn> {
30
+ interface NormalizeSteppingSlicerInput<InterestedIn extends 'dataflow' | 'normalize'> extends BaseSteppingSlicerInput<InterestedIn> {
31
31
  stepOfInterest: InterestedIn;
32
32
  }
33
33
  interface SliceSteppingSlicerInput<InterestedIn extends 'reconstruct' | 'slice' | undefined> extends BaseSteppingSlicerInput<InterestedIn> {
package/core/output.d.ts CHANGED
@@ -9,8 +9,7 @@ type StepResultsHelper<InterestedIn extends StepName> = {
9
9
  'parse': Out<'parse'>;
10
10
  'normalize': StepResultsHelper<'parse'> & Out<'normalize'>;
11
11
  'dataflow': StepResultsHelper<'normalize'> & Out<'dataflow'>;
12
- 'ai': StepResultsHelper<'dataflow'> & Out<'ai'>;
13
- 'slice': StepResultsHelper<'ai'> & Out<'slice'>;
12
+ 'slice': StepResultsHelper<'dataflow'> & Out<'slice'>;
14
13
  'reconstruct': StepResultsHelper<'slice'> & Out<'reconstruct'>;
15
14
  }[InterestedIn];
16
15
  export {};
@@ -1,3 +1,2 @@
1
1
  import type { QuadSerializationConfiguration } from '../../util/quads';
2
- import type { XmlParserConfig } from '../../r-bridge';
3
- export declare function parseToQuads(code: string, config: QuadSerializationConfiguration, parseConfig: XmlParserConfig): Promise<string>;
2
+ export declare function parseToQuads(code: string, config: QuadSerializationConfiguration): string;
@@ -2,7 +2,9 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.parseToQuads = void 0;
4
4
  const quads_1 = require("../../util/quads");
5
- const internal_1 = require("../../r-bridge/lang-4.x/ast/parser/xml/internal");
5
+ const r_bridge_1 = require("../../r-bridge");
6
+ const format_1 = require("../../r-bridge/lang-4.x/ast/parser/json/format");
7
+ const parser_1 = require("../../r-bridge/lang-4.x/ast/parser/json/parser");
6
8
  function filterObject(obj, keys) {
7
9
  if (typeof obj !== 'object') {
8
10
  return obj;
@@ -20,10 +22,10 @@ function filterObject(obj, keys) {
20
22
  .map(([k, v]) => [k, filterObject(v, keys)]));
21
23
  }
22
24
  }
23
- async function parseToQuads(code, config, parseConfig) {
24
- const obj = await (0, internal_1.xlm2jsonObject)(parseConfig, code);
25
+ function parseToQuads(code, config) {
26
+ const obj = (0, parser_1.convertPreparedParsedData)((0, format_1.prepareParsedData)(code));
25
27
  // recursively filter so that if the object contains one of the keys 'a', 'b' or 'c', all other keys are ignored
26
- return (0, quads_1.serialize2quads)(filterObject(obj, new Set([parseConfig.attributeName, parseConfig.childrenName, parseConfig.contentName])), config);
28
+ return (0, quads_1.serialize2quads)(filterObject(obj, new Set([r_bridge_1.attributesKey, r_bridge_1.childrenKey, r_bridge_1.contentKey])), config);
27
29
  }
28
30
  exports.parseToQuads = parseToQuads;
29
31
  //# sourceMappingURL=parse-printer.js.map
package/core/slicer.js CHANGED
@@ -162,22 +162,18 @@ class SteppingSlicer {
162
162
  break;
163
163
  case 1:
164
164
  step = guardStep('normalize');
165
- result = await (0, steps_1.executeSingleSubStep)(step, this.results.parse, await this.shell.tokenMap(), this.hooks, this.getId);
165
+ result = (0, steps_1.executeSingleSubStep)(step, this.results.parse, this.hooks, this.getId);
166
166
  break;
167
167
  case 2:
168
168
  step = guardStep('dataflow');
169
- result = (0, steps_1.executeSingleSubStep)(step, this.results.normalize);
169
+ result = (0, steps_1.executeSingleSubStep)(step, this.request, this.results.normalize);
170
170
  break;
171
171
  case 3:
172
- step = guardStep('ai');
173
- result = (0, steps_1.executeSingleSubStep)(step, this.results.normalize, this.results.dataflow);
174
- break;
175
- case 4:
176
172
  (0, assert_1.guard)(this.criterion !== undefined, 'Cannot decode criteria without a criterion');
177
173
  step = guardStep('slice');
178
- result = (0, steps_1.executeSingleSubStep)(step, this.results.ai.graph, this.results.normalize, this.criterion);
174
+ result = (0, steps_1.executeSingleSubStep)(step, this.results.dataflow.graph, this.results.normalize, this.criterion);
179
175
  break;
180
- case 5:
176
+ case 4:
181
177
  step = guardStep('reconstruct');
182
178
  result = (0, steps_1.executeSingleSubStep)(step, this.results.normalize, this.results.slice.result);
183
179
  break;
package/core/steps.d.ts CHANGED
@@ -13,15 +13,14 @@
13
13
  * @module
14
14
  */
15
15
  import type { MergeableRecord } from '../util/objects';
16
- import { normalize, retrieveXmlFromRCode } from '../r-bridge';
17
- import { produceDataFlowGraph } from '../dataflow';
16
+ import { retrieveParseDataFromRCode } from '../r-bridge';
18
17
  import { reconstructToCode, staticSlicing } from '../slicing';
19
18
  import type { IStepPrinter } from './print/print';
20
19
  import { internalPrinter, StepOutputFormat } from './print/print';
21
20
  import { normalizedAstToJson, normalizedAstToQuads, printNormalizedAstToMermaid, printNormalizedAstToMermaidUrl } from './print/normalize-printer';
22
21
  import { parseToQuads } from './print/parse-printer';
23
22
  import { dataflowGraphToJson, dataflowGraphToMermaid, dataflowGraphToMermaidUrl, dataflowGraphToQuads } from './print/dataflow-printer';
24
- import type { DataflowInformation } from '../dataflow/internal/info';
23
+ import { normalize } from '../r-bridge/lang-4.x/ast/parser/json/parser';
25
24
  /**
26
25
  * This represents close a function that we know completely nothing about.
27
26
  * Nevertheless, this is the basis of what a step processor should look like.
@@ -49,7 +48,7 @@ export interface IStep<Fn extends StepFunction> extends MergeableRecord {
49
48
  export declare const STEPS_PER_FILE: {
50
49
  readonly parse: {
51
50
  description: string;
52
- processor: typeof retrieveXmlFromRCode;
51
+ processor: typeof retrieveParseDataFromRCode;
53
52
  required: "once-per-file";
54
53
  printer: {
55
54
  0: typeof internalPrinter;
@@ -71,7 +70,7 @@ export declare const STEPS_PER_FILE: {
71
70
  };
72
71
  readonly dataflow: {
73
72
  description: string;
74
- processor: typeof produceDataFlowGraph;
73
+ processor: (r: import("../r-bridge").RParseRequest, a: import("../r-bridge").NormalizedAst<import("../r-bridge").ParentInformation>) => import("../dataflow/internal/info").DataflowInformation;
75
74
  required: "once-per-file";
76
75
  printer: {
77
76
  0: typeof internalPrinter;
@@ -81,14 +80,6 @@ export declare const STEPS_PER_FILE: {
81
80
  4: typeof dataflowGraphToMermaidUrl;
82
81
  };
83
82
  };
84
- readonly ai: {
85
- description: string;
86
- processor: (_: import("../r-bridge").NormalizedAst<import("../r-bridge").ParentInformation>, dfInfo: DataflowInformation) => DataflowInformation;
87
- required: "once-per-file";
88
- printer: {
89
- 0: typeof internalPrinter;
90
- };
91
- };
92
83
  };
93
84
  export declare const STEPS_PER_SLICE: {
94
85
  readonly slice: {
@@ -127,7 +118,7 @@ export declare const STEPS: {
127
118
  };
128
119
  readonly parse: {
129
120
  description: string;
130
- processor: typeof retrieveXmlFromRCode;
121
+ processor: typeof retrieveParseDataFromRCode;
131
122
  required: "once-per-file";
132
123
  printer: {
133
124
  0: typeof internalPrinter;
@@ -149,7 +140,7 @@ export declare const STEPS: {
149
140
  };
150
141
  readonly dataflow: {
151
142
  description: string;
152
- processor: typeof produceDataFlowGraph;
143
+ processor: (r: import("../r-bridge").RParseRequest, a: import("../r-bridge").NormalizedAst<import("../r-bridge").ParentInformation>) => import("../dataflow/internal/info").DataflowInformation;
153
144
  required: "once-per-file";
154
145
  printer: {
155
146
  0: typeof internalPrinter;
@@ -159,16 +150,8 @@ export declare const STEPS: {
159
150
  4: typeof dataflowGraphToMermaidUrl;
160
151
  };
161
152
  };
162
- readonly ai: {
163
- description: string;
164
- processor: (_: import("../r-bridge").NormalizedAst<import("../r-bridge").ParentInformation>, dfInfo: DataflowInformation) => DataflowInformation;
165
- required: "once-per-file";
166
- printer: {
167
- 0: typeof internalPrinter;
168
- };
169
- };
170
153
  };
171
- export declare const LAST_PER_FILE_STEP: "ai";
154
+ export declare const LAST_PER_FILE_STEP: "dataflow";
172
155
  export declare const LAST_STEP: "reconstruct";
173
156
  export type StepName = keyof typeof STEPS;
174
157
  export type Step<Name extends StepName> = typeof STEPS[Name];
package/core/steps.js CHANGED
@@ -23,10 +23,11 @@ const normalize_printer_1 = require("./print/normalize-printer");
23
23
  const assert_1 = require("../util/assert");
24
24
  const parse_printer_1 = require("./print/parse-printer");
25
25
  const dataflow_printer_1 = require("./print/dataflow-printer");
26
+ const parser_1 = require("../r-bridge/lang-4.x/ast/parser/json/parser");
26
27
  exports.STEPS_PER_FILE = {
27
28
  'parse': {
28
29
  description: 'Parse the given R code into an AST',
29
- processor: r_bridge_1.retrieveXmlFromRCode,
30
+ processor: r_bridge_1.retrieveParseDataFromRCode,
30
31
  required: 'once-per-file',
31
32
  printer: {
32
33
  [0 /* StepOutputFormat.Internal */]: print_1.internalPrinter,
@@ -36,7 +37,7 @@ exports.STEPS_PER_FILE = {
36
37
  },
37
38
  'normalize': {
38
39
  description: 'Normalize the AST to flowR\'s AST (first step of the normalization)',
39
- processor: r_bridge_1.normalize,
40
+ processor: parser_1.normalize,
40
41
  required: 'once-per-file',
41
42
  printer: {
42
43
  [0 /* StepOutputFormat.Internal */]: print_1.internalPrinter,
@@ -48,7 +49,7 @@ exports.STEPS_PER_FILE = {
48
49
  },
49
50
  'dataflow': {
50
51
  description: 'Construct the dataflow graph',
51
- processor: dataflow_1.produceDataFlowGraph,
52
+ processor: (r, a) => (0, dataflow_1.produceDataFlowGraph)(r, a),
52
53
  required: 'once-per-file',
53
54
  printer: {
54
55
  [0 /* StepOutputFormat.Internal */]: print_1.internalPrinter,
@@ -57,14 +58,6 @@ exports.STEPS_PER_FILE = {
57
58
  [3 /* StepOutputFormat.Mermaid */]: dataflow_printer_1.dataflowGraphToMermaid,
58
59
  [4 /* StepOutputFormat.MermaidUrl */]: dataflow_printer_1.dataflowGraphToMermaidUrl
59
60
  }
60
- },
61
- 'ai': {
62
- description: 'Run abstract interpretation',
63
- processor: (_, dfInfo) => dfInfo, // Use runAbstractInterpretation here when it's ready
64
- required: 'once-per-file',
65
- printer: {
66
- [0 /* StepOutputFormat.Internal */]: print_1.internalPrinter
67
- }
68
61
  }
69
62
  };
70
63
  exports.STEPS_PER_SLICE = {
@@ -86,7 +79,7 @@ exports.STEPS_PER_SLICE = {
86
79
  }
87
80
  };
88
81
  exports.STEPS = { ...exports.STEPS_PER_FILE, ...exports.STEPS_PER_SLICE };
89
- exports.LAST_PER_FILE_STEP = 'ai';
82
+ exports.LAST_PER_FILE_STEP = 'dataflow';
90
83
  exports.LAST_STEP = 'reconstruct';
91
84
  function executeSingleSubStep(subStep, ...input) {
92
85
  // @ts-expect-error - this is safe, as we know that the function arguments are correct by 'satisfies', this saves an explicit cast with 'as'
@@ -77,6 +77,14 @@ exports.DefaultEnvironmentMemory = new Map([
77
77
  definedAt: exports.BuiltIn,
78
78
  name: 'print',
79
79
  nodeId: exports.BuiltIn
80
+ }]],
81
+ ['source', [{
82
+ kind: 'built-in-function',
83
+ scope: scopes_1.GlobalScope,
84
+ used: 'always',
85
+ definedAt: exports.BuiltIn,
86
+ name: 'source',
87
+ nodeId: exports.BuiltIn
80
88
  }]]
81
89
  ]);
82
90
  function initializeCleanEnvironments() {
@@ -10,6 +10,7 @@ const assert_1 = require("../../util/assert");
10
10
  */
11
11
  function define(definition, withinScope, environments) {
12
12
  let newEnvironments = environments;
13
+ (0, assert_1.guard)(withinScope === definition.scope, 'Mismatching scopes');
13
14
  if (withinScope === scopes_1.LocalScope) {
14
15
  newEnvironments = (0, environment_1.cloneEnvironments)(environments, false);
15
16
  newEnvironments.current.memory.set(definition.name, [definition]);
@@ -1,6 +1,6 @@
1
- import type { NormalizedAst, ParentInformation, RBinaryOp } from '../r-bridge';
1
+ import type { NormalizedAst, ParentInformation, RBinaryOp, RParseRequest } from '../r-bridge';
2
2
  import type { DataflowInformation } from './internal/info';
3
3
  import type { DataflowProcessorInformation } from './processor';
4
4
  import type { DataflowScopeName } from './environments';
5
- export declare function produceDataFlowGraph<OtherInfo>(ast: NormalizedAst<OtherInfo & ParentInformation>, initialScope?: DataflowScopeName): DataflowInformation;
5
+ export declare function produceDataFlowGraph<OtherInfo>(request: RParseRequest, ast: NormalizedAst<OtherInfo & ParentInformation>, initialScope?: DataflowScopeName): DataflowInformation;
6
6
  export declare function processBinaryOp<OtherInfo>(node: RBinaryOp<OtherInfo & ParentInformation>, data: DataflowProcessorInformation<OtherInfo & ParentInformation>): DataflowInformation;