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. 117
      src/Transforms/Ast/RemoveGotos.cs

117
src/Transforms/Ast/RemoveGotos.cs

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

Loading…
Cancel
Save