📄 convert.cs
字号:
return new ConvCast (expr, target_type, ConvCast.Mode.R8_I8); if (real_target_type == TypeManager.uint64_type) return new ConvCast (expr, target_type, ConvCast.Mode.R8_U8); if (real_target_type == TypeManager.char_type) return new ConvCast (expr, target_type, ConvCast.Mode.R8_CH); if (real_target_type == TypeManager.float_type) return new ConvCast (expr, target_type, ConvCast.Mode.R8_R4); if (real_target_type == TypeManager.decimal_type) return new CastToDecimal (expr, true); } else if (expr_type == TypeManager.decimal_type) { return new CastFromDecimal (expr, target_type).Resolve (); } return null; } /// <summary> /// Returns whether an explicit reference conversion can be performed /// from source_type to target_type /// </summary> public static bool ExplicitReferenceConversionExists (Type source_type, Type target_type) { bool target_is_value_type = target_type.IsValueType; if (source_type == target_type) return true; // // From object to any reference type // if (source_type == TypeManager.object_type && !target_is_value_type) return true; // // From any class S to any class-type T, provided S is a base class of T // if (target_type.IsSubclassOf (source_type)) return true; // // From any interface type S to any interface T provided S is not derived from T // if (source_type.IsInterface && target_type.IsInterface){ if (!target_type.IsSubclassOf (source_type)) return true; } // // From any class type S to any interface T, provided S is not sealed // and provided S does not implement T. // if (target_type.IsInterface && !source_type.IsSealed && !TypeManager.ImplementsInterface (source_type, target_type)) return true; // // From any interface-type S to to any class type T, provided T is not // sealed, or provided T implements S. // if (source_type.IsInterface && (!target_type.IsSealed || TypeManager.ImplementsInterface (target_type, source_type))) return true; // From an array type S with an element type Se to an array type T with an // element type Te provided all the following are true: // * S and T differe only in element type, in other words, S and T // have the same number of dimensions. // * Both Se and Te are reference types // * An explicit referenc conversions exist from Se to Te // if (source_type.IsArray && target_type.IsArray) { if (source_type.GetArrayRank () == target_type.GetArrayRank ()) { Type source_element_type = TypeManager.GetElementType (source_type); Type target_element_type = TypeManager.GetElementType (target_type); if (!source_element_type.IsValueType && !target_element_type.IsValueType) if (ExplicitReferenceConversionExists (source_element_type, target_element_type)) return true; } } // From System.Array to any array-type if (source_type == TypeManager.array_type && target_type.IsArray){ return true; } // // From System delegate to any delegate-type // if (source_type == TypeManager.delegate_type && target_type.IsSubclassOf (TypeManager.delegate_type)) return true; // // From ICloneable to Array or Delegate types // if (source_type == TypeManager.icloneable_type && (target_type == TypeManager.array_type || target_type == TypeManager.delegate_type)) return true; return false; } /// <summary> /// Implements Explicit Reference conversions /// </summary> static Expression ExplicitReferenceConversion (Expression source, Type target_type) { Type source_type = source.Type; bool target_is_value_type = target_type.IsValueType; // // From object to any reference type // if (source_type == TypeManager.object_type && !target_is_value_type) return new ClassCast (source, target_type); // // Unboxing conversion. // if (((source_type == TypeManager.enum_type && !(source is EmptyCast)) || source_type == TypeManager.value_type) && target_is_value_type) return new UnboxCast (source, target_type); // // From any class S to any class-type T, provided S is a base class of T // if (target_type.IsSubclassOf (source_type)) return new ClassCast (source, target_type); // // From any interface type S to any interface T provided S is not derived from T // if (source_type.IsInterface && target_type.IsInterface){ if (TypeManager.ImplementsInterface (source_type, target_type)) return null; else return new ClassCast (source, target_type); } // // From any class type S to any interface T, provides S is not sealed // and provided S does not implement T. // if (target_type.IsInterface && !source_type.IsSealed) { if (TypeManager.ImplementsInterface (source_type, target_type)) return null; else return new ClassCast (source, target_type); } // // From any interface-type S to to any class type T, provided T is not // sealed, or provided T implements S. // if (source_type.IsInterface) { if (!target_type.IsSealed || TypeManager.ImplementsInterface (target_type, source_type)) { if (target_type.IsClass) return new ClassCast (source, target_type); else return new UnboxCast (source, target_type); } return null; } // From an array type S with an element type Se to an array type T with an // element type Te provided all the following are true: // * S and T differe only in element type, in other words, S and T // have the same number of dimensions. // * Both Se and Te are reference types // * An explicit referenc conversions exist from Se to Te // if (source_type.IsArray && target_type.IsArray) { if (source_type.GetArrayRank () == target_type.GetArrayRank ()) { Type source_element_type = TypeManager.GetElementType (source_type); Type target_element_type = TypeManager.GetElementType (target_type); if (!source_element_type.IsValueType && !target_element_type.IsValueType) if (ExplicitReferenceConversionExists (source_element_type, target_element_type)) return new ClassCast (source, target_type); } } // From System.Array to any array-type if (source_type == TypeManager.array_type && target_type.IsArray) { return new ClassCast (source, target_type); } // // From System delegate to any delegate-type // if (source_type == TypeManager.delegate_type && target_type.IsSubclassOf (TypeManager.delegate_type)) return new ClassCast (source, target_type); // // From ICloneable to Array or Delegate types // if (source_type == TypeManager.icloneable_type && (target_type == TypeManager.array_type || target_type == TypeManager.delegate_type)) return new ClassCast (source, target_type); return null; } /// <summary> /// Performs an explicit conversion of the expression `expr' whose /// type is expr.Type to `target_type'. /// </summary> static public Expression ExplicitConversionCore (EmitContext ec, Expression expr, Type target_type, Location loc) { Type expr_type = expr.Type; // Explicit conversion includes implicit conversion and it used for enum underlying types too Expression ne = ImplicitConversionStandard (ec, expr, target_type, loc); if (ne != null) return ne; // // Unboxing conversions; only object types can be convertible to enum // if (expr_type == TypeManager.object_type && target_type.IsValueType || expr_type == TypeManager.enum_type) return new UnboxCast (expr, target_type); if (TypeManager.IsEnumType (expr_type)) { if (expr is EnumConstant) return ExplicitConversionCore (ec, ((EnumConstant) expr).Child, target_type, loc); return ExplicitConversionCore (ec, new EmptyCast (expr, TypeManager.EnumToUnderlying (expr_type)), target_type, loc); } if (TypeManager.IsEnumType (target_type)) return new EmptyCast (ExplicitConversionCore (ec, expr, TypeManager.EnumToUnderlying (target_type), loc), target_type); ne = ExplicitNumericConversion (expr, target_type); if (ne != null) return ne; // // Skip the ExplicitReferenceConversion because we can not convert // from Null to a ValueType, and ExplicitReference wont check against // null literal explicitly // if (expr_type != TypeManager.null_type){ ne = ExplicitReferenceConversion (expr, target_type); if (ne != null) return ne; } if (ec.InUnsafe){ ne = ExplicitUnsafe (expr, target_type); if (ne != null) return ne; } ne = ExplicitUserConversion (ec, expr, target_type, loc); if (ne != null) return ne; return null; } public static Expression ExplicitUnsafe (Expression expr, Type target_type) { Type expr_type = expr.Type; if (target_type.IsPointer){ if (expr_type.IsPointer) return new EmptyCast (expr, target_type); if (expr_type == TypeManager.sbyte_type || expr_type == TypeManager.short_type || expr_type == TypeManager.int32_type || expr_type == TypeManager.int64_type) return new OpcodeCast (expr, target_type, OpCodes.Conv_I); if (expr_type == TypeManager.ushort_type || expr_type == TypeManager.uint32_type || expr_type == TypeManager.uint64_type || expr_type == TypeManager.byte_type) return new OpcodeCast (expr, target_type, OpCodes.Conv_U); } if (expr_type.IsPointer){ if (target_type == TypeManager.sbyte_type) return new OpcodeCast (expr, target_type, OpCodes.Conv_I1); else if (target_type == TypeManager.byte_type) return new OpcodeCast (expr, target_type, OpCodes.Conv_U1); else if (target_type == TypeManager.short_type) return new OpcodeCast (expr, target_type, OpCodes.Conv_I2); else if (target_type == TypeManager.ushort_type) return new OpcodeCast (expr, target_type, OpCodes.Conv_U2); else if (target_type == TypeManager.int32_type) return new OpcodeCast (expr, target_type, OpCodes.Conv_I4); else if (target_type == TypeManager.uint32_type) return new OpcodeCast (expr, target_type, OpCodes.Conv_U4); else if (target_type == TypeManager.uint64_type) return new OpcodeCast (expr, target_type, OpCodes.Conv_U8); else if (target_type == TypeManager.int64_type){ return new OpcodeCast (expr, target_type, OpCodes.Conv_I8); } } return null; } /// <summary> /// Same as ExplicitConversion, only it doesn't include user defined conversions /// </summary> static public Expression ExplicitConversionStandard (EmitContext ec, Expression expr, Type target_type, Location l) { Expression ne = ImplicitConversionStandard (ec, expr, target_type, l); if (ne != null) return ne; ne = ExplicitNumericConversion (expr, target_type); if (ne != null) return ne; ne = ExplicitReferenceConversion (expr, target_type); if (ne != null) return ne; if (ec.InUnsafe && expr.Type == TypeManager.void_ptr_type && target_type.IsPointer) return new EmptyCast (expr, target_type); expr.Error_ValueCannotBeConverted (l, target_type, true); return null; } /// <summary> /// Performs an explicit conversion of the expression `expr' whose /// type is expr.Type to `target_type'. /// </summary> static public Expression ExplicitConversion (EmitContext ec, Expression expr, Type target_type, Location loc) { Expression e = ExplicitConversionCore (ec, expr, target_type, loc); if (e != null) return e; expr.Error_ValueCannotBeConverted (loc, target_type, true); return null; } }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -