@syntest/cfg-core
Version:
A Control Flow Graph package
108 lines • 3.85 kB
JavaScript
;
/*
* Copyright 2020-2021 Delft University of Technology and SynTest contributors
*
* This file is part of SynTest Framework - SynTest Core.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.CFG = void 0;
const Node_1 = require("./nodes/Node");
class CFG {
constructor() {
this._nodes = [];
this._edges = [];
}
get nodes() {
return this._nodes;
}
set nodes(value) {
this._nodes = value;
}
get edges() {
return this._edges;
}
set edges(value) {
this._edges = value;
}
getRootNodes() {
return this._nodes
.filter((node) => node.type === Node_1.NodeType.Root)
.map((node) => node);
}
getNodeById(nodeId) {
const node = this._nodes.find((node) => node.id == nodeId);
return node;
}
/*
Method return a map that has node ids as keys, and list of pairs as a value.
Each of the pairs in the list of certain node represent a node of a parent as a first value,
and a number that indicates if the edge that connects this two nodes has a defined branch type i.e. weight of the edge
*/
getRotatedAdjacencyList() {
const adjList = new Map();
for (const edge of this._edges) {
if (!adjList.has(edge.from)) {
adjList.set(edge.from, []);
}
if (!adjList.has(edge.to)) {
adjList.set(edge.to, []);
}
adjList.get(edge.to).push({
first: edge.from,
second: edge.branchType !== undefined ? 1 : 0,
});
}
return adjList;
}
findClosestAncestor(from, targets) {
const rotatedAdjList = this.getRotatedAdjacencyList();
const visitedNodeIdSet = new Set([from]);
const searchQueue = [{ first: 0, second: from }];
let current = undefined;
while (searchQueue.length != 0) {
current = searchQueue.shift();
const currentDistance = current.first;
const currentNodeId = current.second;
// get all neigbors of currently considered node
const parentsOfCurrent = rotatedAdjList.get(currentNodeId);
for (const pairOfParent of parentsOfCurrent) {
const nextNodeId = pairOfParent.first;
// ignore if already visited node
if (visitedNodeIdSet.has(nextNodeId)) {
continue;
}
// return if one of targets nodes was found
if (targets.has(nextNodeId)) {
return {
distance: currentDistance + pairOfParent.second,
ancestor: this.getNodeById(nextNodeId),
};
}
// add element to queue and visited nodes to continue search
visitedNodeIdSet.add(nextNodeId);
searchQueue.push({
first: currentDistance + pairOfParent.second,
second: nextNodeId,
});
}
}
return {
distance: -1,
ancestor: null,
};
}
}
exports.CFG = CFG;
//# sourceMappingURL=CFG.js.map