diff --git a/Decompiler.csproj b/Decompiler.csproj index 0e5aa019b..b62aa1fa6 100644 --- a/Decompiler.csproj +++ b/Decompiler.csproj @@ -66,6 +66,7 @@ + diff --git a/src/AstBuilder.cs b/src/AstBuilder.cs index 36bedee71..94d86d32f 100644 --- a/src/AstBuilder.cs +++ b/src/AstBuilder.cs @@ -28,6 +28,8 @@ namespace Decompiler astCompileUnit.AcceptVisitor(new Transforms.Ast.RemoveDeadLabels(), null); astCompileUnit.AcceptVisitor(new Transforms.Ast.SimplifyTypeReferences(), null); astCompileUnit.AcceptVisitor(new Transforms.Ast.RemoveEmptyElseBody(), null); + astCompileUnit.AcceptVisitor(new Transforms.Ast.RestoreLoop(), null); + astCompileUnit.AcceptVisitor(new Transforms.Ast.RemoveDeadLabels(), null); astCompileUnit.AcceptVisitor(csOutVisitor, null); diff --git a/src/AstMetodBodyBuilder.cs b/src/AstMetodBodyBuilder.cs index bb5cb9ff0..8cf8cc2f2 100644 --- a/src/AstMetodBodyBuilder.cs +++ b/src/AstMetodBodyBuilder.cs @@ -86,11 +86,11 @@ namespace Decompiler } else if (node is Loop) { Ast.MyBlockStatement blockStatement = new Ast.MyBlockStatement(); blockStatement.Children.AddRange(TransformNodes(node.Childs)); - yield return new Ast.DoLoopStatement( - new Ast.PrimitiveExpression(true, true.ToString()), - blockStatement, - ConditionType.While, - ConditionPosition.Start + yield return new Ast.ForStatement( + null, + null, + null, + blockStatement ); } else if (node is Block) { foreach(Ast.INode inode in TransformNodes(node.Childs)) { diff --git a/src/Transforms/Ast/RemoveGotos.cs b/src/Transforms/Ast/RemoveGotos.cs index cea72cfdb..1062f1bfb 100644 --- a/src/Transforms/Ast/RemoveGotos.cs +++ b/src/Transforms/Ast/RemoveGotos.cs @@ -13,13 +13,20 @@ namespace Decompiler.Transforms.Ast // Remove redundant jump at the end of block INode lastStmt = blockStatement.Children[blockStatement.Children.Count - 1]; - // End of loop + // End of while loop if (lastStmt is ContinueStatement && blockStatement.Parent is DoLoopStatement) { blockStatement.Children.Remove(lastStmt); return null; } + // End of for loop + if (lastStmt is ContinueStatement && + blockStatement.Parent is ForStatement) + { + blockStatement.Children.Remove(lastStmt); + return null; + } // End of method if (lastStmt is ReturnStatement && blockStatement.Parent is MethodDeclaration && diff --git a/src/Transforms/Ast/RestoreLoop.cs b/src/Transforms/Ast/RestoreLoop.cs new file mode 100644 index 000000000..77f8a8c6e --- /dev/null +++ b/src/Transforms/Ast/RestoreLoop.cs @@ -0,0 +1,38 @@ +using System; + +using Ast = ICSharpCode.NRefactory.Ast; +using ICSharpCode.NRefactory.Ast; +using ICSharpCode.NRefactory.Visitors; + +namespace Decompiler.Transforms.Ast +{ + public class RestoreLoop: AbstractAstTransformer + { + public override object VisitForStatement(ForStatement forStatement, object data) + { + base.VisitForStatement(forStatement, data); + + if (forStatement.Condition.IsNull && + forStatement.EmbeddedStatement.Children.Count >= 3) + { + IfElseStatement condition = forStatement.EmbeddedStatement.Children[0] as IfElseStatement; + BreakStatement breakStmt = forStatement.EmbeddedStatement.Children[1] as BreakStatement; + MyLabelStatement label = forStatement.EmbeddedStatement.Children[2] as MyLabelStatement; + if (condition != null && + breakStmt != null && + label != null && + condition.TrueStatement.Count == 1) + { + MyGotoStatement gotoStmt = condition.TrueStatement[0] as MyGotoStatement; + if (gotoStmt != null && gotoStmt.NodeLabel == label.NodeLabel) { + forStatement.EmbeddedStatement.Children.RemoveAt(0); + forStatement.EmbeddedStatement.Children.RemoveAt(0); + gotoStmt.NodeLabel.ReferenceCount--; + forStatement.Condition = condition.Condition; + } + } + } + return null; + } + } +}