@eagleoutice/flowr 2.9.7 → 2.9.9

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 (40) hide show
  1. package/README.md +21 -21
  2. package/abstract-interpretation/absint-visitor.d.ts +5 -4
  3. package/abstract-interpretation/absint-visitor.js +12 -11
  4. package/control-flow/basic-cfg-guided-visitor.d.ts +3 -3
  5. package/control-flow/basic-cfg-guided-visitor.js +7 -6
  6. package/control-flow/cfg-dead-code.js +12 -9
  7. package/control-flow/cfg-properties.d.ts +2 -2
  8. package/control-flow/cfg-properties.js +3 -2
  9. package/control-flow/cfg-to-basic-blocks.js +9 -12
  10. package/control-flow/control-flow-graph.d.ts +382 -78
  11. package/control-flow/control-flow-graph.js +591 -106
  12. package/control-flow/dfg-cfg-guided-visitor.d.ts +4 -4
  13. package/control-flow/dfg-cfg-guided-visitor.js +3 -3
  14. package/control-flow/diff-cfg.js +35 -29
  15. package/control-flow/extract-cfg.d.ts +3 -3
  16. package/control-flow/extract-cfg.js +145 -125
  17. package/control-flow/happens-before.js +2 -1
  18. package/control-flow/semantic-cfg-guided-visitor.js +2 -1
  19. package/control-flow/simple-visitor.js +8 -6
  20. package/control-flow/syntax-cfg-guided-visitor.js +2 -1
  21. package/control-flow/useless-loop.js +2 -1
  22. package/documentation/wiki-cfg.js +21 -9
  23. package/documentation/wiki-mk/doc-maker.js +1 -1
  24. package/package.json +1 -1
  25. package/project/context/flowr-file.d.ts +5 -0
  26. package/project/context/flowr-file.js +7 -0
  27. package/project/plugins/file-plugins/files/flowr-description-file.d.ts +1 -0
  28. package/project/plugins/file-plugins/files/flowr-description-file.js +5 -0
  29. package/project/plugins/file-plugins/files/flowr-namespace-file.d.ts +4 -0
  30. package/project/plugins/file-plugins/files/flowr-namespace-file.js +8 -0
  31. package/project/plugins/file-plugins/files/flowr-news-file.d.ts +4 -0
  32. package/project/plugins/file-plugins/files/flowr-news-file.js +8 -0
  33. package/queries/catalog/control-flow-query/control-flow-query-format.js +1 -1
  34. package/r-bridge/lang-4.x/tree-sitter/tree-sitter-normalize.d.ts +2 -1
  35. package/r-bridge/lang-4.x/tree-sitter/tree-sitter-normalize.js +19 -19
  36. package/search/search-executor/search-generators.js +2 -2
  37. package/util/assert.d.ts +3 -3
  38. package/util/mermaid/cfg.d.ts +1 -7
  39. package/util/mermaid/cfg.js +37 -44
  40. package/util/version.js +1 -1
@@ -7,7 +7,6 @@ exports.getCallsInCfg = getCallsInCfg;
7
7
  exports.cfg2quads = cfg2quads;
8
8
  const quads_1 = require("../util/quads");
9
9
  const fold_1 = require("../r-bridge/lang-4.x/ast/model/processing/fold");
10
- const convert_values_1 = require("../r-bridge/lang-4.x/convert-values");
11
10
  const r_function_call_1 = require("../r-bridge/lang-4.x/ast/model/nodes/r-function-call");
12
11
  const linker_1 = require("../dataflow/internal/linker");
13
12
  const vertex_1 = require("../dataflow/graph/vertex");
