Browse Source

Splitted the next statement finding algorithm to several reusable parts.

pull/1/head^2
David Srbecký 18 years ago
parent
commit
5b997bd44d
  1. 121
      src/Transforms/Ast/RemoveGotos.cs

121
src/Transforms/Ast/RemoveGotos.cs

@ -64,24 +64,11 @@ namespace Decompiler.Transforms.Ast @@ -64,24 +64,11 @@ namespace Decompiler.Transforms.Ast
lastStmt.Remove();
return null;
}
// End of if body
if (lastStmt is GotoStatement &&
blockStatement.Parent is IfElseStatement)
{
LabelStatement nextNodeAsLabel = blockStatement.Parent.Next() as LabelStatement;
if (nextNodeAsLabel != null) {
if (nextNodeAsLabel.Label == ((GotoStatement)lastStmt).Label) {
lastStmt.Remove();
return null;
}
}
}
return null;
}
// Gets a next fall though statement, entering and exiting code blocks
// It does not matter what the current statement is
// Get the next statement that will be executed after this one
// May return null
public static INode GetNextStatement(Statement statement)
{
@ -89,48 +76,65 @@ namespace Decompiler.Transforms.Ast @@ -89,48 +76,65 @@ namespace Decompiler.Transforms.Ast
Statement next = (Statement)statement.Next();
// Exit a block of code
if (next == null) {
// When an 'if' body is finished the execution continues with the
// next statement after the 'if' statement
if (statement.Parent is BlockStatement &&
statement.Parent.Parent is IfElseStatement) {
return GetNextStatement((Statement)statement.Parent.Parent);
if (next != null) {
return EnterBlockStatement(next);
} else {
if (statement.Parent is BlockStatement) {
return ExitBlockStatement((Statement)statement.Parent.Parent);
} else {
return null;
}
// When a 'for' body is finished the execution continues by:
// Iterator; Condition; Body
if (statement.Parent is BlockStatement &&
statement.Parent.Parent is ForStatement) {
ForStatement forLoop = statement.Parent.Parent as ForStatement;
if (forLoop.Iterator.Count > 0) {
return forLoop.Iterator[0];
} else if (!forLoop.Condition.IsNull) {
return forLoop.Condition;
} else {
return forLoop.EmbeddedStatement.Children.First;
}
}
}
// Get the statement that will be executed once the given block exits by the end brace
// May return null
public static INode ExitBlockStatement(Statement statement)
{
if (statement == null) throw new ArgumentNullException();
// When an 'if' body is finished the execution continues with the
// next statement after the 'if' statement
if (statement is IfElseStatement) {
return GetNextStatement((IfElseStatement)statement);
}
// When a 'for' body is finished the execution continues by:
// Iterator; Condition; Body
if (statement is ForStatement) {
ForStatement forLoop = statement as ForStatement;
if (forLoop.Iterator.Count > 0) {
return forLoop.Iterator[0];
} else if (!forLoop.Condition.IsNull) {
return forLoop.Condition;
} else {
return EnterBlockStatement((Statement)forLoop.EmbeddedStatement.Children.First);
}
return null;
}
// Enter a block of code
while(true) {
// If a 'for' loop does not have initializers and condition,
// the next statement is the entry point
ForStatement nextAsForStmt = next as ForStatement;
if (nextAsForStmt != null &&
nextAsForStmt.Initializers.Count == 0 &&
nextAsForStmt.Condition.IsNull &&
nextAsForStmt.EmbeddedStatement is BlockStatement &&
nextAsForStmt.EmbeddedStatement.Children.Count > 0) {
next = (Statement)nextAsForStmt.EmbeddedStatement.Children.First;
continue; // Restart
return null;
}
// Get the first statement that will be executed in the given block
public static INode EnterBlockStatement(Statement statement)
{
if (statement == null) throw new ArgumentNullException();
// 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];
} 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
}
return next;
}
return statement; // Can not simplify
}
public override object VisitGotoStatement(GotoStatement gotoStatement, object data)
@ -165,15 +169,14 @@ namespace Decompiler.Transforms.Ast @@ -165,15 +169,14 @@ namespace Decompiler.Transforms.Ast
}
// Replace goto with 'continue'
// Continue statement which moves at the very start of for loop if there is no contition and iteration
if ((CurrentLoop is ForStatement) &&
(CurrentLoop as ForStatement).Condition.IsNull &&
(CurrentLoop as ForStatement).Iterator.Count == 0 &&
(CurrentLoop.EmbeddedStatement as BlockStatement) != null &&
((CurrentLoop.EmbeddedStatement as BlockStatement).Children.First as LabelStatement) != null &&
((CurrentLoop.EmbeddedStatement as BlockStatement).Children.First as LabelStatement).Label == gotoStatement.Label) {
ReplaceCurrentNode(new ContinueStatement());
return null;
// Continue statement which moves at the very start of for loop
if (CurrentLoop != null) {
INode continueTarget = ExitBlockStatement(CurrentLoop); // The start of the loop
if ((continueTarget is LabelStatement) &&
(continueTarget as LabelStatement).Label == gotoStatement.Label) {
ReplaceCurrentNode(new ContinueStatement());
return null;
}
}
return null;

Loading…
Cancel
Save