@eagleoutice/flowr 2.0.7 → 2.0.8

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.
@@ -39,7 +39,7 @@ function getSizeOfDfGraph(df) {
39
39
  ...vertex,
40
40
  environment: {
41
41
  ...vertex.environment,
42
- current: killBuiltInEnv(v.environment.current)
42
+ current: killBuiltInEnv(v.environment?.current)
43
43
  }
44
44
  };
45
45
  }
@@ -2,6 +2,7 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.diffEnvironmentInformation = exports.diffEnvironment = exports.diffIdentifierReferences = void 0;
4
4
  const diff_1 = require("../../util/diff");
5
+ const environment_1 = require("./environment");
5
6
  const json_1 = require("../../util/json");
6
7
  const info_1 = require("../info");
7
8
  const built_in_1 = require("./built-in");
@@ -75,7 +76,7 @@ exports.diffEnvironment = diffEnvironment;
75
76
  function diffEnvironmentInformation(a, b, info) {
76
77
  if (a === undefined || b === undefined) {
77
78
  if (a !== b) {
78
- info.report.addComment(`${info.position}Different environments: ${JSON.stringify(a, json_1.jsonReplacer)} vs. ${JSON.stringify(b, json_1.jsonReplacer)}`);
79
+ info.report.addComment(`${info.position}Different environments: ${JSON.stringify(a, environment_1.builtInEnvJsonReplacer)} vs. ${JSON.stringify(b, environment_1.builtInEnvJsonReplacer)}`);
79
80
  }
80
81
  return;
81
82
  }
@@ -41,3 +41,4 @@ export interface REnvironmentInformation {
41
41
  }
42
42
  export declare const BuiltInEnvironment: Environment;
43
43
  export declare function initializeCleanEnvironments(fullBuiltIns?: boolean): REnvironmentInformation;
44
+ export declare function builtInEnvJsonReplacer(k: unknown, v: unknown): unknown;
@@ -1,8 +1,9 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.initializeCleanEnvironments = exports.BuiltInEnvironment = exports.Environment = exports.makeAllMaybe = exports.makeReferenceMaybe = void 0;
3
+ exports.builtInEnvJsonReplacer = exports.initializeCleanEnvironments = exports.BuiltInEnvironment = exports.Environment = exports.makeAllMaybe = exports.makeReferenceMaybe = void 0;
4
4
  const built_in_1 = require("./built-in");
5
5
  const resolve_by_name_1 = require("./resolve-by-name");
6
+ const json_1 = require("../../util/json");
6
7
  function makeReferenceMaybe(ref, graph, environments, includeDefs, defaultCd = undefined) {
7
8
  const node = graph.get(ref.nodeId, true);
8
9
  if (includeDefs) {
@@ -64,4 +65,16 @@ function initializeCleanEnvironments(fullBuiltIns = true) {
64
65
  };
65
66
  }
66
67
  exports.initializeCleanEnvironments = initializeCleanEnvironments;
68
+ function builtInEnvJsonReplacer(k, v) {
69
+ if (v === exports.BuiltInEnvironment) {
70
+ return '<BuiltInEnvironment>';
71
+ }
72
+ else if (v === EmptyBuiltInEnvironment) {
73
+ return '<EmptyBuiltInEnvironment>';
74
+ }
75
+ else {
76
+ return (0, json_1.jsonReplacer)(k, v);
77
+ }
78
+ }
79
+ exports.builtInEnvJsonReplacer = builtInEnvJsonReplacer;
67
80
  //# sourceMappingURL=environment.js.map
@@ -47,6 +47,7 @@ type EdgeData<Edge extends DataflowGraphEdge> = Omit<Edge, 'from' | 'to' | 'type
47
47
  export declare class DataflowGraph<Vertex extends DataflowGraphVertexInfo = DataflowGraphVertexInfo, Edge extends DataflowGraphEdge = DataflowGraphEdge> {
48
48
  private static DEFAULT_ENVIRONMENT;
49
49
  private _idMap;
50
+ readonly functionCache: Map<NodeId, Set<DataflowGraphVertexInfo>>;
50
51
  constructor(idMap: AstIdMap | undefined);
51
52
  /** Contains the vertices of the root level graph (i.e., included those vertices from the complete graph, that are nested within function definitions) */
52
53
  private rootVertices;
@@ -42,6 +42,8 @@ function extractEdgeIds(from, to) {
42
42
  class DataflowGraph {
43
43
  static DEFAULT_ENVIRONMENT = undefined;
44
44
  _idMap;
45
+ // this should be linked separately
46
+ functionCache = new Map();
45
47
  constructor(idMap) {
46
48
  DataflowGraph.DEFAULT_ENVIRONMENT ??= (0, environment_1.initializeCleanEnvironments)();
47
49
  this._idMap = idMap;
@@ -155,7 +157,7 @@ class DataflowGraph {
155
157
  if (oldVertex !== undefined) {
156
158
  return this;
157
159
  }
158
- const fallback = vertex.tag === "variable-definition" /* VertexType.VariableDefinition */ || vertex.tag === "use" /* VertexType.Use */ || vertex.tag === "value" /* VertexType.Value */ ? undefined : DataflowGraph.DEFAULT_ENVIRONMENT;
160
+ const fallback = vertex.tag === "variable-definition" /* VertexType.VariableDefinition */ || vertex.tag === "use" /* VertexType.Use */ || vertex.tag === "value" /* VertexType.Value */ || (vertex.tag === "function-call" /* VertexType.FunctionCall */ && vertex.onlyBuiltin) ? undefined : DataflowGraph.DEFAULT_ENVIRONMENT;
159
161
  // keep a clone of the original environment
160
162
  const environment = vertex.environment === undefined ? fallback : (0, clone_1.cloneEnvironmentInformation)(vertex.environment);
161
163
  this.vertexInformation.set(vertex.id, {
@@ -62,7 +62,7 @@ export interface DataflowGraphVertexFunctionCall extends DataflowGraphVertexBase
62
62
  args: FunctionArgument[];
63
63
  /** a performance flag to indicate that the respective call is _only_ calling a builtin function without any df graph attached */
64
64
  onlyBuiltin: boolean;
65
- readonly environment: REnvironmentInformation;
65
+ environment: REnvironmentInformation | undefined;
66
66
  }
67
67
  /**
68
68
  * Arguments required to construct a vertex which represents the definition of a variable in the dataflow graph.
@@ -17,7 +17,7 @@ export declare function linkFunctionCalls(graph: DataflowGraph, idMap: AstIdMap,
17
17
  functionCall: NodeId;
18
18
  called: readonly DataflowGraphVertexInfo[];
19
19
  }[];
20
- export declare function getAllLinkedFunctionDefinitions(functionDefinitionReadIds: ReadonlySet<NodeId>, dataflowGraph: DataflowGraph): Map<NodeId, DataflowGraphVertexInfo>;
20
+ export declare function getAllLinkedFunctionDefinitions(functionDefinitionReadIds: ReadonlySet<NodeId>, dataflowGraph: DataflowGraph): Set<DataflowGraphVertexInfo>;
21
21
  /**
22
22
  * This method links a set of read variables to definitions in an environment.
23
23
  *
@@ -133,7 +133,7 @@ exports.linkFunctionCalls = linkFunctionCalls;
133
133
  function getAllLinkedFunctionDefinitions(functionDefinitionReadIds, dataflowGraph) {
134
134
  const potential = [...functionDefinitionReadIds];
135
135
  const visited = new Set();
136
- const result = new Map();
136
+ const result = new Set();
137
137
  while (potential.length > 0) {
138
138
  const currentId = potential.pop();
139
139
  // do not traverse builtins
@@ -156,7 +156,7 @@ function getAllLinkedFunctionDefinitions(functionDefinitionReadIds, dataflowGrap
156
156
  const followBits = 1 /* EdgeType.Reads */ | 2 /* EdgeType.DefinedBy */ | 32 /* EdgeType.DefinedByOnCall */;
157
157
  const followEdges = outgoingEdges.filter(([_, e]) => (0, edge_1.edgeIncludesType)(e.types, followBits));
158
158
  if (currentInfo[0].subflow !== undefined) {
159
- result.set(currentId, currentInfo[0]);
159
+ result.add(currentInfo[0]);
160
160
  }
161
161
  // trace all joined reads
162
162
  potential.push(...followEdges.map(([target]) => target).filter(id => !visited.has(id)));
@@ -45,6 +45,7 @@ function processNamedCall(name, args, rootId, data) {
45
45
  const v = information.graph.getVertex(rootId);
46
46
  if (v?.tag === "function-call" /* VertexType.FunctionCall */) {
47
47
  v.onlyBuiltin = true;
48
+ v.environment = undefined;
48
49
  }
49
50
  }
50
51
  return information ?? (0, info_1.initializeCleanDataflowInformation)(rootId, data);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@eagleoutice/flowr",
3
- "version": "2.0.7",
3
+ "version": "2.0.8",
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": {
@@ -4,6 +4,7 @@ exports.handleReturns = exports.sliceForCall = void 0;
4
4
  const assert_1 = require("../../util/assert");
5
5
  const fingerprint_1 = require("./fingerprint");
6
6
  const linker_1 = require("../../dataflow/internal/linker");
7
+ const environment_1 = require("../../dataflow/environments/environment");
7
8
  const scoping_1 = require("../../dataflow/environments/scoping");
8
9
  const overwrite_1 = require("../../dataflow/environments/overwrite");
9
10
  const built_in_1 = require("../../dataflow/environments/built-in");
@@ -11,12 +12,13 @@ const resolve_by_name_1 = require("../../dataflow/environments/resolve-by-name")
11
12
  const edge_1 = require("../../dataflow/graph/edge");
12
13
  function retrieveActiveEnvironment(callerInfo, baseEnvironment) {
13
14
  let callerEnvironment = callerInfo.environment;
14
- if (baseEnvironment.level !== callerEnvironment.level) {
15
- while (baseEnvironment.level < callerEnvironment.level) {
15
+ const level = callerEnvironment?.level ?? 0;
16
+ if (baseEnvironment.level !== level) {
17
+ while (baseEnvironment.level < level) {
16
18
  baseEnvironment = (0, scoping_1.pushLocalEnvironment)(baseEnvironment);
17
19
  }
18
- while (baseEnvironment.level > callerEnvironment.level) {
19
- callerEnvironment = (0, scoping_1.pushLocalEnvironment)(callerEnvironment);
20
+ while (baseEnvironment.level > level) {
21
+ callerEnvironment = (0, scoping_1.pushLocalEnvironment)(callerEnvironment ?? (0, environment_1.initializeCleanEnvironments)(true));
20
22
  }
21
23
  }
22
24
  return (0, overwrite_1.overwriteEnvironment)(baseEnvironment, callerEnvironment);
@@ -40,7 +42,7 @@ function sliceForCall(current, callerInfo, dataflowGraph, queue) {
40
42
  }
41
43
  }
42
44
  const functionCallTargets = (0, linker_1.getAllLinkedFunctionDefinitions)(new Set(functionCallDefs), dataflowGraph);
43
- for (const [_, functionCallTarget] of functionCallTargets) {
45
+ for (const functionCallTarget of functionCallTargets) {
44
46
  // all those linked within the scopes of other functions are already linked when exiting a function definition
45
47
  for (const openIn of functionCallTarget.subflow.in) {
46
48
  const defs = openIn.name ? (0, resolve_by_name_1.resolveByName)(openIn.name, activeEnvironment) : undefined;
@@ -72,7 +74,11 @@ function handleReturns(queue, currentEdges, baseEnvFingerprint, baseEnvironment)
72
74
  queue.add(target, baseEnvironment, baseEnvFingerprint, false);
73
75
  }
74
76
  else if ((0, edge_1.edgeIncludesType)(edge.types, 64 /* EdgeType.Argument */)) {
75
- queue.potentialArguments.add(target);
77
+ queue.potentialArguments.set(target, {
78
+ id: target,
79
+ baseEnvironment,
80
+ onlyForSideEffects: false
81
+ });
76
82
  }
77
83
  }
78
84
  return true;
@@ -9,7 +9,6 @@ const slice_call_1 = require("./slice-call");
9
9
  const parse_1 = require("../criterion/parse");
10
10
  const environment_1 = require("../../dataflow/environments/environment");
11
11
  const edge_1 = require("../../dataflow/graph/edge");
12
- const built_in_1 = require("../../dataflow/environments/built-in");
13
12
  exports.slicerLogger = log_1.log.getSubLogger({ name: 'slicer' });
14
13
  /**
15
14
  * This returns the ids to include in the slice, when slicing with the given seed id's (must be at least one).
@@ -63,16 +62,19 @@ function staticSlicing(graph, ast, criteria, threshold = 75) {
63
62
  }
64
63
  }
65
64
  for (const [target, { types }] of currentEdges) {
66
- if (target === built_in_1.BuiltIn || (0, edge_1.edgeIncludesType)(types, 256 /* EdgeType.NonStandardEvaluation */)) {
65
+ if ((0, edge_1.edgeIncludesType)(types, 256 /* EdgeType.NonStandardEvaluation */)) {
67
66
  continue;
68
67
  }
69
68
  const t = (0, edge_1.shouldTraverseEdge)(types);
70
69
  if (t === 3 /* TraverseEdge.Always */) {
71
70
  queue.add(target, baseEnvironment, baseEnvFingerprint, false);
72
71
  }
73
- else if (t === 2 /* TraverseEdge.DefinedByOnCall */ && queue.potentialArguments.has(target)) {
74
- queue.add(target, baseEnvironment, baseEnvFingerprint, false);
75
- queue.potentialArguments.delete(target);
72
+ else if (t === 2 /* TraverseEdge.DefinedByOnCall */) {
73
+ const n = queue.potentialArguments.get(target);
74
+ if (n) {
75
+ queue.add(target, n.baseEnvironment, (0, fingerprint_1.envFingerprint)(n.baseEnvironment), n.onlyForSideEffects);
76
+ queue.potentialArguments.delete(target);
77
+ }
76
78
  }
77
79
  else if (t === 1 /* TraverseEdge.SideEffect */) {
78
80
  queue.add(target, baseEnvironment, baseEnvFingerprint, true);
@@ -7,7 +7,7 @@ export declare class VisitingQueue {
7
7
  private seen;
8
8
  private idThreshold;
9
9
  private queue;
10
- potentialArguments: Set<NodeId>;
10
+ potentialArguments: Map<NodeId, NodeToSlice>;
11
11
  constructor(threshold: number);
12
12
  /**
13
13
  * Adds a node to the queue if it has not been seen before.
@@ -10,7 +10,7 @@ class VisitingQueue {
10
10
  idThreshold = new Map();
11
11
  queue = [];
12
12
  // the set of potential arguments holds arguments which may be added if found with the `defined-by-on-call` edge
13
- potentialArguments = new Set();
13
+ potentialArguments = new Map();
14
14
  constructor(threshold) {
15
15
  this.threshold = threshold;
16
16
  }
package/util/version.js CHANGED
@@ -3,7 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.flowrVersion = void 0;
4
4
  const semver_1 = require("semver");
5
5
  // this is automatically replaced with the current version by release-it
6
- const version = '2.0.7';
6
+ const version = '2.0.8';
7
7
  function flowrVersion() {
8
8
  return new semver_1.SemVer(version);
9
9
  }