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
public void WriteIdentifier(string identifier) public void WriteIdentifier(string identifier)
{ {
AstNode node = nodeStack.Peek(); MemberReference memberRef = GetCurrentMemberReference();
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>();
}
if (memberRef != null) if (memberRef != null)
output.WriteReference(identifier, memberRef); output.WriteReference(identifier, memberRef);
else else
output.Write(identifier); 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) public void WriteKeyword(string keyword)
{ {
@ -45,7 +49,12 @@ namespace Decompiler
public void WriteToken(string token) 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() public void Space()

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

@ -16,7 +16,7 @@ namespace Decompiler.Transforms.Ast
MethodReference methodRef = invocationExpression.Annotation<MethodReference>(); MethodReference methodRef = invocationExpression.Annotation<MethodReference>();
// Reduce "String.Concat(a, b)" to "a + b" // Reduce "String.Concat(a, b)" to "a + b"
if (methodRef != null && methodRef.FullName == "System.String.Concat" if (methodRef != null && methodRef.FullName == "System.String.Concat"
&& methodRef.Parameters.Count >= 2) && invocationExpression.Arguments.Count() >= 2)
{ {
var arguments = invocationExpression.Arguments.ToArray(); var arguments = invocationExpression.Arguments.ToArray();
invocationExpression.Arguments = null; // detach arguments from invocationExpression invocationExpression.Arguments = null; // detach arguments from invocationExpression
@ -24,11 +24,91 @@ namespace Decompiler.Transforms.Ast
for (int i = 1; i < arguments.Length; i++) { for (int i = 1; i < arguments.Length; i++) {
expr = new BinaryOperatorExpression(expr, BinaryOperatorType.Add, arguments[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; 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) public override object VisitAssignmentExpression(AssignmentExpression assignment, object data)
{ {
base.VisitAssignmentExpression(assignment, data); base.VisitAssignmentExpression(assignment, data);

Loading…
Cancel
Save