Navigation
Synopsis Visualize Pico Control Flow Graphs.
Examples
module demo::lang::Pico::Visualize

import Prelude;
import vis::Figure;
import vis::KeySym;

import demo::lang::Pico::Abstract;
import demo::lang::Pico::ControlFlow;

//  Convert expressions into text

str make(natCon(int N)) = "<N>";
str make(strCon(str S)) = S;
str make(demo::lang::Pico::Abstract::id(PicoId Id)) = Id;
str make(add(EXP E1, EXP E2)) = "<make(E1)> + <make(E2)>";
str make(sub(EXP E1, EXP E2)) = "<make(E1)> - <make(E2)>";
str make(conc(EXP E1, EXP E2)) = "<make(E1)> || <make(E2)>";

//  Add an editor to a node

FProperty editIt(CFNode n) =
   (n has location) ? onMouseDown(bool (int butnr, map[KeyModifier,bool] modifiers){ edit(n.location,[]); return true;})
                    : onMouseDown(bool (int butnr, map[KeyModifier,bool] modifiers) {return false;});
        
//  Visualize one CFG node

Figure visNode(CFNode n:entry(loc location)) = 
       box(text("ENTRY"), vis::Figure::id(getId(n)), fillColor("red"), gap(4));

Figure visNode(CFNode n:exit()) = 
       box(text("EXIT"),  vis::Figure::id(getId(n)), fillColor("grey"), gap(4));

Figure visNode(CFNode n:choice(loc location, EXP exp)) = 
       ellipse(text(make(exp)),  vis::Figure::id(getId(n)), fillColor("yellow"), gap(8), editIt(n));

Figure visNode(CFNode n:statement(loc location, asgStat(PicoId Id, EXP Exp))) =
        box(text("<Id> := <make(Exp)>"),  vis::Figure::id(getId(n)), gap(8), editIt(n));

//  Define the id for each CFG node

str getId(entry(loc location)) = "ENTRY";
str getId(exit()) = "EXIT";
default str getId(CFNode n) = "<n.location>";

//  Visualize a complete CFG

public Figure visCFG(rel[CFNode, CFNode] CFGGraph){
       nodeSet = {};
       edges = [];
       for(< CFNode cf1, CFNode cf2> <- CFGGraph){
           nodeSet += {cf1, cf2};
           edges += edge(getId(cf1), getId(cf2), toArrow(triangle(5, fillColor("black"))));
       }
       nodes = [visNode(n) | n <- nodeSet];
       return graph(nodes, edges, hint("layered"), gap(20));
}
  • We want to include the text of expressions in the relevant Figure nodes, this is achieved by make ()
  • An editor property is attached to each Figure node (): clicking on the node opens an editor for the corresponding file.
  • visNode implements the visualization per CFG node ().
  • Since Figure nodes in a visual graph need an id property, we define here a scheme to associate unique identifiers to each Figure node ().
  • The complete visualization of a CFG is implemented by visCFG (): it gets the CFG hraph as arguments and then
    • creates all Figure edges,
    • creates all Figure nodes,
    • returns a Figure graph.
Let's now apply this:
import demo::lang::Pico::ControlFlow;
import demo::lang::Pico::Visualize;
CFG = cflowProgram("begin declare n : natural, s : string; n := 10; s := \"a\"; while n do s := s + \"a\"; n := n - 1 od end");
render(visCFG(CFG.graph));
The resulting visualization looks like this:

Control flow graph
Is this page unclear, or have you spotted an error? Please add a comment below and help us to improve it. For all other questions and remarks, visit ask.rascal-mpl.org.