@eagleoutice/flowr 2.1.3 → 2.1.5

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 (106) hide show
  1. package/benchmark/slicer.js +1 -1
  2. package/cli/repl/commands/repl-parse.js +1 -1
  3. package/cli/repl/commands/repl-query.js +4 -5
  4. package/cli/repl/server/connection.js +6 -1
  5. package/cli/repl/server/messages/message-query.js +2 -2
  6. package/cli/repl/server/net.js +1 -1
  7. package/cli/repl/server/send.js +3 -6
  8. package/cli/repl/server/server.d.ts +2 -2
  9. package/cli/repl/server/server.js +1 -1
  10. package/config.js +1 -1
  11. package/core/pipeline-executor.js +2 -1
  12. package/core/steps/all/core/00-parse.d.ts +11 -4
  13. package/core/steps/all/core/00-parse.js +5 -5
  14. package/core/steps/all/core/10-normalize.d.ts +2 -1
  15. package/core/steps/all/core/20-dataflow.d.ts +2 -2
  16. package/core/steps/all/core/20-dataflow.js +2 -2
  17. package/core/steps/pipeline/default-pipelines.d.ts +41 -23
  18. package/core/steps/pipeline/pipeline.d.ts +15 -3
  19. package/core/steps/pipeline/pipeline.js +2 -2
  20. package/dataflow/environments/built-in.d.ts +8 -6
  21. package/dataflow/environments/built-in.js +6 -1
  22. package/dataflow/environments/default-builtin-config.js +21 -5
  23. package/dataflow/environments/environment.d.ts +1 -0
  24. package/dataflow/environments/environment.js +5 -5
  25. package/dataflow/extractor.js +23 -0
  26. package/dataflow/graph/dataflowgraph-builder.d.ts +2 -0
  27. package/dataflow/graph/dataflowgraph-builder.js +9 -0
  28. package/dataflow/graph/diff.js +1 -1
  29. package/dataflow/graph/graph.d.ts +7 -2
  30. package/dataflow/graph/graph.js +10 -2
  31. package/dataflow/internal/process/functions/call/argument/unpack-argument.d.ts +1 -1
  32. package/dataflow/internal/process/functions/call/argument/unpack-argument.js +2 -2
  33. package/dataflow/internal/process/functions/call/built-in/built-in-assignment.js +2 -2
  34. package/dataflow/internal/process/functions/call/built-in/built-in-expression-list.js +1 -1
  35. package/dataflow/internal/process/functions/call/built-in/built-in-for-loop.js +1 -1
  36. package/dataflow/internal/process/functions/call/built-in/built-in-if-then-else.js +1 -1
  37. package/dataflow/internal/process/functions/call/built-in/built-in-pipe.js +1 -1
  38. package/dataflow/internal/process/functions/call/built-in/built-in-source.js +13 -1
  39. package/dataflow/internal/process/functions/call/built-in/built-in-while-loop.js +1 -1
  40. package/dataflow/internal/process/functions/call/named-call-handling.js +1 -1
  41. package/dataflow/processor.d.ts +3 -3
  42. package/documentation/data/server/doc-data-server-messages.js +8 -14
  43. package/documentation/doc-util/doc-cli-option.js +4 -4
  44. package/documentation/doc-util/doc-query.d.ts +4 -6
  45. package/documentation/doc-util/doc-query.js +16 -156
  46. package/documentation/doc-util/doc-repl.js +2 -2
  47. package/documentation/print-dataflow-graph-wiki.js +2 -1
  48. package/documentation/print-interface-wiki.js +8 -3
  49. package/documentation/print-query-wiki.js +107 -16
  50. package/package.json +1 -1
  51. package/queries/base-query-format.d.ts +6 -0
  52. package/queries/catalog/call-context-query/call-context-query-executor.d.ts +1 -1
  53. package/queries/catalog/call-context-query/call-context-query-executor.js +26 -80
  54. package/queries/catalog/call-context-query/call-context-query-format.d.ts +14 -13
  55. package/queries/catalog/call-context-query/call-context-query-format.js +32 -14
  56. package/queries/catalog/call-context-query/identify-link-to-last-call-relation.d.ts +17 -0
  57. package/queries/catalog/call-context-query/identify-link-to-last-call-relation.js +99 -0
  58. package/queries/catalog/cluster-query/cluster-query-executor.d.ts +1 -1
  59. package/queries/catalog/cluster-query/cluster-query-format.d.ts +59 -0
  60. package/queries/catalog/cluster-query/cluster-query-format.js +29 -0
  61. package/queries/catalog/dataflow-query/dataflow-query-executor.d.ts +1 -1
  62. package/queries/catalog/dataflow-query/dataflow-query-format.d.ts +59 -0
  63. package/queries/catalog/dataflow-query/dataflow-query-format.js +21 -0
  64. package/queries/catalog/dependencies-query/dependencies-query-executor.d.ts +3 -0
  65. package/queries/catalog/dependencies-query/dependencies-query-executor.js +144 -0
  66. package/queries/catalog/dependencies-query/dependencies-query-format.d.ts +102 -0
  67. package/queries/catalog/dependencies-query/dependencies-query-format.js +187 -0
  68. package/queries/catalog/id-map-query/id-map-query-executor.d.ts +1 -1
  69. package/queries/catalog/id-map-query/id-map-query-format.d.ts +59 -0
  70. package/queries/catalog/id-map-query/id-map-query-format.js +21 -0
  71. package/queries/catalog/lineage-query/lineage-query-executor.d.ts +1 -1
  72. package/queries/catalog/lineage-query/lineage-query-format.d.ts +59 -0
  73. package/queries/catalog/lineage-query/lineage-query-format.js +24 -0
  74. package/queries/catalog/location-map-query/location-map-query-executor.d.ts +3 -0
  75. package/queries/catalog/location-map-query/location-map-query-executor.js +21 -0
  76. package/queries/catalog/location-map-query/location-map-query-format.d.ts +17 -0
  77. package/queries/catalog/location-map-query/location-map-query-format.js +24 -0
  78. package/queries/catalog/normalized-ast-query/normalized-ast-query-executor.d.ts +1 -1
  79. package/queries/catalog/normalized-ast-query/normalized-ast-query-format.d.ts +59 -0
  80. package/queries/catalog/normalized-ast-query/normalized-ast-query-format.js +21 -0
  81. package/queries/catalog/static-slice-query/static-slice-query-executor.d.ts +1 -1
  82. package/queries/catalog/static-slice-query/static-slice-query-executor.js +8 -3
  83. package/queries/catalog/static-slice-query/static-slice-query-format.d.ts +59 -0
  84. package/queries/catalog/static-slice-query/static-slice-query-format.js +40 -0
  85. package/queries/query-print.d.ts +8 -0
  86. package/queries/query-print.js +94 -0
  87. package/queries/query.d.ts +431 -26
  88. package/queries/query.js +36 -18
  89. package/r-bridge/lang-4.x/ast/parser/json/parser.d.ts +2 -1
  90. package/r-bridge/lang-4.x/ast/parser/json/parser.js +2 -2
  91. package/r-bridge/lang-4.x/ast/parser/main/internal/functions/normalize-argument.js +2 -1
  92. package/r-bridge/retriever.js +1 -1
  93. package/r-bridge/shell-executor.js +1 -1
  94. package/r-bridge/shell.d.ts +1 -2
  95. package/r-bridge/shell.js +22 -18
  96. package/slicing/static/static-slicer.js +3 -1
  97. package/statistics/features/supported/used-functions/used-functions.js +1 -1
  98. package/{documentation/doc-util/doc-hover-over.js → util/html-hover-over.js} +1 -1
  99. package/util/json.d.ts +2 -1
  100. package/util/json.js +101 -3
  101. package/util/objects.d.ts +2 -1
  102. package/util/objects.js +3 -0
  103. package/util/version.js +1 -1
  104. package/queries/query-schema.d.ts +0 -13
  105. package/queries/query-schema.js +0 -54
  106. /package/{documentation/doc-util/doc-hover-over.d.ts → util/html-hover-over.d.ts} +0 -0
