diff --git a/ICSharpCode.Decompiler/Ast/AstBuilder.cs b/ICSharpCode.Decompiler/Ast/AstBuilder.cs index 5c105f0f2..494d8ec40 100644 --- a/ICSharpCode.Decompiler/Ast/AstBuilder.cs +++ b/ICSharpCode.Decompiler/Ast/AstBuilder.cs @@ -19,11 +19,11 @@ namespace Decompiler { for (int i = 0; i < 4; i++) { if (Options.ReduceAstJumps) { - //astCompileUnit.AcceptVisitor(new Transforms.Ast.RemoveGotos(), null); - //astCompileUnit.AcceptVisitor(new Transforms.Ast.RemoveDeadLabels(), null); + astCompileUnit.AcceptVisitor(new Transforms.Ast.RemoveGotos(), null); + astCompileUnit.AcceptVisitor(new Transforms.Ast.RemoveDeadLabels(), null); } if (Options.ReduceAstLoops) { - //astCompileUnit.AcceptVisitor(new Transforms.Ast.RestoreLoop(), null); + astCompileUnit.AcceptVisitor(new Transforms.Ast.RestoreLoop(), null); } if (Options.ReduceAstOther) { astCompileUnit.AcceptVisitor(new Transforms.Ast.RemoveEmptyElseBody(), null); diff --git a/ICSharpCode.Decompiler/Ast/Transforms/RemoveDeadLabels.cs b/ICSharpCode.Decompiler/Ast/Transforms/RemoveDeadLabels.cs new file mode 100644 index 000000000..b8f65771a --- /dev/null +++ b/ICSharpCode.Decompiler/Ast/Transforms/RemoveDeadLabels.cs @@ -0,0 +1,56 @@ +using System; +using System.Collections.Generic; +using ICSharpCode.NRefactory.CSharp; + +namespace Decompiler.Transforms.Ast +{ + public class RemoveDeadLabels : DepthFirstAstVisitor + { + List usedLabels = new List(); + bool collectingUsedLabels; + + public override object VisitConstructorDeclaration(ConstructorDeclaration constructorDeclaration, object data) + { + collectingUsedLabels = true; + base.VisitConstructorDeclaration(constructorDeclaration, data); + collectingUsedLabels = false; + base.VisitConstructorDeclaration(constructorDeclaration, data); + return null; + } + + public override object VisitMethodDeclaration(MethodDeclaration methodDeclaration, object data) + { + collectingUsedLabels = true; + base.VisitMethodDeclaration(methodDeclaration, data); + collectingUsedLabels = false; + base.VisitMethodDeclaration(methodDeclaration, data); + return null; + } + + public override object VisitAccessor(Accessor accessor, object data) + { + collectingUsedLabels = true; + base.VisitAccessor(accessor, data); + collectingUsedLabels = false; + return base.VisitAccessor(accessor, data); + } + + public override object VisitGotoStatement(GotoStatement gotoStatement, object data) + { + if (collectingUsedLabels) { + usedLabels.Add(gotoStatement.Label); + } + return null; + } + + public override object VisitLabelStatement(LabelStatement labelStatement, object data) + { + if (!collectingUsedLabels) { + if (!usedLabels.Contains(labelStatement.Label)) { + labelStatement.Remove(); + } + } + return null; + } + } +} diff --git a/ICSharpCode.Decompiler/Ast/Transforms/RemoveGotos.cs b/ICSharpCode.Decompiler/Ast/Transforms/RemoveGotos.cs index abb56dcb3..d45f5d121 100644 --- a/ICSharpCode.Decompiler/Ast/Transforms/RemoveGotos.cs +++ b/ICSharpCode.Decompiler/Ast/Transforms/RemoveGotos.cs @@ -1,16 +1,15 @@ using System; using System.Collections.Generic; - +using System.Linq; using ICSharpCode.NRefactory.CSharp; namespace Decompiler.Transforms.Ast { - /* public class RemoveGotos: DepthFirstAstVisitor { - Stack enteredLoops = new Stack(); + Stack enteredLoops = new Stack(); - Statement CurrentLoop { + ForStatement CurrentLoop { get { if (enteredLoops.Count > 0) { return enteredLoops.Peek(); @@ -28,27 +27,20 @@ namespace Decompiler.Transforms.Ast return null; } - public override object VisitWhileStatement(WhileStatement whileStatement, object data) - { - enteredLoops.Push(whileStatement); - base.VisitWhileStatement(whileStatement, data); - enteredLoops.Pop(); - return null; - } +// public override object VisitWhileStatement(WhileStatement whileStatement, object data) +// { +// enteredLoops.Push(whileStatement); +// base.VisitWhileStatement(whileStatement, data); +// enteredLoops.Pop(); +// return null; +// } public override object VisitBlockStatement(BlockStatement blockStatement, object data) { base.VisitBlockStatement(blockStatement, data); // Remove redundant jump at the end of block - INode lastStmt = blockStatement.Children.Last; - // End of while loop - if (lastStmt is ContinueStatement && - blockStatement.Parent is DoLoopStatement) - { - lastStmt.Remove(); - return null; - } + AstNode lastStmt = blockStatement.Children.LastOrDefault(); // End of for loop if (lastStmt is ContinueStatement && blockStatement.Parent is ForStatement) @@ -74,7 +66,7 @@ namespace Decompiler.Transforms.Ast { if (statement == null) throw new ArgumentNullException(); - Statement next = (Statement)statement.Next(); + Statement next = (Statement)statement.NextSibling; if (next != null) { return EnterBlockStatement(next); @@ -104,12 +96,12 @@ namespace Decompiler.Transforms.Ast // Iterator; Condition; Body if (statement is ForStatement) { ForStatement forLoop = statement as ForStatement; - if (forLoop.Iterator.Count > 0) { - return forLoop.Iterator[0]; + if (forLoop.Iterators.Any()) { + return forLoop.Iterators.First(); } else if (!forLoop.Condition.IsNull) { return forLoop.Condition; } else { - return EnterBlockStatement((Statement)forLoop.EmbeddedStatement.Children.First); + return EnterBlockStatement((Statement)forLoop.EmbeddedStatement.FirstChild); } } @@ -124,14 +116,12 @@ namespace Decompiler.Transforms.Ast // For loop starts as follows: Initializers; Condition; Body if (statement is ForStatement) { ForStatement forLoop = statement as ForStatement; - if (forLoop.Initializers.Count > 0) { - return forLoop.Initializers[0]; + if (forLoop.Initializers.Any()) { + return forLoop.Initializers.First(); } else if (!forLoop.Condition.IsNull) { return forLoop.Condition; - } else if (forLoop.EmbeddedStatement is BlockStatement && - forLoop.EmbeddedStatement.Children.Count > 0) { - statement = (Statement)forLoop.EmbeddedStatement.Children.First; - return EnterBlockStatement(statement); // Simplify again + } else if (forLoop.EmbeddedStatement.Children.FirstOrDefault() is Statement) { + return EnterBlockStatement((Statement)forLoop.EmbeddedStatement.FirstChild); // Simplify again } } @@ -141,11 +131,11 @@ namespace Decompiler.Transforms.Ast public override object VisitGotoStatement(GotoStatement gotoStatement, object data) { // Remove redundant goto which goes to a label that imideately follows - INode fallthoughTarget = GetNextStatement(gotoStatement); + AstNode fallthoughTarget = GetNextStatement(gotoStatement); while(true) { if (fallthoughTarget is LabelStatement) { if ((fallthoughTarget as LabelStatement).Label == gotoStatement.Label) { - RemoveCurrentNode(); + gotoStatement.Remove(); return null; } else { fallthoughTarget = GetNextStatement((LabelStatement)fallthoughTarget); @@ -158,10 +148,10 @@ namespace Decompiler.Transforms.Ast // Replace goto with 'break' // Break statement moves right outside the looop if (CurrentLoop != null) { - INode breakTarget = GetNextStatement(CurrentLoop); + AstNode breakTarget = GetNextStatement(CurrentLoop); if ((breakTarget is LabelStatement) && (breakTarget as LabelStatement).Label == gotoStatement.Label) { - ReplaceCurrentNode(new BreakStatement()); + gotoStatement.ReplaceWith(new BreakStatement()); return null; } } @@ -170,24 +160,24 @@ namespace Decompiler.Transforms.Ast // Continue statement which moves at the very end of loop if (CurrentLoop != null && (CurrentLoop.EmbeddedStatement is BlockStatement) && - ((CurrentLoop.EmbeddedStatement as BlockStatement).Children.Last as LabelStatement) != null && - ((CurrentLoop.EmbeddedStatement as BlockStatement).Children.Last as LabelStatement).Label == gotoStatement.Label) { - ReplaceCurrentNode(new ContinueStatement()); + ((CurrentLoop.EmbeddedStatement as BlockStatement).LastChild as LabelStatement) != null && + ((CurrentLoop.EmbeddedStatement as BlockStatement).LastChild as LabelStatement).Label == gotoStatement.Label) { + gotoStatement.ReplaceWith(new ContinueStatement()); return null; } // Replace goto with 'continue' // Continue statement which moves at the very start of for loop if (CurrentLoop != null) { - INode continueTarget = ExitBlockStatement(CurrentLoop); // The start of the loop + AstNode continueTarget = ExitBlockStatement(CurrentLoop); // The start of the loop if ((continueTarget is LabelStatement) && (continueTarget as LabelStatement).Label == gotoStatement.Label) { - ReplaceCurrentNode(new ContinueStatement()); + gotoStatement.ReplaceWith(new ContinueStatement()); return null; } } return null; } - }*/ + } } diff --git a/ICSharpCode.Decompiler/Ast/Transforms/RestoreLoop.cs b/ICSharpCode.Decompiler/Ast/Transforms/RestoreLoop.cs index 4608497cc..ccd9f14fd 100644 --- a/ICSharpCode.Decompiler/Ast/Transforms/RestoreLoop.cs +++ b/ICSharpCode.Decompiler/Ast/Transforms/RestoreLoop.cs @@ -1,10 +1,9 @@ -using System; - -using ICSharpCode.NRefactory.CSharp; +using System; +using System.Linq; +using ICSharpCode.NRefactory.CSharp; namespace Decompiler.Transforms.Ast { - /* public class RestoreLoop: DepthFirstAstVisitor { public override object VisitForStatement(ForStatement forStatement, object data) @@ -12,25 +11,25 @@ namespace Decompiler.Transforms.Ast base.VisitForStatement(forStatement, data); // Restore loop initializer - if (forStatement.Initializers.Count == 0) { - LocalVariableDeclaration varDeclr = forStatement.Previous() as LocalVariableDeclaration; + if (!forStatement.Initializers.Any()) { + VariableDeclarationStatement varDeclr = forStatement.PrevSibling as VariableDeclarationStatement; if (varDeclr != null) { varDeclr.ReplaceWith(Statement.Null); - forStatement.Initializers.Add(varDeclr); + forStatement.Initializers = new Statement[] { varDeclr }; } } // Restore loop condition if (forStatement.Condition.IsNull && - forStatement.EmbeddedStatement.Children.Count >= 3) + forStatement.EmbeddedStatement.Children.Count() >= 3) { - IfElseStatement condition = forStatement.EmbeddedStatement.Children[0] as IfElseStatement; - BreakStatement breakStmt = forStatement.EmbeddedStatement.Children[1] as BreakStatement; - LabelStatement label = forStatement.EmbeddedStatement.Children[2] as LabelStatement; + IfElseStatement condition = forStatement.EmbeddedStatement.Children.First() as IfElseStatement; + BreakStatement breakStmt = forStatement.EmbeddedStatement.Children.Skip(1).First() as BreakStatement; + LabelStatement label = forStatement.EmbeddedStatement.Children.Skip(2).First() as LabelStatement; if (condition != null && breakStmt != null && label != null && - condition.TrueStatement.Count == 1) + condition.TrueStatement.Children.Count() == 1) { - GotoStatement gotoStmt = condition.TrueStatement[0] as GotoStatement; + GotoStatement gotoStmt = condition.TrueStatement.FirstChild as GotoStatement; if (gotoStmt != null && gotoStmt.Label == label.Label) { condition.Remove(); breakStmt.Remove(); @@ -41,34 +40,34 @@ namespace Decompiler.Transforms.Ast // Restore loop condition (version 2) if (forStatement.Condition.IsNull) { - IfElseStatement condition = forStatement.EmbeddedStatement.Children.First as IfElseStatement; + IfElseStatement condition = forStatement.EmbeddedStatement.FirstChild as IfElseStatement; if (condition != null && - condition.TrueStatement.Count == 1 && - condition.TrueStatement[0] is BlockStatement && - condition.TrueStatement[0].Children.Count == 1 && - condition.TrueStatement[0].Children.First is BreakStatement && - condition.FalseStatement.Count == 1 && - condition.FalseStatement[0] is BlockStatement && - condition.FalseStatement[0].Children.Count == 0) + condition.TrueStatement.Children.Any() && + condition.TrueStatement.FirstChild is BlockStatement && + condition.TrueStatement.Children.Count() == 1 && + condition.TrueStatement.FirstChild.FirstChild is BreakStatement && + condition.FalseStatement.Children.Any() && + condition.FalseStatement.FirstChild is BlockStatement && + condition.FalseStatement.Children.Count() == 0) { condition.Remove(); - forStatement.Condition = new UnaryOperatorExpression(condition.Condition, UnaryOperatorType.Not); + forStatement.Condition = new UnaryOperatorExpression() { Expression = condition.Condition, Operator = UnaryOperatorType.Not }; } } // Restore loop iterator - if (forStatement.EmbeddedStatement.Children.Count > 0 && - forStatement.Iterator.Count == 0) + if (forStatement.EmbeddedStatement.Children.Any() && + !forStatement.Iterators.Any()) { - ExpressionStatement lastStmt = forStatement.EmbeddedStatement.Children.Last as ExpressionStatement; + ExpressionStatement lastStmt = forStatement.EmbeddedStatement.LastChild as ExpressionStatement; if (lastStmt != null && (lastStmt.Expression is AssignmentExpression || lastStmt.Expression is UnaryOperatorExpression)) { lastStmt.Remove(); - forStatement.Iterator.Add(lastStmt); + forStatement.Iterators = new Statement[] { lastStmt }; } } return null; } - }*/ + } } diff --git a/ICSharpCode.Decompiler/ICSharpCode.Decompiler.csproj b/ICSharpCode.Decompiler/ICSharpCode.Decompiler.csproj index a0ed6defa..830d69e9d 100644 --- a/ICSharpCode.Decompiler/ICSharpCode.Decompiler.csproj +++ b/ICSharpCode.Decompiler/ICSharpCode.Decompiler.csproj @@ -57,6 +57,7 @@ +