Browse Source

Add idioms for user-defined operator invocations.

pull/10/head
Daniel Grunwald 15 years ago
parent
commit
faacc976b9
  1. 25
      ICSharpCode.Decompiler/Ast/TextOutputFormatter.cs
  2. 82
      ICSharpCode.Decompiler/Ast/Transforms/Idioms.cs

25
ICSharpCode.Decompiler/Ast/TextOutputFormatter.cs

@ -24,19 +24,23 @@ namespace Decompiler @@ -24,19 +24,23 @@ namespace Decompiler
public void WriteIdentifier(string identifier)
{
AstNode node = nodeStack.Peek();
MemberReference memberRef = node.Annotation<MemberReference>();
if (memberRef == null && node.Role == AstNode.Roles.TargetExpression
&& (node.Parent is InvocationExpression || node.Parent is ObjectCreateExpression))
{
memberRef = node.Parent.Annotation<MemberReference>();
}
MemberReference memberRef = GetCurrentMemberReference();
if (memberRef != null)
output.WriteReference(identifier, memberRef);
else
output.Write(identifier);
}
MemberReference GetCurrentMemberReference()
{
AstNode node = nodeStack.Peek();
MemberReference memberRef = node.Annotation<MemberReference>();
if (memberRef == null && node.Role == AstNode.Roles.TargetExpression && (node.Parent is InvocationExpression || node.Parent is ObjectCreateExpression)) {
memberRef = node.Parent.Annotation<MemberReference>();
}
return memberRef;
}
public void WriteKeyword(string keyword)
{
@ -45,7 +49,12 @@ namespace Decompiler @@ -45,7 +49,12 @@ namespace Decompiler
public void WriteToken(string token)
{
output.Write(token);
// Attach member reference to token only if there's no identifier in the current node.
MemberReference memberRef = GetCurrentMemberReference();
if (memberRef != null && nodeStack.Peek().GetChildByRole(AstNode.Roles.Identifier).IsNull)
output.WriteReference(token, memberRef);
else
output.Write(token);
}
public void Space()

82
ICSharpCode.Decompiler/Ast/Transforms/Idioms.cs

@ -16,7 +16,7 @@ namespace Decompiler.Transforms.Ast @@ -16,7 +16,7 @@ namespace Decompiler.Transforms.Ast
MethodReference methodRef = invocationExpression.Annotation<MethodReference>();
// Reduce "String.Concat(a, b)" to "a + b"
if (methodRef != null && methodRef.FullName == "System.String.Concat"
&& methodRef.Parameters.Count >= 2)
&& invocationExpression.Arguments.Count() >= 2)
{
var arguments = invocationExpression.Arguments.ToArray();
invocationExpression.Arguments = null; // detach arguments from invocationExpression
@ -24,11 +24,91 @@ namespace Decompiler.Transforms.Ast @@ -24,11 +24,91 @@ namespace Decompiler.Transforms.Ast
for (int i = 1; i < arguments.Length; i++) {
expr = new BinaryOperatorExpression(expr, BinaryOperatorType.Add, arguments[i]);
}
invocationExpression.ReplaceWith(expr);
}
if (methodRef != null) {
BinaryOperatorType? bop = GetBinaryOperatorTypeFromMetadataName(methodRef.Name);
if (bop != null && invocationExpression.Arguments.Count() == 2) {
var arguments = invocationExpression.Arguments.ToArray();
invocationExpression.Arguments = null; // detach arguments from invocationExpression
invocationExpression.ReplaceWith(
new BinaryOperatorExpression(arguments[0], bop.Value, arguments[1]).WithAnnotation(methodRef)
);
}
UnaryOperatorType? uop = GetUnaryOperatorTypeFromMetadataName(methodRef.Name);
if (uop != null && invocationExpression.Arguments.Count() == 1) {
var arg = invocationExpression.Arguments.Single();
arg.Remove(); // detach argument
invocationExpression.ReplaceWith(
new UnaryOperatorExpression(uop.Value, arg).WithAnnotation(methodRef)
);
}
}
return null;
}
BinaryOperatorType? GetBinaryOperatorTypeFromMetadataName(string name)
{
switch (name) {
case "op_Addition":
return BinaryOperatorType.Add;
case "op_Subtraction":
return BinaryOperatorType.Subtract;
case "op_Multiply":
return BinaryOperatorType.Multiply;
case "op_Division":
return BinaryOperatorType.Divide;
case "op_Modulus":
return BinaryOperatorType.Modulus;
case "op_BitwiseAnd":
return BinaryOperatorType.BitwiseAnd;
case "op_BitwiseOr":
return BinaryOperatorType.BitwiseOr;
case "op_ExlusiveOr":
return BinaryOperatorType.ExclusiveOr;
case "op_LeftShift":
return BinaryOperatorType.ShiftLeft;
case "op_RightShift":
return BinaryOperatorType.ShiftRight;
case "op_Equality":
return BinaryOperatorType.Equality;
case "op_Inequality":
return BinaryOperatorType.InEquality;
case "op_LessThan":
return BinaryOperatorType.LessThan;
case "op_LessThanOrEqual":
return BinaryOperatorType.LessThanOrEqual;
case "op_GreaterThan":
return BinaryOperatorType.GreaterThan;
case "op_GreaterThanOrEqual":
return BinaryOperatorType.GreaterThanOrEqual;
default:
return null;
}
}
UnaryOperatorType? GetUnaryOperatorTypeFromMetadataName(string name)
{
switch (name) {
case "op_LogicalNot":
return UnaryOperatorType.Not;
case "op_OnesComplement":
return UnaryOperatorType.BitNot;
case "op_UnaryNegation":
return UnaryOperatorType.Minus;
case "op_UnaryPlus":
return UnaryOperatorType.Plus;
case "op_Increment":
return UnaryOperatorType.Increment;
case "op_Decrement":
return UnaryOperatorType.Decrement;
default:
return null;
}
}
public override object VisitAssignmentExpression(AssignmentExpression assignment, object data)
{
base.VisitAssignmentExpression(assignment, data);

Loading…
Cancel
Save