📄 convert.cs
字号:
// // Only allow anonymous method conversions on post ISO_1 // if (RootContext.Version != LanguageVersion.ISO_1){ MethodGroupExpr mg = expr as MethodGroupExpr; if (mg != null) return ImplicitDelegateCreation.Create ( ec, mg, target_type, false, loc); } } if (expr_type == target_type && expr_type != TypeManager.null_type) return expr; e = ImplicitNumericConversion (ec, expr, target_type); if (e != null) return e; e = ImplicitReferenceConversion (expr, target_type); if (e != null) return e; if ((target_type == TypeManager.enum_type || target_type.IsSubclassOf (TypeManager.enum_type)) && expr is IntLiteral){ IntLiteral i = (IntLiteral) expr; if (i.Value == 0) return new EnumConstant ((Constant) expr, target_type); } if (ec.InUnsafe) { if (expr_type.IsPointer){ if (target_type == TypeManager.void_ptr_type) return new EmptyCast (expr, target_type); // // yep, comparing pointer types cant be done with // t1 == t2, we have to compare their element types. // if (target_type.IsPointer){ if (TypeManager.GetElementType(target_type) == TypeManager.GetElementType(expr_type)) return expr; //return null; } } if (expr_type == TypeManager.null_type && target_type.IsPointer) return new EmptyCast (NullPointer.Null, target_type); } if (expr_type == TypeManager.anonymous_method_type){ if (!TypeManager.IsDelegateType (target_type)){ Report.Error (1660, loc, "Cannot convert anonymous method block to type `{0}' because it is not a delegate type", TypeManager.CSharpName (target_type)); return null; } AnonymousMethod am = (AnonymousMethod) expr; int errors = Report.Errors; Expression conv = am.Compatible (ec, target_type, false); if (conv != null) return conv; // // We return something instead of null, to avoid // the duplicate error, since am.Compatible would have // reported that already // if (errors != Report.Errors) return new EmptyCast (expr, target_type); } return null; } /// <summary> /// Attempts to perform an implicit constant conversion of the IntConstant /// into a different data type using casts (See Implicit Constant /// Expression Conversions) /// </summary> static public Expression TryImplicitIntConversion (Type target_type, IntConstant ic) { int value = ic.Value; if (target_type == TypeManager.sbyte_type){ if (value >= SByte.MinValue && value <= SByte.MaxValue) return new SByteConstant ((sbyte) value, ic.Location); } else if (target_type == TypeManager.byte_type){ if (value >= Byte.MinValue && value <= Byte.MaxValue) return new ByteConstant ((byte) value, ic.Location); } else if (target_type == TypeManager.short_type){ if (value >= Int16.MinValue && value <= Int16.MaxValue) return new ShortConstant ((short) value, ic.Location); } else if (target_type == TypeManager.ushort_type){ if (value >= UInt16.MinValue && value <= UInt16.MaxValue) return new UShortConstant ((ushort) value, ic.Location); } else if (target_type == TypeManager.uint32_type){ if (value >= 0) return new UIntConstant ((uint) value, ic.Location); } else if (target_type == TypeManager.uint64_type){ // // we can optimize this case: a positive int32 // always fits on a uint64. But we need an opcode // to do it. // if (value >= 0) return new ULongConstant ((ulong) value, ic.Location); } else if (target_type == TypeManager.double_type) return new DoubleConstant ((double) value, ic.Location); else if (target_type == TypeManager.float_type) return new FloatConstant ((float) value, ic.Location); if (value == 0 && ic is IntLiteral && TypeManager.IsEnumType (target_type)){ Type underlying = TypeManager.EnumToUnderlying (target_type); Constant e = (Constant) ic; // // Possibly, we need to create a different 0 literal before passing // to EnumConstant // if (underlying == TypeManager.int64_type) e = new LongLiteral (0, ic.Location); else if (underlying == TypeManager.uint64_type) e = new ULongLiteral (0, ic.Location); return new EnumConstant (e, target_type); } // // If `target_type' is an interface and the type of `ic' implements the interface // e.g. target_type is IComparable, IConvertible, IFormattable // if (target_type.IsInterface && target_type.IsAssignableFrom (ic.Type)) return new BoxedCast (ic, target_type); return null; } /// <summary> /// Attempts to implicitly convert `source' into `target_type', using /// ImplicitConversion. If there is no implicit conversion, then /// an error is signaled /// </summary> static public Expression ImplicitConversionRequired (EmitContext ec, Expression source, Type target_type, Location loc) { Expression e; e = ImplicitConversion (ec, source, target_type, loc); if (e != null) return e; if (source is DoubleLiteral) { if (target_type == TypeManager.float_type) { Error_664 (loc, "float", "f"); return null; } if (target_type == TypeManager.decimal_type) { Error_664 (loc, "decimal", "m"); return null; } } source.Error_ValueCannotBeConverted (loc, target_type, false); return null; } static void Error_664 (Location loc, string type, string suffix) { Report.Error (664, loc, "Literal of type double cannot be implicitly converted to type `{0}'. Add suffix `{1}' to create a literal of this type", type, suffix); } /// <summary> /// Performs the explicit numeric conversions /// </summary> public static Expression ExplicitNumericConversion (Expression expr, Type target_type) { Type expr_type = expr.Type; Type real_target_type = target_type; if (expr_type == TypeManager.sbyte_type){ // // From sbyte to byte, ushort, uint, ulong, char // if (real_target_type == TypeManager.byte_type) return new ConvCast (expr, target_type, ConvCast.Mode.I1_U1); if (real_target_type == TypeManager.ushort_type) return new ConvCast (expr, target_type, ConvCast.Mode.I1_U2); if (real_target_type == TypeManager.uint32_type) return new ConvCast (expr, target_type, ConvCast.Mode.I1_U4); if (real_target_type == TypeManager.uint64_type) return new ConvCast (expr, target_type, ConvCast.Mode.I1_U8); if (real_target_type == TypeManager.char_type) return new ConvCast (expr, target_type, ConvCast.Mode.I1_CH); } else if (expr_type == TypeManager.byte_type){ // // From byte to sbyte and char // if (real_target_type == TypeManager.sbyte_type) return new ConvCast (expr, target_type, ConvCast.Mode.U1_I1); if (real_target_type == TypeManager.char_type) return new ConvCast (expr, target_type, ConvCast.Mode.U1_CH); } else if (expr_type == TypeManager.short_type){ // // From short to sbyte, byte, ushort, uint, ulong, char // if (real_target_type == TypeManager.sbyte_type) return new ConvCast (expr, target_type, ConvCast.Mode.I2_I1); if (real_target_type == TypeManager.byte_type) return new ConvCast (expr, target_type, ConvCast.Mode.I2_U1); if (real_target_type == TypeManager.ushort_type) return new ConvCast (expr, target_type, ConvCast.Mode.I2_U2); if (real_target_type == TypeManager.uint32_type) return new ConvCast (expr, target_type, ConvCast.Mode.I2_U4); if (real_target_type == TypeManager.uint64_type) return new ConvCast (expr, target_type, ConvCast.Mode.I2_U8); if (real_target_type == TypeManager.char_type) return new ConvCast (expr, target_type, ConvCast.Mode.I2_CH); } else if (expr_type == TypeManager.ushort_type){ // // From ushort to sbyte, byte, short, char // if (real_target_type == TypeManager.sbyte_type) return new ConvCast (expr, target_type, ConvCast.Mode.U2_I1); if (real_target_type == TypeManager.byte_type) return new ConvCast (expr, target_type, ConvCast.Mode.U2_U1); if (real_target_type == TypeManager.short_type) return new ConvCast (expr, target_type, ConvCast.Mode.U2_I2); if (real_target_type == TypeManager.char_type) return new ConvCast (expr, target_type, ConvCast.Mode.U2_CH); } else if (expr_type == TypeManager.int32_type){ // // From int to sbyte, byte, short, ushort, uint, ulong, char // if (real_target_type == TypeManager.sbyte_type) return new ConvCast (expr, target_type, ConvCast.Mode.I4_I1); if (real_target_type == TypeManager.byte_type) return new ConvCast (expr, target_type, ConvCast.Mode.I4_U1); if (real_target_type == TypeManager.short_type) return new ConvCast (expr, target_type, ConvCast.Mode.I4_I2); if (real_target_type == TypeManager.ushort_type) return new ConvCast (expr, target_type, ConvCast.Mode.I4_U2); if (real_target_type == TypeManager.uint32_type) return new ConvCast (expr, target_type, ConvCast.Mode.I4_U4); if (real_target_type == TypeManager.uint64_type) return new ConvCast (expr, target_type, ConvCast.Mode.I4_U8); if (real_target_type == TypeManager.char_type) return new ConvCast (expr, target_type, ConvCast.Mode.I4_CH); } else if (expr_type == TypeManager.uint32_type){ // // From uint to sbyte, byte, short, ushort, int, char // if (real_target_type == TypeManager.sbyte_type) return new ConvCast (expr, target_type, ConvCast.Mode.U4_I1); if (real_target_type == TypeManager.byte_type) return new ConvCast (expr, target_type, ConvCast.Mode.U4_U1); if (real_target_type == TypeManager.short_type) return new ConvCast (expr, target_type, ConvCast.Mode.U4_I2); if (real_target_type == TypeManager.ushort_type) return new ConvCast (expr, target_type, ConvCast.Mode.U4_U2); if (real_target_type == TypeManager.int32_type) return new ConvCast (expr, target_type, ConvCast.Mode.U4_I4); if (real_target_type == TypeManager.char_type) return new ConvCast (expr, target_type, ConvCast.Mode.U4_CH); } else if (expr_type == TypeManager.int64_type){ // // From long to sbyte, byte, short, ushort, int, uint, ulong, char // if (real_target_type == TypeManager.sbyte_type) return new ConvCast (expr, target_type, ConvCast.Mode.I8_I1); if (real_target_type == TypeManager.byte_type) return new ConvCast (expr, target_type, ConvCast.Mode.I8_U1); if (real_target_type == TypeManager.short_type) return new ConvCast (expr, target_type, ConvCast.Mode.I8_I2); if (real_target_type == TypeManager.ushort_type) return new ConvCast (expr, target_type, ConvCast.Mode.I8_U2); if (real_target_type == TypeManager.int32_type) return new ConvCast (expr, target_type, ConvCast.Mode.I8_I4); if (real_target_type == TypeManager.uint32_type) return new ConvCast (expr, target_type, ConvCast.Mode.I8_U4); if (real_target_type == TypeManager.uint64_type) return new ConvCast (expr, target_type, ConvCast.Mode.I8_U8); if (real_target_type == TypeManager.char_type) return new ConvCast (expr, target_type, ConvCast.Mode.I8_CH); } else if (expr_type == TypeManager.uint64_type){ // // From ulong to sbyte, byte, short, ushort, int, uint, long, char // if (real_target_type == TypeManager.sbyte_type) return new ConvCast (expr, target_type, ConvCast.Mode.U8_I1); if (real_target_type == TypeManager.byte_type) return new ConvCast (expr, target_type, ConvCast.Mode.U8_U1); if (real_target_type == TypeManager.short_type) return new ConvCast (expr, target_type, ConvCast.Mode.U8_I2); if (real_target_type == TypeManager.ushort_type) return new ConvCast (expr, target_type, ConvCast.Mode.U8_U2); if (real_target_type == TypeManager.int32_type) return new ConvCast (expr, target_type, ConvCast.Mode.U8_I4); if (real_target_type == TypeManager.uint32_type) return new ConvCast (expr, target_type, ConvCast.Mode.U8_U4); if (real_target_type == TypeManager.int64_type) return new ConvCast (expr, target_type, ConvCast.Mode.U8_I8); if (real_target_type == TypeManager.char_type) return new ConvCast (expr, target_type, ConvCast.Mode.U8_CH); } else if (expr_type == TypeManager.char_type){ // // From char to sbyte, byte, short // if (real_target_type == TypeManager.sbyte_type) return new ConvCast (expr, target_type, ConvCast.Mode.CH_I1); if (real_target_type == TypeManager.byte_type) return new ConvCast (expr, target_type, ConvCast.Mode.CH_U1); if (real_target_type == TypeManager.short_type) return new ConvCast (expr, target_type, ConvCast.Mode.CH_I2); } else if (expr_type == TypeManager.float_type){ // // From float to sbyte, byte, short, // ushort, int, uint, long, ulong, char // or decimal // if (real_target_type == TypeManager.sbyte_type) return new ConvCast (expr, target_type, ConvCast.Mode.R4_I1); if (real_target_type == TypeManager.byte_type) return new ConvCast (expr, target_type, ConvCast.Mode.R4_U1); if (real_target_type == TypeManager.short_type) return new ConvCast (expr, target_type, ConvCast.Mode.R4_I2); if (real_target_type == TypeManager.ushort_type) return new ConvCast (expr, target_type, ConvCast.Mode.R4_U2); if (real_target_type == TypeManager.int32_type) return new ConvCast (expr, target_type, ConvCast.Mode.R4_I4); if (real_target_type == TypeManager.uint32_type) return new ConvCast (expr, target_type, ConvCast.Mode.R4_U4); if (real_target_type == TypeManager.int64_type) return new ConvCast (expr, target_type, ConvCast.Mode.R4_I8); if (real_target_type == TypeManager.uint64_type) return new ConvCast (expr, target_type, ConvCast.Mode.R4_U8); if (real_target_type == TypeManager.char_type) return new ConvCast (expr, target_type, ConvCast.Mode.R4_CH); if (real_target_type == TypeManager.decimal_type) return new CastToDecimal (expr, true); } else if (expr_type == TypeManager.double_type){ // // From double to sbyte, byte, short, // ushort, int, uint, long, ulong, // char, float or decimal // if (real_target_type == TypeManager.sbyte_type) return new ConvCast (expr, target_type, ConvCast.Mode.R8_I1); if (real_target_type == TypeManager.byte_type) return new ConvCast (expr, target_type, ConvCast.Mode.R8_U1); if (real_target_type == TypeManager.short_type) return new ConvCast (expr, target_type, ConvCast.Mode.R8_I2); if (real_target_type == TypeManager.ushort_type) return new ConvCast (expr, target_type, ConvCast.Mode.R8_U2); if (real_target_type == TypeManager.int32_type) return new ConvCast (expr, target_type, ConvCast.Mode.R8_I4); if (real_target_type == TypeManager.uint32_type) return new ConvCast (expr, target_type, ConvCast.Mode.R8_U4); if (real_target_type == TypeManager.int64_type)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -