From 8de1230bf97093e56a7c87cd1d82e1c5d280665e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jindra=20Pet=C5=99=C3=ADk?= Date: Mon, 1 Feb 2021 09:37:29 +0100 Subject: [PATCH] Precontinue detector handles do..while properly. --- .../graph/precontinues/DoWhileNode.java | 14 +++ .../GraphPrecontinueDetector.java | 103 +++++++++++++----- .../decompiler/flash/ActionScript2Test.java | 11 +- 3 files changed, 93 insertions(+), 35 deletions(-) create mode 100644 libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/precontinues/DoWhileNode.java diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/precontinues/DoWhileNode.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/precontinues/DoWhileNode.java new file mode 100644 index 000000000..c04edcc4c --- /dev/null +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/precontinues/DoWhileNode.java @@ -0,0 +1,14 @@ +package com.jpexs.decompiler.graph.precontinues; + +/** + * + * @author JPEXS + */ +public class DoWhileNode extends Node { + public Node body; + + @Override + public String toString() { + return "dowhile" + super.toString(); + } +} diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/precontinues/GraphPrecontinueDetector.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/precontinues/GraphPrecontinueDetector.java index 806ab1774..f92b2373b 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/precontinues/GraphPrecontinueDetector.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/precontinues/GraphPrecontinueDetector.java @@ -76,7 +76,6 @@ public class GraphPrecontinueDetector { headNodes.add(partToNode.get(head)); } - boolean changed = true; while (changed) { changed = false; @@ -129,7 +128,14 @@ public class GraphPrecontinueDetector { StringBuilder sb = new StringBuilder(); sb.append("digraph mygraph {\r\n"); for (Node node : allNodes) { - sb.append("node" + node.getId() + "[label=\"" + node.toString() + "\"];\r\n"); + String label = node.toString(); + for (Node n : node.next) { + label += " next " + n.toString(); + } + for (Node p : node.prev) { + label += " prev " + p.toString(); + } + sb.append("node" + node.getId() + "[label=\"" + label + "\"];\r\n"); for (Node n : node.next) { sb.append("node" + node.getId() + "->node" + n.getId() + ";\r\n"); } @@ -189,33 +195,62 @@ public class GraphPrecontinueDetector { Node result = node; - Node bodyNode = null; - Node breakNode = null; - if (node.next.size() == 2 - && node.next.get(0).next.size() == 1 - && node.next.get(0).next.get(0) == node) { - breakNode = node.next.get(1); - bodyNode = node.next.get(0); - } else if (node.next.size() == 2 - && node.next.get(1).next.size() == 1 - && node.next.get(1).next.get(0) == node) { - breakNode = node.next.get(0); - bodyNode = node.next.get(1); - } - - if (bodyNode != null) { - - WhileNode whileNode = new WhileNode(); - bodyNode.parentNode = whileNode; - whileNode.graphPart = node.graphPart; - whileNode.body = bodyNode; - whileNode.body.removeFromGraph(); - whileNode.prev = new ArrayList<>(node.prev); - node.replacePrevs(whileNode); - node.replaceNexts(whileNode); - whileNode.next.add(breakNode); - result = whileNode; + //do..while + if (node.prev.contains(node) && node.next.contains(node) && node.next.size() == 2) { + DoWhileNode doWhileNode = new DoWhileNode(); + doWhileNode.body = node; + doWhileNode.graphPart = node.graphPart; + doWhileNode.prev = new ArrayList<>(node.prev); + for (int i = doWhileNode.prev.size() - 1; i >= 0; i--) { + if (doWhileNode.prev.get(i) == node) { + doWhileNode.prev.remove(i); + } + } + doWhileNode.next = new ArrayList<>(node.next); + for (int i = doWhileNode.next.size() - 1; i >= 0; i--) { + if (doWhileNode.next.get(i) == node) { + doWhileNode.next.remove(i); + } + } + node.replacePrevs(doWhileNode); + node.replaceNexts(doWhileNode); + node.removeFromGraph(); + node.parentNode = doWhileNode; + result = doWhileNode; numWhile.setVal(numWhile.getVal() + 1); + + } else { //while + + Node bodyNode = null; + Node breakNode = null; + if (node.next.size() == 2 + && node.next.get(0).next.size() == 1 + && node.next.get(0).next.get(0) == node + && node.next.get(0).prev.size() == 1) { + breakNode = node.next.get(1); + bodyNode = node.next.get(0); + } else if (node.next.size() == 2 + && node.next.get(1).next.size() == 1 + && node.next.get(1).next.get(0) == node + && node.next.get(1).prev.size() == 1) { + breakNode = node.next.get(0); + bodyNode = node.next.get(1); + } + + if (bodyNode != null) { + + WhileNode whileNode = new WhileNode(); + bodyNode.parentNode = whileNode; + whileNode.graphPart = node.graphPart; + whileNode.body = bodyNode; + whileNode.body.removeFromGraph(); + whileNode.prev = new ArrayList<>(node.prev); + node.replacePrevs(whileNode); + node.replaceNexts(whileNode); + whileNode.next.add(breakNode); + result = whileNode; + numWhile.setVal(numWhile.getVal() + 1); + } } List nexts = new ArrayList<>(result.next); @@ -247,7 +282,19 @@ public class GraphPrecontinueDetector { joinedNode.graphPart = node.graphPart; joinedNode.nodes = nodeList; joinedNode.next = new ArrayList<>(currentNode.next); + for (int i = 0; i < joinedNode.next.size(); i++) { + Node n = joinedNode.next.get(i); + if (n == node) { + joinedNode.next.set(i, joinedNode); + } + } joinedNode.prev = new ArrayList<>(node.prev); + for (int i = 0; i < joinedNode.prev.size(); i++) { + Node n = joinedNode.prev.get(i); + if (n == currentNode) { + joinedNode.prev.set(i, joinedNode); + } + } node.replacePrevs(joinedNode); currentNode.replaceNexts(joinedNode); for (Node n : nodeList) { diff --git a/libsrc/ffdec_lib/test/com/jpexs/decompiler/flash/ActionScript2Test.java b/libsrc/ffdec_lib/test/com/jpexs/decompiler/flash/ActionScript2Test.java index 1fff7833f..5e5a6ef04 100644 --- a/libsrc/ffdec_lib/test/com/jpexs/decompiler/flash/ActionScript2Test.java +++ b/libsrc/ffdec_lib/test/com/jpexs/decompiler/flash/ActionScript2Test.java @@ -954,18 +954,15 @@ public class ActionScript2Test extends ActionScript2TestBase { + "if(_loc1_ == \"b\")\r\n" + "{\r\n" + "trace(\"hi\");\r\n" + + "break;\r\n" + "}\r\n" - + "else if(_loc1_ == \"c\")\r\n" + + "if(_loc1_ == \"c\")\r\n" + "{\r\n" + "trace(\"hello\");\r\n" - + "}\r\n" - + "else\r\n" - + "{\r\n" - + "trace(\"hohoho\");\r\n" - + "continue;\r\n" - + "}\r\n" + "break;\r\n" + "}\r\n" + + "trace(\"hohoho\");\r\n" + + "}\r\n" + "trace(\"after\");\r\n" + "}\r\n" + "function testFunc5()\r\n"