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);
 }