@eagleoutice/flowr 2.0.16 → 2.0.18

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 (71) hide show
  1. package/README.md +1 -1
  2. package/cli/repl/commands/commands.js +3 -1
  3. package/cli/repl/commands/lineage.d.ts +15 -0
  4. package/cli/repl/commands/lineage.js +66 -0
  5. package/cli/repl/server/connection.d.ts +1 -0
  6. package/cli/repl/server/connection.js +36 -2
  7. package/cli/repl/server/messages/lineage.d.ts +16 -0
  8. package/cli/repl/server/messages/lineage.js +17 -0
  9. package/cli/repl/server/messages/messages.d.ts +2 -1
  10. package/cli/slicer-app.js +2 -2
  11. package/dataflow/environments/built-in.js +29 -9
  12. package/dataflow/environments/environment.js +4 -3
  13. package/dataflow/environments/resolve-by-name.d.ts +1 -1
  14. package/dataflow/environments/resolve-by-name.js +4 -4
  15. package/dataflow/graph/diff.js +1 -0
  16. package/dataflow/graph/graph.d.ts +24 -20
  17. package/dataflow/graph/graph.js +51 -24
  18. package/dataflow/graph/vertex.d.ts +6 -1
  19. package/dataflow/graph/vertex.js +21 -0
  20. package/dataflow/info.d.ts +1 -1
  21. package/dataflow/internal/process/functions/call/built-in/built-in-access.d.ts +2 -1
  22. package/dataflow/internal/process/functions/call/built-in/built-in-access.js +29 -7
  23. package/dataflow/internal/process/functions/call/built-in/built-in-apply.d.ts +14 -0
  24. package/dataflow/internal/process/functions/call/built-in/built-in-apply.js +65 -0
  25. package/dataflow/internal/process/functions/call/built-in/built-in-assignment.d.ts +19 -2
  26. package/dataflow/internal/process/functions/call/built-in/built-in-assignment.js +40 -24
  27. package/dataflow/internal/process/functions/call/built-in/built-in-for-loop.js +1 -1
  28. package/dataflow/internal/process/functions/call/built-in/built-in-function-definition.js +10 -1
  29. package/dataflow/internal/process/functions/call/built-in/built-in-if-then-else.js +4 -4
  30. package/dataflow/internal/process/functions/call/built-in/built-in-library.js +7 -3
  31. package/dataflow/internal/process/functions/call/built-in/built-in-quote.d.ts +3 -2
  32. package/dataflow/internal/process/functions/call/built-in/built-in-quote.js +1 -1
  33. package/dataflow/internal/process/functions/call/built-in/built-in-replacement.d.ts +3 -2
  34. package/dataflow/internal/process/functions/call/built-in/built-in-replacement.js +2 -1
  35. package/dataflow/internal/process/functions/call/built-in/built-in-source.d.ts +2 -2
  36. package/dataflow/internal/process/functions/call/built-in/built-in-source.js +18 -7
  37. package/dataflow/internal/process/functions/call/built-in/{built-in-logical-bin-op.d.ts → built-in-special-bin-op.d.ts} +2 -1
  38. package/dataflow/internal/process/functions/call/built-in/{built-in-logical-bin-op.js → built-in-special-bin-op.js} +3 -3
  39. package/dataflow/internal/process/functions/call/common.d.ts +6 -2
  40. package/dataflow/internal/process/functions/call/common.js +36 -1
  41. package/dataflow/internal/process/functions/call/known-call-handling.d.ts +8 -3
  42. package/dataflow/internal/process/functions/call/known-call-handling.js +10 -7
  43. package/dataflow/internal/process/functions/call/named-call-handling.js +3 -1
  44. package/dataflow/internal/process/functions/call/unnamed-call-handling.js +1 -0
  45. package/dataflow/internal/process/functions/process-argument.js +0 -28
  46. package/package.json +3 -2
  47. package/r-bridge/data/data.d.ts +10 -0
  48. package/r-bridge/data/data.js +12 -0
  49. package/r-bridge/lang-4.x/ast/model/operators.js +1 -1
  50. package/reconstruct/auto-select/auto-select-defaults.d.ts +1 -6
  51. package/reconstruct/auto-select/auto-select-defaults.js +1 -13
  52. package/reconstruct/reconstruct.js +1 -1
  53. package/slicing/criterion/parse.d.ts +3 -4
  54. package/slicing/criterion/parse.js +3 -3
  55. package/slicing/static/static-slicer.d.ts +1 -1
  56. package/slicing/static/static-slicer.js +10 -4
  57. package/statistics/statistics.js +1 -1
  58. package/util/json.d.ts +1 -1
  59. package/util/json.js +3 -3
  60. package/util/logic.d.ts +5 -1
  61. package/util/version.js +1 -1
  62. package/abstract-interpretation/domain.d.ts +0 -57
  63. package/abstract-interpretation/domain.js +0 -176
  64. package/abstract-interpretation/handler/binop/binop.d.ts +0 -15
  65. package/abstract-interpretation/handler/binop/binop.js +0 -42
  66. package/abstract-interpretation/handler/binop/operators.d.ts +0 -2
  67. package/abstract-interpretation/handler/binop/operators.js +0 -28
  68. package/abstract-interpretation/handler/handler.d.ts +0 -6
  69. package/abstract-interpretation/handler/handler.js +0 -3
  70. package/abstract-interpretation/processor.d.ts +0 -11
  71. package/abstract-interpretation/processor.js +0 -84