@@ -64,7 +64,7 @@ class BenchmarkSlicer {
64
64
  criterion: [],
65
65
  autoSelectIf
66
66
  });
67
- this.loadedXml = await this.measureCommonStep('parse', 'retrieve AST from R code');
67
+ this.loadedXml = (await this.measureCommonStep('parse', 'retrieve AST from R code')).parsed;
68
68
  this.normalizedAst = await this.measureCommonStep('normalize', 'normalize R AST');
69
69
  this.dataflow = await this.measureCommonStep('dataflow', 'produce dataflow information');
70
70
  this.pipeline.switchToRequestStage();
@@ -95,7 +95,7 @@ exports.parseCommand = {
95
95
  shell,
96
96
  request: (0, retriever_1.requestFromInput)((0, retriever_1.removeRQuotes)(remainingLine.trim()))
97
97
  }).allRemainingSteps();
98
- const object = (0, format_1.convertPreparedParsedData)((0, format_1.prepareParsedData)(result.parse));
98
+ const object = (0, format_1.convertPreparedParsedData)((0, format_1.prepareParsedData)(result.parse.parsed));
99
99
  output.stdout(depthListToTextTree(toDepthMap(object), output.formatter));
100
100
  }
101
101
  };
@@ -9,7 +9,7 @@ const ansi_1 = require("../../../util/ansi");
9
9
  const schema_1 = require("../../../util/schema");
10
10
  const query_1 = require("../../../queries/query");
11
11
  const json_1 = require("../../../util/json");
