@@ -5421,23 +5421,154 @@ private static MethodInfo FindBinaryOperandMethod(
54215421 return null;
54225422 }
54235423
5424+ /// <summary>Operation accepting IComparable inputs and producing bool output</summary>
5425+ private static bool IsComparison(ExpressionType nodeType) =>
5426+ nodeType == ExpressionType.Equal |
5427+ nodeType == ExpressionType.NotEqual |
5428+ nodeType == ExpressionType.GreaterThan |
5429+ nodeType == ExpressionType.GreaterThanOrEqual |
5430+ nodeType == ExpressionType.LessThan |
5431+ nodeType == ExpressionType.LessThanOrEqual;
5432+
5433+ /// <summary>Operation accepting bool inputs and producing bool output</summary>
5434+ private static bool IsLogical(ExpressionType nodeType) =>
5435+ nodeType == ExpressionType.AndAlso |
5436+ nodeType == ExpressionType.OrElse |
5437+ nodeType == ExpressionType.Not;
5438+
5439+ /// <summary>Operation accepting the same primitive type inputs (or of the coalescing types) and producing the "same" primitive type output</summary>
5440+ private static bool IsArithmetic(ExpressionType nodeType) =>
5441+ nodeType == ExpressionType.Add |
5442+ nodeType == ExpressionType.Subtract |
5443+ nodeType == ExpressionType.Multiply |
5444+ nodeType == ExpressionType.Divide |
5445+ nodeType == ExpressionType.Modulo |
5446+ nodeType == ExpressionType.Negate;
5447+
5448+ /// <summary>Eval negate</summary>
5449+ public static object EvalNegateOrNull(object operand)
5450+ {
5451+ return Type.GetTypeCode(operand.GetType()) switch
5452+ {
5453+ TypeCode.SByte => -(sbyte)operand,
5454+ TypeCode.Byte => -(byte)operand,
5455+ TypeCode.Int16 => -(short)operand,
5456+ TypeCode.UInt16 => -(ushort)operand,
5457+ TypeCode.Int32 => -(int)operand,
5458+ TypeCode.UInt32 => -(uint)operand,
5459+ TypeCode.Int64 => -(long)operand,
5460+ TypeCode.Single => -(float)operand,
5461+ TypeCode.Double => -(double)operand,
5462+ TypeCode.Decimal => -(decimal)operand,
5463+ TypeCode.UInt64 => null,
5464+ _ => null,
5465+ };
5466+ }
5467+
5468+ /// <summary>Eval arithmetic</summary>
5469+ public static object EvalArithmeticOrNull(object left, object right, ExpressionType nodeType)
5470+ {
5471+ return nodeType switch
5472+ {
5473+ ExpressionType.Add => Type.GetTypeCode(left.GetType()) switch
5474+ {
5475+ TypeCode.SByte => (sbyte)left + (sbyte)right,
5476+ TypeCode.Byte => (byte)left + (byte)right,
5477+ TypeCode.Int16 => (short)left + (short)right,
5478+ TypeCode.UInt16 => (ushort)left + (ushort)right,
5479+ TypeCode.Int32 => (int)left + (int)right,
5480+ TypeCode.UInt32 => (uint)left + (uint)right,
5481+ TypeCode.Int64 => (long)left + (long)right,
5482+ TypeCode.UInt64 => (ulong)left + (ulong)right,
5483+ TypeCode.Single => (float)left + (float)right,
5484+ TypeCode.Double => (double)left + (double)right,
5485+ TypeCode.Decimal => (decimal)left + (decimal)right,
5486+ _ => null,
5487+ },
5488+ ExpressionType.Subtract => Type.GetTypeCode(left.GetType()) switch
5489+ {
5490+ TypeCode.SByte => (sbyte)left - (sbyte)right,
5491+ TypeCode.Byte => (byte)left - (byte)right,
5492+ TypeCode.Int16 => (short)left - (short)right,
5493+ TypeCode.UInt16 => (ushort)left - (ushort)right,
5494+ TypeCode.Int32 => (int)left - (int)right,
5495+ TypeCode.UInt32 => (uint)left - (uint)right,
5496+ TypeCode.Int64 => (long)left - (long)right,
5497+ TypeCode.UInt64 => (ulong)left - (ulong)right,
5498+ TypeCode.Single => (float)left - (float)right,
5499+ TypeCode.Double => (double)left - (double)right,
5500+ TypeCode.Decimal => (decimal)left - (decimal)right,
5501+ _ => null,
5502+ },
5503+ ExpressionType.Multiply => Type.GetTypeCode(left.GetType()) switch
5504+ {
5505+ TypeCode.SByte => (sbyte)left * (sbyte)right,
5506+ TypeCode.Byte => (byte)left * (byte)right,
5507+ TypeCode.Int16 => (short)left * (short)right,
5508+ TypeCode.UInt16 => (ushort)left * (ushort)right,
5509+ TypeCode.Int32 => (int)left * (int)right,
5510+ TypeCode.UInt32 => (uint)left * (uint)right,
5511+ TypeCode.Int64 => (long)left * (long)right,
5512+ TypeCode.UInt64 => (ulong)left * (ulong)right,
5513+ TypeCode.Single => (float)left * (float)right,
5514+ TypeCode.Double => (double)left * (double)right,
5515+ TypeCode.Decimal => (decimal)left * (decimal)right,
5516+ _ => null,
5517+ },
5518+ ExpressionType.Divide => Type.GetTypeCode(left.GetType()) switch
5519+ {
5520+ TypeCode.SByte => (sbyte)left / (sbyte)right,
5521+ TypeCode.Byte => (byte)left / (byte)right,
5522+ TypeCode.Int16 => (short)left / (short)right,
5523+ TypeCode.UInt16 => (ushort)left / (ushort)right,
5524+ TypeCode.Int32 => (int)left / (int)right,
5525+ TypeCode.UInt32 => (uint)left / (uint)right,
5526+ TypeCode.Int64 => (long)left / (long)right,
5527+ TypeCode.UInt64 => (ulong)left / (ulong)right,
5528+ TypeCode.Single => (float)left / (float)right,
5529+ TypeCode.Double => (double)left / (double)right,
5530+ TypeCode.Decimal => (decimal)left / (decimal)right,
5531+ _ => null,
5532+ },
5533+ ExpressionType.Modulo => Type.GetTypeCode(left.GetType()) switch
5534+ {
5535+ TypeCode.SByte => (sbyte)left % (sbyte)right,
5536+ TypeCode.Byte => (byte)left % (byte)right,
5537+ TypeCode.Int16 => (short)left % (short)right,
5538+ TypeCode.UInt16 => (ushort)left % (ushort)right,
5539+ TypeCode.Int32 => (int)left % (int)right,
5540+ TypeCode.UInt32 => (uint)left % (uint)right,
5541+ TypeCode.Int64 => (long)left % (long)right,
5542+ TypeCode.UInt64 => (ulong)left % (ulong)right,
5543+ TypeCode.Single => (float)left % (float)right,
5544+ TypeCode.Double => (double)left % (double)right,
5545+ TypeCode.Decimal => (decimal)left % (decimal)right,
5546+ _ => null,
5547+ },
5548+ _ => null,
5549+ };
5550+ }
54245551
54255552 // todo: @wip #468
5426- internal static bool TryReduceComparisonByEvalConstantsAndArithmetics(out bool result, Expression left, Expression right, bool isEquality)
5553+ internal static bool TryReduceLogicalExpression(out bool result,
5554+ ExpressionType nodeType, Expression left, Expression right)
54275555 {
5428- if (left is ConstantExpression lc && lc.Type.IsPrimitive &&
5429- right is ConstantExpression rc && rc.Type.IsPrimitive
5556+ result = false;
5557+ if (left is BinaryExpression lb && IsLogical(lb.NodeType))
5558+ {
5559+ var ll = lb.Left;
5560+ var lr = lb.Right;
5561+ if (right is ConstantExpression rc
54305562#if LIGHT_EXPRESSION
5431- // exclude the ref
5432- && lc is not ConstantRefExpression && rc is not ConstantRefExpression
5563+ && right is not ConstantRefExpression
54335564#endif
5434- )
5435- {
5565+ )
5566+ {
54365567
5437- result = lc.Value.Equals(rc.Value) && !isEquality;
5438- return true;
5568+ }
54395569 }
54405570
5571+
54415572 result = false;
54425573 return false;
54435574 }
@@ -5474,9 +5605,8 @@ private static bool TryEmitComparison(
54745605 var isEqualityOp = nodeType == ExpressionType.Equal | nodeType == ExpressionType.NotEqual;
54755606 if (isEqualityOp)
54765607 {
5477-
54785608 // if (leftType.IsPrimitive &&
5479- // TryReduceComparisonByEvalConstantsAndArithmetics (out bool result, left, right, nodeType == ExpressionType.Equal ))
5609+ // TryReduceArithmeticsOrComparisonOrLogical (out bool result, nodeType, left, right ))
54805610 // {
54815611 // il.Demit((bool)result ? OpCodes.Ldc_I4_1 : OpCodes.Ldc_I4_0);
54825612 // return il.EmitPopIfIgnoreResult(parent);
@@ -6074,28 +6204,30 @@ private static Expression TryReduceCondition(Expression testExpr)
60746204 {
60756205 // simplify the not `==` -> `!=`, `!=` -> `==`
60766206 var op = TryReduceCondition(((UnaryExpression)testExpr).Operand);
6077- if (op.NodeType == ExpressionType.Equal) // ensures that it is a BinaryExpression
6207+ var nodeType = op.NodeType;
6208+ if (nodeType == ExpressionType.Equal) // ensures that it is a BinaryExpression
60786209 {
60796210 var binOp = (BinaryExpression)op;
60806211 return NotEqual(binOp.Left, binOp.Right);
60816212 }
6082- else if (op.NodeType == ExpressionType.NotEqual) // ensures that it is a BinaryExpression
6213+ else if (nodeType == ExpressionType.NotEqual) // ensures that it is a BinaryExpression
60836214 {
60846215 var binOp = (BinaryExpression)op;
60856216 return Equal(binOp.Left, binOp.Right);
60866217 }
60876218 }
60886219 else if (testExpr is BinaryExpression b)
60896220 {
6090- if (b.NodeType == ExpressionType.OrElse || b.NodeType == ExpressionType.Or)
6221+ var nodeType = b.NodeType;
6222+ if (nodeType == ExpressionType.OrElse | nodeType == ExpressionType.Or)
60916223 {
60926224 if (b.Left is ConstantExpression lc && lc.Value is bool lcb)
60936225 return lcb ? lc : TryReduceCondition(b.Right);
60946226
60956227 if (b.Right is ConstantExpression rc && rc.Value is bool rcb && !rcb)
60966228 return TryReduceCondition(b.Left);
60976229 }
6098- else if (b.NodeType == ExpressionType.AndAlso || b.NodeType == ExpressionType.And)
6230+ else if (nodeType == ExpressionType.AndAlso | nodeType == ExpressionType.And)
60996231 {
61006232 if (b.Left is ConstantExpression lc && lc.Value is bool lcb)
61016233 return !lcb ? lc : TryReduceCondition(b.Right);
0 commit comments