Navigation Menu

Skip to content

Commit

Permalink
Merge pull request #309 from jbevain-forks/mcsGeneratedSwitchOnString
Browse files Browse the repository at this point in the history
mcs generated switch on string
  • Loading branch information
dgrunwald committed Jan 29, 2012
2 parents 703274f + 5e87658 commit 7c71408
Show file tree
Hide file tree
Showing 2 changed files with 69 additions and 18 deletions.
85 changes: 68 additions & 17 deletions ICSharpCode.Decompiler/Ast/Transforms/PatternStatementTransform.cs
Expand Up @@ -716,7 +716,7 @@ public SwitchStatement TransformSwitchOnString(IfElseStatement node)
return null;
}
FieldReference cachedDictField = m.Get<AstNode>("cachedDict").Single().Annotation<FieldReference>();
if (cachedDictField == null || !cachedDictField.DeclaringType.Name.StartsWith("<PrivateImplementationDetails>", StringComparison.Ordinal))
if (cachedDictField == null)
return null;
List<Statement> dictCreation = m.Get<BlockStatement>("dictCreation").Single().Statements.ToList();
List<KeyValuePair<string, int>> dict = BuildDictionary(dictCreation);
Expand Down Expand Up @@ -764,22 +764,73 @@ public SwitchStatement TransformSwitchOnString(IfElseStatement node)
}

List<KeyValuePair<string, int>> BuildDictionary(List<Statement> dictCreation)
{
List<KeyValuePair<string, int>> dict = new List<KeyValuePair<string, int>>();
for (int i = 0; i < dictCreation.Count; i++) {
ExpressionStatement es = dictCreation[i] as ExpressionStatement;
if (es == null)
continue;
InvocationExpression ie = es.Expression as InvocationExpression;
if (ie == null)
continue;
PrimitiveExpression arg1 = ie.Arguments.ElementAtOrDefault(0) as PrimitiveExpression;
PrimitiveExpression arg2 = ie.Arguments.ElementAtOrDefault(1) as PrimitiveExpression;
if (arg1 != null && arg2 != null && arg1.Value is string && arg2.Value is int)
dict.Add(new KeyValuePair<string, int>((string)arg1.Value, (int)arg2.Value));
}
return dict;
}
{
if (context.Settings.ObjectOrCollectionInitializers && dictCreation.Count == 1)
return BuildDictionaryFromInitializer(dictCreation[0]);

return BuildDictionaryFromAddMethodCalls(dictCreation);
}

static readonly Statement assignInitializedDictionary = new ExpressionStatement {
Expression = new AssignmentExpression {
Left = new AnyNode().ToExpression(),
Right = new ObjectCreateExpression {
Type = new AnyNode(),
Arguments = { new Repeat(new AnyNode()) },
Initializer = new ArrayInitializerExpression {
Elements = { new Repeat(new AnyNode("dictJumpTable")) }
}
},
},
};

private List<KeyValuePair<string, int>> BuildDictionaryFromInitializer(Statement statement)
{
List<KeyValuePair<string, int>> dict = new List<KeyValuePair<string, int>>();
Match m = assignInitializedDictionary.Match(statement);
if (!m.Success)
return dict;

foreach (ArrayInitializerExpression initializer in m.Get<ArrayInitializerExpression>("dictJumpTable")) {
KeyValuePair<string, int> pair;
if (TryGetPairFrom(initializer.Elements, out pair))
dict.Add(pair);
}

return dict;
}

private static List<KeyValuePair<string, int>> BuildDictionaryFromAddMethodCalls(List<Statement> dictCreation)
{
List<KeyValuePair<string, int>> dict = new List<KeyValuePair<string, int>>();
for (int i = 0; i < dictCreation.Count; i++) {
ExpressionStatement es = dictCreation[i] as ExpressionStatement;
if (es == null)
continue;
InvocationExpression ie = es.Expression as InvocationExpression;
if (ie == null)
continue;

KeyValuePair<string, int> pair;
if (TryGetPairFrom(ie.Arguments, out pair))
dict.Add(pair);
}
return dict;
}

private static bool TryGetPairFrom(AstNodeCollection<Expression> expressions, out KeyValuePair<string, int> pair)
{
PrimitiveExpression arg1 = expressions.ElementAtOrDefault(0) as PrimitiveExpression;
PrimitiveExpression arg2 = expressions.ElementAtOrDefault(1) as PrimitiveExpression;
if (arg1 != null && arg2 != null && arg1.Value is string && arg2.Value is int) {
pair = new KeyValuePair<string, int>((string)arg1.Value, (int)arg2.Value);
return true;
}

pair = default(KeyValuePair<string, int>);
return false;
}

#endregion

#region Automatic Properties
Expand Down
Expand Up @@ -385,7 +385,7 @@ static bool IsAddMethodCall(ILExpression expr)
{
MethodReference addMethod;
List<ILExpression> args;
if (expr.Match(ILCode.Callvirt, out addMethod, out args)) {
if (expr.Match(ILCode.Callvirt, out addMethod, out args) || expr.Match(ILCode.Call, out addMethod, out args)) {
if (addMethod.Name == "Add" && addMethod.HasThis) {
return args.Count >= 2;
}
Expand Down

0 comments on commit 7c71408

Please sign in to comment.