12
- const query_schema_1 = require("../../../queries/query-schema");
12
+ const query_print_1 = require("../../../queries/query-print");
13
13
  async function getDataflow(shell, remainingLine) {
14
14
  return await new pipeline_executor_1.PipelineExecutor(default_pipelines_1.DEFAULT_DATAFLOW_PIPELINE, {
15
15
  shell,
@@ -19,7 +19,7 @@ async function getDataflow(shell, remainingLine) {
19
19
  function printHelp(output) {
20
20
  output.stderr(`Format: ${(0, ansi_1.italic)(':query "<query>" <code>', output.formatter)}`);
21
21
  output.stdout('The query is an array of query objects to represent multiple queries. Each query object may have the following properties:');
22
- output.stdout((0, schema_1.describeSchema)(query_schema_1.AnyQuerySchema, output.formatter));
22
+ output.stdout((0, schema_1.describeSchema)(query_1.AnyQuerySchema, output.formatter));
23
23
  output.stdout(`\n\nThe example ${(0, ansi_1.italic)(':query "[{\\"type\\": \\"call-context\\", \\"callName\\": \\"mean\\" }]" mean(1:10)', output.formatter)} would return the call context of the mean function.`);
24
24
  output.stdout('As a convenience, we interpret any (non-help) string not starting with \'[\' as a regex for the simple call-context query.');
25
25
  output.stdout(`Hence, ${(0, ansi_1.italic)(':query "mean" mean(1:10)', output.formatter)} is equivalent to the above example.`);
@@ -38,7 +38,7 @@ async function processQueryArgs(line, shell, output) {
38
38
  let parsedQuery = [];
39
39
  if (query.startsWith('[')) {
40
40
  parsedQuery = JSON.parse(query);
41
- const validationResult = query_schema_1.QueriesSchema.validate(parsedQuery);
41
+ const validationResult = query_1.QueriesSchema.validate(parsedQuery);
42
42
  if (validationResult.error) {
43
43
  output.stderr(`Invalid query: ${validationResult.error.message}`);
44
44
  printHelp(output);
@@ -64,8 +64,7 @@ exports.queryCommand = {
64
64
  const results = await processQueryArgs(remainingLine, shell, output);
65
65
  const totalEnd = Date.now();
66
66
  if (results) {
67
- output.stdout(JSON.stringify(results));
68
- output.stdout('Total time: ' + (totalEnd - totalStart) + 'ms');
67
+ output.stdout((0, query_print_1.asciiSummaryOfQueryResult)(ansi_1.ansiFormatter, totalEnd - totalStart, results.query, results.processed));
69
68
  }
70
69
  }
71
70
  };
@@ -74,6 +74,9 @@ class FlowRServerConnection {
74
74
  this.logger = server_1.serverLog.getSubLogger({ name });
75
75
  this.socket.on('data', data => this.handleData(String(data)));
76
76
  this.socket.on('error', e => this.logger.error(`[${this.name}] Error while handling connection: ${String(e)}`));
77
+ this.socket.on('close', () => {
78
+ this.fileMap.clear();
79
+ });
77
80
  this.allowRSessionAccess = allowRSessionAccess;
78
81
  }
79
82
  currentMessageBuffer = '';
@@ -129,6 +132,8 @@ class FlowRServerConnection {
129
132
  this.logger.info(`[${this.name}] Received file analysis request for ${message.filename ?? 'unknown file'}${message.filetoken ? ' with token: ' + message.filetoken : ''}`);
130
133
  if (message.filetoken && this.fileMap.has(message.filetoken)) {
131
134
  this.logger.warn(`File token ${message.filetoken} already exists. Overwriting.`);
135
+ // explicitly delete the previous store
136
+ this.fileMap.delete(message.filetoken);
132
137
  }
133
138
  const tempFile = tmp.fileSync({ postfix: '.R' });
134
139
  const slicer = this.createPipelineExecutorForRequest(message, tempFile.name);
@@ -307,7 +312,7 @@ class FlowRServerConnection {
307
312
  return;
308
313
  }
309
314
  const request = requestResult.message;
310
- this.logger.info(`[${this.name}] Received query request for query ${JSON.stringify(request.query)}`);
315
+ this.logger.info(`[${this.name}] Received query request`);
311
316
  const fileInformation = this.fileMap.get(request.filetoken);
312
317
  if (!fileInformation) {
313
318
  (0, send_1.sendMessage)(this.socket, {
@@ -5,14 +5,14 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.responseQueryMessage = exports.requestQueryMessage = void 0;
7
7
  const joi_1 = __importDefault(require("joi"));
8
- const query_schema_1 = require("../../../../queries/query-schema");
8
+ const query_1 = require("../../../../queries/query");
9
9
  exports.requestQueryMessage = {
10
10
  type: 'request-query',
11
11
  schema: joi_1.default.object({
12
12
  type: joi_1.default.string().valid('request-query').required().description('The type of the message.'),
13
13
  id: joi_1.default.string().optional().description('If you give the id, the response will be sent to the client with the same id.'),
14
14
  filetoken: joi_1.default.string().required().description('The filetoken of the file/data retrieved from the analysis request.'),
15
- query: query_schema_1.QueriesSchema.required().description('The query to run on the file analysis information.')
15
+ query: query_1.QueriesSchema.required().description('The query to run on the file analysis information.')
16
16
  }).description('Request a query to be run on the file analysis information.')
17
17
  };
18
18
  exports.responseQueryMessage = {
@@ -17,7 +17,7 @@ class WebSocketServerWrapper {
17
17
  this.connectHandler = handler;
18
18
  }
19
19
  start(port) {
20
- this.server = new ws_1.WebSocketServer({ port });
20
+ this.server = new ws_1.WebSocketServer({ port, maxPayload: 1024 * 1024 * 1024 * 1024 });
21
21
  server_1.serverLog.info('WebSocket-Server wrapper is active!');
22
22
  this.server.on('connection', c => this.connectHandler?.(new WebSocketWrapper(c)));
23
23
  }
@@ -2,16 +2,13 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.getUnnamedSocketName = getUnnamedSocketName;
4
4
  exports.sendMessage = sendMessage;
5
- const server_1 = require("./server");
6
5
  const json_1 = require("../../../util/json");
7
6
  function getUnnamedSocketName(c) {
8
7
  return `${c.remoteAddress ?? '?'}@${c.remotePort ?? '?'}`;
9
8
  }
10
9
  function sendMessage(c, message) {
11
- const msg = JSON.stringify(message, json_1.jsonReplacer);
12
- if (server_1.serverLog.settings.minLevel >= 2 /* LogLevel.Debug */) {
13
- server_1.serverLog.debug(`[${getUnnamedSocketName(c)}] sending message: ${msg}`);
14
- }
15
- c.write(`${msg}\n`);
10
+ return (0, json_1.superBigJsonStringify)(message, '\n', msg => {
11
+ c.write(msg);
12
+ });
16
13
  }
17
14
  //# sourceMappingURL=send.js.map
@@ -11,9 +11,9 @@ export declare class FlowRServer {
11
11
  private readonly server;
12
12
  private readonly shell;
13
13
  private versionInformation;
14
- private allowRSessionAccess;
14
+ private readonly allowRSessionAccess;
15
15
  /** maps names to the respective connection */
16
- private connections;
16
+ private readonly connections;
17
17
  private nameCounter;
18
18
  constructor(shell: RShell, allowRSessionAccess: boolean, server?: Server);
19
19
  start(port: number): Promise<void>;
@@ -17,7 +17,7 @@ class FlowRServer {
17
17
  server;
18
18
  shell;
19
19
  versionInformation;
20
- allowRSessionAccess = false;
20
+ allowRSessionAccess;
21
21
  /** maps names to the respective connection */
22
22
  connections = new Map();
23
23
  nameCounter = 0;
package/config.js CHANGED
@@ -41,7 +41,7 @@ exports.flowrConfigFileSchema = joi_1.default.object({
41
41
  // we don't load from a config file at all by default unless setConfigFile is called
42
42
  let configFile = undefined;
43
43
  let configWorkingDirectory = process.cwd();
44
- let currentConfig;
44
+ let currentConfig = undefined;
45
45
  function setConfigFile(file, workingDirectory = process.cwd(), forceLoad = false) {
46
46
  configFile = file;
47
47
  configWorkingDirectory = workingDirectory;
@@ -169,9 +169,10 @@ class PipelineExecutor {
169
169
  * _Without `expectedStepName`, please refrain from accessing the result, as you have no safeguards if the pipeline changes._
170
170
  */
171
171
  async nextStep(expectedStepName) {
172
+ const start = Date.now();
172
173
  const [step, result] = this._doNextStep(expectedStepName);
173
174
  const awaitedResult = await result;
174
- this.output[step] = awaitedResult;
175
+ this.output[step] = { ...awaitedResult, '.meta': { timing: Date.now() - start } };
175
176
  this.stepCounter++;
176
177
  return { name: step, result: awaitedResult };
177
178
  }
@@ -1,16 +1,20 @@
1
1
  import { internalPrinter } from '../../../print/print';
2
- import { parseToQuads } from '../../../print/parse-printer';
3
2
  import { PipelineStepStage } from '../../pipeline-step';
4
3
  import type { RShellExecutor } from '../../../../r-bridge/shell-executor';
5
4
  import type { RShell } from '../../../../r-bridge/shell';
6
5
  import type { RParseRequests } from '../../../../r-bridge/retriever';
6
+ import type { QuadSerializationConfiguration } from '../../../../util/quads';
7
7
  export interface ParseRequiredInput {
8
8
  /** This is the {@link RShell} or {@link RShellExecutor} connection to be used to obtain the original parses AST of the R code */
9
9
  readonly shell: RShell | RShellExecutor;
10
10
  /** The request which essentially indicates the input to extract the AST from */
11
11
  readonly request: RParseRequests;
12
12
  }
13
- declare function processor(_results: unknown, input: Partial<ParseRequiredInput>): Promise<string>;
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>;
14
18
  export declare const PARSE_WITH_R_SHELL_STEP: {
15
19
  readonly name: "parse";
16
20
  readonly humanReadableName: "parse with R shell";
@@ -19,8 +23,11 @@ export declare const PARSE_WITH_R_SHELL_STEP: {
19
23
  readonly executed: PipelineStepStage.OncePerFile;
20
24
  readonly printer: {
21
25
  readonly 0: typeof internalPrinter;
22
- readonly 2: (text: string) => string;
23
- readonly 5: typeof parseToQuads;
26
+ readonly 2: {
27
+ (value: any, replacer?: (this: any, key: string, value: any) => any, space?: string | number): string;
28
+ (value: any, replacer?: (number | string)[] | null, space?: string | number): string;
29
+ };
30
+ readonly 5: ({ parsed }: ParseStepOutput, config: QuadSerializationConfiguration) => string;
24
31
  };
25
32
  readonly dependencies: readonly [];
26
33
  readonly requiredInput: ParseRequiredInput;
@@ -4,13 +4,13 @@ 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
6
  const retriever_1 = require("../../../../r-bridge/retriever");
7
- function processor(_results, input) {
7
+ async function processor(_results, input) {
8
8
  /* in the future, we want to expose all cases */
9
9
  if (Array.isArray(input.request)) {
10
- return (0, retriever_1.retrieveParseDataFromRCode)(input.request[0], input.shell);
10
+ return { parsed: await (0, retriever_1.retrieveParseDataFromRCode)(input.request[0], input.shell) };
11
11
  }
12
12
  else {
13
- return (0, retriever_1.retrieveParseDataFromRCode)(input.request, input.shell);
13
+ return { parsed: await (0, retriever_1.retrieveParseDataFromRCode)(input.request, input.shell) };
14
14
  }
15
15
  }
16
16
  exports.PARSE_WITH_R_SHELL_STEP = {
@@ -21,8 +21,8 @@ exports.PARSE_WITH_R_SHELL_STEP = {
21
21
  executed: 0 /* PipelineStepStage.OncePerFile */,
22
22
  printer: {
23
23
  [0 /* StepOutputFormat.Internal */]: print_1.internalPrinter,
24
- [2 /* StepOutputFormat.Json */]: text => text,
25
- [5 /* StepOutputFormat.RdfQuads */]: parse_printer_1.parseToQuads
24
+ [2 /* StepOutputFormat.Json */]: JSON.stringify,
25
+ [5 /* StepOutputFormat.RdfQuads */]: ({ parsed }, config) => (0, parse_printer_1.parseToQuads)(parsed, config)
26
26
  },
27
27
  dependencies: [],
28
28
  requiredInput: undefined
@@ -3,12 +3,13 @@ import { normalizedAstToJson, normalizedAstToQuads, printNormalizedAstToMermaid,
3
3
  import { PipelineStepStage } from '../../pipeline-step';
4
4
  import type { IdGenerator } from '../../../../r-bridge/lang-4.x/ast/model/processing/decorate';
5
5
  import type { NoInfo } from '../../../../r-bridge/lang-4.x/ast/model/model';
6
+ import type { ParseStepOutput } from './00-parse';
6
7
  export interface NormalizeRequiredInput {
7
8
  /** This id generator is only necessary if you want to retrieve a dataflow from the parsed R AST, it determines the id generator to use and by default uses the {@link deterministicCountingIdGenerator}*/
8
9
  readonly getId?: IdGenerator<NoInfo>;
9
10
  }
10
11
  declare function processor(results: {
11
- parse?: string;
12
+ parse?: ParseStepOutput;
12
13
  }, input: Partial<NormalizeRequiredInput>): import("../../../../r-bridge/lang-4.x/ast/model/processing/decorate").NormalizedAst<import("../../../../r-bridge/lang-4.x/ast/model/processing/decorate").ParentInformation, import("../../../../r-bridge/lang-4.x/ast/model/model").RNode<import("../../../../r-bridge/lang-4.x/ast/model/processing/decorate").ParentInformation>>;
13
14
  export declare const NORMALIZE: {
14
15
  readonly name: "normalize";
@@ -3,14 +3,14 @@ import { PipelineStepStage } from '../../pipeline-step';
3
3
  import { dataflowGraphToJson, dataflowGraphToMermaid, dataflowGraphToMermaidUrl, dataflowGraphToQuads } from '../../../print/dataflow-printer';
4
4
  import type { NormalizedAst } from '../../../../r-bridge/lang-4.x/ast/model/processing/decorate';
5
5
  import type { RParseRequests } from '../../../../r-bridge/retriever';
6
- declare function legacyProcessor(results: {
6
+ declare function processor(results: {
7
7
  normalize?: NormalizedAst;
8
8
  }, input: {
9
9
  request?: RParseRequests;
10
10
  }): import("../../../../dataflow/info").DataflowInformation;
11
11
  export declare const STATIC_DATAFLOW: {
12
12
  readonly humanReadableName: "dataflow";
13
- readonly processor: typeof legacyProcessor;
13
+ readonly processor: typeof processor;
14
14
  readonly requiredInput: {};
15
15
  readonly name: "dataflow";
16
16
  readonly description: "Construct the dataflow graph";
@@ -17,13 +17,13 @@ const staticDataflowCommon = {
17
17
  },
18
18
  dependencies: ['normalize'],
19
19
  };
20
- function legacyProcessor(results, input) {
20
+ function processor(results, input) {
21
21
  return (0, extractor_1.produceDataFlowGraph)(input.request, results.normalize);
22
22
  }
23
23
  exports.STATIC_DATAFLOW = {
24
24
  ...staticDataflowCommon,
25
25
  humanReadableName: 'dataflow',
26
- processor: legacyProcessor,
26
+ processor,
27
27
  requiredInput: {}
28
28
  };
29
29
  //# sourceMappingURL=20-dataflow.js.map
@@ -2,12 +2,15 @@ export declare const DEFAULT_SLICING_PIPELINE: import("./pipeline").Pipeline<{
2
2
  readonly name: "parse";
3
3
  readonly humanReadableName: "parse with R shell";
4
4
  readonly description: "Parse the given R code into an AST";
5
- readonly processor: (_results: unknown, input: Partial<import("../all/core/00-parse").ParseRequiredInput>) => Promise<string>;
5
+ readonly processor: (_results: unknown, input: Partial<import("../all/core/00-parse").ParseRequiredInput>) => Promise<import("../all/core/00-parse").ParseStepOutput>;
6
6
  readonly executed: import("../pipeline-step").PipelineStepStage.OncePerFile;
7
7
  readonly printer: {
8
8
  readonly 0: typeof import("../../print/print").internalPrinter;
9
- readonly 2: (text: string) => string;
10
- readonly 5: typeof import("../../print/parse-printer").parseToQuads;
9
+ readonly 2: {
10
+ (value: any, replacer?: (this: any, key: string, value: any) => any, space?: string | number): string;
11
+ (value: any, replacer?: (number | string)[] | null, space?: string | number): string;
12
+ };
13
+ readonly 5: ({ parsed }: import("../all/core/00-parse").ParseStepOutput, config: import("../../../util/quads").QuadSerializationConfiguration) => string;
11
14
  };
12
15
  readonly dependencies: readonly [];
13
16
  readonly requiredInput: import("../all/core/00-parse").ParseRequiredInput;
@@ -16,7 +19,7 @@ export declare const DEFAULT_SLICING_PIPELINE: import("./pipeline").Pipeline<{
16
19
  readonly humanReadableName: "normalize";
17
20
  readonly description: "Normalize the AST to flowR's AST";
18
21
  readonly processor: (results: {
19
- parse?: string;
22
+ parse?: import("../all/core/00-parse").ParseStepOutput;
20
23
  }, input: Partial<import("../all/core/10-normalize").NormalizeRequiredInput>) => import("../../../r-bridge/lang-4.x/ast/model/processing/decorate").NormalizedAst<import("../../../r-bridge/lang-4.x/ast/model/processing/decorate").ParentInformation, import("../../../r-bridge/lang-4.x/ast/model/model").RNode<import("../../../r-bridge/lang-4.x/ast/model/processing/decorate").ParentInformation>>;
21
24
  readonly executed: import("../pipeline-step").PipelineStepStage.OncePerFile;
22
25
  readonly printer: {
@@ -80,12 +83,15 @@ export declare const DEFAULT_SLICE_AND_RECONSTRUCT_PIPELINE: import("./pipeline"
80
83
  readonly name: "parse";
81
84
  readonly humanReadableName: "parse with R shell";
82
85
  readonly description: "Parse the given R code into an AST";
83
- readonly processor: (_results: unknown, input: Partial<import("../all/core/00-parse").ParseRequiredInput>) => Promise<string>;
86
+ readonly processor: (_results: unknown, input: Partial<import("../all/core/00-parse").ParseRequiredInput>) => Promise<import("../all/core/00-parse").ParseStepOutput>;
84
87
  readonly executed: import("../pipeline-step").PipelineStepStage.OncePerFile;
85
88
  readonly printer: {
86
89
  readonly 0: typeof import("../../print/print").internalPrinter;
87
- readonly 2: (text: string) => string;
88
- readonly 5: typeof import("../../print/parse-printer").parseToQuads;
90
+ readonly 2: {
91
+ (value: any, replacer?: (this: any, key: string, value: any) => any, space?: string | number): string;
92
+ (value: any, replacer?: (number | string)[] | null, space?: string | number): string;
93
+ };
94
+ readonly 5: ({ parsed }: import("../all/core/00-parse").ParseStepOutput, config: import("../../../util/quads").QuadSerializationConfiguration) => string;
89
95
  };
90
96
  readonly dependencies: readonly [];
91
97
  readonly requiredInput: import("../all/core/00-parse").ParseRequiredInput;
@@ -94,7 +100,7 @@ export declare const DEFAULT_SLICE_AND_RECONSTRUCT_PIPELINE: import("./pipeline"
94
100
  readonly humanReadableName: "normalize";
95
101
  readonly description: "Normalize the AST to flowR's AST";
96
102
  readonly processor: (results: {
97
- parse?: string;
103
+ parse?: import("../all/core/00-parse").ParseStepOutput;
98
104
  }, input: Partial<import("../all/core/10-normalize").NormalizeRequiredInput>) => import("../../../r-bridge/lang-4.x/ast/model/processing/decorate").NormalizedAst<import("../../../r-bridge/lang-4.x/ast/model/processing/decorate").ParentInformation, import("../../../r-bridge/lang-4.x/ast/model/model").RNode<import("../../../r-bridge/lang-4.x/ast/model/processing/decorate").ParentInformation>>;
99
105
  readonly executed: import("../pipeline-step").PipelineStepStage.OncePerFile;
100
106
  readonly printer: {
@@ -158,12 +164,15 @@ export declare const DEFAULT_SLICE_WITHOUT_RECONSTRUCT_PIPELINE: import("./pipel
158
164
  readonly name: "parse";
159
165
  readonly humanReadableName: "parse with R shell";
160
166
  readonly description: "Parse the given R code into an AST";
161
- readonly processor: (_results: unknown, input: Partial<import("../all/core/00-parse").ParseRequiredInput>) => Promise<string>;
167
+ readonly processor: (_results: unknown, input: Partial<import("../all/core/00-parse").ParseRequiredInput>) => Promise<import("../all/core/00-parse").ParseStepOutput>;
162
168
  readonly executed: import("../pipeline-step").PipelineStepStage.OncePerFile;
163
169
  readonly printer: {
164
170
  readonly 0: typeof import("../../print/print").internalPrinter;
165
- readonly 2: (text: string) => string;
166
- readonly 5: typeof import("../../print/parse-printer").parseToQuads;
171
+ readonly 2: {
172
+ (value: any, replacer?: (this: any, key: string, value: any) => any, space?: string | number): string;
173
+ (value: any, replacer?: (number | string)[] | null, space?: string | number): string;
174
+ };
175
+ readonly 5: ({ parsed }: import("../all/core/00-parse").ParseStepOutput, config: import("../../../util/quads").QuadSerializationConfiguration) => string;
167
176
  };
168
177
  readonly dependencies: readonly [];
169
178
  readonly requiredInput: import("../all/core/00-parse").ParseRequiredInput;
@@ -172,7 +181,7 @@ export declare const DEFAULT_SLICE_WITHOUT_RECONSTRUCT_PIPELINE: import("./pipel
172
181
  readonly humanReadableName: "normalize";
173
182
  readonly description: "Normalize the AST to flowR's AST";
174
183
  readonly processor: (results: {
175
- parse?: string;
184
+ parse?: import("../all/core/00-parse").ParseStepOutput;
176
185
  }, input: Partial<import("../all/core/10-normalize").NormalizeRequiredInput>) => import("../../../r-bridge/lang-4.x/ast/model/processing/decorate").NormalizedAst<import("../../../r-bridge/lang-4.x/ast/model/processing/decorate").ParentInformation, import("../../../r-bridge/lang-4.x/ast/model/model").RNode<import("../../../r-bridge/lang-4.x/ast/model/processing/decorate").ParentInformation>>;
177
186
  readonly executed: import("../pipeline-step").PipelineStepStage.OncePerFile;
178
187
  readonly printer: {
@@ -222,12 +231,15 @@ export declare const DEFAULT_DATAFLOW_PIPELINE: import("./pipeline").Pipeline<{
222
231
  readonly name: "parse";
223
232
  readonly humanReadableName: "parse with R shell";
224
233
  readonly description: "Parse the given R code into an AST";
225
- readonly processor: (_results: unknown, input: Partial<import("../all/core/00-parse").ParseRequiredInput>) => Promise<string>;
234
+ readonly processor: (_results: unknown, input: Partial<import("../all/core/00-parse").ParseRequiredInput>) => Promise<import("../all/core/00-parse").ParseStepOutput>;
226
235
  readonly executed: import("../pipeline-step").PipelineStepStage.OncePerFile;
227
236
  readonly printer: {
228
237
  readonly 0: typeof import("../../print/print").internalPrinter;
229
- readonly 2: (text: string) => string;
230
- readonly 5: typeof import("../../print/parse-printer").parseToQuads;
238
+ readonly 2: {
239
+ (value: any, replacer?: (this: any, key: string, value: any) => any, space?: string | number): string;
240
+ (value: any, replacer?: (number | string)[] | null, space?: string | number): string;
241
+ };
242
+ readonly 5: ({ parsed }: import("../all/core/00-parse").ParseStepOutput, config: import("../../../util/quads").QuadSerializationConfiguration) => string;
231
243
  };
232
244
  readonly dependencies: readonly [];
233
245
  readonly requiredInput: import("../all/core/00-parse").ParseRequiredInput;
@@ -236,7 +248,7 @@ export declare const DEFAULT_DATAFLOW_PIPELINE: import("./pipeline").Pipeline<{
236
248
  readonly humanReadableName: "normalize";
237
249
  readonly description: "Normalize the AST to flowR's AST";
238
250
  readonly processor: (results: {
239
- parse?: string;
251
+ parse?: import("../all/core/00-parse").ParseStepOutput;
240
252
  }, input: Partial<import("../all/core/10-normalize").NormalizeRequiredInput>) => import("../../../r-bridge/lang-4.x/ast/model/processing/decorate").NormalizedAst<import("../../../r-bridge/lang-4.x/ast/model/processing/decorate").ParentInformation, import("../../../r-bridge/lang-4.x/ast/model/model").RNode<import("../../../r-bridge/lang-4.x/ast/model/processing/decorate").ParentInformation>>;
241
253
  readonly executed: import("../pipeline-step").PipelineStepStage.OncePerFile;
242
254
  readonly printer: {
@@ -272,12 +284,15 @@ export declare const DEFAULT_NORMALIZE_PIPELINE: import("./pipeline").Pipeline<{
272
284
  readonly name: "parse";
273
285
  readonly humanReadableName: "parse with R shell";
274
286
  readonly description: "Parse the given R code into an AST";
275
- readonly processor: (_results: unknown, input: Partial<import("../all/core/00-parse").ParseRequiredInput>) => Promise<string>;
287
+ readonly processor: (_results: unknown, input: Partial<import("../all/core/00-parse").ParseRequiredInput>) => Promise<import("../all/core/00-parse").ParseStepOutput>;
276
288
  readonly executed: import("../pipeline-step").PipelineStepStage.OncePerFile;
277
289
  readonly printer: {
278
290
  readonly 0: typeof import("../../print/print").internalPrinter;
279
- readonly 2: (text: string) => string;
280
- readonly 5: typeof import("../../print/parse-printer").parseToQuads;
291
+ readonly 2: {
292
+ (value: any, replacer?: (this: any, key: string, value: any) => any, space?: string | number): string;
293
+ (value: any, replacer?: (number | string)[] | null, space?: string | number): string;
294
+ };
295
+ readonly 5: ({ parsed }: import("../all/core/00-parse").ParseStepOutput, config: import("../../../util/quads").QuadSerializationConfiguration) => string;
281
296
  };
282
297
  readonly dependencies: readonly [];
283
298
  readonly requiredInput: import("../all/core/00-parse").ParseRequiredInput;
@@ -286,7 +301,7 @@ export declare const DEFAULT_NORMALIZE_PIPELINE: import("./pipeline").Pipeline<{
286
301
  readonly humanReadableName: "normalize";
287
302
  readonly description: "Normalize the AST to flowR's AST";
288
303
  readonly processor: (results: {
289
- parse?: string;
304
+ parse?: import("../all/core/00-parse").ParseStepOutput;
290
305
  }, input: Partial<import("../all/core/10-normalize").NormalizeRequiredInput>) => import("../../../r-bridge/lang-4.x/ast/model/processing/decorate").NormalizedAst<import("../../../r-bridge/lang-4.x/ast/model/processing/decorate").ParentInformation, import("../../../r-bridge/lang-4.x/ast/model/model").RNode<import("../../../r-bridge/lang-4.x/ast/model/processing/decorate").ParentInformation>>;
291
306
  readonly executed: import("../pipeline-step").PipelineStepStage.OncePerFile;
292
307
  readonly printer: {
@@ -303,12 +318,15 @@ export declare const DEFAULT_PARSE_PIPELINE: import("./pipeline").Pipeline<{
303
318
  readonly name: "parse";
304
319
  readonly humanReadableName: "parse with R shell";
305
320
  readonly description: "Parse the given R code into an AST";
306
- readonly processor: (_results: unknown, input: Partial<import("../all/core/00-parse").ParseRequiredInput>) => Promise<string>;
321
+ readonly processor: (_results: unknown, input: Partial<import("../all/core/00-parse").ParseRequiredInput>) => Promise<import("../all/core/00-parse").ParseStepOutput>;
307
322
  readonly executed: import("../pipeline-step").PipelineStepStage.OncePerFile;
308
323
  readonly printer: {
309
324
  readonly 0: typeof import("../../print/print").internalPrinter;
310
- readonly 2: (text: string) => string;
311
- readonly 5: typeof import("../../print/parse-printer").parseToQuads;
325
+ readonly 2: {
326
+ (value: any, replacer?: (this: any, key: string, value: any) => any, space?: string | number): string;
327
+ (value: any, replacer?: (number | string)[] | null, space?: string | number): string;
328
+ };
329
+ readonly 5: ({ parsed }: import("../all/core/00-parse").ParseStepOutput, config: import("../../../util/quads").QuadSerializationConfiguration) => string;
312
330
  };
313
331
  readonly dependencies: readonly [];
314
332
  readonly requiredInput: import("../all/core/00-parse").ParseRequiredInput;
@@ -23,10 +23,22 @@ export interface Pipeline<T extends IPipelineStep = IPipelineStep> {
23
23
  */
24
24
  export type PipelineStepNames<P extends Pipeline> = PipelineStep<P>['name'];
25
25
  export type PipelineStep<P extends Pipeline> = P extends Pipeline<infer U> ? U : never;
26
+ /**
27
+ * Meta-information attached to every step result
28
+ */
29
+ export interface PipelinePerStepMetaInformation {
30
+ readonly '.meta': {
31
+ /**
32
+ * The time it took to execute the step in milliseconds,
33
+ * the required accuracy is dependent on the measuring system, but usually at around 1 ms.
34
+ */
35
+ readonly timing: number;
36
+ };
37
+ }
26
38
  export type PipelineStepWithName<P extends Pipeline, Name extends PipelineStepName> = P extends Pipeline<infer U> ? U extends IPipelineStep<Name> ? U : never : never;
27
39
  export type PipelineStepProcessorWithName<P extends Pipeline, Name extends PipelineStepName> = PipelineStepWithName<P, Name>['processor'];
28
40
  export type PipelineStepPrintersWithName<P extends Pipeline, Name extends PipelineStepName> = PipelineStepWithName<P, Name>['printer'];
29
- export type PipelineStepOutputWithName<P extends Pipeline, Name extends PipelineStepName> = Awaited<ReturnType<PipelineStepProcessorWithName<P, Name>>>;
41
+ export type PipelineStepOutputWithName<P extends Pipeline, Name extends PipelineStepName> = Awaited<ReturnType<PipelineStepProcessorWithName<P, Name>>> & PipelinePerStepMetaInformation;
30
42
  export type PipelineInput<P extends Pipeline> = UnionToIntersection<PipelineStep<P>['requiredInput']>;
31
43
  /**
32
44
  * Only gets the union of 'requiredInput' of those PipelineSteps which have a 'execute' field of type 'OncePerRequest'.
@@ -40,8 +52,8 @@ export type PipelineOutput<P extends Pipeline> = {
40
52
  };
41
53
  /**
42
54
  * Creates a {@link Pipeline|pipeline} from a given collection of {@link IPipelineStep|steps}.
43
- * In order to be valid, the collection of {@link IPipelineStep|steps} must satisfy the following set of constraints
44
- * (which should be logical, when you consider what a pipeline should accomplish):
55
+ * To be valid, the collection of {@link IPipelineStep|steps} must satisfy the following set of constraints
56
+ * (which should be logical, when you consider what a pipeline should achieve):
45
57
  *
46
58
  * 0) the collection of {@link IPipelineStep|steps} is not empty
47
59
  * 1) all {@link IPipelineStepOrder#name|names} of {@link IPipelineStep|steps} are unique for the given pipeline
@@ -4,8 +4,8 @@ exports.createPipeline = createPipeline;
4
4
  const create_pipeline_1 = require("./create-pipeline");
5
5
  /**
6
6
  * Creates a {@link Pipeline|pipeline} from a given collection of {@link IPipelineStep|steps}.
7
- * In order to be valid, the collection of {@link IPipelineStep|steps} must satisfy the following set of constraints
8
- * (which should be logical, when you consider what a pipeline should accomplish):
7
+ * To be valid, the collection of {@link IPipelineStep|steps} must satisfy the following set of constraints
8
+ * (which should be logical, when you consider what a pipeline should achieve):
9
9
  *
10
10
  * 0) the collection of {@link IPipelineStep|steps} is not empty
11
11
  * 1) all {@link IPipelineStepOrder#name|names} of {@link IPipelineStep|steps} are unique for the given pipeline
@@ -23,6 +23,7 @@ import { processLibrary } from '../internal/process/functions/call/built-in/buil
23
23
  import { processSourceCall } from '../internal/process/functions/call/built-in/built-in-source';
24
24
  import type { ForceArguments } from '../internal/process/functions/call/common';
25
25
  import { processApply } from '../internal/process/functions/call/built-in/built-in-apply';
26
+ import type { LinkTo } from '../../queries/catalog/call-context-query/call-context-query-format';
26
27
  export declare const BuiltIn = "built-in";
27
28
  export type BuiltInIdentifierProcessor = <OtherInfo>(name: RSymbol<OtherInfo & ParentInformation>, args: readonly RFunctionArgument<OtherInfo & ParentInformation>[], rootId: NodeId, data: DataflowProcessorInformation<OtherInfo & ParentInformation>) => DataflowInformation;
28
29
  export type BuiltInIdentifierProcessorWithConfig<Config> = <OtherInfo>(name: RSymbol<OtherInfo & ParentInformation>, args: readonly RFunctionArgument<OtherInfo & ParentInformation>[], rootId: NodeId, data: DataflowProcessorInformation<OtherInfo & ParentInformation>, config: Config) => DataflowInformation;
@@ -36,12 +37,13 @@ export interface BuiltInIdentifierConstant<T = unknown> extends IdentifierRefere
36
37
  definedAt: typeof BuiltIn;
37
38
  value: T;
38
39
  }
39
- declare function defaultBuiltInProcessor<OtherInfo>(name: RSymbol<OtherInfo & ParentInformation>, args: readonly RFunctionArgument<OtherInfo & ParentInformation>[], rootId: NodeId, data: DataflowProcessorInformation<OtherInfo & ParentInformation>, config: {
40
- returnsNthArgument?: number | 'last';
41
- cfg?: ExitPointType;
42
- readAllArguments?: boolean;
43
- hasUnknownSideEffects?: boolean;
44
- } & ForceArguments): DataflowInformation;
40
+ export interface DefaultBuiltInProcessorConfiguration extends ForceArguments {
41
+ readonly returnsNthArgument?: number | 'last';
42
+ readonly cfg?: ExitPointType;
43
+ readonly readAllArguments?: boolean;
44
+ readonly hasUnknownSideEffects?: boolean | LinkTo<RegExp | string>;
45
+ }
46
+ declare function defaultBuiltInProcessor<OtherInfo>(name: RSymbol<OtherInfo & ParentInformation>, args: readonly RFunctionArgument<OtherInfo & ParentInformation>[], rootId: NodeId, data: DataflowProcessorInformation<OtherInfo & ParentInformation>, config: DefaultBuiltInProcessorConfiguration): DataflowInformation;
45
47
  export declare function registerBuiltInFunctions<Config, Proc extends BuiltInIdentifierProcessorWithConfig<Config>>(both: boolean, names: readonly Identifier[], processor: Proc, config: Config): void;
46
48
  export declare const BuiltInProcessorMapper: {
47
49
  readonly 'builtin:default': typeof defaultBuiltInProcessor;
@@ -41,7 +41,12 @@ function defaultBuiltInProcessor(name, args, rootId, data, config) {
41
41
  }
42
42
  }
43
43
  if (config.hasUnknownSideEffects) {
44
- res.graph.markIdForUnknownSideEffects(rootId);
44
+ if (typeof config.hasUnknownSideEffects !== 'boolean') {
45
+ res.graph.markIdForUnknownSideEffects(rootId, config.hasUnknownSideEffects);
46
+ }
47
+ else {
48
+ res.graph.markIdForUnknownSideEffects(rootId);
49
+ }
45
50
  }
46
51
  if (config.cfg !== undefined) {
47
52
  res.exitPoints = [...res.exitPoints, { type: config.cfg, nodeId: rootId, controlDependencies: data.controlDependencies }];
@@ -11,12 +11,22 @@ exports.DefaultBuiltinConfig = [
11
11
  {
12
12
  type: 'function',
13
13
  names: [
14
- '~', '+', '-', '*', '/', '^', '!', '?', '**', '==', '!=', '>', '<', '>=', '<=', '%%', '%/%', '%*%', '%in%', ':', 'list', 'c',
14
+ '~', '+', '-', '*', '/', '^', '!', '?', '**', '==', '!=', '>', '<', '>=', '<=', '%%', '%/%', '%*%', '%in%', ':', 'list',
15
15
  'rep', 'seq', 'seq_len', 'seq_along', 'seq.int', 'gsub', 'which', 'class', 'dimnames', 'min', 'max',
16
16
  'intersect', 'subset', 'match', 'sqrt', 'abs', 'round', 'floor', 'ceiling', 'signif', 'trunc', 'log', 'log10', 'log2', 'sum', 'mean',
17
- 'unique', 'paste', 'paste0', 'read.csv', 'stop', 'is.null', 'plot', 'numeric', 'as.character', 'as.integer', 'as.logical', 'as.numeric', 'as.matrix',
17
+ 'unique', 'paste', 'paste0', 'read.csv', 'stop', 'is.null', 'numeric', 'as.character', 'as.integer', 'as.logical', 'as.numeric', 'as.matrix',
18
18
  'rbind', 'nrow', 'ncol', 'tryCatch', 'expression', 'factor',
19
- 'missing', 'as.data.frame', 'data.frame', 'na.omit', 'rownames', 'names', 'order', 'length', 'any', 'dim', 'matrix', 'cbind', 'nchar', 't'
19
+ 'missing', 'as.data.frame', 'data.frame', 'na.omit', 'rownames', 'names', 'order', 'length', 'any', 'dim', 'matrix', 'cbind', 'nchar',
20
+ 'pdf', 'jpeg', 'png', 'windows', 'postscript', 'xfig', 'bitmap', 'pictex', 'cairo_pdf', 'svg', 'bmp', 'tiff', 'X11', 'quartz'
21
+ ],
22
+ processor: 'builtin:default',
23
+ config: { readAllArguments: true },
24
+ assumePrimitive: true
25
+ },
26
+ {
27
+ type: 'function',
28
+ names: [
29
+ 'c', 't'
20
30
  ],
21
31
  processor: 'builtin:default',
22
32
  config: { readAllArguments: true },
@@ -27,11 +37,17 @@ exports.DefaultBuiltinConfig = [
27
37
  { type: 'function', names: ['lapply', 'sapply', 'vapply'], processor: 'builtin:apply', config: { indexOfFunction: 1, nameOfFunctionArgument: 'FUN' }, assumePrimitive: false },
28
38
  { type: 'function', names: ['Lapply', 'Sapply', 'Vapply'], processor: 'builtin:apply', config: { indexOfFunction: 1, nameOfFunctionArgument: 'FUN' }, assumePrimitive: false }, /* functool wrappers */
29
39
  { type: 'function', names: ['apply', 'tapply', 'Tapply'], processor: 'builtin:apply', config: { indexOfFunction: 2, nameOfFunctionArgument: 'FUN' }, assumePrimitive: false },
30
- { type: 'function', names: ['print'], processor: 'builtin:default', config: { returnsNthArgument: 0, forceArgs: 'all' }, assumePrimitive: false },
40
+ { type: 'function', names: ['print', 'message', 'warning'], processor: 'builtin:default', config: { returnsNthArgument: 0, forceArgs: 'all', hasUnknownSideEffects: { type: 'link-to-last-call', callName: /^sink$/ } }, assumePrimitive: false },
41
+ // graphics base
42
+ { type: 'function', names: ['plot', 'plot.new', 'curve', 'map', 'image', 'boxplot', 'dotchart', 'sunflowerplot', 'barplot', 'matplot', 'hist', 'stem', 'density', 'smoothScatter', 'contour', 'persp'],
43
+ processor: 'builtin:default', config: { forceArgs: 'all', hasUnknownSideEffects: { type: 'link-to-last-call', callName: /^pdf|jpeg|png|windows|postscript|xfig|bitmap|pictex|cairo_pdf|svg|bmp|tiff|X11|quartz$/ } }, assumePrimitive: true },
44
+ // graphics addons
45
+ { type: 'function', names: ['points', 'abline', 'mtext', 'lines', 'text', 'legend', 'title', 'axis', 'polygon', 'polypath', 'pie', 'rect', 'segments', 'arrows', 'symbols', 'tiplabels'],
46
+ processor: 'builtin:default', config: { forceArgs: 'all', hasUnknownSideEffects: { type: 'link-to-last-call', callName: /^dev\.new|dev\.copy|plot\.new|xspline|sunflowerplot|dotchart|plot|map|image|curve|boxplot|barplot|matplot|hist|stem|density|smoothScatter|contour|persp$/ } }, assumePrimitive: true },
31
47
  { type: 'function', names: ['('], processor: 'builtin:default', config: { returnsNthArgument: 0 }, assumePrimitive: true },
32
48
  { type: 'function', names: ['load', 'load_all', 'setwd', 'set.seed'], processor: 'builtin:default', config: { hasUnknownSideEffects: true, forceArgs: [true] }, assumePrimitive: false },
33
49
  { type: 'function', names: ['eval', 'body', 'formals', 'environment'], processor: 'builtin:default', config: { hasUnknownSideEffects: true, forceArgs: [true] }, assumePrimitive: false },
34
- { type: 'function', names: ['cat'], processor: 'builtin:default', config: { forceArgs: 'all' }, assumePrimitive: false },
50
+ { type: 'function', names: ['cat'], processor: 'builtin:default', config: { forceArgs: 'all', hasUnknownSideEffects: { type: 'link-to-last-call', callName: /^sink$/ } }, assumePrimitive: false },
35
51
  { type: 'function', names: ['switch'], processor: 'builtin:default', config: { forceArgs: [true] }, assumePrimitive: false },
36
52
  { type: 'function', names: ['return'], processor: 'builtin:default', config: { returnsNthArgument: 0, cfg: 1 /* ExitPointType.Return */ }, assumePrimitive: false },
37
53
  { type: 'function', names: ['break'], processor: 'builtin:default', config: { cfg: 2 /* ExitPointType.Break */ }, assumePrimitive: false },