Browse Source

Compound assignment support for overloaded operators

pull/205/head
Pent Ploompuu 14 years ago
parent
commit
66fde6d0ee
  1. 8
      ICSharpCode.Decompiler/Ast/AstMethodBodyBuilder.cs
  2. 9
      ICSharpCode.Decompiler/Ast/Transforms/ReplaceMethodCallsWithOperators.cs
  3. 24
      ICSharpCode.Decompiler/ILAst/PeepholeTransform.cs
  4. 6
      ICSharpCode.Decompiler/Tests/NullableOperators.cs

8
ICSharpCode.Decompiler/Ast/AstMethodBodyBuilder.cs

@ -429,7 +429,13 @@ namespace ICSharpCode.Decompiler.Ast
case ILCode.CompoundAssignment:
{
CastExpression cast = arg1 as CastExpression;
BinaryOperatorExpression boe = (BinaryOperatorExpression)(cast != null ? cast.Expression : arg1);
var boe = cast != null ? (BinaryOperatorExpression)cast.Expression : arg1 as BinaryOperatorExpression;
// AssignmentExpression doesn't support overloaded operators so they have to be processed to BinaryOperatorExpression
if (boe == null) {
var tmp = new ParenthesizedExpression(arg1);
ReplaceMethodCallsWithOperators.ProcessInvocationExpression((InvocationExpression)arg1);
boe = (BinaryOperatorExpression)tmp.Expression;
}
var assignment = new Ast.AssignmentExpression {
Left = boe.Left.Detach(),
Operator = ReplaceMethodCallsWithOperators.GetAssignmentOperatorForBinaryOperator(boe.Operator),

9
ICSharpCode.Decompiler/Ast/Transforms/ReplaceMethodCallsWithOperators.cs

@ -51,6 +51,11 @@ namespace ICSharpCode.Decompiler.Ast.Transforms
{
base.VisitInvocationExpression(invocationExpression, data);
return ProcessInvocationExpression(invocationExpression);
}
internal static object ProcessInvocationExpression(InvocationExpression invocationExpression)
{
MethodReference methodRef = invocationExpression.Annotation<MethodReference>();
if (methodRef == null)
return null;
@ -115,7 +120,7 @@ namespace ICSharpCode.Decompiler.Ast.Transforms
return null;
}
BinaryOperatorType? GetBinaryOperatorTypeFromMetadataName(string name)
static BinaryOperatorType? GetBinaryOperatorTypeFromMetadataName(string name)
{
switch (name) {
case "op_Addition":
@ -155,7 +160,7 @@ namespace ICSharpCode.Decompiler.Ast.Transforms
}
}
UnaryOperatorType? GetUnaryOperatorTypeFromMetadataName(string name)
static UnaryOperatorType? GetUnaryOperatorTypeFromMetadataName(string name)
{
switch (name) {
case "op_LogicalNot":

24
ICSharpCode.Decompiler/ILAst/PeepholeTransform.cs

@ -403,7 +403,7 @@ namespace ICSharpCode.Decompiler.ILAst
op = op.Arguments[0];
nullable = true;
}
if (!CanBeRepresentedAsCompoundAssignment(op.Code))
if (!CanBeRepresentedAsCompoundAssignment(op))
return false;
ILExpression ldelem = op.Arguments[0];
@ -426,9 +426,9 @@ namespace ICSharpCode.Decompiler.ILAst
return true;
}
static bool CanBeRepresentedAsCompoundAssignment(ILCode code)
static bool CanBeRepresentedAsCompoundAssignment(ILExpression expr)
{
switch (code) {
switch (expr.Code) {
case ILCode.Add:
case ILCode.Add_Ovf:
case ILCode.Add_Ovf_Un:
@ -449,6 +449,24 @@ namespace ICSharpCode.Decompiler.ILAst
case ILCode.Shr:
case ILCode.Shr_Un:
return true;
case ILCode.Call:
var m = expr.Operand as MethodReference;
if (m == null || m.HasThis || expr.Arguments.Count != 2) return false;
switch (m.Name) {
case "op_Addition":
case "op_Subtraction":
case "op_Multiply":
case "op_Division":
case "op_Modulus":
case "op_BitwiseAnd":
case "op_BitwiseOr":
case "op_ExclusiveOr":
case "op_LeftShift":
case "op_RightShift":
return true;
default:
return false;
}
default:
return false;
}

6
ICSharpCode.Decompiler/Tests/NullableOperators.cs

@ -538,8 +538,7 @@ public static class NullableOperators
a %= x();
Console.WriteLine(x() + a);
// TODO: compound assignment with custom operators needs to be fixed first
//list[0] += x();
list[0] += x();
}
public static void NumberValueConst(decimal? a)
@ -713,8 +712,7 @@ public static class NullableOperators
a >>= i();
Console.WriteLine(x() + a);
// TODO: compound assignment with custom operators needs to be fixed first
//list[0] += x();
list[0] += x();
}
}

Loading…
Cancel
Save