internal static ConversionSymbol ResolveDynamicConversion(Expr expr, TypeSymbol type, BindOptions options) { if (expr.Datatype.NativeType == NativeType.Object) { var inner = Conversion(expr, Compilation.Get(NativeType.Usual), options); var outer = Conversion(TypeConversion.Bound(expr, Compilation.Get(NativeType.Usual), inner), type, options); if (outer.Exists) { return(ConversionSymbol.Create(outer, inner)); } } return(null); }
internal static ConversionSymbol ResolveUsualConversion(Expr expr, TypeSymbol type, BindOptions options) { if (expr.Datatype.NativeType == NativeType.Usual) { if (type.NativeType == NativeType.Object) { if (options.HasFlag(BindOptions.BoxUsual)) { return(ConversionSymbol.Create(ConversionKind.Boxing)); } else { MethodSymbol converter = null; ResolveConversionMethod(expr, type, Compilation.Get(NativeType.Usual).Lookup(XSharpFunctionNames.ToObject), ref converter, options); if (converter != null) { return(ConversionSymbol.Create(ConversionKind.ImplicitUserDefined, converter)); } } } else { MethodSymbol converter = null; ResolveConversionMethod(expr, Compilation.Get(NativeType.Object), Compilation.Get(NativeType.Usual).Lookup(XSharpFunctionNames.ToObject), ref converter, options); if (converter != null) { var inner = ConversionSymbol.Create(ConversionKind.ImplicitUserDefined, converter); var outer = type.IsReferenceType ? ConversionSymbol.Create(ConversionKind.ExplicitReference) : type.IsValueType ? ConversionSymbol.Create(ConversionKind.Unboxing) : ConversionSymbol.Create(ConversionKind.NoConversion); if (outer.Exists) { return(ConversionSymbol.Create(outer, inner)); } } } } else if (type.NativeType == NativeType.Usual && expr.Datatype.IsReferenceType) { var inner = Conversion(expr, Compilation.Get(NativeType.Object), options | BindOptions.Explicit); if (inner.Exists) { var outer = Conversion(TypeConversion.Bound(expr, Compilation.Get(NativeType.Object), inner), type, options); if (outer.Exists) { return(ConversionSymbol.Create(outer, inner)); } } } return(null); }
internal static ConversionSymbol ResolveByRefConversion(Expr expr, TypeSymbol type, BindOptions options) { if (type.IsByRef && TypesMatch(expr.Datatype, type.ElementType)) { return(ConversionSymbol.CreateByRef()); } else { var inner = ConversionSymbol.Create(ConversionKind.Deref); var outer = Conversion(TypeConversion.Bound(expr, expr.Datatype.ElementType, inner), type, options); if (outer.Exists) { return(ConversionSymbol.Create(outer, inner)); } } return(null); }
internal static void Convert(ref Expr e, TypeSymbol type, ConversionSymbol conv) { switch (conv.Kind) { case ConversionKind.Identity: break; case ConversionKind.ConstantReduction: e = LiteralExpr.Bound(((ConversionSymbolToConstant)conv).Constant); break; case ConversionKind.NoConversion: throw ConversionError(e, type); case ConversionKind.NoImplicitConversion: throw ImplicitConversionError(e, type); default: e = TypeConversion.Bound(e, type, conv); break; } }
internal static ConversionSymbol ResolveEnumConversion(Expr expr, TypeSymbol type, BindOptions options) { if (expr.Datatype.IsEnum) { if (TypesMatch(expr.Datatype.EnumUnderlyingType, type)) { return(ConversionSymbol.Create(ConversionKind.ImplicitEnumeration)); } else { var inner = ConversionSymbol.Create(ConversionKind.ImplicitEnumeration); var outer = Conversion(TypeConversion.Bound(expr, expr.Datatype.EnumUnderlyingType, inner), type, options); if (outer.Exists) { return(ConversionSymbol.Create(outer, inner)); } } } if (type.IsEnum && options.HasFlag(BindOptions.Explicit)) { if (TypesMatch(type.EnumUnderlyingType, expr.Datatype)) { return(ConversionSymbol.Create(ConversionKind.ExplicitEnumeration)); } else { var inner = Conversion(expr, type.EnumUnderlyingType, options); if (inner.Exists) { var outer = ConversionSymbol.Create(ConversionKind.ExplicitEnumeration); return(ConversionSymbol.Create(outer, inner)); } } } return(null); }