11cb0ef41Sopenharmony_ciimport { GNode, MINIMUM_EDGE_SEPARATION } from "./node"; 21cb0ef41Sopenharmony_ciimport { Edge } from "./edge"; 31cb0ef41Sopenharmony_ci 41cb0ef41Sopenharmony_ciexport class Graph { 51cb0ef41Sopenharmony_ci nodeMap: Array<GNode>; 61cb0ef41Sopenharmony_ci minGraphX: number; 71cb0ef41Sopenharmony_ci maxGraphX: number; 81cb0ef41Sopenharmony_ci minGraphY: number; 91cb0ef41Sopenharmony_ci maxGraphY: number; 101cb0ef41Sopenharmony_ci maxGraphNodeX: number; 111cb0ef41Sopenharmony_ci maxBackEdgeNumber: number; 121cb0ef41Sopenharmony_ci width: number; 131cb0ef41Sopenharmony_ci height: number; 141cb0ef41Sopenharmony_ci 151cb0ef41Sopenharmony_ci constructor(data: any) { 161cb0ef41Sopenharmony_ci this.nodeMap = []; 171cb0ef41Sopenharmony_ci 181cb0ef41Sopenharmony_ci this.minGraphX = 0; 191cb0ef41Sopenharmony_ci this.maxGraphX = 1; 201cb0ef41Sopenharmony_ci this.minGraphY = 0; 211cb0ef41Sopenharmony_ci this.maxGraphY = 1; 221cb0ef41Sopenharmony_ci this.width = 1; 231cb0ef41Sopenharmony_ci this.height = 1; 241cb0ef41Sopenharmony_ci 251cb0ef41Sopenharmony_ci data.nodes.forEach((jsonNode: any) => { 261cb0ef41Sopenharmony_ci this.nodeMap[jsonNode.id] = new GNode(jsonNode.nodeLabel); 271cb0ef41Sopenharmony_ci }); 281cb0ef41Sopenharmony_ci 291cb0ef41Sopenharmony_ci data.edges.forEach((e: any) => { 301cb0ef41Sopenharmony_ci const t = this.nodeMap[e.target]; 311cb0ef41Sopenharmony_ci const s = this.nodeMap[e.source]; 321cb0ef41Sopenharmony_ci const newEdge = new Edge(t, e.index, s, e.type); 331cb0ef41Sopenharmony_ci t.inputs.push(newEdge); 341cb0ef41Sopenharmony_ci s.outputs.push(newEdge); 351cb0ef41Sopenharmony_ci if (e.type == 'control') { 361cb0ef41Sopenharmony_ci // Every source of a control edge is a CFG node. 371cb0ef41Sopenharmony_ci s.cfg = true; 381cb0ef41Sopenharmony_ci } 391cb0ef41Sopenharmony_ci }); 401cb0ef41Sopenharmony_ci 411cb0ef41Sopenharmony_ci } 421cb0ef41Sopenharmony_ci 431cb0ef41Sopenharmony_ci *nodes(p = (n: GNode) => true) { 441cb0ef41Sopenharmony_ci for (const node of this.nodeMap) { 451cb0ef41Sopenharmony_ci if (!node || !p(node)) continue; 461cb0ef41Sopenharmony_ci yield node; 471cb0ef41Sopenharmony_ci } 481cb0ef41Sopenharmony_ci } 491cb0ef41Sopenharmony_ci 501cb0ef41Sopenharmony_ci *filteredEdges(p: (e: Edge) => boolean) { 511cb0ef41Sopenharmony_ci for (const node of this.nodes()) { 521cb0ef41Sopenharmony_ci for (const edge of node.inputs) { 531cb0ef41Sopenharmony_ci if (p(edge)) yield edge; 541cb0ef41Sopenharmony_ci } 551cb0ef41Sopenharmony_ci } 561cb0ef41Sopenharmony_ci } 571cb0ef41Sopenharmony_ci 581cb0ef41Sopenharmony_ci forEachEdge(p: (e: Edge) => void) { 591cb0ef41Sopenharmony_ci for (const node of this.nodeMap) { 601cb0ef41Sopenharmony_ci if (!node) continue; 611cb0ef41Sopenharmony_ci for (const edge of node.inputs) { 621cb0ef41Sopenharmony_ci p(edge); 631cb0ef41Sopenharmony_ci } 641cb0ef41Sopenharmony_ci } 651cb0ef41Sopenharmony_ci } 661cb0ef41Sopenharmony_ci 671cb0ef41Sopenharmony_ci redetermineGraphBoundingBox(showTypes: boolean): [[number, number], [number, number]] { 681cb0ef41Sopenharmony_ci this.minGraphX = 0; 691cb0ef41Sopenharmony_ci this.maxGraphNodeX = 1; 701cb0ef41Sopenharmony_ci this.maxGraphX = undefined; // see below 711cb0ef41Sopenharmony_ci this.minGraphY = 0; 721cb0ef41Sopenharmony_ci this.maxGraphY = 1; 731cb0ef41Sopenharmony_ci 741cb0ef41Sopenharmony_ci for (const node of this.nodes()) { 751cb0ef41Sopenharmony_ci if (!node.visible) { 761cb0ef41Sopenharmony_ci continue; 771cb0ef41Sopenharmony_ci } 781cb0ef41Sopenharmony_ci 791cb0ef41Sopenharmony_ci if (node.x < this.minGraphX) { 801cb0ef41Sopenharmony_ci this.minGraphX = node.x; 811cb0ef41Sopenharmony_ci } 821cb0ef41Sopenharmony_ci if ((node.x + node.getTotalNodeWidth()) > this.maxGraphNodeX) { 831cb0ef41Sopenharmony_ci this.maxGraphNodeX = node.x + node.getTotalNodeWidth(); 841cb0ef41Sopenharmony_ci } 851cb0ef41Sopenharmony_ci if ((node.y - 50) < this.minGraphY) { 861cb0ef41Sopenharmony_ci this.minGraphY = node.y - 50; 871cb0ef41Sopenharmony_ci } 881cb0ef41Sopenharmony_ci if ((node.y + node.getNodeHeight(showTypes) + 50) > this.maxGraphY) { 891cb0ef41Sopenharmony_ci this.maxGraphY = node.y + node.getNodeHeight(showTypes) + 50; 901cb0ef41Sopenharmony_ci } 911cb0ef41Sopenharmony_ci } 921cb0ef41Sopenharmony_ci 931cb0ef41Sopenharmony_ci this.maxGraphX = this.maxGraphNodeX + 941cb0ef41Sopenharmony_ci this.maxBackEdgeNumber * MINIMUM_EDGE_SEPARATION; 951cb0ef41Sopenharmony_ci 961cb0ef41Sopenharmony_ci this.width = this.maxGraphX - this.minGraphX; 971cb0ef41Sopenharmony_ci this.height = this.maxGraphY - this.minGraphY; 981cb0ef41Sopenharmony_ci 991cb0ef41Sopenharmony_ci const extent: [[number, number], [number, number]] = [ 1001cb0ef41Sopenharmony_ci [this.minGraphX - this.width / 2, this.minGraphY - this.height / 2], 1011cb0ef41Sopenharmony_ci [this.maxGraphX + this.width / 2, this.maxGraphY + this.height / 2] 1021cb0ef41Sopenharmony_ci ]; 1031cb0ef41Sopenharmony_ci 1041cb0ef41Sopenharmony_ci return extent; 1051cb0ef41Sopenharmony_ci } 1061cb0ef41Sopenharmony_ci 1071cb0ef41Sopenharmony_ci} 108