From daa1c2d90abce25dafffb09ed868c5ff298643f9 Mon Sep 17 00:00:00 2001 From: Carlos Galindo Date: Thu, 4 Apr 2019 18:00:16 +0200 Subject: [PATCH] Added support for any continue statements, fixed empty for loops (set condition to true if empty) --- src/main/java/grafos/CFG.java | 46 +++++++++++++++++++++++--- src/main/java/grafos/Visitador.java | 39 +++++++++++++--------- src/test/res/mytest/BasicContinue.java | 17 ++++++++++ 3 files changed, 82 insertions(+), 20 deletions(-) create mode 100644 src/test/res/mytest/BasicContinue.java diff --git a/src/main/java/grafos/CFG.java b/src/main/java/grafos/CFG.java index 8a77bcc..4b39dd6 100644 --- a/src/main/java/grafos/CFG.java +++ b/src/main/java/grafos/CFG.java @@ -17,6 +17,10 @@ public class CFG { private final Map labelMap = new HashMap<>(); private final Map> breakMap = new HashMap<>(); private final Stack> breakStack = new Stack<>(); + private final Map continueMap = new HashMap<>(); + private final Stack continueStack = new Stack<>(); + + private SimpleName lastLabel; private void registerNode(Node stmt) { nodes.add(stmt); @@ -122,14 +126,14 @@ public class CFG { breakStack.push(new LinkedList<>()); } - public void registerBreak(BreakStmt stmt) { - List list; + public void connectBreak(BreakStmt stmt) { + connectTo(stmt); if (stmt.getLabel().isPresent()) { - list = breakMap.get(stmt.getLabel().get()); + breakMap.get(stmt.getLabel().get()).add(stmt); } else { - list = breakStack.peek(); + breakStack.peek().add(stmt); } - list.add(stmt); + clearNode(); } public void endBreakSection(SimpleName name) { @@ -140,6 +144,38 @@ public class CFG { nodeList.addAll(breakStack.pop()); } + public void beginContinueSection(SimpleName name) { + assert lastLabel == null; + lastLabel = name; + } + + public void beginContinueSection(Node node) { + continueStack.push(node); + if (lastLabel != null) { + assert !continueMap.containsKey(lastLabel); + continueMap.put(lastLabel, node); + lastLabel = null; + } + } + + public void connectContinue(ContinueStmt stmt) { + connectTo(stmt); + if (stmt.getLabel().isPresent()) { + connectTo(continueMap.get(stmt.getLabel().get())); + } else { + connectTo(continueStack.peek()); + } + clearNode(); + } + + public void endContinueSection(SimpleName name) { + continueMap.remove(name); + } + + public void endContinueSection() { + continueStack.pop(); + } + public List toStringList(GraphViz gv) { List res = new LinkedList<>(); res.add(gv.start_graph()); diff --git a/src/main/java/grafos/Visitador.java b/src/main/java/grafos/Visitador.java index 9fbd8cf..5f8563e 100755 --- a/src/main/java/grafos/Visitador.java +++ b/src/main/java/grafos/Visitador.java @@ -3,6 +3,7 @@ package grafos; import com.github.javaparser.ast.Node; import com.github.javaparser.ast.NodeList; import com.github.javaparser.ast.body.MethodDeclaration; +import com.github.javaparser.ast.expr.BooleanLiteralExpr; import com.github.javaparser.ast.expr.Expression; import com.github.javaparser.ast.stmt.*; import com.github.javaparser.ast.visitor.VoidVisitorAdapter; @@ -53,7 +54,9 @@ public class Visitador extends VoidVisitorAdapter { @Override public void visit(LabeledStmt n, CFG graph) { graph.beginBreakSection(n.getLabel()); + graph.beginContinueSection(n.getLabel()); super.visit(n, graph); + graph.endContinueSection(n.getLabel()); graph.endBreakSection(n.getLabel()); } @@ -62,11 +65,13 @@ public class Visitador extends VoidVisitorAdapter { Node whileStart = n.getCondition(); graph.beginBlock(n, whileStart); graph.beginBreakSection(); + graph.beginContinueSection(whileStart); graph.connectTo(whileStart); graph.setNextLabel(true); n.getBody().accept(this, graph); graph.connectTo(whileStart); graph.setNextLabel(false); + graph.endContinueSection(); graph.endBreakSection(); graph.endBlock(); } @@ -76,10 +81,12 @@ public class Visitador extends VoidVisitorAdapter { Node condition = n.getCondition(); graph.beginBlock(n, condition); graph.beginBreakSection(); + graph.beginContinueSection(condition); graph.appendNode(condition); n.getBody().accept(this, graph); graph.connectTo(condition); graph.setNextLabel(false); + graph.endContinueSection(); graph.endBreakSection(); graph.endBlock(); } @@ -96,10 +103,12 @@ public class Visitador extends VoidVisitorAdapter { } // Comparison expression // TODO: shortcut conditions (||, &&) - if (n.getCompare().isPresent()) { - graph.connectTo(n.getCompare().get()); - graph.setNextLabel(true); - } + assert n.getTokenRange().isPresent(); + if (!n.getCompare().isPresent()) + n.setCompare(new BooleanLiteralExpr(n.getTokenRange().get(), true)); + graph.beginContinueSection(n.getCompare().get()); + graph.connectTo(n.getCompare().get()); + graph.setNextLabel(true); // Loop body n.getBody().accept(this, graph); // Update expressions @@ -108,14 +117,9 @@ public class Visitador extends VoidVisitorAdapter { graph.connectTo(e); // Connect to comparison expression // Set comparison as last possible statement - if (n.getCompare().isPresent()) { - graph.connectTo(n.getCompare().get()); - graph.setNextLabel(false); - } else { - // TODO: connect last update / end of loop with first element of loop body - // There is no comparison, can't exit the loop TODO implement break and continue as way to exit - graph.clearNode(); - } + graph.connectTo(n.getCompare().get()); + graph.setNextLabel(false); + graph.endContinueSection(); graph.endBreakSection(); graph.endBlock(); } @@ -125,11 +129,13 @@ public class Visitador extends VoidVisitorAdapter { ForeachStmt copy = new ForeachStmt(n.getTokenRange().orElse(null), n.getVariable(), n.getIterable(), new EmptyStmt()); graph.beginBlock(n, copy); graph.beginBreakSection(); + graph.beginContinueSection(copy); graph.connectTo(copy); graph.setNextLabel(true); n.getBody().accept(this, graph); graph.connectTo(copy); graph.setNextLabel(false); + graph.endContinueSection(); graph.endBreakSection(); graph.endBlock(); } @@ -168,9 +174,12 @@ public class Visitador extends VoidVisitorAdapter { @Override public void visit(BreakStmt n, CFG graph) { - graph.connectTo(n, false); - graph.clearNode(); - graph.registerBreak(n); + graph.connectBreak(n); + } + + @Override + public void visit(ContinueStmt n, CFG graph) { + graph.connectContinue(n); } @Override diff --git a/src/test/res/mytest/BasicContinue.java b/src/test/res/mytest/BasicContinue.java new file mode 100644 index 0000000..a55a66b --- /dev/null +++ b/src/test/res/mytest/BasicContinue.java @@ -0,0 +1,17 @@ +package mytest; + +public class BasicContinue { + public static void main(String[] args) { + int x = 0; + bucle: + while (x < 20) { + x++; + for (int y = 0; y < 10; y++) { + if (y == x) continue; + if (y * 2 == x) continue bucle; + } + if (x > 10) continue; + x++; + } + } +}