diff --git a/reusablecfg/src/main/jastadd/PrintCfg.jrag b/reusablecfg/src/main/jastadd/PrintCfg.jrag index 9ee8b3613aa65c75c15038ec4a73f8a9548e3adb..41c32a70bfc4c8e1b32e6913f780fb93d59ac5fc 100644 --- a/reusablecfg/src/main/jastadd/PrintCfg.jrag +++ b/reusablecfg/src/main/jastadd/PrintCfg.jrag @@ -24,11 +24,31 @@ import java.util.Queue; /** Helper attributes used to print a CFG in dot graph format. */ aspect PrintCfg { - @Override - public String CfgNode.toString() { - return name(); +// @Override +// public String CfgNode.toString() { +// return name(); +// } + + syn String CFG.prettyPrint() { + StringBuilder sb = new StringBuilder(); + for (CfgNode cfgNode : getCfgNodeList()) { + sb.append(cfgNode.prettyPrint()); + } + return sb.toString(); } + syn String CfgNode.prettyPrint() { + StringBuilder sb = new StringBuilder(); + sb.append("Node ").append(name()).append(" for\n"); + sb.append(getStmt().prettyPrint()).append("\n"); + for (CfgNode succ : getSuccessorList()) { + sb.append("| ").append(name()).append(" -succ-> ").append(succ.name()).append("\n"); + } + return sb.toString(); + } + + // ======================== old implementation below ======================== + public void BodyDecl.printReverseCfg() { entry().initPredecessors(); System.out.println("digraph " + graphName() + " {"); @@ -104,7 +124,7 @@ aspect PrintCfg { eq CfgException.dotAttributes() = " [label=\"" + name() + "\",shape=box]"; eq CfgMarker.dotAttributes() = " [label=\"" + name() + "\",shape=box]"; - syn String CfgNode.name() = "a node"; + syn String CfgNode.name() = "CfgNode@" + hashCode(); eq CfgBranch.name() = branchLabel(); eq CfgEntry.name() = "entry"; eq CfgExit.name() = "exit"; diff --git a/reusablecfg/src/main/jastadd/ReusableCfg.jrag b/reusablecfg/src/main/jastadd/ReusableCfg.jrag index 791cf0297d1b35c2057af0e0bf848f44cfb7bb42..afe745ed6a497dc2d9279cbcf2fb105fbcea0104 100644 --- a/reusablecfg/src/main/jastadd/ReusableCfg.jrag +++ b/reusablecfg/src/main/jastadd/ReusableCfg.jrag @@ -1,29 +1,29 @@ aspect ReusableCfg { - syn CfgNode BodyDecl.emptyCFG() = new CfgNode(); + syn CFG BodyDecl.emptyCFG() = new CFG(); /** * Get the relational NTA of the CFG. Empty by default. */ - syn CfgNode BodyDecl.reusableCFG() = emptyCFG(); + syn CFG BodyDecl.reusableCFG() = emptyCFG(); eq MethodDecl.reusableCFG() = hasBlock() ? getBlock().buildReusableCFG() : emptyCFG(); eq ConstructorDecl.reusableCFG() = getBlock().buildReusableCFG(); /** * Build the relational NTA of the CFG for a Block. */ - syn lazy CfgNode Block.buildReusableCFG() { -// CfgNode result = entry(); // TODO alternative: take first expression - CfgNode result = new CfgNode(); + syn lazy CFG Block.buildReusableCFG() { + CFG result = new CFG(); if (getNumStmt() == 0) { - // dangling link to a stmt :( return result; } Map<Stmt, CfgNode> cfgNodes = new HashMap<>(); +// Stmt first = entry(); // TODO alternative: take first expression Stmt first = getStmt(0); - result.setStmt(first); - cfgNodes.put(first, result); + CfgNode cfgNodeForFirst = first.cfgMakeCfgNode(); + result.addCfgNode(cfgNodeForFirst); + cfgNodes.put(first, cfgNodeForFirst); Map<CfgNode, Stmt> todo = new HashMap<>(); - first.cfgSuccessors().forEach(succ -> todo.put(result, succ)); + first.cfgSuccessors().forEach(succ -> todo.put(cfgNodeForFirst, succ)); while (!todo.isEmpty()) { // Stmt current = todo.pop(); // this should be an tuple (node, successor). to set the relation CfgNode cfgNodeForPredecessor = todo.entrySet().iterator().next().getKey(); @@ -36,6 +36,7 @@ aspect ReusableCfg { } else { cfgNodeForCurrent = current.cfgMakeCfgNode(); cfgNodes.put(current, cfgNodeForCurrent); + result.addCfgNode(cfgNodeForCurrent); // add successors to be inspected current.cfgSuccessors().forEach(succ -> todo.put(cfgNodeForCurrent, succ)); } @@ -45,8 +46,15 @@ aspect ReusableCfg { return result; } - syn CfgNode Stmt.cfgMakeCfgNode() = null; // TODO implement - syn Set<Stmt> Stmt.cfgSuccessors() = null; // TODO implement + // TODO implement + syn CfgNode Stmt.cfgMakeCfgNode() { + CfgNode result = new CfgNode(); + result.setStmt(this); + return result; + } + syn Set<Stmt> Stmt.cfgSuccessors() = Collections.emptySet(); // TODO implement + + eq IfStmt.cfgSuccessors() = hasElse() ? smallSet(getThen(), getElse()) : Collections.singleton(getThen()); // ======================== old implementation below ======================== diff --git a/reusablecfg/src/main/java/de/tudresden/inf/st/reusablecfg/PrintCfg.java b/reusablecfg/src/main/java/de/tudresden/inf/st/reusablecfg/PrintCfg.java index eecee6cefc2670436958e60ddc35e75aa6ee9e80..3a96404e1eb29f90b59a341744d29e2f78b2ebb0 100644 --- a/reusablecfg/src/main/java/de/tudresden/inf/st/reusablecfg/PrintCfg.java +++ b/reusablecfg/src/main/java/de/tudresden/inf/st/reusablecfg/PrintCfg.java @@ -15,10 +15,7 @@ */ package de.tudresden.inf.st.reusablecfg; -import org.extendj.ast.BodyDecl; -import org.extendj.ast.CompilationUnit; -import org.extendj.ast.Program; -import org.extendj.ast.TypeDecl; +import org.extendj.ast.*; import org.extendj.parser.JavaParser; import java.io.FileInputStream; @@ -56,10 +53,10 @@ public class PrintCfg { unit = program.getCompilationUnit(0); for (TypeDecl type : unit.getTypeDeclList()) { for (BodyDecl bd : type.getBodyDeclList()) { - if (reverse) { - bd.printReverseCfg(); - } else { - bd.printCfg(); + CFG cfg = bd.reusableCFG(); + System.out.println(cfg.prettyPrint()); + if (cfg.getNumCfgNode() == 0) { + System.out.println("No nodes in the CFG for '" + path + "'!"); } } }