Browse Source

Simplify "x == false" to "!x" in PushNegation.

pull/37/head
Daniel Grunwald 15 years ago
parent
commit
d6f94bbc75
  1. 74
      ICSharpCode.Decompiler/Ast/Transforms/PushNegation.cs
  2. 4
      ICSharpCode.Decompiler/Ast/Transforms/TransformationPipeline.cs

74
ICSharpCode.Decompiler/Ast/Transforms/PushNegation.cs

@ -3,7 +3,7 @@ using System.Collections.Generic;
using ICSharpCode.NRefactory.CSharp; using ICSharpCode.NRefactory.CSharp;
namespace Decompiler.Transforms.Ast namespace Decompiler.Transforms
{ {
public class PushNegation: DepthFirstAstVisitor<object, object> public class PushNegation: DepthFirstAstVisitor<object, object>
{ {
@ -24,29 +24,48 @@ namespace Decompiler.Transforms.Ast
// !((a) op (b)) // !((a) op (b))
BinaryOperatorExpression binaryOp = unary.Expression as BinaryOperatorExpression; BinaryOperatorExpression binaryOp = unary.Expression as BinaryOperatorExpression;
if (unary.Operator == UnaryOperatorType.Not && binaryOp != null) { if (unary.Operator == UnaryOperatorType.Not && binaryOp != null) {
bool sucessful = true; bool successful = true;
switch (binaryOp.Operator) { switch (binaryOp.Operator) {
case BinaryOperatorType.Equality: binaryOp.Operator = BinaryOperatorType.InEquality; break; case BinaryOperatorType.Equality:
case BinaryOperatorType.InEquality: binaryOp.Operator = BinaryOperatorType.Equality; break; binaryOp.Operator = BinaryOperatorType.InEquality;
// TODO: these are invalid for floats (stupid NaN) break;
case BinaryOperatorType.GreaterThan: binaryOp.Operator = BinaryOperatorType.LessThanOrEqual; break; case BinaryOperatorType.InEquality:
case BinaryOperatorType.GreaterThanOrEqual: binaryOp.Operator = BinaryOperatorType.LessThan; break; binaryOp.Operator = BinaryOperatorType.Equality;
case BinaryOperatorType.LessThanOrEqual: binaryOp.Operator = BinaryOperatorType.GreaterThan; break; break;
case BinaryOperatorType.LessThan: binaryOp.Operator = BinaryOperatorType.GreaterThanOrEqual; break; case BinaryOperatorType.GreaterThan: // TODO: these are invalid for floats (stupid NaN)
default: sucessful = false; break; binaryOp.Operator = BinaryOperatorType.LessThanOrEqual;
break;
case BinaryOperatorType.GreaterThanOrEqual:
binaryOp.Operator = BinaryOperatorType.LessThan;
break;
case BinaryOperatorType.LessThanOrEqual:
binaryOp.Operator = BinaryOperatorType.GreaterThan;
break;
case BinaryOperatorType.LessThan:
binaryOp.Operator = BinaryOperatorType.GreaterThanOrEqual;
break;
default:
successful = false;
break;
} }
if (sucessful) { if (successful) {
unary.ReplaceWith(binaryOp); unary.ReplaceWith(binaryOp);
return binaryOp.AcceptVisitor(this, data); return binaryOp.AcceptVisitor(this, data);
} }
sucessful = true; successful = true;
switch (binaryOp.Operator) { switch (binaryOp.Operator) {
case BinaryOperatorType.ConditionalAnd: binaryOp.Operator = BinaryOperatorType.ConditionalOr; break; case BinaryOperatorType.ConditionalAnd:
case BinaryOperatorType.ConditionalOr: binaryOp.Operator = BinaryOperatorType.ConditionalAnd; break; binaryOp.Operator = BinaryOperatorType.ConditionalOr;
default: sucessful = false; break; break;
case BinaryOperatorType.ConditionalOr:
binaryOp.Operator = BinaryOperatorType.ConditionalAnd;
break;
default:
successful = false;
break;
} }
if (sucessful) { if (successful) {
binaryOp.Left.ReplaceWith(e => new UnaryOperatorExpression(UnaryOperatorType.Not, e)); binaryOp.Left.ReplaceWith(e => new UnaryOperatorExpression(UnaryOperatorType.Not, e));
binaryOp.Right.ReplaceWith(e => new UnaryOperatorExpression(UnaryOperatorType.Not, e)); binaryOp.Right.ReplaceWith(e => new UnaryOperatorExpression(UnaryOperatorType.Not, e));
unary.ReplaceWith(binaryOp); unary.ReplaceWith(binaryOp);
@ -55,5 +74,28 @@ namespace Decompiler.Transforms.Ast
} }
return base.VisitUnaryOperatorExpression(unary, data); return base.VisitUnaryOperatorExpression(unary, data);
} }
public override object VisitBinaryOperatorExpression(BinaryOperatorExpression binaryOperatorExpression, object data)
{
BinaryOperatorType op = binaryOperatorExpression.Operator;
bool? rightOperand = null;
if (binaryOperatorExpression.Right is PrimitiveExpression)
rightOperand = ((PrimitiveExpression)binaryOperatorExpression.Right).Value as bool?;
if (op == BinaryOperatorType.Equality && rightOperand == true || op == BinaryOperatorType.InEquality && rightOperand == false) {
// 'b == true' or 'b != false' is useless
binaryOperatorExpression.AcceptVisitor(this, data);
binaryOperatorExpression.ReplaceWith(binaryOperatorExpression.Left);
return null;
} else if (op == BinaryOperatorType.Equality && rightOperand == false || op == BinaryOperatorType.InEquality && rightOperand == true) {
// 'b == false' or 'b != true' is a negation:
Expression left = binaryOperatorExpression.Left;
left.Remove();
UnaryOperatorExpression uoe = new UnaryOperatorExpression(UnaryOperatorType.Not, left);
binaryOperatorExpression.ReplaceWith(uoe);
return uoe.AcceptVisitor(this, data);
} else {
return base.VisitBinaryOperatorExpression(binaryOperatorExpression, data);
}
}
} }
} }

4
ICSharpCode.Decompiler/Ast/Transforms/TransformationPipeline.cs

@ -12,9 +12,10 @@ namespace Decompiler.Transforms
public static IAstVisitor<object, object>[] CreatePipeline(CancellationToken cancellationToken) public static IAstVisitor<object, object>[] CreatePipeline(CancellationToken cancellationToken)
{ {
return new IAstVisitor<object, object>[] { return new IAstVisitor<object, object>[] {
new PushNegation(),
new DelegateConstruction() { CancellationToken = cancellationToken }, new DelegateConstruction() { CancellationToken = cancellationToken },
new ConvertConstructorCallIntoInitializer(), new ConvertConstructorCallIntoInitializer(),
new ReplaceMethodCallsWithOperators() new ReplaceMethodCallsWithOperators(),
}; };
} }
@ -33,7 +34,6 @@ namespace Decompiler.Transforms
} }
if (Options.ReduceAstOther) { if (Options.ReduceAstOther) {
node.AcceptVisitor(new Transforms.Ast.RemoveEmptyElseBody(), null); node.AcceptVisitor(new Transforms.Ast.RemoveEmptyElseBody(), null);
node.AcceptVisitor(new Transforms.Ast.PushNegation(), null);
} }
} }

Loading…
Cancel
Save