private static void EmitNumericConversion(ILGenerator il, Type typeFrom, Type typeTo, bool isChecked) { if ( !(typeFrom.IsEnum || TypeUtil.IsNumeric(typeFrom)) || !(typeTo.IsEnum || TypeUtil.IsNumeric(typeTo)) ) { throw new InvalidOperationException("Unhandled convert"); } bool isFromUnsigned = TypeUtil.IsUnsigned(typeFrom); bool isFromFloatingPoint = TypeUtil.IsFloatingPoint(typeFrom); if (typeTo == typeof(Single)) { if (isFromUnsigned) { il.Emit(OpCodes.Conv_R_Un); } il.Emit(OpCodes.Conv_R4); } else if (typeTo == typeof(Double)) { if (isFromUnsigned) { il.Emit(OpCodes.Conv_R_Un); } il.Emit(OpCodes.Conv_R8); } else { TypeCode tc = Type.GetTypeCode(typeTo); if (isChecked) { // Overflow checking needs to know if the source value on the IL stack is unsigned or not. if (isFromUnsigned) { switch (tc) { case TypeCode.SByte: il.Emit(OpCodes.Conv_Ovf_I1_Un); break; case TypeCode.Int16: il.Emit(OpCodes.Conv_Ovf_I2_Un); break; case TypeCode.Int32: il.Emit(OpCodes.Conv_Ovf_I4_Un); break; case TypeCode.Int64: il.Emit(OpCodes.Conv_Ovf_I8_Un); break; case TypeCode.Byte: il.Emit(OpCodes.Conv_Ovf_U1_Un); break; case TypeCode.UInt16: case TypeCode.Char: il.Emit(OpCodes.Conv_Ovf_U2_Un); break; case TypeCode.UInt32: il.Emit(OpCodes.Conv_Ovf_U4_Un); break; case TypeCode.UInt64: il.Emit(OpCodes.Conv_Ovf_U8_Un); break; default: throw new InvalidOperationException("Unhandled convert"); } } else { switch (tc) { case TypeCode.SByte: il.Emit(OpCodes.Conv_Ovf_I1); break; case TypeCode.Int16: il.Emit(OpCodes.Conv_Ovf_I2); break; case TypeCode.Int32: il.Emit(OpCodes.Conv_Ovf_I4); break; case TypeCode.Int64: il.Emit(OpCodes.Conv_Ovf_I8); break; case TypeCode.Byte: il.Emit(OpCodes.Conv_Ovf_U1); break; case TypeCode.UInt16: case TypeCode.Char: il.Emit(OpCodes.Conv_Ovf_U2); break; case TypeCode.UInt32: il.Emit(OpCodes.Conv_Ovf_U4); break; case TypeCode.UInt64: il.Emit(OpCodes.Conv_Ovf_U8); break; default: throw new InvalidOperationException("Unhandled convert"); } } } else { switch (tc) { case TypeCode.SByte: il.Emit(OpCodes.Conv_I1); break; case TypeCode.Byte: il.Emit(OpCodes.Conv_U1); break; case TypeCode.Int16: il.Emit(OpCodes.Conv_I2); break; case TypeCode.UInt16: case TypeCode.Char: il.Emit(OpCodes.Conv_U2); break; case TypeCode.Int32: il.Emit(OpCodes.Conv_I4); break; case TypeCode.UInt32: il.Emit(OpCodes.Conv_U4); break; case TypeCode.Int64: if (isFromUnsigned) { il.Emit(OpCodes.Conv_U8); } else { il.Emit(OpCodes.Conv_I8); } break; case TypeCode.UInt64: if (isFromUnsigned || isFromFloatingPoint) { il.Emit(OpCodes.Conv_U8); } else { il.Emit(OpCodes.Conv_I8); } break; default: throw new InvalidOperationException("Unhandled convert"); } } } }
private Type ResolveExpressionType(Type left, Type right, Type commonType, ExpressionType type) { Require.NotNull(left, "left"); Require.NotNull(right, "right"); // TODO: Implicit/explicit operators and operators for the expression type. // Boolean operators. switch (type) { case ExpressionType.And: case ExpressionType.Or: case ExpressionType.Xor: case ExpressionType.AndBoth: case ExpressionType.OrBoth: if (TypeUtil.IsInteger(commonType)) { return(commonType); } else if (left != typeof(bool) || right != typeof(bool)) { throw new ExpressionsException("Invalid operand for expression type", ExpressionsExceptionType.TypeMismatch); } return(typeof(bool)); case ExpressionType.Greater: case ExpressionType.GreaterOrEquals: case ExpressionType.Less: case ExpressionType.LessOrEquals: if ( !(left.IsEnum || TypeUtil.IsNumeric(left)) || !(right.IsEnum || TypeUtil.IsNumeric(right)) ) { throw new ExpressionsException("Invalid operand for expression type", ExpressionsExceptionType.TypeMismatch); } return(typeof(bool)); case ExpressionType.Equals: case ExpressionType.NotEquals: case ExpressionType.In: case ExpressionType.LogicalAnd: case ExpressionType.LogicalOr: case ExpressionType.Compares: case ExpressionType.NotCompares: return(typeof(bool)); case ExpressionType.Add: if ( !(left == typeof(string) || right == typeof(string)) && !(TypeUtil.IsNumeric(left) && TypeUtil.IsNumeric(right)) ) { throw new ExpressionsException("Invalid operand for expression type", ExpressionsExceptionType.TypeMismatch); } return(commonType); case ExpressionType.Subtract: case ExpressionType.Multiply: case ExpressionType.Divide: case ExpressionType.Power: if (!TypeUtil.IsNumeric(left) || !TypeUtil.IsNumeric(right)) { throw new ExpressionsException("Invalid operand for expression type", ExpressionsExceptionType.TypeMismatch); } return(commonType); default: return(commonType); } }