Browse Source

Improve use of dynamic expressions in conditional context:

Let "operator true" be invoked implicitly where possible.
pull/1165/head
Daniel Grunwald 7 years ago
parent
commit
02dde92bcb
  1. 14
      ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs
  2. 2
      ICSharpCode.Decompiler/CSharp/OutputVisitor/CSharpOutputVisitor.cs
  3. 14
      ICSharpCode.Decompiler/CSharp/OutputVisitor/InsertParenthesesVisitor.cs
  4. 5
      ICSharpCode.Decompiler/CSharp/Syntax/Expressions/UnaryOperatorExpression.cs

14
ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs

@ -2527,12 +2527,16 @@ namespace ICSharpCode.Decompiler.CSharp @@ -2527,12 +2527,16 @@ namespace ICSharpCode.Decompiler.CSharp
return CreateUnaryOperator(UnaryOperatorType.Plus);
case ExpressionType.IsTrue:
var operand = TranslateDynamicArgument(inst.Operand, inst.OperandArgumentInfo);
if (IfInstruction.IsInConditionSlot(inst)) {
// TODO
Expression expr;
if (inst.SlotInfo == IfInstruction.ConditionSlot) {
// We rely on the context implicitly invoking "operator true".
expr = new UnaryOperatorExpression(UnaryOperatorType.IsTrue, operand);
} else {
// Create a dummy conditional to ensure "operator true" will be invoked.
expr = new ConditionalExpression(operand, new PrimitiveExpression(true), new PrimitiveExpression(false));
}
return new ConditionalExpression(operand.Expression, new PrimitiveExpression(true), new PrimitiveExpression(false))
.WithILInstruction(inst)
.WithRR(new ResolveResult(compilation.FindType(KnownTypeCode.Boolean)));
return expr.WithILInstruction(inst)
.WithRR(new ResolveResult(compilation.FindType(KnownTypeCode.Boolean)));
default:
return base.VisitDynamicUnaryOperatorInstruction(inst, context);
}

2
ICSharpCode.Decompiler/CSharp/OutputVisitor/CSharpOutputVisitor.cs

@ -1102,7 +1102,7 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor @@ -1102,7 +1102,7 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor
var opSymbol = UnaryOperatorExpression.GetOperatorRole(opType);
if (opType == UnaryOperatorType.Await) {
WriteKeyword(opSymbol);
} else if (!IsPostfixOperator(opType) && opType != UnaryOperatorType.NullConditionalRewrap) {
} else if (!IsPostfixOperator(opType) && opSymbol != null) {
WriteToken(opSymbol);
}
unaryOperatorExpression.Expression.AcceptVisitor(this);

14
ICSharpCode.Decompiler/CSharp/OutputVisitor/InsertParenthesesVisitor.cs

@ -64,6 +64,8 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor @@ -64,6 +64,8 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor
return Primary;
case UnaryOperatorType.NullConditionalRewrap:
return NullableRewrap;
case UnaryOperatorType.IsTrue:
return Conditional;
default:
return Unary;
}
@ -264,12 +266,13 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor @@ -264,12 +266,13 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor
if (InsertParenthesesForReadability && precedence < Equality) {
// In readable mode, boost the priority of the left-hand side if the operator
// there isn't the same as the operator on this expression.
int boostTo = IsBitwise(binaryOperatorExpression.Operator) ? Unary : Equality;
if (GetBinaryOperatorType(binaryOperatorExpression.Left) == binaryOperatorExpression.Operator) {
ParenthesizeIfRequired(binaryOperatorExpression.Left, precedence);
} else {
ParenthesizeIfRequired(binaryOperatorExpression.Left, Equality);
ParenthesizeIfRequired(binaryOperatorExpression.Left, boostTo);
}
ParenthesizeIfRequired(binaryOperatorExpression.Right, Equality);
ParenthesizeIfRequired(binaryOperatorExpression.Right, boostTo);
} else {
// all other binary operators are left-associative
ParenthesizeIfRequired(binaryOperatorExpression.Left, precedence);
@ -279,6 +282,13 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor @@ -279,6 +282,13 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor
base.VisitBinaryOperatorExpression(binaryOperatorExpression);
}
static bool IsBitwise(BinaryOperatorType op)
{
return op == BinaryOperatorType.BitwiseAnd
|| op == BinaryOperatorType.BitwiseOr
|| op == BinaryOperatorType.ExclusiveOr;
}
BinaryOperatorType? GetBinaryOperatorType(Expression expr)
{
BinaryOperatorExpression boe = expr as BinaryOperatorExpression;

5
ICSharpCode.Decompiler/CSharp/Syntax/Expressions/UnaryOperatorExpression.cs

@ -117,6 +117,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax @@ -117,6 +117,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
case UnaryOperatorType.NullConditional:
return NullConditionalRole;
case UnaryOperatorType.NullConditionalRewrap:
case UnaryOperatorType.IsTrue:
return null; // no syntax
default:
throw new NotSupportedException("Invalid value for UnaryOperatorType");
@ -193,5 +194,9 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax @@ -193,5 +194,9 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
/// This has no syntax in C#, but the node is used to ensure parentheses are inserted where necessary.
/// </summary>
NullConditionalRewrap,
/// <summary>
/// Implicit call of "operator true".
/// </summary>
IsTrue,
}
}

Loading…
Cancel
Save