@@ -102,35 +101,57 @@ function cfgFoldProject(proj, folds) {
102
101
  else if (proj.files.length === 1) {
103
102
  return (0, fold_1.foldAst)(proj.files[0].root, folds);
104
103
  }
105
- const perProject = proj.files.map(file => (0, fold_1.foldAst)(file.root, folds));
106
- const finalGraph = perProject[0].graph;
107
- for (let i = 1; i < perProject.length; i++) {
108
- finalGraph.mergeWith(perProject[i].graph);
109
- for (const exitPoint of perProject[i - 1].exitPoints) {
110
- for (const entryPoint of perProject[i].entryPoints) {
111
- finalGraph.addEdge(entryPoint, exitPoint, { label: 0 /* CfgEdgeType.Fd */ });
104
+ /* for many files, it is too expensive to keep all asts at once, hence we create and merge them incrementally */
105
+ let exitPoints;
106
+ let finalGraph;
107
+ let firstEntryPoints;
108
+ let breaks;
109
+ let nexts;
110
+ let returns;
111
+ {
112
+ const firstInfo = (0, fold_1.foldAst)(proj.files[0].root, folds);
113
+ exitPoints = firstInfo.exitPoints;
114
+ finalGraph = firstInfo.graph;
115
+ firstEntryPoints = firstInfo.entryPoints;
116
+ breaks = firstInfo.breaks;
117
+ nexts = firstInfo.nexts;
118
+ returns = firstInfo.returns;
119
+ }
120
+ for (let i = 1; i < proj.files.length; i++) {
121
+ const nextInfo = (0, fold_1.foldAst)(proj.files[i].root, folds);
122
+ finalGraph.mergeWith(nextInfo.graph);
123
+ for (const exitPoint of exitPoints) {
124
+ for (const entryPoint of nextInfo.entryPoints) {
125
+ finalGraph.addEdge(entryPoint, exitPoint, control_flow_graph_1.CfgEdge.makeFd());
112
126
  }
113
127
  }
128
+ exitPoints = nextInfo.exitPoints;
129
+ breaks.push(...nextInfo.breaks);
130
+ nexts.push(...nextInfo.nexts);
131
+ returns.push(...nextInfo.returns);
114
132
  }
115
133
  return {
116
- breaks: perProject.flatMap(e => e.breaks),
117
- nexts: perProject.flatMap(e => e.nexts),
118
- returns: perProject.flatMap(e => e.returns),
119
- exitPoints: perProject.at(-1).exitPoints,
120
- entryPoints: perProject[0].entryPoints,
134
+ breaks,
135
+ nexts,
136
+ returns,
137
+ exitPoints,
138
+ entryPoints: firstEntryPoints,
121
139
  graph: finalGraph
122
140
  };
123
141
  }
124
142
  function cfgLeaf(type) {
125
- return ({ info: { id } }) => {
126
- return { graph: new control_flow_graph_1.ControlFlowGraph().addVertex({ id, type }), breaks: [], nexts: [], returns: [], exitPoints: [id], entryPoints: [id] };
143
+ return type === control_flow_graph_1.CfgVertexType.Expression ? ({ info: { id } }) => {
144
+ return { graph: new control_flow_graph_1.ControlFlowGraph().addVertex(control_flow_graph_1.CfgVertex.makeExpression(id)), breaks: [], nexts: [], returns: [], exitPoints: [id], entryPoints: [id] };
145
+ } : ({ info: { id } }) => {
146
+ return { graph: new control_flow_graph_1.ControlFlowGraph().addVertex(control_flow_graph_1.CfgVertex.makeStatement(id)), breaks: [], nexts: [], returns: [], exitPoints: [id], entryPoints: [id] };
127
147
  };
128
148
  }
149
+ const cfgLeafStatement = cfgLeaf(control_flow_graph_1.CfgVertexType.Statement);
129
150
  function cfgBreak(leaf) {
130
- return { ...cfgLeaf(control_flow_graph_1.CfgVertexType.Statement)(leaf), breaks: [leaf.info.id], exitPoints: [] };
151
+ return { ...cfgLeafStatement(leaf), breaks: [leaf.info.id], exitPoints: [] };
131
152
  }
132
153
  function cfgNext(leaf) {
133
- return { ...cfgLeaf(control_flow_graph_1.CfgVertexType.Statement)(leaf), nexts: [leaf.info.id], exitPoints: [] };
154
+ return { ...cfgLeafStatement(leaf), nexts: [leaf.info.id], exitPoints: [] };
134
155
  }
135
156
  function cfgIgnore(_leaf) {
136
157
  return { graph: new control_flow_graph_1.ControlFlowGraph(), breaks: [], nexts: [], returns: [], exitPoints: [], entryPoints: [] };
@@ -141,32 +162,34 @@ function identifyMayStatementType(node) {
141
162
  function cfgIfThenElse(ifNode, condition, then, otherwise) {
142
163
  const ifId = ifNode.info.id;
143
164
  const graph = new control_flow_graph_1.ControlFlowGraph();
144
- graph.addVertex({ id: ifId, type: identifyMayStatementType(ifNode), mid: condition.exitPoints, end: [ifId + '-exit'] });
145
- graph.addVertex({ id: ifId + '-exit', type: control_flow_graph_1.CfgVertexType.EndMarker, root: ifId });
165
+ graph.addVertex(control_flow_graph_1.CfgVertex.makeExprOrStm(ifId, identifyMayStatementType(ifNode), { mid: condition.exitPoints, end: [control_flow_graph_1.CfgVertex.toExitId(ifId)] }));
166
+ graph.addVertex(control_flow_graph_1.CfgVertex.makeExitMarker(ifId));
146
167
  graph.mergeWith(condition.graph);
147
168
  graph.mergeWith(then.graph);
148
169
  if (otherwise) {
149
170
  graph.mergeWith(otherwise.graph);
150
171
  }
172
+ const cdTrue = control_flow_graph_1.CfgEdge.makeCdTrue(ifId);
173
+ const cdFalse = control_flow_graph_1.CfgEdge.makeCdFalse(ifId);
151
174
  for (const e of condition.exitPoints) {
152
175
  for (const entryPoint of then.entryPoints) {
153
- graph.addEdge(entryPoint, e, { label: 1 /* CfgEdgeType.Cd */, when: convert_values_1.RTrue, caused: ifId });
176
+ graph.addEdge(entryPoint, e, cdTrue);
154
177
  }
155
178
  for (const entryPoint of otherwise?.entryPoints ?? []) {
156
- graph.addEdge(entryPoint, e, { label: 1 /* CfgEdgeType.Cd */, when: convert_values_1.RFalse, caused: ifId });
179
+ graph.addEdge(entryPoint, e, cdFalse);
157
180
  }
158
181
  }
159
182
  for (const entryPoint of condition.entryPoints) {
160
- graph.addEdge(entryPoint, ifId, { label: 0 /* CfgEdgeType.Fd */ });
183
+ graph.addEdge(entryPoint, ifId, control_flow_graph_1.CfgEdge.makeFd());
161
184
  }
162
185
  for (const exits of [then.exitPoints, otherwise?.exitPoints ?? []]) {
163
186
  for (const exit of exits) {
164
- graph.addEdge(ifId + '-exit', exit, { label: 0 /* CfgEdgeType.Fd */ });
187
+ graph.addEdge(control_flow_graph_1.CfgVertex.toExitId(ifId), exit, control_flow_graph_1.CfgEdge.makeFd());
165
188
  }
166
189
  }
167
190
  if (!otherwise) {
168
191
  for (const e of condition.exitPoints) {
169
- graph.addEdge(ifId + '-exit', e, { label: 1 /* CfgEdgeType.Cd */, when: convert_values_1.RFalse, caused: ifId });
192
+ graph.addEdge(control_flow_graph_1.CfgVertex.toExitId(ifId), e, control_flow_graph_1.CfgEdge.makeCdFalse(ifId));
170
193
  }
171
194
  }
172
195
  return {
@@ -174,107 +197,100 @@ function cfgIfThenElse(ifNode, condition, then, otherwise) {
174
197
  breaks: then.breaks.concat(otherwise?.breaks ?? []),
175
198
  nexts: then.nexts.concat(otherwise?.nexts ?? []),
176
199
  returns: then.returns.concat(otherwise?.returns ?? []),
177
- exitPoints: [ifId + '-exit'],
200
+ exitPoints: [control_flow_graph_1.CfgVertex.toExitId(ifId)],
178
201
  entryPoints: [ifId]
179
202
  };
180
203
  }
181
204
  function cfgRepeat(repeat, body) {
182
205
  const graph = body.graph;
183
- graph.addVertex({ id: repeat.info.id, type: identifyMayStatementType(repeat), end: [repeat.info.id + '-exit'] });
184
- graph.addVertex({ id: repeat.info.id + '-exit', type: control_flow_graph_1.CfgVertexType.EndMarker, root: repeat.info.id });
206
+ const rid = repeat.info.id;
207
+ graph.addVertex(control_flow_graph_1.CfgVertex.makeExprOrStm(rid, identifyMayStatementType(repeat), { end: [control_flow_graph_1.CfgVertex.toExitId(rid)] }));
208
+ graph.addVertex(control_flow_graph_1.CfgVertex.makeExitMarker(rid));
185
209
  for (const entryPoint of body.entryPoints) {
186
- graph.addEdge(entryPoint, repeat.info.id, { label: 0 /* CfgEdgeType.Fd */ });
210
+ graph.addEdge(entryPoint, rid, control_flow_graph_1.CfgEdge.makeFd());
187
211
  }
188
212
  // loops automatically
189
213
  for (const nexts of [body.nexts, body.exitPoints]) {
190
214
  for (const next of nexts) {
191
- graph.addEdge(repeat.info.id, next, { label: 0 /* CfgEdgeType.Fd */ });
215
+ graph.addEdge(rid, next, control_flow_graph_1.CfgEdge.makeFd());
192
216
  }
193
217
  }
194
218
  for (const breakPoint of body.breaks) {
195
- graph.addEdge(repeat.info.id + '-exit', breakPoint, { label: 0 /* CfgEdgeType.Fd */ });
219
+ graph.addEdge(control_flow_graph_1.CfgVertex.toExitId(rid), breakPoint, control_flow_graph_1.CfgEdge.makeFd());
196
220
  }
197
- return { graph, breaks: [], nexts: [], returns: body.returns, exitPoints: [repeat.info.id + '-exit'], entryPoints: [repeat.info.id] };
221
+ return { graph, breaks: [], nexts: [], returns: body.returns, exitPoints: [control_flow_graph_1.CfgVertex.toExitId(rid)], entryPoints: [rid] };
198
222
  }
199
223
  function cfgWhile(whileLoop, condition, body) {
200
224
  const whileId = whileLoop.info.id;
201
225
  const graph = condition.graph;
202
- graph.addVertex({ id: whileId, type: identifyMayStatementType(whileLoop), mid: condition.exitPoints, end: [whileId + '-exit'] });
203
- graph.addVertex({ id: whileId + '-exit', type: control_flow_graph_1.CfgVertexType.EndMarker, root: whileId });
226
+ graph.addVertex(control_flow_graph_1.CfgVertex.makeExprOrStm(whileId, identifyMayStatementType(whileLoop), { mid: condition.exitPoints, end: [control_flow_graph_1.CfgVertex.toExitId(whileId)] }));
227
+ graph.addVertex(control_flow_graph_1.CfgVertex.makeExitMarker(whileId));
204
228
  graph.mergeWith(body.graph);
205
229
  for (const entry of condition.entryPoints) {
206
- graph.addEdge(entry, whileId, { label: 0 /* CfgEdgeType.Fd */ });
230
+ graph.addEdge(entry, whileId, control_flow_graph_1.CfgEdge.makeFd());
207
231
  }
208
232
  for (const e of condition.exitPoints) {
209
233
  for (const entry of body.entryPoints) {
210
- graph.addEdge(entry, e, { label: 1 /* CfgEdgeType.Cd */, when: convert_values_1.RTrue, caused: whileId });
234
+ graph.addEdge(entry, e, control_flow_graph_1.CfgEdge.makeCdTrue(whileId));
211
235
  }
212
236
  }
213
237
  for (const nexts of [body.nexts, body.exitPoints]) {
214
238
  for (const next of nexts) {
215
- graph.addEdge(whileId, next, { label: 0 /* CfgEdgeType.Fd */ });
239
+ graph.addEdge(whileId, next, control_flow_graph_1.CfgEdge.makeFd());
216
240
  }
217
241
  }
218
242
  for (const breakPoint of body.breaks) {
219
- graph.addEdge(whileId + '-exit', breakPoint, { label: 0 /* CfgEdgeType.Fd */ });
243
+ graph.addEdge(control_flow_graph_1.CfgVertex.toExitId(whileId), breakPoint, control_flow_graph_1.CfgEdge.makeFd());
220
244
  }
221
245
  // while can break on the condition as well
222
246
  for (const e of condition.exitPoints) {
223
- graph.addEdge(whileId + '-exit', e, {
224
- label: 1 /* CfgEdgeType.Cd */,
225
- when: convert_values_1.RFalse,
226
- caused: whileId
227
- });
247
+ graph.addEdge(control_flow_graph_1.CfgVertex.toExitId(whileId), e, control_flow_graph_1.CfgEdge.makeCdFalse(whileId));
228
248
  }
229
- return { graph, breaks: [], nexts: [], returns: body.returns, exitPoints: [whileId + '-exit'], entryPoints: [whileId] };
249
+ return { graph, breaks: [], nexts: [], returns: body.returns, exitPoints: [control_flow_graph_1.CfgVertex.toExitId(whileId)], entryPoints: [whileId] };
230
250
  }
231
251
  function cfgFor(forLoop, variable, vector, body) {
232
252
  const forLoopId = forLoop.info.id;
233
253
  const graph = variable.graph;
234
- graph.addVertex({ id: forLoopId, type: identifyMayStatementType(forLoop), end: [forLoopId + '-exit'], mid: variable.exitPoints });
254
+ graph.addVertex(control_flow_graph_1.CfgVertex.makeExprOrStm(forLoopId, identifyMayStatementType(forLoop), { mid: variable.exitPoints, end: [control_flow_graph_1.CfgVertex.toExitId(forLoopId)] }));
235
255
  graph.mergeWith(vector.graph);
236
256
  graph.mergeWith(body.graph);
237
257
  for (const entry of vector.entryPoints) {
238
- graph.addEdge(entry, forLoopId, { label: 0 /* CfgEdgeType.Fd */ });
258
+ graph.addEdge(entry, forLoopId, control_flow_graph_1.CfgEdge.makeFd());
239
259
  }
240
260
  for (const exit of vector.exitPoints) {
241
261
  for (const entry of variable.entryPoints) {
242
- graph.addEdge(entry, exit, { label: 0 /* CfgEdgeType.Fd */ });
262
+ graph.addEdge(entry, exit, control_flow_graph_1.CfgEdge.makeFd());
243
263
  }
244
264
  }
245
265
  for (const e of variable.exitPoints) {
246
266
  for (const entry of body.entryPoints) {
247
- graph.addEdge(entry, e, { label: 1 /* CfgEdgeType.Cd */, when: convert_values_1.RTrue, caused: forLoopId });
267
+ graph.addEdge(entry, e, control_flow_graph_1.CfgEdge.makeCdTrue(forLoopId));
248
268
  }
249
269
  }
250
270
  for (const points of [body.nexts, body.exitPoints]) {
251
271
  for (const next of points) {
252
- graph.addEdge(forLoopId, next, { label: 0 /* CfgEdgeType.Fd */ });
272
+ graph.addEdge(forLoopId, next, control_flow_graph_1.CfgEdge.makeFd());
253
273
  }
254
274
  }
255
275
  for (const breakPoint of body.breaks) {
256
- graph.addEdge(forLoopId + '-exit', breakPoint, { label: 0 /* CfgEdgeType.Fd */ });
276
+ graph.addEdge(control_flow_graph_1.CfgVertex.toExitId(forLoopId), breakPoint, control_flow_graph_1.CfgEdge.makeFd());
257
277
  }
258
278
  const isNotEndless = body.exitPoints.length > 0 || body.breaks.length > 0;
259
279
  if (isNotEndless) {
260
- graph.addVertex({
261
- id: forLoopId + '-exit',
262
- type: control_flow_graph_1.CfgVertexType.EndMarker,
263
- root: forLoopId
264
- });
280
+ graph.addVertex(control_flow_graph_1.CfgVertex.makeExitMarker(forLoopId));
265
281
  for (const e of variable.exitPoints) {
266
- graph.addEdge(forLoopId + '-exit', e, { label: 1 /* CfgEdgeType.Cd */, when: convert_values_1.RFalse, caused: forLoopId });
282
+ graph.addEdge(control_flow_graph_1.CfgVertex.toExitId(forLoopId), e, control_flow_graph_1.CfgEdge.makeCdFalse(forLoopId));
267
283
  }
268
284
  }
269
- return { graph, breaks: [], nexts: [], returns: body.returns, exitPoints: isNotEndless ? [forLoopId + '-exit'] : [], entryPoints: [forLoopId] };
285
+ return { graph, breaks: [], nexts: [], returns: body.returns, exitPoints: isNotEndless ? [control_flow_graph_1.CfgVertex.toExitId(forLoopId)] : [], entryPoints: [forLoopId] };
270
286
  }
271
287
  function cfgFunctionDefinition(fn, params, body) {
272
288
  const fnId = fn.info.id;
273
289
  const graph = new control_flow_graph_1.ControlFlowGraph();
274
290
  let paramExits = params.flatMap(e => e.exitPoints);
275
- const children = [...paramExits, fnId + '-exit'];
276
- graph.addVertex({ id: fnId + '-exit', type: control_flow_graph_1.CfgVertexType.EndMarker, root: fnId }, false);
277
- graph.addVertex({ id: fnId, children, type: identifyMayStatementType(fn), mid: paramExits, end: [fnId + '-exit'] });
291
+ const children = [...paramExits, control_flow_graph_1.CfgVertex.toExitId(fnId)];
292
+ graph.addVertex(control_flow_graph_1.CfgVertex.makeExitMarker(fnId), false);
293
+ graph.addVertex(control_flow_graph_1.CfgVertex.makeExprOrStm(fnId, identifyMayStatementType(fn), { children, mid: paramExits, end: [control_flow_graph_1.CfgVertex.toExitId(fnId)] }));
278
294
  graph.mergeWith(body.graph, true);
279
295
  for (const r of body.graph.rootIds()) {
280
296
  children.push(r);
@@ -285,7 +301,7 @@ function cfgFunctionDefinition(fn, params, body) {
285
301
  children.push(r);
286
302
  }
287
303
  for (const entry of param.entryPoints) {
288
- graph.addEdge(entry, fnId, { label: 0 /* CfgEdgeType.Fd */ });
304
+ graph.addEdge(entry, fnId, control_flow_graph_1.CfgEdge.makeFd());
289
305
  }
290
306
  }
291
307
  if (paramExits.length === 0) {
@@ -293,16 +309,16 @@ function cfgFunctionDefinition(fn, params, body) {
293
309
  }
294
310
  for (const e of paramExits) {
295
311
  for (const entry of body.entryPoints) {
296
- graph.addEdge(entry, e, { label: 0 /* CfgEdgeType.Fd */ });
312
+ graph.addEdge(entry, e, control_flow_graph_1.CfgEdge.makeFd());
297
313
  }
298
314
  }
299
315
  // breaks and nexts should be illegal but safe is safe, I guess
300
316
  for (const next of body.returns.concat(body.breaks, body.nexts, body.exitPoints)) {
301
- graph.addEdge(fnId + '-exit', next, { label: 0 /* CfgEdgeType.Fd */ });
317
+ graph.addEdge(control_flow_graph_1.CfgVertex.toExitId(fnId), next, control_flow_graph_1.CfgEdge.makeFd());
302
318
  }
303
319
  return { graph: graph, breaks: [], nexts: [], returns: [], exitPoints: [fnId], entryPoints: [fnId] };
304
320
  }
305
- function cfgFunctionCall(call, name, args, exit = 'exit') {
321
+ function cfgFunctionCall(call, name, args) {
306
322
  if (call.named && call.functionName.content === 'ifelse') {
307
323
  // special built-in handling for ifelse as it is an expression that does not short-circuit
308
324
  return cfgIfThenElse(call, args[0] === r_function_call_1.EmptyArgument ? (0, control_flow_graph_1.emptyControlFlowInformation)() : args[0], args[1] === r_function_call_1.EmptyArgument ? (0, control_flow_graph_1.emptyControlFlowInformation)() : args[1], args[2] === r_function_call_1.EmptyArgument ? (0, control_flow_graph_1.emptyControlFlowInformation)() : args[2]);
@@ -314,14 +330,14 @@ function cfgFunctionCall(call, name, args, exit = 'exit') {
314
330
  breaks: Array.from(name.breaks),
315
331
  nexts: Array.from(name.nexts),
316
332
  returns: Array.from(name.returns),
317
- exitPoints: [callId + '-' + exit],
333
+ exitPoints: [control_flow_graph_1.CfgVertex.toExitId(callId)],
318
334
  entryPoints: [callId]
319
335
  };
320
- graph.addVertex({ id: callId, type: identifyMayStatementType(call), mid: name.exitPoints, end: [callId + '-' + exit] });
336
+ graph.addVertex(control_flow_graph_1.CfgVertex.makeExprOrStm(callId, identifyMayStatementType(call), { mid: name.exitPoints, end: [control_flow_graph_1.CfgVertex.toExitId(callId)] }));
321
337
  for (const entryPoint of name.entryPoints) {
322
- graph.addEdge(entryPoint, callId, { label: 0 /* CfgEdgeType.Fd */ });
338
+ graph.addEdge(entryPoint, callId, control_flow_graph_1.CfgEdge.makeFd());
323
339
  }
324
- graph.addVertex({ id: callId + '-' + exit, type: control_flow_graph_1.CfgVertexType.EndMarker, root: callId });
340
+ graph.addVertex(control_flow_graph_1.CfgVertex.makeExitMarker(callId));
325
341
  let lastArgExits = name.exitPoints;
326
342
  for (const arg of args) {
327
343
  if (arg === r_function_call_1.EmptyArgument) {
@@ -333,22 +349,22 @@ function cfgFunctionCall(call, name, args, exit = 'exit') {
333
349
  info.returns = info.returns.concat(arg.returns);
334
350
  for (const entry of arg.entryPoints) {
335
351
  for (const exit of lastArgExits) {
336
- graph.addEdge(entry, exit, { label: 0 /* CfgEdgeType.Fd */ });
352
+ graph.addEdge(entry, exit, control_flow_graph_1.CfgEdge.makeFd());
337
353
  }
338
354
  }
339
355
  lastArgExits = arg.exitPoints;
340
356
  }
341
357
  for (const exit of lastArgExits) {
342
- graph.addEdge(callId + '-exit', exit, { label: 0 /* CfgEdgeType.Fd */ });
358
+ graph.addEdge(control_flow_graph_1.CfgVertex.toExitId(callId), exit, control_flow_graph_1.CfgEdge.makeFd());
343
359
  }
344
360
  if (call.named && call.functionName.content === 'return') {
345
- info.returns.push(callId + '-exit');
361
+ info.returns.push(control_flow_graph_1.CfgVertex.toExitId(callId));
346
362
  info.exitPoints.length = 0;
347
363
  }
348
364
  // should not contain any breaks, nexts, or returns, (except for the body if something like 'break()')
349
365
  return info;
350
366
  }
351
- exports.ResolvedCallSuffix = '-resolved-call-exit';
367
+ exports.ResolvedCallSuffix = control_flow_graph_1.CfgVertex.toExitId('-resolved-call');
352
368
  const OriginToFoldTypeMap = {
353
369
  [built_in_1.BuiltInProcName.IfThenElse]: (folds, call, args) => {
354
370
  // arguments are in order!
@@ -374,20 +390,21 @@ function cfgFunctionCallWithDataflow(graph, folds) {
374
390
  for (const target of targets) {
375
391
  // we have to filter out non-func-call targets as the call targets contains names and call ids
376
392
  if ((0, vertex_1.isFunctionDefinitionVertex)(graph.getVertex(target))) {
377
- callVertex.callTargets ??= new Set();
378
- callVertex.callTargets.add(target);
379
- exits.push(target + '-exit');
393
+ const ct = control_flow_graph_1.CfgVertex.getCallTargets(callVertex);
394
+ if (!ct) {
395
+ control_flow_graph_1.CfgVertex.setCallTargets(callVertex, new Set([target]));
396
+ }
397
+ else {
398
+ ct.add(target);
399
+ }
400
+ exits.push(control_flow_graph_1.CfgVertex.toExitId(target));
380
401
  }
381
402
  }
382
403
  if (exits.length > 0) {
383
- baseCfg.graph.addVertex({
384
- id: call.info.id + exports.ResolvedCallSuffix,
385
- type: control_flow_graph_1.CfgVertexType.EndMarker,
386
- root: call.info.id
387
- });
404
+ baseCfg.graph.addVertex(control_flow_graph_1.CfgVertex.makeMarker(call.info.id + exports.ResolvedCallSuffix, call.info.id));
388
405
  for (const col of [baseCfg.exitPoints, exits]) {
389
406
  for (const exit of col) {
390
- baseCfg.graph.addEdge(call.info.id + exports.ResolvedCallSuffix, exit, { label: 0 /* CfgEdgeType.Fd */ });
407
+ baseCfg.graph.addEdge(call.info.id + exports.ResolvedCallSuffix, exit, control_flow_graph_1.CfgEdge.makeFd());
391
408
  }
392
409
  }
393
410
  return {
@@ -402,16 +419,17 @@ function cfgFunctionCallWithDataflow(graph, folds) {
402
419
  }
403
420
  function cfgArgumentOrParameter(node, name, value) {
404
421
  const graph = new control_flow_graph_1.ControlFlowGraph();
405
- const info = { graph, breaks: [], nexts: [], returns: [], exitPoints: [node.info.id + '-exit'], entryPoints: [node.info.id] };
406
- let currentExitPoints = name?.exitPoints ?? [node.info.id];
407
- graph.addVertex({ id: node.info.id, type: control_flow_graph_1.CfgVertexType.Expression, mid: currentExitPoints, end: [node.info.id + '-exit'] });
422
+ const nodeId = node.info.id;
423
+ const info = { graph, breaks: [], nexts: [], returns: [], exitPoints: [control_flow_graph_1.CfgVertex.toExitId(nodeId)], entryPoints: [nodeId] };
424
+ let currentExitPoints = name?.exitPoints ?? [nodeId];
425
+ graph.addVertex(control_flow_graph_1.CfgVertex.makeExpressionWithEnd(nodeId, { mid: currentExitPoints }));
408
426
  if (name) {
409
427
  graph.mergeWith(name.graph);
410
428
  info.breaks = info.breaks.concat(name.breaks);
411
429
  info.nexts = info.nexts.concat(name.nexts);
412
430
  info.returns = info.returns.concat(name.returns);
413
431
  for (const entry of name.entryPoints) {
414
- graph.addEdge(entry, node.info.id, { label: 0 /* CfgEdgeType.Fd */ });
432
+ graph.addEdge(entry, nodeId, control_flow_graph_1.CfgEdge.makeFd());
415
433
  }
416
434
  }
417
435
  if (value) {
@@ -421,42 +439,46 @@ function cfgArgumentOrParameter(node, name, value) {
421
439
  info.returns = info.returns.concat(value.returns);
422
440
  for (const exitPoint of currentExitPoints) {
423
441
  for (const entry of value.entryPoints) {
424
- graph.addEdge(entry, exitPoint, { label: 0 /* CfgEdgeType.Fd */ });
442
+ graph.addEdge(entry, exitPoint, control_flow_graph_1.CfgEdge.makeFd());
425
443
  }
426
444
  }
427
445
  currentExitPoints = value.exitPoints;
428
446
  }
429
- graph.addVertex({ id: node.info.id + '-exit', type: control_flow_graph_1.CfgVertexType.EndMarker, root: node.info.id });
447
+ graph.addVertex(control_flow_graph_1.CfgVertex.makeExitMarker(nodeId));
430
448
  for (const exit of currentExitPoints) {
431
- graph.addEdge(node.info.id + '-exit', exit, { label: 0 /* CfgEdgeType.Fd */ });
449
+ graph.addEdge(control_flow_graph_1.CfgVertex.toExitId(nodeId), exit, control_flow_graph_1.CfgEdge.makeFd());
432
450
  }
433
451
  return info;
434
452
  }
435
453
  function cfgBinaryOp(binOp, lhs, rhs) {
436
- const graph = new control_flow_graph_1.ControlFlowGraph().mergeWith(lhs.graph).mergeWith(rhs.graph);
437
- const result = { graph, breaks: lhs.breaks.concat(rhs.breaks), nexts: lhs.nexts.concat(rhs.nexts), returns: lhs.returns.concat(rhs.returns), entryPoints: [binOp.info.id], exitPoints: [binOp.info.id + '-exit'] };
438
- graph.addVertex({ id: binOp.info.id, type: binOp.flavor === 'assignment' ? control_flow_graph_1.CfgVertexType.Statement : control_flow_graph_1.CfgVertexType.Expression, end: [binOp.info.id + '-exit'] });
439
- graph.addVertex({ id: binOp.info.id + '-exit', type: control_flow_graph_1.CfgVertexType.EndMarker, root: binOp.info.id });
454
+ const graph = lhs.graph.mergeWith(rhs.graph);
455
+ const binId = binOp.info.id;
456
+ const binExit = control_flow_graph_1.CfgVertex.toExitId(binId);
457
+ const result = { graph, breaks: lhs.breaks.concat(rhs.breaks), nexts: lhs.nexts.concat(rhs.nexts), returns: lhs.returns.concat(rhs.returns), entryPoints: [binId], exitPoints: [binExit] };
458
+ graph.addVertex(control_flow_graph_1.CfgVertex.makeExprOrStm(binId, binOp.flavor === 'assignment' ? control_flow_graph_1.CfgVertexType.Statement : control_flow_graph_1.CfgVertexType.Expression, { end: [binExit] }));
459
+ graph.addVertex(control_flow_graph_1.CfgVertex.makeExitMarker(binId));
460
+ const fd = control_flow_graph_1.CfgEdge.makeFd();
440
461
  for (const exitPoint of lhs.exitPoints) {
441
462
  for (const entryPoint of rhs.entryPoints) {
442
- result.graph.addEdge(entryPoint, exitPoint, { label: 0 /* CfgEdgeType.Fd */ });
463
+ result.graph.addEdge(entryPoint, exitPoint, fd);
443
464
  }
444
465
  }
445
466
  for (const entryPoint of lhs.entryPoints) {
446
- graph.addEdge(entryPoint, binOp.info.id, { label: 0 /* CfgEdgeType.Fd */ });
467
+ graph.addEdge(entryPoint, binId, fd);
447
468
  }
448
469
  for (const exitPoint of rhs.exitPoints) {
449
- graph.addEdge(binOp.info.id + '-exit', exitPoint, { label: 0 /* CfgEdgeType.Fd */ });
470
+ graph.addEdge(binExit, exitPoint, fd);
450
471
  }
451
472
  return result;
452
473
  }
453
474
  function cfgAccess(access, name, accessors) {
454
475
  const result = { ...name };
455
476
  const graph = result.graph;
456
- graph.addVertex({ id: access.info.id, type: control_flow_graph_1.CfgVertexType.Expression, mid: name.exitPoints, end: [access.info.id + '-exit'] });
457
- result.entryPoints = [access.info.id];
477
+ const accessId = access.info.id;
478
+ graph.addVertex(control_flow_graph_1.CfgVertex.makeExpressionWithEnd(accessId, { mid: name.exitPoints }));
479
+ result.entryPoints = [accessId];
458
480
  for (const entry of name.entryPoints) {
459
- graph.addEdge(entry, access.info.id, { label: 0 /* CfgEdgeType.Fd */ });
481
+ graph.addEdge(entry, accessId, control_flow_graph_1.CfgEdge.makeFd());
460
482
  }
461
483
  result.exitPoints = name.exitPoints;
462
484
  for (const accessor of accessors) {
@@ -466,7 +488,7 @@ function cfgAccess(access, name, accessors) {
466
488
  graph.mergeWith(accessor.graph);
467
489
  for (const exitPoint of result.exitPoints) {
468
490
  for (const entry of accessor.entryPoints) {
469
- graph.addEdge(entry, exitPoint, { label: 0 /* CfgEdgeType.Fd */ });
491
+ graph.addEdge(entry, exitPoint, control_flow_graph_1.CfgEdge.makeFd());
470
492
  }
471
493
  }
472
494
  result.exitPoints = accessor.exitPoints;
@@ -475,58 +497,56 @@ function cfgAccess(access, name, accessors) {
475
497
  result.returns = result.returns.concat(accessor.returns);
476
498
  }
477
499
  for (const exitPoint of result.exitPoints) {
478
- graph.addEdge(access.info.id + '-exit', exitPoint, { label: 0 /* CfgEdgeType.Fd */ });
500
+ graph.addEdge(control_flow_graph_1.CfgVertex.toExitId(accessId), exitPoint, control_flow_graph_1.CfgEdge.makeFd());
479
501
  }
480
- graph.addVertex({ id: access.info.id + '-exit', type: control_flow_graph_1.CfgVertexType.EndMarker, root: access.info.id });
481
- result.exitPoints = [access.info.id + '-exit'];
502
+ graph.addVertex(control_flow_graph_1.CfgVertex.makeExitMarker(accessId));
503
+ result.exitPoints = [control_flow_graph_1.CfgVertex.toExitId(accessId)];
482
504
  return result;
483
505
  }
484
506
  function cfgUnaryOp(unary, operand) {
485
507
  const graph = operand.graph;
486
- graph.addVertex({ id: unary.info.id, type: control_flow_graph_1.CfgVertexType.EndMarker, root: unary.info.id });
508
+ const unaryId = unary.info.id;
509
+ graph.addVertex(control_flow_graph_1.CfgVertex.makeMarker(unaryId, unaryId));
510
+ const fd = control_flow_graph_1.CfgEdge.makeFd();
487
511
  for (const entry of operand.exitPoints) {
488
- graph.addEdge(unary.info.id, entry, { label: 0 /* CfgEdgeType.Fd */ });
512
+ graph.addEdge(unaryId, entry, fd);
489
513
  }
490
- return { ...operand, graph, exitPoints: [unary.info.id] };
514
+ return { ...operand, graph, exitPoints: [unaryId] };
491
515
  }
492
516
  function cfgExprList(node, _grouping, expressions) {
517
+ const nodeId = node.info.id;
493
518
  const result = {
494
519
  graph: new control_flow_graph_1.ControlFlowGraph(),
495
520
  breaks: [],
496
521
  nexts: [],
497
522
  returns: [],
498
- exitPoints: [node.info.id],
499
- entryPoints: [node.info.id]
523
+ exitPoints: [nodeId],
524
+ entryPoints: [nodeId]
500
525
  };
501
- const vtx = { id: node.info.id, type: control_flow_graph_1.CfgVertexType.Expression, end: [] };
526
+ const vtx = control_flow_graph_1.CfgVertex.makeExpression(nodeId);
502
527
  result.graph.addVertex(vtx);
528
+ const fd = control_flow_graph_1.CfgEdge.makeFd();
503
529
  for (const expression of expressions) {
504
530
  for (const previousExitPoint of result.exitPoints) {
505
531
  for (const entryPoint of expression.entryPoints) {
506
- result.graph.addEdge(entryPoint, previousExitPoint, { label: 0 /* CfgEdgeType.Fd */ });
532
+ result.graph.addEdge(entryPoint, previousExitPoint, fd);
507
533
  }
508
534
  }
509
535
  result.graph.mergeWith(expression.graph);
510
- result.breaks = result.breaks.concat(expression.breaks);
511
- result.nexts = result.nexts.concat(expression.nexts);
512
- result.returns = result.returns.concat(expression.returns);
536
+ result.breaks.push(...expression.breaks);
537
+ result.nexts.push(...expression.nexts);
538
+ result.returns.push(...expression.returns);
513
539
  result.exitPoints = expression.exitPoints;
514
540
  }
541
+ const exitId = control_flow_graph_1.CfgVertex.toExitId(nodeId);
515
542
  if (result.exitPoints.length > 0) {
516
- result.graph.addVertex({
517
- id: node.info.id + '-exit',
518
- type: control_flow_graph_1.CfgVertexType.EndMarker,
519
- root: node.info.id
520
- });
521
- vtx.end = [node.info.id + '-exit'];
522
- }
523
- else {
524
- vtx.end = undefined;
543
+ result.graph.addVertex(control_flow_graph_1.CfgVertex.makeExitMarker(nodeId));
544
+ control_flow_graph_1.CfgVertex.setEnd(vtx, [exitId]);
525
545
  }
526
546
  for (const exit of result.exitPoints) {
527
- result.graph.addEdge(node.info.id + '-exit', exit, { label: 0 /* CfgEdgeType.Fd */ });
547
+ result.graph.addEdge(exitId, exit, fd);
528
548
  }
529
- result.exitPoints = result.exitPoints.length > 0 ? [node.info.id + '-exit'] : [];
549
+ result.exitPoints = result.exitPoints.length > 0 ? [exitId] : [];
530
550
  return result;
531
551
  }
532
552
  /**
@@ -541,13 +561,13 @@ function cfg2quads(cfg, config) {
541
561
  vertices: [...cfg.graph.vertices().entries()]
542
562
  .map(([id, v]) => ({
543
563
  id,
544
- children: v.children
564
+ children: control_flow_graph_1.CfgVertex.getChildren(v)
545
565
  })),
546
566
  edges: [...cfg.graph.edges()].flatMap(([fromId, targets]) => [...targets].map(([toId, info]) => ({
547
567
  from: fromId,
548
568
  to: toId,
549
- type: info.label,
550
- when: info.when
569
+ type: control_flow_graph_1.CfgEdge.getType(info),
570
+ when: control_flow_graph_1.CfgEdge.getWhen(info)
551
571
  }))),
552
572
  entryPoints: cfg.entryPoints,
553
573
  exitPoints: cfg.exitPoints,
@@ -2,6 +2,7 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.happensBefore = happensBefore;
4
4
  const logic_1 = require("../util/logic");
5
+ const control_flow_graph_1 = require("./control-flow-graph");
5
6
  /**
6
7
  * Determines if node `a` happens before node `b` in the control flow graph.
7
8
  */
@@ -23,7 +24,7 @@ function happensBefore(cfg, a, b) {
23
24
  }
24
25
  visited.add(current);
25
26
  for (const [id, t] of cfg.outgoingEdges(current) ?? []) {
26
- const marker = t.label === 1 /* CfgEdgeType.Cd */ ? `${t.caused}-exit` : useCd;
27
+ const marker = control_flow_graph_1.CfgEdge.isControlDependency(t) ? control_flow_graph_1.CfgVertex.toExitId(control_flow_graph_1.CfgEdge.unpackCause(t)) : useCd;
27
28
  stack.push([id, useCd ?? marker]);
28
29
  }
29
30
  }
@@ -1,6 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.SemanticCfgGuidedVisitor = void 0;
4
+ const control_flow_graph_1 = require("./control-flow-graph");
4
5
  const dfg_cfg_guided_visitor_1 = require("./dfg-cfg-guided-visitor");
5
6
  const dfg_get_origin_1 = require("../dataflow/origin/dfg-get-origin");
6
7
  const type_1 = require("../r-bridge/lang-4.x/ast/model/type");
@@ -132,7 +133,7 @@ class SemanticCfgGuidedVisitor extends dfg_cfg_guided_visitor_1.DataflowAwareCfg
132
133
  */
133
134
  visitUnknown(vertex) {
134
135
  super.visitUnknown(vertex);
135
- const ast = this.getNormalizedAst(vertex.id);
136
+ const ast = this.getNormalizedAst(control_flow_graph_1.CfgVertex.getId(vertex));
136
137
  if (ast && ast.type === type_1.RType.ExpressionList && ast.info.parent === undefined) {
137
138
  this.onProgram(ast);
138
139
  }
@@ -30,9 +30,10 @@ visitor) {
30
30
  }
31
31
  else if (hasBb) {
32
32
  const get = graph.getVertex(current);
33
- if (get?.type === control_flow_graph_1.CfgVertexType.Block) {
34
- for (const e of get.elems.toReversed()) {
35
- queue.push(e.id);
33
+ if (control_flow_graph_1.CfgVertex.isBlock(get)) {
34
+ const elems = control_flow_graph_1.CfgVertex.getBasicBlockElements(get);
35
+ for (const e of elems.toReversed()) {
36
+ queue.push(control_flow_graph_1.CfgVertex.getId(e));
36
37
  }
37
38
  }
38
39
  }
@@ -70,9 +71,10 @@ visitor) {
70
71
  }
71
72
  else if (hasBb) {
72
73
  const get = graph.getVertex(current);
73
- if (get?.type === control_flow_graph_1.CfgVertexType.Block) {
74
- for (const e of get.elems.toReversed()) {
75
- queue.push(e.id);
74
+ if (control_flow_graph_1.CfgVertex.isBlock(get)) {
75
+ const elems = control_flow_graph_1.CfgVertex.getBasicBlockElements(get);
76
+ for (const e of elems.toReversed()) {
77
+ queue.push(control_flow_graph_1.CfgVertex.getId(e));
76
78
  }
77
79
  }
78
80
  }
@@ -1,6 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.SyntaxAwareCfgGuidedVisitor = void 0;
4
+ const control_flow_graph_1 = require("./control-flow-graph");
4
5
  const basic_cfg_guided_visitor_1 = require("./basic-cfg-guided-visitor");
5
6
  const type_1 = require("../r-bridge/lang-4.x/ast/model/type");
6
7
  const assert_1 = require("../util/assert");
@@ -25,7 +26,7 @@ class SyntaxAwareCfgGuidedVisitor extends basic_cfg_guided_visitor_1.BasicCfgGui
25
26
  this.onExprOrStmtNode(node);
26
27
  }
27
28
  onExprOrStmtNode(node) {
28
- const astVertex = this.getNormalizedAst(node.id);
29
+ const astVertex = this.getNormalizedAst(control_flow_graph_1.CfgVertex.getId(node));
29
30
  if (!astVertex) {
30
31
  return;
31
32
  }