public IType GetPromotedNumberType(IType left, IType right)
{
if (left == DecimalType || right == DecimalType)
return DecimalType;
if (left == DoubleType || right == DoubleType)
return DoubleType;
if (left == SingleType || right == SingleType)
return SingleType;
if (left == ULongType)
{
if (IsSignedInteger(right))
{
// This is against the C# spec but allows expressions like:
// ulong x = 4
// y = x + 1
// y will be long.
// C# disallows mixing ulongs and signed numbers
// but in the above case it promotes the constant to ulong
// and the result is ulong.
// Since its too late here to promote the constant,
// maybe we should return LongType. I didn't chose ULongType
// because in other cases <unsigned> <op> <signed> returns <signed>.
return LongType;
}
return ULongType;
}
if (right == ULongType)
{
if (IsSignedInteger(left))
{
// This is against the C# spec but allows expressions like:
// ulong x = 4
// y = 1 + x
// y will be long.
// C# disallows mixing ulongs and signed numbers
// but in the above case it promotes the constant to ulong
// and the result is ulong.
// Since its too late here to promote the constant,
// maybe we should return LongType. I didn't chose ULongType
// because in other cases <signed> <op> <unsigned> returns <signed>.
return LongType;
}
return ULongType;
}
if (left == LongType || right == LongType)
return LongType;
if (left == UIntType)
{
if (right == SByteType || right == ShortType || right == IntType)
{
// This is allowed per C# spec and y is long:
// uint x = 4
// y = x + 1
// C# promotes <uint> <op> <signed> to <long> also
// but in the above case it promotes the constant to uint first
// and the result of "x + 1" is uint.
// Since its too late here to promote the constant,
// "y = x + 1" will be long in boo.
return LongType;
}
return UIntType;
}
if (right == UIntType)
{
if (left == SByteType || left == ShortType || left == IntType)
{
// This is allowed per C# spec and y is long:
// uint x = 4
// y = 1 + x
// C# promotes <signed> <op> <uint> to <long> also
// but in the above case it promotes the constant to uint first
// and the result of "1 + x" is uint.
// Since its too late here to promote the constant,
// "y = x + 1" will be long in boo.
return LongType;
}
return UIntType;
}
if (left == IntType ||
right == IntType ||
left == ShortType ||
right == ShortType ||
left == UShortType ||
right == UShortType ||
left == ByteType ||
right == ByteType ||
left == SByteType ||
right == SByteType)
return IntType;
return left;
}