package/README.md CHANGED
@@ -16,7 +16,7 @@ You can enter `:help` to gain more information on its capabilities.
16
16
 
17
17
  <details>
18
18
 
19
- <summary>Example REPL session.</summary>
19
+ <summary>Example REPL session</summary>
20
20
 
21
21
  ![Example of a simple REPL session](wiki/gif/repl-demo.gif)
22
22
 
@@ -14,6 +14,7 @@ const ansi_1 = require("../../../util/ansi");
14
14
  const args_1 = require("../../../util/args");
15
15
  const assert_1 = require("../../../util/assert");
16
16
  const scripts_info_1 = require("../../common/scripts-info");
17
+ const lineage_1 = require("./lineage");
17
18
  function printHelpForScript(script, f) {
18
19
  const base = ` ${(0, ansi_1.bold)(padCmd(':' + script[0]), f)}${script[1].description}`;
19
20
  if (script[1].aliases.length === 0) {
@@ -58,7 +59,8 @@ const _commands = {
58
59
  'dataflow': dataflow_1.dataflowCommand,
59
60
  'dataflow*': dataflow_1.dataflowStarCommand,
60
61
  'controlflow': cfg_1.controlflowCommand,
61
- 'controlflow*': cfg_1.controlflowStarCommand
62
+ 'controlflow*': cfg_1.controlflowStarCommand,
63
+ 'lineage': lineage_1.getLineageCommand
62
64
  };
63
65
  let commandsInitialized = false;
64
66
  function hasModule(path) {
@@ -0,0 +1,15 @@
1
+ import type { ReplCommand } from './main';
2
+ import type { SingleSlicingCriterion } from '../../../slicing/criterion/parse';
3
+ import type { NodeId } from '../../../r-bridge/lang-4.x/ast/model/processing/node-id';
4
+ import type { DataflowInformation } from '../../../dataflow/info';
5
+ import type { NormalizedAst } from '../../../r-bridge/lang-4.x/ast/model/processing/decorate';
6
+ /**
7
+ * Get the lineage of a node in the dataflow graph
8
+ *
9
+ * @param criterion - The criterion to get the lineage of
10
+ * @param ast - The normalized AST
11
+ * @param dfg - The dataflow graph
12
+ * @returns The lineage of the node represented as a set of node ids
13
+ */
14
+ export declare function getLineage(criterion: SingleSlicingCriterion, { idMap }: NormalizedAst, dfg: DataflowInformation): Set<NodeId>;
15
+ export declare const getLineageCommand: ReplCommand;
@@ -0,0 +1,66 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.getLineageCommand = exports.getLineage = void 0;
4
+ const pipeline_executor_1 = require("../../../core/pipeline-executor");
5
+ const default_pipelines_1 = require("../../../core/steps/pipeline/default-pipelines");
6
+ const retriever_1 = require("../../../r-bridge/retriever");
7
+ const parse_1 = require("../../../slicing/criterion/parse");
8
+ const edge_1 = require("../../../dataflow/graph/edge");
9
+ const assert_1 = require("../../../util/assert");
10
+ function splitAt(str, idx) {
11
+ return [str.slice(0, idx), str.slice(idx)];
12
+ }
13
+ async function getDfg(shell, remainingLine) {
14
+ return await new pipeline_executor_1.PipelineExecutor(default_pipelines_1.DEFAULT_DATAFLOW_PIPELINE, {
15
+ shell,
16
+ request: (0, retriever_1.requestFromInput)(remainingLine.trim())
17
+ }).allRemainingSteps();
18
+ }
19
+ function filterRelevantEdges(edge) {
20
+ return (0, edge_1.edgeIncludesType)(2 /* EdgeType.DefinedBy */ | 32 /* EdgeType.DefinedByOnCall */ | 8 /* EdgeType.Returns */ | 1 /* EdgeType.Reads */, edge.types);
21
+ }
22
+ function pushRelevantEdges(queue, outgoingEdges) {
23
+ queue.push(...[...outgoingEdges].filter(([_, edge]) => filterRelevantEdges(edge)));
24
+ }
25
+ /**
26
+ * Get the lineage of a node in the dataflow graph
27
+ *
28
+ * @param criterion - The criterion to get the lineage of
29
+ * @param ast - The normalized AST
30
+ * @param dfg - The dataflow graph
31
+ * @returns The lineage of the node represented as a set of node ids
32
+ */
33
+ function getLineage(criterion, { idMap }, dfg) {
34
+ const src = dfg.graph.get((0, parse_1.slicingCriterionToId)(criterion, idMap));
35
+ (0, assert_1.guard)(src !== undefined, 'The ID pointed to by the criterion does not exist in the dataflow graph');
36
+ const [vertex, outgoingEdges] = src;
37
+ const result = new Set([vertex.id]);
38
+ const edgeQueue = [];
39
+ pushRelevantEdges(edgeQueue, outgoingEdges);
40
+ while (edgeQueue.length > 0) {
41
+ const [target] = edgeQueue.shift();
42
+ if (result.has(target)) {
43
+ continue;
44
+ }
45
+ result.add(target);
46
+ const outgoingEdges = dfg.graph.outgoingEdges(target);
47
+ if (outgoingEdges !== undefined) {
48
+ pushRelevantEdges(edgeQueue, outgoingEdges);
49
+ }
50
+ }
51
+ return result;
52
+ }
53
+ exports.getLineage = getLineage;
54
+ exports.getLineageCommand = {
55
+ description: 'Get the lineage of an R object',
56
+ usageExample: ':lineage',
57
+ aliases: ['lin'],
58
+ script: false,
59
+ fn: async (output, shell, remainingLine) => {
60
+ const [criterion, rest] = splitAt(remainingLine, remainingLine.indexOf(' '));
61
+ const { dataflow: dfg, normalize: ast } = await getDfg(shell, rest);
62
+ const lineageIds = getLineage(criterion, ast, dfg);
63
+ output.stdout([...lineageIds].join('\n'));
64
+ }
65
+ };
66
+ //# sourceMappingURL=lineage.js.map
@@ -22,5 +22,6 @@ export declare class FlowRServerConnection {
22
22
  private createPipelineExecutorForRequest;
23
23
  private handleSliceRequest;
24
24
  private handleRepl;
25
+ private handleLineageRequest;
25
26
  }
26
27
  export declare function sanitizeAnalysisResults(results: Partial<PipelineOutput<typeof DEFAULT_SLICING_PIPELINE>>): DeepPartial<PipelineOutput<typeof DEFAULT_SLICING_PIPELINE>>;
@@ -46,8 +46,11 @@ const default_pipelines_1 = require("../../../core/steps/pipeline/default-pipeli
46
46
  const graph_1 = require("../../../dataflow/graph/graph");
47
47
  const tmp = __importStar(require("tmp"));
48
48
  const fs_1 = __importDefault(require("fs"));
49
- const auto_select_defaults_1 = require("../../../reconstruct/auto-select/auto-select-defaults");
50
49
  const magic_comments_1 = require("../../../reconstruct/auto-select/magic-comments");
50
+ const lineage_1 = require("./messages/lineage");
51
+ const lineage_2 = require("../commands/lineage");
52
+ const assert_1 = require("../../../util/assert");
53
+ const auto_select_defaults_1 = require("../../../reconstruct/auto-select/auto-select-defaults");
51
54
  /**
52
55
  * Each connection handles a single client, answering to its requests.
53
56
  * There is no need to construct this class manually, {@link FlowRServer} will do it for you.
@@ -97,6 +100,9 @@ class FlowRServerConnection {
97
100
  case 'request-repl-execution':
98
101
  this.handleRepl(request.message);
99
102
  break;
103
+ case 'request-lineage':
104
+ this.handleLineageRequest(request.message);
105
+ break;
100
106
  default:
101
107
  (0, send_1.sendMessage)(this.socket, {
102
108
  id: request.message.id,
@@ -215,7 +221,7 @@ class FlowRServerConnection {
215
221
  }
216
222
  fileInformation.pipeline.updateRequest({
217
223
  criterion: request.criterion,
218
- autoSelectIf: request.noMagicComments ? auto_select_defaults_1.autoSelectLibrary : (0, magic_comments_1.makeMagicCommentHandler)(auto_select_defaults_1.autoSelectLibrary)
224
+ autoSelectIf: request.noMagicComments ? auto_select_defaults_1.doNotAutoSelect : (0, magic_comments_1.makeMagicCommentHandler)(auto_select_defaults_1.doNotAutoSelect)
219
225
  });
220
226
  void fileInformation.pipeline.allRemainingSteps(true).then(results => {
221
227
  (0, send_1.sendMessage)(this.socket, {
@@ -260,6 +266,34 @@ class FlowRServerConnection {
260
266
  });
261
267
  });
262
268
  }
269
+ handleLineageRequest(base) {
270
+ const requestResult = (0, validate_1.validateMessage)(base, lineage_1.requestLineageMessage);
271
+ if (requestResult.type === 'error') {
272
+ (0, validate_1.answerForValidationError)(this.socket, requestResult, base.id);
273
+ return;
274
+ }
275
+ const request = requestResult.message;
276
+ this.logger.info(`[${this.name}] Received lineage request for criterion ${request.criterion}`);
277
+ const fileInformation = this.fileMap.get(request.filetoken);
278
+ if (!fileInformation) {
279
+ (0, send_1.sendMessage)(this.socket, {
280
+ id: request.id,
281
+ type: 'error',
282
+ fatal: false,
283
+ reason: `The file token ${request.filetoken} has never been analyzed.`
284
+ });
285
+ return;
286
+ }
287
+ const { dataflow: dfg, normalize: ast } = fileInformation.pipeline.getResults(true);
288
+ (0, assert_1.guard)(dfg !== undefined, `Dataflow graph must be present (request: ${request.filetoken})`);
289
+ (0, assert_1.guard)(ast !== undefined, `AST must be present (request: ${request.filetoken})`);
290
+ const lineageIds = (0, lineage_2.getLineage)(request.criterion, ast, dfg);
291
+ (0, send_1.sendMessage)(this.socket, {
292
+ type: 'response-lineage',
293
+ id: request.id,
294
+ lineage: [...lineageIds]
295
+ });
296
+ }
263
297
  }
264
298
  exports.FlowRServerConnection = FlowRServerConnection;
265
299
  function sanitizeAnalysisResults(results) {
@@ -0,0 +1,16 @@
1
+ import type { SingleSlicingCriterion } from '../../../../slicing/criterion/parse';
2
+ import type { IdMessageBase, MessageDefinition } from './messages';
3
+ import type { NodeId } from '../../../../r-bridge/lang-4.x/ast/model/processing/node-id';
4
+ export interface LineageRequestMessage extends IdMessageBase {
5
+ type: 'request-lineage';
6
+ /** The {@link FileAnalysisRequestMessage#filetoken} of the file/data */
7
+ filetoken: string;
8
+ /** The criterion to start the lineage from */
9
+ criterion: SingleSlicingCriterion;
10
+ }
11
+ export declare const requestLineageMessage: MessageDefinition<LineageRequestMessage>;
12
+ export interface LineageResponseMessage extends IdMessageBase {
13
+ type: 'response-lineage';
14
+ /** The lineage of the given criterion. With this being the representation of a set, there is no guarantee about order. */
15
+ lineage: NodeId[];
16
+ }
@@ -0,0 +1,17 @@
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.requestLineageMessage = void 0;
7
+ const joi_1 = __importDefault(require("joi"));
8
+ exports.requestLineageMessage = {
9
+ type: 'request-lineage',
10
+ schema: joi_1.default.object({
11
+ type: joi_1.default.string().valid('request-lineage').required(),
12
+ id: joi_1.default.string().optional(),
13
+ filetoken: joi_1.default.string().required(),
14
+ criterion: joi_1.default.string().required()
15
+ })
16
+ };
17
+ //# sourceMappingURL=lineage.js.map
@@ -9,6 +9,7 @@ import type { FileAnalysisRequestMessage, FileAnalysisResponseMessageJson } from
9
9
  import type { ExecuteEndMessage, ExecuteIntermediateResponseMessage, ExecuteRequestMessage } from './repl';
10
10
  import type { SliceRequestMessage, SliceResponseMessage } from './slice';
11
11
  import type { FlowrErrorMessage } from './error';
12
+ import type { LineageRequestMessage, LineageResponseMessage } from './lineage';
12
13
  /**
13
14
  * If you send a message it must *not* contain a newline but the message must be terminated by a newline.
14
15
  */
@@ -32,4 +33,4 @@ export declare const baseMessage: MessageDefinition<IdMessageBase>;
32
33
  /**
33
34
  * This is the main message type that should be used to represent a message in *flowR*
34
35
  */
35
- export type FlowrMessage = FlowrHelloResponseMessage | FileAnalysisRequestMessage | FileAnalysisResponseMessageJson | ExecuteRequestMessage | ExecuteIntermediateResponseMessage | ExecuteEndMessage | SliceRequestMessage | SliceResponseMessage | FlowrErrorMessage;
36
+ export type FlowrMessage = FlowrHelloResponseMessage | FileAnalysisRequestMessage | FileAnalysisResponseMessageJson | ExecuteRequestMessage | ExecuteIntermediateResponseMessage | ExecuteEndMessage | SliceRequestMessage | SliceResponseMessage | LineageRequestMessage | LineageResponseMessage | FlowrErrorMessage;
package/cli/slicer-app.js CHANGED
@@ -12,8 +12,8 @@ const json_1 = require("../util/json");
12
12
  const script_1 = require("./common/script");
13
13
  const slicer_1 = require("../benchmark/slicer");
14
14
  const print_1 = require("../benchmark/stats/print");
15
- const auto_select_defaults_1 = require("../reconstruct/auto-select/auto-select-defaults");
16
15
  const magic_comments_1 = require("../reconstruct/auto-select/magic-comments");
16
+ const auto_select_defaults_1 = require("../reconstruct/auto-select/auto-select-defaults");
17
17
  const options = (0, script_1.processCommandLineArgs)('slicer', ['input', 'criterion'], {
18
18
  subtitle: 'Slice R code based on a given slicing criterion',
19
19
  examples: [
@@ -30,7 +30,7 @@ async function getSlice() {
30
30
  (0, assert_1.guard)(options.criterion !== undefined, 'a slicing criterion must be given');
31
31
  await slicer.init(options['input-is-text']
32
32
  ? { request: 'text', content: options.input }
33
- : { request: 'file', content: options.input }, options['no-magic-comments'] ? auto_select_defaults_1.autoSelectLibrary : (0, magic_comments_1.makeMagicCommentHandler)(auto_select_defaults_1.autoSelectLibrary));
33
+ : { request: 'file', content: options.input }, options['no-magic-comments'] ? auto_select_defaults_1.doNotAutoSelect : (0, magic_comments_1.makeMagicCommentHandler)(auto_select_defaults_1.doNotAutoSelect));
34
34
  let mappedSlices = [];
35
35
  let reconstruct = undefined;
36
36
  const doSlicing = options.criterion.trim() !== '';
@@ -2,11 +2,10 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.EmptyBuiltInMemory = exports.BuiltInMemory = exports.registerReplacementFunctions = exports.registerBuiltInFunctions = exports.BuiltIn = void 0;
4
4
  const known_call_handling_1 = require("../internal/process/functions/call/known-call-handling");
5
- const built_in_source_1 = require("../internal/process/functions/call/built-in/built-in-source");
6
5
  const built_in_access_1 = require("../internal/process/functions/call/built-in/built-in-access");
7
6
  const built_in_if_then_else_1 = require("../internal/process/functions/call/built-in/built-in-if-then-else");
8
7
  const built_in_assignment_1 = require("../internal/process/functions/call/built-in/built-in-assignment");
9
- const built_in_logical_bin_op_1 = require("../internal/process/functions/call/built-in/built-in-logical-bin-op");
8
+ const built_in_special_bin_op_1 = require("../internal/process/functions/call/built-in/built-in-special-bin-op");
10
9
  const built_in_pipe_1 = require("../internal/process/functions/call/built-in/built-in-pipe");
11
10
  const built_in_for_loop_1 = require("../internal/process/functions/call/built-in/built-in-for-loop");
12
11
  const built_in_repeat_loop_1 = require("../internal/process/functions/call/built-in/built-in-repeat-loop");
@@ -18,9 +17,11 @@ const built_in_function_definition_1 = require("../internal/process/functions/ca
18
17
  const built_in_expression_list_1 = require("../internal/process/functions/call/built-in/built-in-expression-list");
19
18
  const built_in_get_1 = require("../internal/process/functions/call/built-in/built-in-get");
20
19
  const built_in_library_1 = require("../internal/process/functions/call/built-in/built-in-library");
20
+ const built_in_source_1 = require("../internal/process/functions/call/built-in/built-in-source");
21
+ const built_in_apply_1 = require("../internal/process/functions/call/built-in/built-in-apply");
21
22
  exports.BuiltIn = 'built-in';
22
23
  function defaultBuiltInProcessor(name, args, rootId, data, config) {
23
- const { information: res, processedArguments } = (0, known_call_handling_1.processKnownFunctionCall)({ name, args, rootId, data });
24
+ const { information: res, processedArguments } = (0, known_call_handling_1.processKnownFunctionCall)({ name, args, rootId, data, forceArgs: config.forceArgs });
24
25
  if (config.returnsNthArgument !== undefined) {
25
26
  const arg = config.returnsNthArgument === 'last' ? processedArguments[args.length - 1] : processedArguments[config.returnsNthArgument];
26
27
  if (arg !== undefined) {
@@ -34,6 +35,9 @@ function defaultBuiltInProcessor(name, args, rootId, data, config) {
34
35
  }
35
36
  }
36
37
  }
38
+ if (config.hasUnknownSideEffects) {
39
+ res.graph.markIdForUnknownSideEffects(rootId);
40
+ }
37
41
  if (config.cfg !== undefined) {
38
42
  res.exitPoints = [...res.exitPoints, { type: config.cfg, nodeId: rootId, controlDependencies: data.controlDependencies }];
39
43
  }
@@ -41,6 +45,7 @@ function defaultBuiltInProcessor(name, args, rootId, data, config) {
41
45
  }
42
46
  function registerBuiltInFunctions(both, names, processor, config) {
43
47
  for (const name of names) {
48
+ (0, assert_1.guard)(processor !== undefined, `Processor for ${name} is undefined, maybe you have an import loop? You may run 'npm run detect-circular-deps' - although by far not all are bad`);
44
49
  (0, assert_1.guard)(!exports.BuiltInMemory.has(name), `Built-in ${name} already defined`);
45
50
  const d = [{
46
51
  kind: 'built-in-function',
@@ -101,9 +106,16 @@ registerBuiltInConstant(true, 'TRUE', true);
101
106
  registerBuiltInConstant(true, 'T', true);
102
107
  registerBuiltInConstant(true, 'FALSE', false);
103
108
  registerBuiltInConstant(true, 'F', false);
104
- registerSimpleFunctions('~', '+', '-', '*', '/', '^', '!', '?', '**', '==', '!=', '>', '<', '>=', '<=', '%%', '%/%', '%*%', '%in%', ':', 'list', 'c', 'rep', 'seq', 'seq_len', 'seq_along', 'seq.int', 'gsub', 'which', 'class', 'dimnames', 'min', 'max', 'intersect', 'subset', 'match', 'sqrt', 'abs', 'round', 'floor', 'ceiling', 'signif', 'trunc', 'log', 'log10', 'log2', 'sum', 'mean', 'unique', 'paste', 'paste0', 'read.csv', 'stop', 'is.null', 'plot', 'numeric', 'as.character', 'as.integer', 'as.logical', 'as.numeric', 'as.matrix', 'apply', 'lapply', 'sapply', 'tapply', 'mapply', 'do.call', 'rbind', 'nrow', 'ncol', 'tryCatch', 'expression', 'factor', 'missing', 'as.data.frame', 'data.frame', 'na.omit', 'rownames', 'names', 'order', 'length', 'any', 'dim', 'matrix', 'cbind', 'nchar', 't');
105
- registerBuiltInFunctions(true, ['print', '('], defaultBuiltInProcessor, { returnsNthArgument: 0 });
106
- registerBuiltInFunctions(false, ['cat', 'switch'], defaultBuiltInProcessor, {}); /* returns null */
109
+ registerSimpleFunctions('~', '+', '-', '*', '/', '^', '!', '?', '**', '==', '!=', '>', '<', '>=', '<=', '%%', '%/%', '%*%', '%in%', ':', 'list', 'c', 'rep', 'seq', 'seq_len', 'seq_along', 'seq.int', 'gsub', 'which', 'class', 'dimnames', 'min', 'max', 'intersect', 'subset', 'match', 'sqrt', 'abs', 'round', 'floor', 'ceiling', 'signif', 'trunc', 'log', 'log10', 'log2', 'sum', 'mean', 'unique', 'paste', 'paste0', 'read.csv', 'stop', 'is.null', 'plot', 'numeric', 'as.character', 'as.integer', 'as.logical', 'as.numeric', 'as.matrix', 'do.call', 'rbind', 'nrow', 'ncol', 'tryCatch', 'expression', 'factor', 'missing', 'as.data.frame', 'data.frame', 'na.omit', 'rownames', 'names', 'order', 'length', 'any', 'dim', 'matrix', 'cbind', 'nchar', 't');
110
+ registerBuiltInFunctions(true, ['lapply', 'sapply', 'vapply', 'mapply'], built_in_apply_1.processApply, { indexOfFunction: 1, nameOfFunctionArgument: 'FUN' });
111
+ /* functool wrappers */
112
+ registerBuiltInFunctions(true, ['Lapply', 'Sapply', 'Vapply', 'Mapply'], built_in_apply_1.processApply, { indexOfFunction: 1, nameOfFunctionArgument: 'FUN' });
113
+ registerBuiltInFunctions(true, ['apply', 'tapply', 'Tapply'], built_in_apply_1.processApply, { indexOfFunction: 2, nameOfFunctionArgument: 'FUN' });
114
+ registerBuiltInFunctions(true, ['print'], defaultBuiltInProcessor, { returnsNthArgument: 0, forceArgs: 'all' });
115
+ registerBuiltInFunctions(true, ['('], defaultBuiltInProcessor, { returnsNthArgument: 0 });
116
+ registerBuiltInFunctions(true, ['load', 'load_all', 'setwd', 'set.seed'], defaultBuiltInProcessor, { hasUnknownSideEffects: true, forceArgs: [true] });
117
+ registerBuiltInFunctions(false, ['cat'], defaultBuiltInProcessor, { forceArgs: 'all' }); /* returns null */
118
+ registerBuiltInFunctions(false, ['switch'], defaultBuiltInProcessor, {}); /* returns null */
107
119
  registerBuiltInFunctions(true, ['return'], defaultBuiltInProcessor, { returnsNthArgument: 0, cfg: 1 /* ExitPointType.Return */ });
108
120
  registerBuiltInFunctions(true, ['break'], defaultBuiltInProcessor, { cfg: 2 /* ExitPointType.Break */ });
109
121
  registerBuiltInFunctions(true, ['next'], defaultBuiltInProcessor, { cfg: 3 /* ExitPointType.Next */ });
@@ -113,21 +125,29 @@ registerBuiltInFunctions(true, ['[', '[['], built_in_access_1.processAccess, { t
113
125
  registerBuiltInFunctions(true, ['$', '@'], built_in_access_1.processAccess, { treatIndicesAsString: true });
114
126
  registerBuiltInFunctions(true, ['if', 'ifelse'], built_in_if_then_else_1.processIfThenElse, {});
115
127
  registerBuiltInFunctions(true, ['get'], built_in_get_1.processGet, {});
116
- registerBuiltInFunctions(false, ['library'], built_in_library_1.processLibrary, {});
128
+ registerBuiltInFunctions(false, ['library', 'require'], built_in_library_1.processLibrary, {});
117
129
  registerBuiltInFunctions(true, ['<-', '='], built_in_assignment_1.processAssignment, { canBeReplacement: true });
118
130
  registerBuiltInFunctions(true, [':=', 'assign'], built_in_assignment_1.processAssignment, {});
119
131
  registerBuiltInFunctions(true, ['delayedAssign'], built_in_assignment_1.processAssignment, { quoteSource: true });
120
132
  registerBuiltInFunctions(true, ['<<-'], built_in_assignment_1.processAssignment, { superAssignment: true, canBeReplacement: true });
121
133
  registerBuiltInFunctions(true, ['->'], built_in_assignment_1.processAssignment, { swapSourceAndTarget: true, canBeReplacement: true });
122
134
  registerBuiltInFunctions(true, ['->>'], built_in_assignment_1.processAssignment, { superAssignment: true, swapSourceAndTarget: true, canBeReplacement: true });
123
- registerBuiltInFunctions(true, ['&&', '&'], built_in_logical_bin_op_1.processSpecialBinOp, { lazy: true, evalRhsWhen: true });
124
- registerBuiltInFunctions(true, ['||', '|'], built_in_logical_bin_op_1.processSpecialBinOp, { lazy: true, evalRhsWhen: false });
135
+ registerBuiltInFunctions(true, ['&&', '&'], built_in_special_bin_op_1.processSpecialBinOp, { lazy: true, evalRhsWhen: true });
136
+ registerBuiltInFunctions(true, ['||', '|'], built_in_special_bin_op_1.processSpecialBinOp, { lazy: true, evalRhsWhen: false });
125
137
  registerBuiltInFunctions(true, ['|>', '%>%'], built_in_pipe_1.processPipe, {});
126
138
  registerBuiltInFunctions(true, ['function', '\\'], built_in_function_definition_1.processFunctionDefinition, {});
127
139
  registerBuiltInFunctions(true, ['quote', 'substitute', 'bquote'], built_in_quote_1.processQuote, { quoteArgumentsWithIndex: 0 });
128
140
  registerBuiltInFunctions(true, ['for'], built_in_for_loop_1.processForLoop, {});
129
141
  registerBuiltInFunctions(true, ['repeat'], built_in_repeat_loop_1.processRepeatLoop, {});
130
142
  registerBuiltInFunctions(true, ['while'], built_in_while_loop_1.processWhileLoop, {});
143
+ registerBuiltInFunctions(true, ['options'], defaultBuiltInProcessor, { hasUnknownSideEffects: true, forceArgs: 'all' });
144
+ registerBuiltInFunctions(true, ['on.exit', 'sys.on.exit'], defaultBuiltInProcessor, { hasUnknownSideEffects: true });
145
+ /* library and require is handled above */
146
+ registerBuiltInFunctions(true, ['requireNamespace', 'loadNamespace', 'attachNamespace', 'asNamespace'], defaultBuiltInProcessor, { hasUnknownSideEffects: true });
147
+ /* downloader and installer functions (R, devtools, BiocManager) */
148
+ registerBuiltInFunctions(true, ['library.dynam', 'install.packages', 'install', 'install_github', 'install_gitlab', 'install_bitbucket', 'install_url', 'install_git', 'install_svn', 'install_local', 'install_version', 'update_packages'], defaultBuiltInProcessor, { hasUnknownSideEffects: true });
149
+ /* weird env attachments */
150
+ registerBuiltInFunctions(true, ['attach'], defaultBuiltInProcessor, { hasUnknownSideEffects: true });
131
151
  /* they are all mapped to `<-` but we separate super assignments */
132
152
  registerReplacementFunctions({ makeMaybe: true }, ['<-', '<<-'], '[', '[[', '$', '@', 'names', 'dimnames', 'attributes', 'attr', 'class', 'levels', 'rownames', 'colnames');
133
153
  //# sourceMappingURL=built-in.js.map
@@ -20,11 +20,12 @@ function makeReferenceMaybe(ref, graph, environments, includeDefs, defaultCd = u
20
20
  }
21
21
  }
22
22
  if (node) {
23
- if (node[0].controlDependencies && defaultCd && !node[0].controlDependencies.includes(defaultCd)) {
24
- node[0].controlDependencies.push(defaultCd);
23
+ const [fst] = node;
24
+ if (fst.controlDependencies && defaultCd && !fst.controlDependencies.includes(defaultCd)) {
25
+ fst.controlDependencies.push(defaultCd);
25
26
  }
26
27
  else {
27
- node[0].controlDependencies = defaultCd ? [defaultCd] : [];
28
+ fst.controlDependencies = defaultCd ? [defaultCd] : [];
28
29
  }
29
30
  }
30
31
  return { ...ref, controlDependencies: [...ref.controlDependencies ?? [], ...(defaultCd ? [defaultCd] : [])] };
@@ -1,5 +1,5 @@
1
1
  import type { REnvironmentInformation } from './environment';
2
- import type { Ternary } from '../../util/logic';
2
+ import { Ternary } from '../../util/logic';
3
3
  import type { Identifier, IdentifierDefinition } from './identifier';
4
4
  /**
5
5
  * Resolves a given identifier name to a list of its possible definition location using R scoping and resolving rules.
@@ -24,11 +24,11 @@ function resolveByName(name, environment) {
24
24
  exports.resolveByName = resolveByName;
25
25
  function resolvesToBuiltInConstant(name, environment, wantedValue) {
26
26
  if (name === undefined) {
27
- return 'never';
27
+ return 2 /* Ternary.Never */;
28
28
  }
29
29
  const definition = resolveByName(name, environment);
30
30
  if (definition === undefined) {
31
- return 'never';
31
+ return 2 /* Ternary.Never */;
32
32
  }
33
33
  let all = true;
34
34
  let some = false;
@@ -41,10 +41,10 @@ function resolvesToBuiltInConstant(name, environment, wantedValue) {
41
41
  }
42
42
  }
43
43
  if (all) {
44
- return 'always';
44
+ return 0 /* Ternary.Always */;
45
45
  }
46
46
  else {
47
- return some ? 'maybe' : 'never';
47
+ return some ? 1 /* Ternary.Maybe */ : 2 /* Ternary.Never */;
48
48
  }
49
49
  }
50
50
  exports.resolvesToBuiltInConstant = resolvesToBuiltInConstant;
@@ -94,6 +94,7 @@ function diffOutgoingEdges(ctx) {
94
94
  }
95
95
  function diffRootVertices(ctx) {
96
96
  (0, diff_1.setDifference)(ctx.left.rootIds(), ctx.right.rootIds(), { ...ctx, position: `${ctx.position}Root vertices differ in graphs. ` });
97
+ (0, diff_1.setDifference)(ctx.left.unknownSideEffects, ctx.right.unknownSideEffects, { ...ctx, position: `${ctx.position}Unknown side effects differ in graphs. ` });
97
98
  }
98
99
  function diffOfDataflowGraphs(left, right, config) {
99
100
  if (left.graph === right.graph) {
@@ -1,8 +1,7 @@
1
1
  import type { DataflowGraphEdge } from './edge';
2
2
  import { EdgeType } from './edge';
3
3
  import type { DataflowInformation } from '../info';
4
- import type { DataflowDifferenceReport } from './diff';
5
- import type { DataflowGraphVertexArgument, DataflowGraphVertexInfo } from './vertex';
4
+ import type { DataflowGraphVertexArgument, DataflowGraphVertexFunctionCall, DataflowGraphVertexInfo } from './vertex';
6
5
  import { EmptyArgument } from '../../r-bridge/lang-4.x/ast/model/nodes/r-function-call';
7
6
  import type { IdentifierDefinition, IdentifierReference } from '../environments/identifier';
8
7
  import type { NodeId } from '../../r-bridge/lang-4.x/ast/model/processing/node-id';
@@ -47,10 +46,10 @@ type EdgeData<Edge extends DataflowGraphEdge> = Omit<Edge, 'from' | 'to' | 'type
47
46
  export declare class DataflowGraph<Vertex extends DataflowGraphVertexInfo = DataflowGraphVertexInfo, Edge extends DataflowGraphEdge = DataflowGraphEdge> {
48
47
  private static DEFAULT_ENVIRONMENT;
49
48
  private _idMap;
50
- readonly functionCache: Map<NodeId, Set<DataflowGraphVertexInfo>>;
49
+ private _unknownSideEffects;
51
50
  constructor(idMap: AstIdMap | undefined);
52
51
  /** Contains the vertices of the root level graph (i.e., included those vertices from the complete graph, that are nested within function definitions) */
53
- private rootVertices;
52
+ protected rootVertices: Set<NodeId>;
54
53
  /** All vertices in the complete graph (including those nested in function definition) */
55
54
  private vertexInformation;
56
55
  /** All edges in the complete graph (including those nested in function definition) */
@@ -79,14 +78,18 @@ export declare class DataflowGraph<Vertex extends DataflowGraphVertexInfo = Data
79
78
  ingoingEdges(id: NodeId): IngoingEdges | undefined;
80
79
  /** Retrieves the id-map to the normalized AST attached to the dataflow graph */
81
80
  get idMap(): AstIdMap | undefined;
81
+ /**
82
+ * Retrieves the set of vertices which have side effects that we do not know anything about.
83
+ */
84
+ get unknownSideEffects(): ReadonlySet<NodeId>;
82
85
  /** Allows setting the id-map explicitly (which should only be used when, e.g., you plan to compare two dataflow graphs on the same AST-basis) */
83
86
  setIdMap(idMap: AstIdMap): void;
84
87
  /**
85
- * @param includeDefinedFunctions - If true this will iterate over function definitions as well and not just the toplevel
86
- * @returns the ids of all toplevel vertices in the graph together with their vertex information
88
+ * @param includeDefinedFunctions - If true this will iterate over function definitions as well and not just the toplevel
89
+ * @returns the ids of all toplevel vertices in the graph together with their vertex information
87
90
  *
88
91
  * @see #edges
89
- */
92
+ */
90
93
  vertices(includeDefinedFunctions: boolean): IterableIterator<[NodeId, Vertex]>;
91
94
  /**
92
95
  * @returns the ids of all edges in the graph together with their edge information
@@ -107,15 +110,15 @@ export declare class DataflowGraph<Vertex extends DataflowGraphVertexInfo = Data
107
110
  isRoot(id: NodeId): boolean;
108
111
  rootIds(): ReadonlySet<NodeId>;
109
112
  /**
110
- * Adds a new vertex to the graph, for ease of use, some arguments are optional and filled automatically.
111
- *
113
+ * Adds a new vertex to the graph, for ease of use, some arguments are optional and filled automatically.
114
+ *
112
115
  * @param vertex - The vertex to add
113
116
  * @param asRoot - If false, this will only add the vertex but do not add it to the {@link rootIds|root vertices} of the graph.
114
117
  * This is probably only of use, when you construct dataflow graphs for tests.
115
118
  *
116
- * @see DataflowGraphVertexInfo
117
- * @see DataflowGraphVertexArgument
118
- */
119
+ * @see DataflowGraphVertexInfo
120
+ * @see DataflowGraphVertexArgument
121
+ */
119
122
  addVertex(vertex: DataflowGraphVertexArgument & Omit<Vertex, keyof DataflowGraphVertexArgument>, asRoot?: boolean): this;
120
123
  /** {@inheritDoc} */
121
124
  addEdge(from: NodeId, to: NodeId, edgeInfo: EdgeData<Edge>): this;
@@ -133,18 +136,19 @@ export declare class DataflowGraph<Vertex extends DataflowGraphVertexInfo = Data
133
136
  */
134
137
  mergeWith(otherGraph: DataflowGraph<Vertex, Edge> | undefined, mergeRootVertices?: boolean): this;
135
138
  private mergeEdges;
136
- equals(other: DataflowGraph<Vertex, Edge>, diff: true, names?: {
137
- left: string;
138
- right: string;
139
- }): DataflowDifferenceReport;
140
- equals(other: DataflowGraph<Vertex, Edge>, diff?: false, names?: {
141
- left: string;
142
- right: string;
143
- }): boolean;
144
139
  /**
145
140
  * Marks a vertex in the graph to be a definition
146
141
  * @param reference - The reference to the vertex to mark as definition
147
142
  */
148
143
  setDefinitionOfVertex(reference: IdentifierReference): void;
144
+ /**
145
+ * Marks a vertex in the graph to be a function call with the new information
146
+ * @param info - The information about the new function call node
147
+ */
148
+ updateToFunctionCall(info: DataflowGraphVertexFunctionCall): void;
149
+ /** If you do not pass the `to` node, this will just mark the node as maybe */
150
+ addControlDependency(from: NodeId, to?: NodeId, when?: boolean): this;
151
+ /** Marks the given node as having unknown side effects */
152
+ markIdForUnknownSideEffects(id: NodeId): this;
149
153
  }
150
154
  export {};