@eagleoutice/flowr 2.4.0 → 2.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 (60) hide show
  1. package/README.md +20 -20
  2. package/benchmark/stats/size-of.js +3 -3
  3. package/cli/repl/commands/repl-query.js +1 -1
  4. package/control-flow/simple-visitor.js +3 -3
  5. package/core/pipeline-executor.js +0 -8
  6. package/core/steps/all/static-slicing/00-slice.js +1 -1
  7. package/dataflow/environments/append.js +1 -1
  8. package/dataflow/environments/built-in-config.d.ts +12 -4
  9. package/dataflow/environments/built-in-config.js +23 -82
  10. package/dataflow/environments/built-in.d.ts +38 -4
  11. package/dataflow/environments/built-in.js +106 -11
  12. package/dataflow/environments/clone.d.ts +3 -2
  13. package/dataflow/environments/clone.js +6 -5
  14. package/dataflow/environments/define.js +1 -2
  15. package/dataflow/environments/diff.js +1 -3
  16. package/dataflow/environments/environment.d.ts +18 -24
  17. package/dataflow/environments/environment.js +25 -37
  18. package/dataflow/environments/overwrite.d.ts +1 -1
  19. package/dataflow/environments/overwrite.js +1 -1
  20. package/dataflow/environments/remove.d.ts +2 -2
  21. package/dataflow/environments/remove.js +3 -4
  22. package/dataflow/environments/resolve-by-name.d.ts +3 -3
  23. package/dataflow/environments/resolve-by-name.js +4 -5
  24. package/dataflow/eval/resolve/alias-tracking.d.ts +12 -12
  25. package/dataflow/eval/resolve/alias-tracking.js +12 -12
  26. package/dataflow/eval/resolve/resolve.js +1 -1
  27. package/dataflow/extractor.js +6 -1
  28. package/dataflow/graph/dataflowgraph-builder.d.ts +3 -1
  29. package/dataflow/graph/graph.d.ts +1 -0
  30. package/dataflow/graph/graph.js +5 -1
  31. package/dataflow/info.d.ts +1 -1
  32. package/dataflow/internal/linker.js +11 -11
  33. package/dataflow/internal/process/functions/call/built-in/built-in-access.js +1 -1
  34. package/dataflow/internal/process/functions/call/built-in/built-in-assignment.d.ts +3 -4
  35. package/dataflow/internal/process/functions/call/built-in/built-in-assignment.js +5 -5
  36. package/dataflow/internal/process/functions/call/built-in/built-in-expression-list.js +8 -6
  37. package/dataflow/internal/process/functions/call/built-in/built-in-function-definition.js +2 -2
  38. package/dataflow/internal/process/functions/call/built-in/built-in-rm.js +1 -1
  39. package/dataflow/processor.d.ts +5 -1
  40. package/documentation/doc-util/doc-env.js +1 -2
  41. package/package.json +1 -1
  42. package/queries/base-query-format.d.ts +2 -0
  43. package/queries/catalog/call-context-query/identify-link-to-last-call-relation.js +8 -8
  44. package/queries/catalog/dependencies-query/dependencies-query-executor.js +18 -0
  45. package/queries/catalog/dependencies-query/function-info/function-info.d.ts +9 -5
  46. package/queries/catalog/dependencies-query/function-info/read-functions.js +4 -2
  47. package/queries/catalog/dependencies-query/function-info/write-functions.js +5 -0
  48. package/queries/catalog/static-slice-query/static-slice-query-executor.d.ts +1 -1
  49. package/queries/catalog/static-slice-query/static-slice-query-executor.js +2 -2
  50. package/slicing/static/fingerprint.js +1 -2
  51. package/slicing/static/slice-call.d.ts +2 -1
  52. package/slicing/static/slice-call.js +3 -3
  53. package/slicing/static/static-slicer.d.ts +3 -4
  54. package/slicing/static/static-slicer.js +4 -4
  55. package/util/containers.d.ts +1 -0
  56. package/util/containers.js +1 -0
  57. package/util/json.js +1 -4
  58. package/util/mermaid/dfg.js +1 -2
  59. package/util/prefix.d.ts +1 -1
  60. package/util/version.js +1 -1
