Skip to content

Commit

Permalink
Add pattern for "for" loops. Closes #4.
Browse files Browse the repository at this point in the history
  • Loading branch information
dgrunwald committed Feb 21, 2011
1 parent bb2c1a7 commit d5dcfea
Show file tree
Hide file tree
Showing 2 changed files with 69 additions and 4 deletions.
6 changes: 6 additions & 0 deletions ICSharpCode.Decompiler/Ast/AstBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,14 @@ public static bool MemberIsHidden(MemberReference member)
MethodDefinition method = member as MethodDefinition;
if (method != null && (method.IsGetter || method.IsSetter || method.IsAddOn || method.IsRemoveOn))
return true;
if (method != null && method.Name.StartsWith("<", StringComparison.Ordinal) && method.IsCompilerGenerated())
return true;
TypeDefinition type = member as TypeDefinition;
if (type != null && type.DeclaringType != null && type.Name.StartsWith("<>c__DisplayClass", StringComparison.Ordinal) && type.IsCompilerGenerated())
return true;
FieldDefinition field = member as FieldDefinition;
if (field != null && field.Name.StartsWith("CS$<>", StringComparison.Ordinal) && field.IsCompilerGenerated())
return true;
return false;
}

Expand Down Expand Up @@ -411,6 +416,7 @@ void AddTypeMembers(TypeDeclaration astType, TypeDefinition typeDef)
{
// Add fields
foreach(FieldDefinition fieldDef in typeDef.Fields) {
if (MemberIsHidden(fieldDef)) continue;
astType.AddChild(CreateField(fieldDef), TypeDeclaration.MemberRole);
}

Expand Down
67 changes: 63 additions & 4 deletions ICSharpCode.Decompiler/Ast/Transforms/PatternStatementTransform.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,26 +19,35 @@ public void Run(AstNode compilationUnit)
{
TransformUsings(compilationUnit);
TransformForeach(compilationUnit);
TransformFor(compilationUnit);
}

#region using
static readonly AstNode usingVarDeclPattern = new VariableDeclarationStatement {
/// <summary>
/// $type $variable = $initializer;
/// </summary>
static readonly AstNode variableDeclPattern = new VariableDeclarationStatement {
Type = new AnyNode("type").ToType(),
Variables = {
new NamedNode(
"variable",
new VariableInitializer {
Initializer = new AnyNode().ToExpression()
Initializer = new AnyNode("initializer").ToExpression()
}
).ToVariable()
}
};

/// <summary>
/// Variable declaration without initializer.
/// </summary>
static readonly AstNode simpleVariableDefinition = new VariableDeclarationStatement {
Type = new AnyNode().ToType(),
Variables = {
new VariableInitializer() // any name but no initializer
}
};

#region using
static readonly AstNode usingTryCatchPattern = new TryCatchStatement {
TryBlock = new AnyNode("body").ToBlock(),
FinallyBlock = new BlockStatement {
Expand All @@ -65,7 +74,7 @@ public void Run(AstNode compilationUnit)
public void TransformUsings(AstNode compilationUnit)
{
foreach (AstNode node in compilationUnit.Descendants.ToArray()) {
Match m1 = usingVarDeclPattern.Match(node);
Match m1 = variableDeclPattern.Match(node);
if (m1 == null) continue;
AstNode tryCatch = node.NextSibling;
while (simpleVariableDefinition.Match(tryCatch) != null)
Expand Down Expand Up @@ -178,5 +187,55 @@ public void TransformForeach(AstNode compilationUnit)
}
}
#endregion

#region for
WhileStatement forPattern = new WhileStatement {
Condition = new BinaryOperatorExpression {
Left = new NamedNode("ident", new IdentifierExpression()).ToExpression(),
Operator = BinaryOperatorType.Any,
Right = new AnyNode("endExpr").ToExpression()
},
EmbeddedStatement = new BlockStatement {
new Repeat(new AnyNode("statement")).ToStatement(),
new NamedNode(
"increment",
new ExpressionStatement(
new AssignmentExpression {
Left = new Backreference("ident").ToExpression(),
Operator = AssignmentOperatorType.Any,
Right = new AnyNode().ToExpression()
})).ToStatement(),
new ContinueStatement()
}
};

public void TransformFor(AstNode compilationUnit)
{
foreach (AstNode node in compilationUnit.Descendants.ToArray()) {
Match m1 = variableDeclPattern.Match(node);
if (m1 == null) continue;
AstNode next = node.NextSibling;
while (simpleVariableDefinition.Match(next) != null)
next = next.NextSibling;
Match m2 = forPattern.Match(next);
if (m2 == null) continue;
// ensure the variable in the for pattern is the same as in the declaration
if (m1.Get<VariableInitializer>("variable").Single().Name != m2.Get<IdentifierExpression>("ident").Single().Identifier)
continue;
WhileStatement loop = (WhileStatement)next;
node.Remove();
BlockStatement newBody = new BlockStatement();
foreach (Statement stmt in m2.Get<Statement>("statement"))
newBody.Add(stmt.Detach());
loop.ReplaceWith(
new ForStatement {
Initializers = { (VariableDeclarationStatement)node },
Condition = loop.Condition.Detach(),
Iterators = { m2.Get<Statement>("increment").Single().Detach() },
EmbeddedStatement = newBody
});
}
}
#endregion
}
}

0 comments on commit d5dcfea

Please sign in to comment.