bool BinaryNumericPromotion(bool isNullable, ref ResolveResult lhs, ref ResolveResult rhs, bool allowNullableConstants)
{
// C# 4.0 spec: §7.3.6.2
TypeCode lhsCode = ReflectionHelper.GetTypeCode(NullableType.GetUnderlyingType(lhs.Type));
TypeCode rhsCode = ReflectionHelper.GetTypeCode(NullableType.GetUnderlyingType(rhs.Type));
// if one of the inputs is the null literal, promote that to the type of the other operand
if (isNullable && lhs.Type.Kind == TypeKind.Null && rhsCode >= TypeCode.Boolean && rhsCode <= TypeCode.Decimal) {
lhs = CastTo(rhsCode, isNullable, lhs, allowNullableConstants);
lhsCode = rhsCode;
} else if (isNullable && rhs.Type.Kind == TypeKind.Null && lhsCode >= TypeCode.Boolean && lhsCode <= TypeCode.Decimal) {
rhs = CastTo(lhsCode, isNullable, rhs, allowNullableConstants);
rhsCode = lhsCode;
}
bool bindingError = false;
if (lhsCode >= TypeCode.Char && lhsCode <= TypeCode.Decimal
&& rhsCode >= TypeCode.Char && rhsCode <= TypeCode.Decimal)
{
TypeCode targetType;
if (lhsCode == TypeCode.Decimal || rhsCode == TypeCode.Decimal) {
targetType = TypeCode.Decimal;
bindingError = (lhsCode == TypeCode.Single || lhsCode == TypeCode.Double
|| rhsCode == TypeCode.Single || rhsCode == TypeCode.Double);
} else if (lhsCode == TypeCode.Double || rhsCode == TypeCode.Double) {
targetType = TypeCode.Double;
} else if (lhsCode == TypeCode.Single || rhsCode == TypeCode.Single) {
targetType = TypeCode.Single;
} else if (lhsCode == TypeCode.UInt64 || rhsCode == TypeCode.UInt64) {
targetType = TypeCode.UInt64;
bindingError = IsSigned(lhsCode, lhs) || IsSigned(rhsCode, rhs);
} else if (lhsCode == TypeCode.Int64 || rhsCode == TypeCode.Int64) {
targetType = TypeCode.Int64;
} else if (lhsCode == TypeCode.UInt32 || rhsCode == TypeCode.UInt32) {
targetType = (IsSigned(lhsCode, lhs) || IsSigned(rhsCode, rhs)) ? TypeCode.Int64 : TypeCode.UInt32;
} else {
targetType = TypeCode.Int32;
}
lhs = CastTo(targetType, isNullable, lhs, allowNullableConstants);
rhs = CastTo(targetType, isNullable, rhs, allowNullableConstants);
}
return !bindingError;
}