@eagleoutice/flowr 2.8.0 → 2.8.1

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.
@@ -383,6 +383,7 @@ export declare const DefaultBuiltinConfig: [{
383
383
  readonly processor: "builtin:assignment";
384
384
  readonly config: {
385
385
  readonly targetVariable: true;
386
+ readonly mayHaveMoreArgs: true;
386
387
  };
387
388
  readonly assumePrimitive: true;
388
389
  }, {
@@ -247,7 +247,7 @@ exports.DefaultBuiltinConfig = [
247
247
  { type: 'function', names: ['library', 'require'], processor: 'builtin:library', config: {}, assumePrimitive: false },
248
248
  { type: 'function', names: ['<-', '='], processor: 'builtin:assignment', config: { canBeReplacement: true }, assumePrimitive: true },
249
249
  { type: 'function', names: [':='], processor: 'builtin:assignment', config: {}, assumePrimitive: true },
250
- { type: 'function', names: ['assign', 'setGeneric', 'setValidity'], processor: 'builtin:assignment', config: { targetVariable: true }, assumePrimitive: true },
250
+ { type: 'function', names: ['assign', 'setGeneric', 'setValidity'], processor: 'builtin:assignment', config: { targetVariable: true, mayHaveMoreArgs: true }, assumePrimitive: true },
251
251
  { type: 'function', names: ['setMethod'], processor: 'builtin:assignment-like', config: { targetVariable: true, canBeReplacement: false, target: { idx: 0, name: 'f' }, source: { idx: 2, name: 'definition' } }, assumePrimitive: true },
252
252
  { type: 'function', names: ['delayedAssign'], processor: 'builtin:assignment', config: { quoteSource: true, targetVariable: true }, assumePrimitive: true },
253
253
  { type: 'function', names: ['<<-'], processor: 'builtin:assignment', config: { superAssignment: true, canBeReplacement: true }, assumePrimitive: true },
@@ -41,10 +41,10 @@ function computeCallGraph(graph) {
41
41
  knownReachability: new defaultmap_1.DefaultMap(() => new Set())
42
42
  };
43
43
  for (const [, vert] of graph.vertices(false)) {
44
- if (vert?.tag === vertex_1.VertexType.FunctionCall) {
44
+ if (vert.tag === vertex_1.VertexType.FunctionCall) {
45
45
  processCall(vert, undefined, graph, result, state);
46
46
  }
47
- else if (vert?.tag === vertex_1.VertexType.FunctionDefinition) {
47
+ else if (vert.tag === vertex_1.VertexType.FunctionDefinition) {
48
48
  processFunctionDefinition(vert, undefined, graph, result, state);
49
49
  }
50
50
  }
@@ -74,6 +74,8 @@ function processCds(vtx, graph, result, state) {
74
74
  }
75
75
  }
76
76
  }
77
+ const UntargetedCallFollow = edge_1.EdgeType.Reads | edge_1.EdgeType.DefinedByOnCall | edge_1.EdgeType.DefinedBy | edge_1.EdgeType.Returns;
78
+ const UntargetedCallAvoid = edge_1.EdgeType.NonStandardEvaluation | edge_1.EdgeType.Argument;
77
79
  /**
78
80
  * This tracks the known symbol origins for a function call for which we know that flowr found no targets!
79
81
  */
@@ -94,7 +96,7 @@ function fallbackUntargetedCall(vtx, graph) {
94
96
  }
95
97
  let addedNew = false;
96
98
  for (const [tar, { types }] of graph.outgoingEdges(currentId) ?? []) {
97
- if ((0, edge_1.edgeIncludesType)(types, edge_1.EdgeType.Reads | edge_1.EdgeType.DefinedByOnCall | edge_1.EdgeType.DefinedBy | edge_1.EdgeType.Returns) && (0, edge_1.edgeDoesNotIncludeType)(types, edge_1.EdgeType.NonStandardEvaluation | edge_1.EdgeType.Argument)) {
99
+ if ((0, edge_1.edgeIncludesType)(types, UntargetedCallFollow) && (0, edge_1.edgeDoesNotIncludeType)(types, UntargetedCallAvoid)) {
98
100
  addedNew = true;
99
101
  toVisit.push(tar);
100
102
  }
@@ -107,21 +109,22 @@ function fallbackUntargetedCall(vtx, graph) {
107
109
  return collected;
108
110
  }
109
111
  function processCall(vtx, from, graph, result, state) {
110
- if (from && !reaches(from, vtx.id, result, state.knownReachability)) {
111
- result.addEdge(from, vtx.id, edge_1.EdgeType.Calls);
112
+ const vid = vtx.id;
113
+ if (from && !reaches(from, vid, result, state.knownReachability)) {
114
+ result.addEdge(from, vid, edge_1.EdgeType.Calls);
112
115
  }
113
- if (state.visited.has(vtx.id)) {
116
+ if (state.visited.has(vid)) {
114
117
  return;
115
118
  }
119
+ state.visited.add(vid);
116
120
  result.addVertex(vtx, undefined, true);
117
121
  processCds(vtx, graph, result, state);
118
- state.visited.add(vtx.id);
119
122
  // for each call, resolve the targets
120
- const tars = (0, linker_1.getAllFunctionCallTargets)(vtx.id, graph, vtx.environment);
123
+ const tars = (0, linker_1.getAllFunctionCallTargets)(vid, graph, vtx.environment);
121
124
  let addedTarget = false;
122
125
  for (const tar of tars) {
123
126
  if ((0, built_in_1.isBuiltIn)(tar)) {
124
- result.addEdge(vtx.id, tar, edge_1.EdgeType.Calls);
127
+ result.addEdge(vid, tar, edge_1.EdgeType.Calls);
125
128
  addedTarget = true;
126
129
  continue;
127
130
  }
@@ -130,13 +133,13 @@ function processCall(vtx, from, graph, result, state) {
130
133
  continue;
131
134
  }
132
135
  addedTarget = true;
133
- processFunctionDefinition(targetVtx, vtx.id, graph, result, state);
136
+ processFunctionDefinition(targetVtx, vid, graph, result, state);
134
137
  }
135
138
  if (vtx.origin !== 'unnamed') {
136
139
  for (const origs of vtx.origin) {
137
140
  if (origs.startsWith('builtin:')) {
138
141
  addedTarget = true;
139
- result.addEdge(vtx.id, (0, built_in_1.builtInId)(origs.substring('builtin:'.length)), edge_1.EdgeType.Calls);
142
+ result.addEdge(vid, (0, built_in_1.builtInId)(origs.substring('builtin:'.length)), edge_1.EdgeType.Calls);
140
143
  }
141
144
  }
142
145
  }
@@ -147,7 +150,7 @@ function processCall(vtx, from, graph, result, state) {
147
150
  if (!oriVtx) {
148
151
  continue;
149
152
  }
150
- result.addEdge(vtx.id, ori, edge_1.EdgeType.Calls);
153
+ result.addEdge(vid, ori, edge_1.EdgeType.Calls);
151
154
  const name = graph.idMap?.get(ori);
152
155
  if (name?.lexeme && oriVtx.tag === vertex_1.VertexType.Use) {
153
156
  result.addVertex({
@@ -198,12 +201,12 @@ function processFunctionDefinition(vtx, from, graph, result, state) {
198
201
  result.addVertex(vtx, undefined, true);
199
202
  processCds(vtx, graph, result, state);
200
203
  const exits = new Set(vtx.exitPoints);
204
+ state.potentials.push([vtx.id, vtx.subflow.graph.difference(exits)]);
201
205
  for (const { nodeId } of exits) {
202
206
  const v = graph.getVertex(nodeId, true);
203
207
  if (v) {
204
208
  processUnknown(v, vtx.id, graph, result, state);
205
209
  }
206
210
  }
207
- state.potentials.push([vtx.id, vtx.subflow.graph.difference(exits)]);
208
211
  }
209
212
  //# sourceMappingURL=call-graph.js.map
@@ -34,33 +34,21 @@ function findNonLocalReads(graph, ignore) {
34
34
  const ids = new Set(graph.vertexIdsOfType(vertex_1.VertexType.Use).concat(graph.vertexIdsOfType(vertex_1.VertexType.FunctionCall)));
35
35
  /* find all variable use ids which do not link to a given id */
36
36
  const nonLocalReads = [];
37
- for (const id of ids) {
38
- if (ignores.has(id)) {
37
+ for (const nodeId of ids) {
38
+ if (ignores.has(nodeId)) {
39
39
  continue;
40
40
  }
41
- const outgoing = graph.outgoingEdges(id);
42
- const name = (0, node_id_1.recoverName)(id, graph.idMap);
43
- const origin = graph.getVertex(id, true);
41
+ const outgoing = graph.outgoingEdges(nodeId);
42
+ const name = (0, node_id_1.recoverName)(nodeId, graph.idMap);
43
+ const origin = graph.getVertex(nodeId, true);
44
+ const type = origin?.tag === vertex_1.VertexType.FunctionCall ? identifier_1.ReferenceType.Function : identifier_1.ReferenceType.Variable;
44
45
  if (outgoing === undefined) {
45
- nonLocalReads.push({
46
- name: (0, node_id_1.recoverName)(id, graph.idMap),
47
- nodeId: id,
48
- controlDependencies: undefined,
49
- type: origin?.tag === vertex_1.VertexType.FunctionCall ? identifier_1.ReferenceType.Function : identifier_1.ReferenceType.Variable
50
- });
46
+ nonLocalReads.push({ name, nodeId, type });
51
47
  continue;
52
48
  }
53
49
  for (const [target, { types }] of outgoing) {
54
50
  if ((0, edge_1.edgeIncludesType)(types, edge_1.EdgeType.Reads) && !ids.has(target)) {
55
- if (!name) {
56
- logger_1.dataflowLogger.warn('found non-local read without name for id ' + id);
57
- }
58
- nonLocalReads.push({
59
- name: (0, node_id_1.recoverName)(id, graph.idMap),
60
- nodeId: id,
61
- controlDependencies: undefined,
62
- type: origin?.tag === vertex_1.VertexType.FunctionCall ? identifier_1.ReferenceType.Function : identifier_1.ReferenceType.Variable
63
- });
51
+ nonLocalReads.push({ name, nodeId, type });
64
52
  break;
65
53
  }
66
54
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@eagleoutice/flowr",
3
- "version": "2.8.0",
3
+ "version": "2.8.1",
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": {
@@ -2,16 +2,41 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.executeHigherOrderQuery = executeHigherOrderQuery;
4
4
  const higher_order_function_1 = require("../../../dataflow/fn/higher-order-function");
5
- const inspect_exception_query_executor_1 = require("../inspect-exceptions-query/inspect-exception-query-executor");
5
+ const parse_1 = require("../../../slicing/criterion/parse");
6
+ const vertex_1 = require("../../../dataflow/graph/vertex");
6
7
  /**
7
8
  * Execute higher-order function inspection queries on the given analyzer.
8
9
  */
9
10
  async function executeHigherOrderQuery({ analyzer }, queries) {
10
11
  const start = Date.now();
11
- const { cg, fns } = await (0, inspect_exception_query_executor_1.getFunctionsToConsiderInCallGraph)(queries, analyzer);
12
+ let filters = undefined;
13
+ // filter will remain undefined if at least one of the queries wants all functions
14
+ for (const q of queries) {
15
+ if (q.filter === undefined) {
16
+ filters = undefined;
17
+ break;
18
+ }
19
+ else {
20
+ filters ??= [];
21
+ filters = filters.concat(q.filter);
22
+ }
23
+ }
24
+ const ast = await analyzer.normalize();
25
+ const filterFor = new Set();
26
+ if (filters) {
27
+ for (const f of filters) {
28
+ const i = (0, parse_1.tryResolveSliceCriterionToId)(f, ast.idMap);
29
+ if (i !== undefined) {
30
+ filterFor.add(i);
31
+ }
32
+ }
33
+ }
34
+ const graph = (await analyzer.dataflow()).graph;
35
+ const fns = graph.verticesOfType(vertex_1.VertexType.FunctionDefinition)
36
+ .filter(([, v]) => filterFor.size === 0 || filterFor.has(v.id));
12
37
  const result = {};
13
38
  for (const [id,] of fns) {
14
- result[id] = (0, higher_order_function_1.isFunctionHigherOrder)(id, cg, analyzer.inspectContext());
39
+ result[id] = (0, higher_order_function_1.isFunctionHigherOrder)(id, graph, analyzer.inspectContext());
15
40
  }
16
41
  return {
17
42
  '.meta': {
package/util/version.js CHANGED
@@ -6,7 +6,7 @@ exports.printVersionInformation = printVersionInformation;
6
6
  const semver_1 = require("semver");
7
7
  const assert_1 = require("./assert");
8
8
  // this is automatically replaced with the current version by release-it
9
- const version = '2.8.0';
9
+ const version = '2.8.1';
10
10
  /**
11
11
  * Retrieves the current flowR version as a new {@link SemVer} object.
12
12
  */