Exemple #1
0
        public static UnaryOperatorSymbol ClassifyOperation(UnaryOperatorKind kind, TypeSymbol expr)
        {
            int exprIdx = ConversionEasyOut.TypeToIndex(expr);

            if (exprIdx < 0)
            {
                return(null);
            }
            return(s_unOp[(int)kind][exprIdx]);
        }
        public static BinaryOperatorSymbol ClassifyOperation(BinaryOperatorKind kind, TypeSymbol left, TypeSymbol right)
        {
            int leftIdx = ConversionEasyOut.TypeToIndex(left);

            if (leftIdx < 0)
            {
                return(null);
            }
            int rightIdx = ConversionEasyOut.TypeToIndex(right);

            if (rightIdx < 0)
            {
                return(null);
            }
            return(s_binOp[(int)kind][leftIdx, rightIdx]);
        }
        internal static ConversionSymbol Conversion(Expr expr, TypeSymbol type, BindOptions options)
        {
            var noConversion = ConversionKind.NoConversion;

            var conversion = ConversionEasyOut.ClassifyConversion(expr.Datatype, type);

            if (expr.Symbol.IsConstant() || expr.IsConstant)
            {
                options |= BindOptions.Explicit;
            }

            if (conversion != ConversionKind.NoConversion)
            {
                var conv = ConversionSymbol.Create(conversion);
                if (!conv.IsCast && options.HasFlag(BindOptions.Explicit) || conv.IsImplicit)
                {
                    return(conv);
                }
                if (conv.IsCast && options.HasFlag(BindOptions.Cast))
                {
                    return(conv);
                }
                if (conv.IsExplicit && conv.Kind == ConversionKind.ExplicitNumeric && options.HasFlag(BindOptions.AllowImplicitNarrowingConversions))
                {
                    return(conv); // TODO nvk: this should raise a warning!
                }
                if (conv.Exists)
                {
                    noConversion = ConversionKind.NoImplicitConversion;
                }
            }

            if (TypesMatch(expr.Datatype, type))
            {
                return(ConversionSymbol.Create(ConversionKind.Identity));
            }

            if (type.Type.IsGenericType || expr.Datatype.Type.IsGenericType)
            {
                return(ConversionSymbol.Create(noConversion));
            }

            MethodSymbol converter = null;

            ResolveUserDefinedConversion(expr, type, expr.Datatype.Lookup(OperatorNames.Implicit), type.Lookup(OperatorNames.Implicit), ref converter, options | BindOptions.Special);
            if (converter != null)
            {
                return(ConversionSymbol.Create(ConversionKind.ImplicitUserDefined, converter));
            }

            if (options.HasFlag(BindOptions.Explicit))
            {
                ResolveUserDefinedConversion(expr, type, expr.Datatype.Lookup(OperatorNames.Explicit), type.Lookup(OperatorNames.Explicit), ref converter, options | BindOptions.Special);
                if (converter != null)
                {
                    return(ConversionSymbol.Create(ConversionKind.ExplicitUserDefined, converter));
                }
            }

            {
                var conv = ResolveUsualConversion(expr, type, options);
                if (conv != null)
                {
                    return(conv);
                }
            }

            if (type.IsByRef != expr.Datatype.IsByRef)
            {
                var conv = ResolveByRefConversion(expr, type, options);
                if (conv != null)
                {
                    return(conv);
                }
            }

            if (type.NativeType == NativeType.Object)
            {
                if (expr.Datatype.Type.IsValueType)
                {
                    return(ConversionSymbol.Create(ConversionKind.Boxing));
                }
                else
                {
                    return(ConversionSymbol.Create(ConversionKind.ImplicitReference));
                }
            }
            else if (expr.Datatype.NativeType == NativeType.Object)
            {
                if (!options.HasFlag(BindOptions.AllowDynamic))
                {
                    if (options.HasFlag(BindOptions.Explicit))
                    {
                        return(type.IsValueType ? ConversionSymbol.Create(ConversionKind.Unboxing) : ConversionSymbol.Create(ConversionKind.ExplicitReference));
                    }
                    else
                    {
                        noConversion = ConversionKind.NoImplicitConversion;
                    }
                }
            }
            else if (type.IsReferenceType && expr.Datatype.IsReferenceType)
            {
                if (expr.Datatype.IsSubclassOf(type))
                {
                    return(ConversionSymbol.Create(ConversionKind.ImplicitReference));
                }
                if (type.IsSubclassOf(expr.Datatype))
                {
                    if (options.HasFlag(BindOptions.Explicit))
                    {
                        return(ConversionSymbol.Create(ConversionKind.ExplicitReference));
                    }
                    else
                    {
                        noConversion = ConversionKind.NoImplicitConversion;
                    }
                }
            }

            {
                var conv = ResolveEnumConversion(expr, type, options);
                if (conv != null)
                {
                    return(conv);
                }
            }

            if (options.HasFlag(BindOptions.AllowDynamic))
            {
                var conv = ResolveDynamicConversion(expr, type, options);
                if (conv != null)
                {
                    return(conv);
                }
            }

            if (!options.HasFlag(BindOptions.Explicit) && noConversion == ConversionKind.NoConversion)
            {
                ResolveUserDefinedConversion(expr, type, expr.Datatype.Lookup(OperatorNames.Explicit), type.Lookup(OperatorNames.Explicit), ref converter, options | BindOptions.Special);
                if (converter != null)
                {
                    noConversion = ConversionKind.NoImplicitConversion;
                }
            }

            return(ConversionSymbol.Create(noConversion));
        }