@@ -215,11 +215,11 @@ function checkTargetReferenceType(source, sourceInfo) {
215
215
  * @param nodeToDefine - `x`
216
216
  * @param sourceIds - `v`
217
217
  * @param rootIdOfAssignment - `<-`
218
- * @param config - The flowr config
218
+ * @param data - The dataflow analysis fold backpack
219
219
  * @param assignmentConfig - configuration for the assignment processing
220
220
  */
221
- function markAsAssignment(information, nodeToDefine, sourceIds, rootIdOfAssignment, config, assignmentConfig) {
222
- if (config.solver.pointerTracking) {
221
+ function markAsAssignment(information, nodeToDefine, sourceIds, rootIdOfAssignment, data, assignmentConfig) {
222
+ if (data.flowrConfig.solver.pointerTracking) {
223
223
  let indicesCollection = undefined;
224
224
  if (sourceIds.length === 1) {
225
225
  // support for tracking indices.
@@ -248,7 +248,7 @@ function markAsAssignment(information, nodeToDefine, sourceIds, rootIdOfAssignme
248
248
  }
249
249
  nodeToDefine.indicesCollection ??= indicesCollection;
250
250
  }
251
- information.environment = (0, define_1.define)(nodeToDefine, assignmentConfig?.superAssignment, information.environment, config);
251
+ information.environment = (0, define_1.define)(nodeToDefine, assignmentConfig?.superAssignment, information.environment, data.flowrConfig);
252
252
  information.graph.setDefinitionOfVertex(nodeToDefine);
253
253
  if (!assignmentConfig?.quoteSource) {
254
254
  for (const sourceId of sourceIds) {
@@ -285,7 +285,7 @@ function processAssignmentToSymbol(config) {
285
285
  information.environment = (0, overwrite_1.overwriteEnvironment)(sourceArg.environment, targetArg.environment);
286
286
  // install assigned variables in environment
287
287
  for (const write of writeNodes) {
288
- markAsAssignment(information, write, [source.info.id], rootId, data.flowrConfig, config);
288
+ markAsAssignment(information, write, [source.info.id], rootId, data, config);
289
289
  }
290
290
  information.graph.addEdge(rootId, targetArg.entryPoint, edge_1.EdgeType.Returns);
291
291
  if (quoteSource) {
@@ -50,24 +50,24 @@ function linkReadNameToWriteIfPossible(read, environments, listEnvironments, rem
50
50
  }
51
51
  function processNextExpression(currentElement, environment, listEnvironments, remainingRead, nextGraph) {
52
52
  // all inputs that have not been written until now are read!
53
- for (const read of [...currentElement.in, ...currentElement.unknownReferences]) {
53
+ for (const read of currentElement.in.concat(currentElement.unknownReferences)) {
54
54
  linkReadNameToWriteIfPossible(read, environment, listEnvironments, remainingRead, nextGraph);
55
55
  }
56
56
  }
57
57
  function updateSideEffectsForCalledFunctions(calledEnvs, inputEnvironment, nextGraph, localDefs) {
58
58
  for (const { functionCall, called } of calledEnvs) {
59
- const callDependencies = nextGraph.getVertex(functionCall, true)?.cds;
59
+ let callDependencies = null;
60
60
  for (const calledFn of called) {
61
61
  (0, assert_1.guard)(calledFn.tag === vertex_1.VertexType.FunctionDefinition, 'called function must be a function definition');
62
62
  // only merge the environments they have in common
63
- let environment = calledFn.environment;
63
+ let environment = calledFn.subflow.environment;
64
64
  while (environment.level > inputEnvironment.level) {
65
65
  environment = (0, scoping_1.popLocalEnvironment)(environment);
66
66
  }
67
67
  // update alle definitions to be defined at this function call
68
68
  let current = environment.current;
69
69
  let hasUpdate = false;
70
- while (current !== undefined && current.id !== environment_1.BuiltInEnvironment.id) {
70
+ while (!current?.builtInEnv) {
71
71
  for (const definitions of current.memory.values()) {
72
72
  for (const def of definitions) {
73
73
  if (!(0, built_in_1.isBuiltIn)(def.definedAt)) {
@@ -84,6 +84,9 @@ function updateSideEffectsForCalledFunctions(calledEnvs, inputEnvironment, nextG
84
84
  if (localDefs.length > 0) {
85
85
  environment = (0, remove_1.removeAll)(localDefs, environment);
86
86
  }
87
+ if (callDependencies === null) {
88
+ callDependencies = nextGraph.getVertex(functionCall, true)?.cds;
89
+ }
87
90
  inputEnvironment = (0, overwrite_1.overwriteEnvironment)(inputEnvironment, environment, callDependencies);
88
91
  }
89
92
  }
@@ -110,7 +113,7 @@ function processExpressionList(name, args, rootId, data) {
110
113
  continue;
111
114
  }
112
115
  // use the current environments for processing
113
- data = { ...data, environment: environment };
116
+ data.environment = environment;
114
117
  const processed = (0, processor_1.processDataflowFor)(expression, data);
115
118
  processedExpressions.push(processed);
116
119
  nextGraph.mergeWith(processed.graph);
@@ -140,7 +143,6 @@ function processExpressionList(name, args, rootId, data) {
140
143
  break;
141
144
  }
142
145
  }
143
- logger_1.dataflowLogger.trace(`expression list exits with ${remainingRead.size} remaining read names`);
144
146
  if (defaultReturnExpr) {
145
147
  exitPoints.push({
146
148
  type: 0 /* ExitPointType.Default */,
@@ -107,7 +107,7 @@ function processFunctionDefinition(name, args, rootId, data) {
107
107
  // this is no longer necessary when we update environments to be back to front (e.g., with a list of environments)
108
108
  // this favors the bigger environment
109
109
  function retrieveActiveEnvironment(callerEnvironment, baseEnvironment) {
110
- callerEnvironment ??= (0, environment_1.initializeCleanEnvironments)(true);
110
+ callerEnvironment ??= (0, environment_1.initializeCleanEnvironments)(undefined, true);
111
111
  let level = callerEnvironment.level ?? 0;
112
112
  if (baseEnvironment.level !== level) {
113
113
  while (baseEnvironment.level < level) {
@@ -212,7 +212,7 @@ function updateNestedFunctionCalls(graph, outEnvironment) {
212
212
  }
213
213
  }
214
214
  function prepareFunctionEnvironment(data) {
215
- let env = (0, environment_1.initializeCleanEnvironments)();
215
+ let env = (0, environment_1.initializeCleanEnvironments)(data.builtInEnvironment.memory);
216
216
  for (let i = 0; i < data.environment.level + 1 /* add another env */; i++) {
217
217
  env = (0, scoping_1.pushLocalEnvironment)(env);
218
218
  }
@@ -31,7 +31,7 @@ function processRm(name, args, rootId, data) {
31
31
  }
32
32
  let env = res.environment;
33
33
  for (const name of names) {
34
- env = (0, remove_1.remove)(name, env);
34
+ env = (0, remove_1.remove)(name, env, data.builtInEnvironment);
35
35
  }
36
36
  return {
37
37
  ...res,
@@ -3,7 +3,7 @@
3
3
  */
4
4
  import type { ControlDependency, DataflowInformation } from './info';
5
5
  import type { NormalizedAst, ParentInformation, RNodeWithParent } from '../r-bridge/lang-4.x/ast/model/processing/decorate';
6
- import type { REnvironmentInformation } from './environments/environment';
6
+ import type { IEnvironment, REnvironmentInformation } from './environments/environment';
7
7
  import type { RParseRequest } from '../r-bridge/retriever';
8
8
  import type { RNode } from '../r-bridge/lang-4.x/ast/model/model';
9
9
  import type { KnownParserType, Parser } from '../r-bridge/parser';
@@ -36,6 +36,10 @@ export interface DataflowProcessorInformation<OtherInfo> {
36
36
  * The chain of control-flow {@link NodeId}s that lead to the current node (e.g., of known ifs).
37
37
  */
38
38
  readonly controlDependencies: ControlDependency[] | undefined;
39
+ /**
40
+ * The built-in environment
41
+ */
42
+ readonly builtInEnvironment: IEnvironment;
39
43
  /**
40
44
  * The flowr configuration used for environment seeding, and precision control
41
45
  */
@@ -1,13 +1,12 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.printEnvironmentToMarkdown = printEnvironmentToMarkdown;
4
- const environment_1 = require("../../dataflow/environments/environment");
5
4
  const dfg_1 = require("../../util/mermaid/dfg");
6
5
  function printEnvironmentToMarkdown(env) {
7
6
  if (env === undefined) {
8
7
  return '?? (error)';
9
8
  }
10
- else if (env.id === environment_1.BuiltInEnvironment.id) {
9
+ else if (env.builtInEnv) {
11
10
  return `_Built-in Environment (${env.memory.size} entries)_`;
12
11
  }
13
12
  const lines = ['| Name | Definitions |', '|------|-------------|'];
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@eagleoutice/flowr",
3
- "version": "2.4.0",
3
+ "version": "2.4.2",
4
4
  "description": "Static Dataflow Analyzer and Program Slicer for the R Programming Language",
5
5
  "types": "dist/src/index.d.ts",
6
6
  "repository": {
@@ -1,6 +1,7 @@
1
1
  import type { NormalizedAst } from '../r-bridge/lang-4.x/ast/model/processing/decorate';
2
2
  import type { DataflowInformation } from '../dataflow/info';
3
3
  import type { FlowrConfigOptions } from '../config';
4
+ import type { SemVer } from 'semver';
4
5
  export interface BaseQueryFormat {
5
6
  /** used to select the query type :) */
6
7
  readonly type: string;
@@ -13,6 +14,7 @@ export interface BaseQueryResult {
13
14
  readonly '.meta': BaseQueryMeta;
14
15
  }
15
16
  export interface BasicQueryData {
17
+ readonly lib?: Record<string, SemVer>;
16
18
  readonly ast: NormalizedAst;
17
19
  readonly dataflow: DataflowInformation;
18
20
  readonly config: FlowrConfigOptions;
@@ -41,13 +41,7 @@ function satisfiesCallTargets(id, graph, callTarget) {
41
41
  .filter(([, { types }]) => (0, edge_1.edgeIncludesType)(types, edge_1.EdgeType.Calls))
42
42
  .map(([t]) => t);
43
43
  let builtIn = false;
44
- if (callVertex.environment === undefined) {
45
- /* if we have a call with an unbound environment,
46
- * this only happens if we are sure of built-in relations and want to save references
47
- */
48
- builtIn = true;
49
- }
50
- else {
44
+ if (callVertex.environment !== undefined) {
51
45
  /*
52
46
  * for performance and scoping reasons, flowR will not identify the global linkage,
53
47
  * including any potential built-in mapping.
@@ -57,6 +51,12 @@ function satisfiesCallTargets(id, graph, callTarget) {
57
51
  builtIn = true;
58
52
  }
59
53
  }
54
+ else {
55
+ /* if we have a call with an unbound environment,
56
+ * this only happens if we are sure of built-in relations and want to save references
57
+ */
58
+ builtIn = true;
59
+ }
60
60
  switch (callTarget) {
61
61
  case CallTargets.Any:
62
62
  return callTargets;
@@ -108,7 +108,7 @@ function getValueOfArgument(graph, call, argument, additionalAllowedTypes) {
108
108
  }
109
109
  }
110
110
  function identifyLinkToLastCallRelation(from, cfg, graph, { callName, ignoreIf, cascadeIf }) {
111
- if (ignoreIf && ignoreIf(from, graph)) {
111
+ if (ignoreIf?.(from, graph)) {
112
112
  return [];
113
113
  }
114
114
  const found = [];
@@ -15,6 +15,7 @@ const write_functions_1 = require("./function-info/write-functions");
15
15
  const function_info_1 = require("./function-info/function-info");
16
16
  const identify_link_to_last_call_relation_1 = require("../call-context-query/identify-link-to-last-call-relation");
17
17
  const resolve_argument_1 = require("../../../dataflow/eval/resolve/resolve-argument");
18
+ const assert_1 = require("../../../util/assert");
18
19
  function collectNamespaceAccesses(data, libraries) {
19
20
  /* for libraries, we have to additionally track all uses of `::` and `:::`, for this we currently simply traverse all uses */
20
21
  (0, visitor_1.visitAst)(data.ast.ast, n => {
@@ -113,6 +114,8 @@ function dropInfoOnLinkedIds(linkedIds) {
113
114
  }
114
115
  return linkedIds.map(id => typeof id === 'object' ? id.id : id);
115
116
  }
117
+ const readOnlyModes = new Set(['r', 'rt', 'rb']);
118
+ const writeOnlyModes = new Set(['w', 'wt', 'wb', 'a', 'at', 'ab']);
116
119
  function getResults(data, results, kind, functions, makeInfo) {
117
120
  const kindEntries = Object.entries(results?.kinds[kind]?.subkinds ?? {});
118
121
  return kindEntries.flatMap(([name, results]) => results.flatMap(({ id, linkedIds }) => {
@@ -128,6 +131,21 @@ function getResults(data, results, kind, functions, makeInfo) {
128
131
  const record = (0, objects_1.compactRecord)(makeInfo(id, vertex, undefined, undefined, dropInfoOnLinkedIds(linkedIds)));
129
132
  return record ? [record] : [];
130
133
  }
134
+ else if (info.ignoreIf === 'mode-only-read' || info.ignoreIf === 'mode-only-write') {
135
+ (0, assert_1.guard)('mode' in (info.additionalArgs ?? {}), 'Need additional argument mode when checking for mode');
136
+ const margs = info.additionalArgs?.mode;
137
+ (0, assert_1.guard)(margs, 'Need additional argument mode when checking for mode');
138
+ const modeArgs = (0, resolve_argument_1.getArgumentStringValue)(data.config.solver.variables, data.dataflow.graph, vertex, margs.argIdx, margs.argName, margs.resolveValue);
139
+ const modeValues = modeArgs?.values().flatMap(v => [...v]) ?? [];
140
+ if (info.ignoreIf === 'mode-only-read' && modeValues.every(m => m && readOnlyModes.has(m))) {
141
+ // all modes are read-only, so we can ignore this
142
+ return [];
143
+ }
144
+ else if (info.ignoreIf === 'mode-only-write' && modeValues.every(m => m && writeOnlyModes.has(m))) {
145
+ // all modes are write-only, so we can ignore this
146
+ return [];
147
+ }
148
+ }
131
149
  const results = [];
132
150
  for (const [arg, values] of foundValues.entries()) {
133
151
  for (const value of values) {
@@ -12,13 +12,17 @@ export type DependencyInfoLink = LinkTo<RegExp | string, Omit<FunctionInfo, 'nam
12
12
  when: DependencyInfoLinkConstraint;
13
13
  } | undefined>;
14
14
  export type DependencyInfoLinkAttachedInfo = DependencyInfoLink['attachLinkInfo'];
15
- export interface FunctionInfo {
16
- package?: string;
17
- name: string;
15
+ export interface FunctionArgInfo {
18
16
  /** the index if the argument can be positional, unnamed in case of something like `...`, if the argument must be given with the name, please leave undefined */
19
17
  argIdx?: number | 'unnamed';
20
18
  argName?: string;
21
- linkTo?: DependencyInfoLink[];
22
19
  resolveValue?: boolean | 'library';
23
- ignoreIf?: 'arg-missing';
20
+ }
21
+ export interface FunctionInfo extends FunctionArgInfo {
22
+ package?: string;
23
+ name: string;
24
+ linkTo?: DependencyInfoLink[];
25
+ ignoreIf?: 'arg-missing' | 'mode-only-read' | 'mode-only-write';
26
+ /** additional info on arguments - e.g. for the mode flag */
27
+ additionalArgs?: Record<string, FunctionArgInfo>;
24
28
  }
@@ -10,8 +10,8 @@ exports.ReadFunctions = [
10
10
  { package: 'base', name: 'read.dcf', argIdx: 0, argName: 'file', resolveValue: true },
11
11
  { package: 'base', name: 'scan', argIdx: 0, argName: 'file', resolveValue: true },
12
12
  { package: 'utils', name: 'read.fwf', argIdx: 0, argName: 'file', resolveValue: true },
13
- { package: 'base', name: 'file', argIdx: 1, argName: 'open', resolveValue: true },
14
- { package: 'base', name: 'url', argIdx: 1, argName: 'open', resolveValue: true },
13
+ { package: 'base', name: 'file', argIdx: 0, argName: 'description', resolveValue: true, ignoreIf: 'mode-only-write', additionalArgs: { mode: { argIdx: 1, argName: 'open', resolveValue: true } } },
14
+ { package: 'base', name: 'url', argIdx: 0, argName: 'description', resolveValue: true, ignoreIf: 'mode-only-write', additionalArgs: { mode: { argIdx: 1, argName: 'open', resolveValue: true } } },
15
15
  { package: 'base', name: 'load', argIdx: 0, argName: 'file', resolveValue: true },
16
16
  { package: 'base', name: 'gzfile', argIdx: 1, argName: 'open', resolveValue: true },
17
17
  { package: 'base', name: 'bzfile', argIdx: 1, argName: 'open', resolveValue: true },
@@ -22,6 +22,8 @@ exports.ReadFunctions = [
22
22
  { package: 'base', name: 'matrix', argIdx: 0, argName: 'data', resolveValue: true },
23
23
  { package: 'base', name: 'readRDS', argIdx: 0, argName: 'file', resolveValue: true },
24
24
  { package: 'base', name: 'readLines', argIdx: 0, argName: 'con', resolveValue: true },
25
+ { package: 'base', name: 'readChar', argIdx: 0, argName: 'con', resolveValue: true },
26
+ { package: 'base', name: 'readBin', argIdx: 0, argName: 'con', resolveValue: true },
25
27
  { package: 'base', name: 'readRenviron', argIdx: 0, argName: 'path', resolveValue: true },
26
28
  { package: 'readr', name: 'read_csv', argIdx: 0, argName: 'file', resolveValue: true },
27
29
  { package: 'readr', name: 'read_csv2', argIdx: 0, argName: 'file', resolveValue: true },
@@ -19,6 +19,11 @@ exports.WriteFunctions = [
19
19
  { package: 'base', name: 'cat', linkTo: OutputRedirects, argName: 'file', resolveValue: true },
20
20
  { package: 'base', name: 'message', linkTo: OutputRedirects, resolveValue: true },
21
21
  { package: 'base', name: 'warning', linkTo: OutputRedirects, resolveValue: true },
22
+ { package: 'base', name: 'writeLines', argIdx: 1, argName: 'con', resolveValue: true },
23
+ { package: 'base', name: 'writeChar', argIdx: 1, argName: 'con', resolveValue: true },
24
+ { package: 'base', name: 'writeBin', argIdx: 1, argName: 'con', resolveValue: true },
25
+ { package: 'base', name: 'file', argIdx: 0, argName: 'description', resolveValue: true, ignoreIf: 'mode-only-read', additionalArgs: { mode: { argIdx: 1, argName: 'open', resolveValue: true } } },
26
+ { package: 'base', name: 'url', argIdx: 0, argName: 'description', resolveValue: true, ignoreIf: 'mode-only-read', additionalArgs: { mode: { argIdx: 1, argName: 'open', resolveValue: true } } },
22
27
  { package: 'readr', name: 'write_csv', argIdx: 1, argName: 'file', resolveValue: true },
23
28
  { package: 'readr', name: 'write_csv2', argIdx: 1, argName: 'file', resolveValue: true },
24
29
  { package: 'readr', name: 'write_delim', argIdx: 1, argName: 'file', resolveValue: true },
@@ -1,4 +1,4 @@
1
1
  import type { StaticSliceQuery, StaticSliceQueryResult } from './static-slice-query-format';
2
2
  import type { BasicQueryData } from '../../base-query-format';
3
3
  export declare function fingerPrintOfQuery(query: StaticSliceQuery): string;
4
- export declare function executeStaticSliceQuery({ dataflow: { graph }, ast, config }: BasicQueryData, queries: readonly StaticSliceQuery[]): StaticSliceQueryResult;
4
+ export declare function executeStaticSliceQuery({ dataflow, ast, config }: BasicQueryData, queries: readonly StaticSliceQuery[]): StaticSliceQueryResult;
@@ -11,7 +11,7 @@ const _00_slice_1 = require("../../../core/steps/all/static-slicing/00-slice");
11
11
  function fingerPrintOfQuery(query) {
12
12
  return JSON.stringify(query);
13
13
  }
14
- function executeStaticSliceQuery({ dataflow: { graph }, ast, config }, queries) {
14
+ function executeStaticSliceQuery({ dataflow, ast, config }, queries) {
15
15
  const start = Date.now();
16
16
  const results = {};
17
17
  for (const query of queries) {
@@ -21,7 +21,7 @@ function executeStaticSliceQuery({ dataflow: { graph }, ast, config }, queries)
21
21
  }
22
22
  const { criteria, noReconstruction, noMagicComments } = query;
23
23
  const sliceStart = Date.now();
24
- const slice = (0, static_slicer_1.staticSlice)(graph, ast, criteria, query.direction ?? _00_slice_1.SliceDirection.Backward, config.solver.slicer?.threshold);
24
+ const slice = (0, static_slicer_1.staticSlice)(dataflow, ast, criteria, query.direction ?? _00_slice_1.SliceDirection.Backward, config.solver.slicer?.threshold);
25
25
  const sliceEnd = Date.now();
26
26
  if (noReconstruction) {
27
27
  results[key] = { slice: { ...slice, '.meta': { timing: sliceEnd - sliceStart } } };
@@ -7,7 +7,6 @@ exports.envFingerprint = envFingerprint;
7
7
  exports.fingerprint = fingerprint;
8
8
  const object_hash_1 = __importDefault(require("object-hash"));
9
9
  const environment_1 = require("../../dataflow/environments/environment");
10
- const built_in_1 = require("../../dataflow/environments/built-in");
11
10
  function envFingerprint(env) {
12
11
  return (0, object_hash_1.default)(env, {
13
12
  algorithm: 'md5',
@@ -15,7 +14,7 @@ function envFingerprint(env) {
15
14
  respectFunctionProperties: false,
16
15
  respectFunctionNames: false,
17
16
  ignoreUnknown: true,
18
- replacer: (v) => (v === environment_1.BuiltInEnvironment || v === built_in_1.EmptyBuiltInMemory) ? undefined : v
17
+ replacer: (v) => (0, environment_1.isDefaultBuiltInEnvironment)(v) ? undefined : v
19
18
  });
20
19
  }
21
20
  function fingerprint(id, envFingerprint, onlyForSideEffects) {
@@ -5,11 +5,12 @@ import type { DataflowGraphVertexFunctionCall, DataflowGraphVertexInfo } from '.
5
5
  import type { REnvironmentInformation } from '../../dataflow/environments/environment';
6
6
  import type { DataflowGraph, OutgoingEdges } from '../../dataflow/graph/graph';
7
7
  import type { NodeId } from '../../r-bridge/lang-4.x/ast/model/processing/node-id';
8
+ import type { DataflowInformation } from '../../dataflow/info';
8
9
  /**
9
10
  * Returns the function call targets (definitions) by the given caller
10
11
  */
11
12
  export declare function getAllFunctionCallTargets(dataflowGraph: DataflowGraph, callerInfo: DataflowGraphVertexFunctionCall, baseEnvironment: REnvironmentInformation, queue: VisitingQueue): [Set<DataflowGraphVertexInfo>, REnvironmentInformation];
12
13
  /** returns the new threshold hit count */
13
- export declare function sliceForCall(current: NodeToSlice, callerInfo: DataflowGraphVertexFunctionCall, dataflowGraph: DataflowGraph, queue: VisitingQueue): void;
14
+ export declare function sliceForCall(current: NodeToSlice, callerInfo: DataflowGraphVertexFunctionCall, dataflowInformation: DataflowInformation, queue: VisitingQueue): void;
14
15
  /** Returns true if we found at least one return edge */
15
16
  export declare function handleReturns(from: NodeId, queue: VisitingQueue, currentEdges: OutgoingEdges, baseEnvFingerprint: Fingerprint, baseEnvironment: REnvironmentInformation): boolean;
@@ -59,9 +59,9 @@ function linkCallTargets(onlyForSideEffects, functionCallTargets, activeEnvironm
59
59
  }
60
60
  }
61
61
  /** returns the new threshold hit count */
62
- function sliceForCall(current, callerInfo, dataflowGraph, queue) {
62
+ function sliceForCall(current, callerInfo, dataflowInformation, queue) {
63
63
  const baseEnvironment = current.baseEnvironment;
64
- const [functionCallTargets, activeEnvironment] = getAllFunctionCallTargets(dataflowGraph, callerInfo, current.baseEnvironment, queue);
64
+ const [functionCallTargets, activeEnvironment] = getAllFunctionCallTargets(dataflowInformation.graph, callerInfo, current.baseEnvironment, queue);
65
65
  const activeEnvironmentFingerprint = (0, fingerprint_1.envFingerprint)(activeEnvironment);
66
66
  if (functionCallTargets.size === 0) {
67
67
  /*
@@ -69,7 +69,7 @@ function sliceForCall(current, callerInfo, dataflowGraph, queue) {
69
69
  * hence, we add a new flag and add all argument values to the queue causing directly
70
70
  */
71
71
  for (const arg of callerInfo.args) {
72
- includeArgumentFunctionCallClosure(arg, baseEnvironment, activeEnvironment, queue, dataflowGraph);
72
+ includeArgumentFunctionCallClosure(arg, baseEnvironment, activeEnvironment, queue, dataflowInformation.graph);
73
73
  }
74
74
  return;
75
75
  }
@@ -1,24 +1,23 @@
1
1
  import type { SliceResult } from './slicer-types';
2
2
  import type { Fingerprint } from './fingerprint';
3
3
  import { VisitingQueue } from './visiting-queue';
4
- import type { DataflowGraph } from '../../dataflow/graph/graph';
5
4
  import type { NormalizedAst } from '../../r-bridge/lang-4.x/ast/model/processing/decorate';
6
5
  import type { SlicingCriteria } from '../criterion/parse';
7
6
  import type { REnvironmentInformation } from '../../dataflow/environments/environment';
8
7
  import type { NodeId } from '../../r-bridge/lang-4.x/ast/model/processing/node-id';
9
8
  import { SliceDirection } from '../../core/steps/all/static-slicing/00-slice';
9
+ import type { DataflowInformation } from '../../dataflow/info';
10
10
  export declare const slicerLogger: import("tslog").Logger<import("tslog").ILogObj>;
11
11
  /**
12
12
  * This returns the ids to include in the static slice of the given type, when slicing with the given seed id's (must be at least one).
13
13
  * <p>
14
14
  * The returned ids can be used to {@link reconstructToCode|reconstruct the slice to R code}.
15
15
  *
16
- * @param graph - The dataflow graph to conduct the slicing on.
17
- * @param ast - The normalized AST of the code (used to get static nesting information of the lexemes in case of control flow dependencies that may have no effect on the slicing scope).
16
+ * @param info - The dataflow information used for slicing.
18
17
  * @param criteria - The criteria to slice on.
19
18
  * @param direction - The direction to slice in.
20
19
  * @param threshold - The maximum number of nodes to visit in the graph. If the threshold is reached, the slice will side with inclusion and drop its minimal guarantee. The limit ensures that the algorithm halts.
21
20
  * @param cache - A cache to store the results of the slice. If provided, the slice may use this cache to speed up the slicing process.
22
21
  */
23
- export declare function staticSlice(graph: DataflowGraph, { idMap }: NormalizedAst, criteria: SlicingCriteria, direction: SliceDirection, threshold?: number, cache?: Map<Fingerprint, Set<NodeId>>): Readonly<SliceResult>;
22
+ export declare function staticSlice(info: DataflowInformation, { idMap }: NormalizedAst, criteria: SlicingCriteria, direction: SliceDirection, threshold?: number, cache?: Map<Fingerprint, Set<NodeId>>): Readonly<SliceResult>;
24
23
  export declare function updatePotentialAddition(queue: VisitingQueue, id: NodeId, target: NodeId, baseEnvironment: REnvironmentInformation, envFingerprint: string): void;
@@ -20,17 +20,17 @@ exports.slicerLogger = log_1.log.getSubLogger({ name: 'slicer' });
20
20
  * <p>
21
21
  * The returned ids can be used to {@link reconstructToCode|reconstruct the slice to R code}.
22
22
  *
23
- * @param graph - The dataflow graph to conduct the slicing on.
24
- * @param ast - The normalized AST of the code (used to get static nesting information of the lexemes in case of control flow dependencies that may have no effect on the slicing scope).
23
+ * @param info - The dataflow information used for slicing.
25
24
  * @param criteria - The criteria to slice on.
26
25
  * @param direction - The direction to slice in.
27
26
  * @param threshold - The maximum number of nodes to visit in the graph. If the threshold is reached, the slice will side with inclusion and drop its minimal guarantee. The limit ensures that the algorithm halts.
28
27
  * @param cache - A cache to store the results of the slice. If provided, the slice may use this cache to speed up the slicing process.
29
28
  */
30
- function staticSlice(graph, { idMap }, criteria, direction, threshold = 75, cache) {
29
+ function staticSlice(info, { idMap }, criteria, direction, threshold = 75, cache) {
31
30
  (0, assert_1.guard)(criteria.length > 0, 'must have at least one seed id to calculate slice');
32
31
  const decodedCriteria = (0, parse_1.convertAllSlicingCriteriaToIds)(criteria, idMap);
33
32
  (0, log_1.expensiveTrace)(exports.slicerLogger, () => `calculating ${direction} slice for ${decodedCriteria.length} seed criteria: ${decodedCriteria.map(s => JSON.stringify(s)).join(', ')}`);
33
+ let { graph } = info;
34
34
  if (direction === _00_slice_1.SliceDirection.Forward) {
35
35
  graph = (0, invert_dfg_1.invertDfg)(graph);
36
36
  }
@@ -77,7 +77,7 @@ function staticSlice(graph, { idMap }, criteria, direction, threshold = 75, cach
77
77
  }
78
78
  if (!onlyForSideEffects) {
79
79
  if (currentVertex.tag === vertex_1.VertexType.FunctionCall && !currentVertex.onlyBuiltin) {
80
- (0, slice_call_1.sliceForCall)(current, currentVertex, graph, queue);
80
+ (0, slice_call_1.sliceForCall)(current, currentVertex, info, queue);
81
81
  }
82
82
  const ret = (0, slice_call_1.handleReturns)(id, queue, currentEdges, baseEnvFingerprint, baseEnvironment);
83
83
  if (ret) {
@@ -17,6 +17,7 @@ export declare function getAccessOperands<OtherInfo>(args: readonly RFunctionArg
17
17
  *
18
18
  * @param name - Name to resolve
19
19
  * @param environment - Environment in which name is resolved
20
+ * @param builtInEnvironment - Built-in environment
20
21
  * @returns The indicesCollection of the resolved definitions
21
22
  */
22
23
  export declare function resolveIndicesByName(name: Identifier, environment: REnvironmentInformation): ContainerIndices[] | undefined;
@@ -24,6 +24,7 @@ function getAccessOperands(args) {
24
24
  *
25
25
  * @param name - Name to resolve
26
26
  * @param environment - Environment in which name is resolved
27
+ * @param builtInEnvironment - Built-in environment
27
28
  * @returns The indicesCollection of the resolved definitions
28
29
  */
29
30
  function resolveIndicesByName(name, environment) {
package/util/json.js CHANGED
@@ -46,12 +46,9 @@ function bigStringify(obj, current, send) {
46
46
  if (obj === undefined || obj === null) {
47
47
  return current + 'null';
48
48
  }
49
- else if (obj === environment_1.BuiltInEnvironment) {
49
+ else if ((0, environment_1.isDefaultBuiltInEnvironment)(obj)) {
50
50
  return current + '<BuiltInEnvironment>';
51
51
  }
52
- else if (obj === environment_1.EmptyBuiltInEnvironment) {
53
- return current + '<EmptyBuiltInEnvironment>';
54
- }
55
52
  else if (Array.isArray(obj)) {
56
53
  let str = current + '[';
57
54
  for (let i = 0; i < obj.length; i++) {
@@ -13,7 +13,6 @@ const identifier_1 = require("../../dataflow/environments/identifier");
13
13
  const r_function_call_1 = require("../../r-bridge/lang-4.x/ast/model/nodes/r-function-call");
14
14
  const edge_1 = require("../../dataflow/graph/edge");
15
15
  const vertex_1 = require("../../dataflow/graph/vertex");
16
- const environment_1 = require("../../dataflow/environments/environment");
17
16
  const type_1 = require("../../r-bridge/lang-4.x/ast/model/type");
18
17
  const built_in_1 = require("../../dataflow/environments/built-in");
19
18
  /**
@@ -134,7 +133,7 @@ function printEnvironmentToLines(env) {
134
133
  if (env === undefined) {
135
134
  return ['??'];
136
135
  }
137
- else if (env.id === environment_1.BuiltInEnvironment.id) {
136
+ else if (env.builtInEnv) {
138
137
  return ['Built-in'];
139
138
  }
140
139
  const lines = [...printEnvironmentToLines(env.parent), `${env.id}${'-'.repeat(40)}`];
package/util/prefix.d.ts CHANGED
@@ -10,4 +10,4 @@
10
10
  * findByPrefixIfUnique('', { 'hello', 'hell' }) // => undefined (empty prefix)
11
11
  * ```
12
12
  */
13
- export declare function findByPrefixIfUnique(prefix: string, keys: readonly string[]): string | undefined;
13
+ export declare function findByPrefixIfUnique(prefix: string, keys: readonly string[] | MapIterator<string>): string | undefined;
package/util/version.js CHANGED
@@ -3,7 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.flowrVersion = flowrVersion;
4
4
  const semver_1 = require("semver");
5
5
  // this is automatically replaced with the current version by release-it
6
- const version = '2.4.0';
6
+ const version = '2.4.2';
7
7
  function flowrVersion() {
8
8
  return new semver_1.SemVer(version);
9
9
  }