FunctionOverloadResolver.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ 4.0 / 4.0 / DEVDIV_TFS / Dev10 / Releases / RTMRel / ndp / fx / src / DataEntity / System / Data / Common / EntitySql / FunctionOverloadResolver.cs / 1305376 / FunctionOverloadResolver.cs

                            //---------------------------------------------------------------------- 
// 
//      Copyright (c) Microsoft Corporation.  All rights reserved.
// 
// 
// @owner  [....]
// @backupOwner [....] 
//--------------------------------------------------------------------- 

namespace System.Data.Common.EntitySql 
{
    using System;
    using System.Collections.Generic;
    using System.Linq; 
    using System.Diagnostics;
    using System.Data.Metadata.Edm; 
    using System.Data.Entity; 

    ///  
    /// Represents function overload resolution mechanism, used by L2E and eSQL frontends.
    /// 
    internal static class FunctionOverloadResolver
    { 
        /// 
        /// Resolves  against the list of function signatures. 
        ///  
        /// Funciton metadata
        internal static EdmFunction ResolveFunctionOverloads(IList functionsMetadata, 
                                                             IList argTypes,
                                                             bool isGroupAggregateFunction,
                                                             out bool isAmbiguous)
        { 
            return ResolveFunctionOverloads(
                functionsMetadata, 
                argTypes, 
                (edmFunction) => edmFunction.Parameters,
                (functionParameter) => functionParameter.TypeUsage, 
                (functionParameter) => functionParameter.Mode,
                isGroupAggregateFunction,
                out isAmbiguous);
        } 

        ///  
        /// Resolves  against the list of function signatures. 
        /// 
        /// function formal signature getter 
        /// TypeUsage getter for a signature param
        /// ParameterMode getter for a signature param
        /// Funciton metadata
        internal static TFunctionMetadata ResolveFunctionOverloads 
            (IList functionsMetadata,
             IList argTypes, 
             Func> getSignatureParams, 
             Func getParameterTypeUsage,
             Func getParameterMode, 
             bool isGroupAggregateFunction,
             out bool isAmbiguous) where TFunctionMetadata : class
        {
            // 
            // Flatten argument list
            // 
            List argTypesFlat = new List(argTypes.Count); 
            foreach (TypeUsage argType in argTypes)
            { 
                argTypesFlat.AddRange(TypeSemantics.FlattenType(argType));
            }

            // 
            // Find a candidate overload with the best total rank, remeber the candidate and its composite rank.
            // 
            TFunctionMetadata bestCandidate = null; 
            isAmbiguous = false;
            List ranks = new List(functionsMetadata.Count); 
            int[] bestCandidateRank = null;
            for (int i = 0, maxTotalRank = int.MinValue; i < functionsMetadata.Count; i++)
            {
                int totalRank; 
                int[] rank;
                if (TryRankFunctionParameters(argTypes, 
                                              argTypesFlat, 
                                              getSignatureParams(functionsMetadata[i]),
                                              getParameterTypeUsage, 
                                              getParameterMode,
                                              isGroupAggregateFunction,
                                              out totalRank, out rank))
                { 
                    if (totalRank == maxTotalRank)
                    { 
                        isAmbiguous = true; 
                    }
                    else if (totalRank > maxTotalRank) 
                    {
                        isAmbiguous = false;
                        maxTotalRank = totalRank;
                        bestCandidate = functionsMetadata[i]; 
                        bestCandidateRank = rank;
                    } 
 
                    Debug.Assert(argTypesFlat.Count == rank.Length, "argTypesFlat.Count == rank.Length");
 
                    ranks.Add(rank);
                }
            }
 
            //
            // If there is a best candidate, check it for ambiguity against composite ranks of other candidates 
            // 
            if (bestCandidate != null &&
                !isAmbiguous && 
                argTypesFlat.Count > 1 && // best candidate may be ambiguous only in the case of 2 or more arguments
                ranks.Count > 1)
            {
                Debug.Assert(bestCandidateRank != null); 

                // 
                // Search collection of composite ranks to see if there is an overload that would render the best candidate ambiguous 
                //
                isAmbiguous = ranks.Any(rank => 
                {
                    Debug.Assert(rank.Length == bestCandidateRank.Length, "composite ranks have different number of elements");

                    if (!Object.ReferenceEquals(bestCandidateRank, rank)) // do not compare best cadnidate against itself 
                    {
                        // All individual ranks of the best candidate must equal or better than the ranks of all other candidates, 
                        // otherwise we consider it ambigous, even though it has an unambigously best total rank. 
                        for (int i = 0; i < rank.Length; ++i)
                        { 
                            if (bestCandidateRank[i] < rank[i])
                            {
                                return true;
                            } 
                        }
                    } 
 
                    return false;
                }); 
            }

            return bestCandidate;
        } 

        ///  
        /// Check promotability, returns true if argument list is promotable to the overload and overload was successfully ranked, otherwise false. 
        /// Ranks the overload parameter types against the argument list.
        ///  
        /// list of argument types
        /// flattened list of argument types
        /// list of overload parameter types
        /// TypeUsage getter for the overload parameters 
        /// ParameterMode getter for the overload parameters
        /// returns total promotion rank of the overload, 0 if no arguments 
        /// returns individual promotion ranks of the overload parameters, empty array if no arguments 
        private static bool TryRankFunctionParameters(IList argumentList,
                                                                                  IList flatArgumentList, 
                                                                                  IList overloadParamList,
                                                                                  Func getParameterTypeUsage,
                                                                                  Func getParameterMode,
                                                                                  bool isGroupAggregateFunction, 
                                                                                  out int totalRank,
                                                                                  out int[] parameterRanks) 
        { 
            totalRank = 0;
            parameterRanks = null; 

            if (argumentList.Count != overloadParamList.Count)
            {
                return false; 
            }
 
            // 
            // Check promotability and flatten the parameter types
            // 
            List flatOverloadParamList = new List(flatArgumentList.Count);
            for (int i = 0; i < overloadParamList.Count; ++i)
            {
                TypeUsage argumentType = argumentList[i]; 
                TypeUsage parameterType = getParameterTypeUsage(overloadParamList[i]);
 
                // 
                // Parameter mode must match.
                // 
                ParameterMode parameterMode = getParameterMode(overloadParamList[i]);
                if (parameterMode != ParameterMode.In && parameterMode != ParameterMode.InOut)
                {
                    return false; 
                }
 
                // 
                // If function being ranked is a group aggregate, consider the element type.
                // 
                if (isGroupAggregateFunction)
                {
                    if (!TypeSemantics.IsCollectionType(parameterType))
                    { 
                        //
                        // Even though it is the job of metadata to ensure that the provider manifest is consistent. 
                        // Ensure that if a function is marked as aggregate, then the argument type must be of collection{GivenType}. 
                        //
                        throw EntityUtil.EntitySqlError(Strings.InvalidArgumentTypeForAggregateFunction); 
                    }
                    parameterType = TypeHelpers.GetElementTypeUsage(parameterType);
                }
 
                //
                // If argument is not promotable - reject the overload. 
                // 
                if (!TypeSemantics.IsPromotableTo(argumentType, parameterType))
                { 
                    return false;
                }

                if (TypeSemantics.IsNullType(argumentType)) 
                {
                    // 
                    // NULL type is promotable regardless of target type structure, so do not flatten the target (parameter) type. 
                    //
                    flatOverloadParamList.Add(parameterType); 
                }
                else
                {
                    // 
                    // Flatten the parameter type.
                    // 
                    flatOverloadParamList.AddRange(TypeSemantics.FlattenType(parameterType)); 
                }
            } 

            Debug.Assert(flatArgumentList.Count == flatOverloadParamList.Count, "flatArgumentList.Count == flatOverloadParamList.Count");

            // 
            // Rank argument promotions
            // 
            parameterRanks = new int[flatOverloadParamList.Count]; 
            for (int i = 0; i < parameterRanks.Length; ++i)
            { 
                int rank = GetPromotionRank(flatArgumentList[i], flatOverloadParamList[i]);
                totalRank += rank;
                parameterRanks[i] = rank;
            } 

            return true; 
        } 

        ///  
        /// Ranks the  ->  promotion.
        /// Range of values: 0 to negative infinity, with 0 as the best rank (promotion to self).
        ///  must be promotable to , otherwise internal error is thrown.
        ///  
        private static int GetPromotionRank(TypeUsage fromType, TypeUsage toType)
        { 
            // 
            // Only promotable types are allowed at this point.
            // 
            Debug.Assert(TypeSemantics.IsPromotableTo(fromType, toType), "TypeSemantics.IsPromotableTo(fromType, toType)");
            //
            // NULL type in toType can only be coming from metadata which does not allow it in definitions.
            // 
            Debug.Assert(!TypeSemantics.IsNullType(toType), "!TypeSemantics.IsNullType(toType)");
 
            // 
            // If both types are the same or if fromType is NULL (compatible with any type except collection) -
            // return rank 0 - best match. 
            //
            if (TypeSemantics.IsStructurallyEqual(fromType, toType) || TypeSemantics.IsNullType(fromType))
            {
                return 0; 
            }
 
            // 
            // Handle primitive types
            // 
            PrimitiveType primitiveFromType = fromType.EdmType as PrimitiveType;
            PrimitiveType primitiveToType = toType.EdmType as PrimitiveType;
            if (primitiveFromType != null && primitiveToType != null)
            { 
                IList promotions = EdmProviderManifest.Instance.GetPromotionTypes(primitiveFromType);
 
                int promotionIndex = promotions.IndexOf(primitiveToType); 

                if (promotionIndex < 0) 
                {
                    throw EntityUtil.InternalError(EntityUtil.InternalErrorCode.FailedToGeneratePromotionRank, 1);
                }
 
                return -promotionIndex;
            } 
 
            //
            // Handle entity/relship types 
            //
            EntityTypeBase entityBaseFromType = fromType.EdmType as EntityTypeBase;
            EntityTypeBase entityBaseToType = toType.EdmType as EntityTypeBase;
            if (entityBaseFromType != null && entityBaseToType != null) 
            {
                int promotionIndex = 0; 
                EdmType t; 
                for (t = entityBaseFromType; t != entityBaseToType && t != null; t = t.BaseType, ++promotionIndex);
 
                if (t == null)
                {
                    throw EntityUtil.InternalError(EntityUtil.InternalErrorCode.FailedToGeneratePromotionRank, 2);
                } 

                return -promotionIndex; 
            } 

            throw EntityUtil.InternalError(EntityUtil.InternalErrorCode.FailedToGeneratePromotionRank, 3); 
        }
    }
}

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
//---------------------------------------------------------------------- 
// 
//      Copyright (c) Microsoft Corporation.  All rights reserved.
// 
// 
// @owner  [....]
// @backupOwner [....] 
//--------------------------------------------------------------------- 

namespace System.Data.Common.EntitySql 
{
    using System;
    using System.Collections.Generic;
    using System.Linq; 
    using System.Diagnostics;
    using System.Data.Metadata.Edm; 
    using System.Data.Entity; 

    ///  
    /// Represents function overload resolution mechanism, used by L2E and eSQL frontends.
    /// 
    internal static class FunctionOverloadResolver
    { 
        /// 
        /// Resolves  against the list of function signatures. 
        ///  
        /// Funciton metadata
        internal static EdmFunction ResolveFunctionOverloads(IList functionsMetadata, 
                                                             IList argTypes,
                                                             bool isGroupAggregateFunction,
                                                             out bool isAmbiguous)
        { 
            return ResolveFunctionOverloads(
                functionsMetadata, 
                argTypes, 
                (edmFunction) => edmFunction.Parameters,
                (functionParameter) => functionParameter.TypeUsage, 
                (functionParameter) => functionParameter.Mode,
                isGroupAggregateFunction,
                out isAmbiguous);
        } 

        ///  
        /// Resolves  against the list of function signatures. 
        /// 
        /// function formal signature getter 
        /// TypeUsage getter for a signature param
        /// ParameterMode getter for a signature param
        /// Funciton metadata
        internal static TFunctionMetadata ResolveFunctionOverloads 
            (IList functionsMetadata,
             IList argTypes, 
             Func> getSignatureParams, 
             Func getParameterTypeUsage,
             Func getParameterMode, 
             bool isGroupAggregateFunction,
             out bool isAmbiguous) where TFunctionMetadata : class
        {
            // 
            // Flatten argument list
            // 
            List argTypesFlat = new List(argTypes.Count); 
            foreach (TypeUsage argType in argTypes)
            { 
                argTypesFlat.AddRange(TypeSemantics.FlattenType(argType));
            }

            // 
            // Find a candidate overload with the best total rank, remeber the candidate and its composite rank.
            // 
            TFunctionMetadata bestCandidate = null; 
            isAmbiguous = false;
            List ranks = new List(functionsMetadata.Count); 
            int[] bestCandidateRank = null;
            for (int i = 0, maxTotalRank = int.MinValue; i < functionsMetadata.Count; i++)
            {
                int totalRank; 
                int[] rank;
                if (TryRankFunctionParameters(argTypes, 
                                              argTypesFlat, 
                                              getSignatureParams(functionsMetadata[i]),
                                              getParameterTypeUsage, 
                                              getParameterMode,
                                              isGroupAggregateFunction,
                                              out totalRank, out rank))
                { 
                    if (totalRank == maxTotalRank)
                    { 
                        isAmbiguous = true; 
                    }
                    else if (totalRank > maxTotalRank) 
                    {
                        isAmbiguous = false;
                        maxTotalRank = totalRank;
                        bestCandidate = functionsMetadata[i]; 
                        bestCandidateRank = rank;
                    } 
 
                    Debug.Assert(argTypesFlat.Count == rank.Length, "argTypesFlat.Count == rank.Length");
 
                    ranks.Add(rank);
                }
            }
 
            //
            // If there is a best candidate, check it for ambiguity against composite ranks of other candidates 
            // 
            if (bestCandidate != null &&
                !isAmbiguous && 
                argTypesFlat.Count > 1 && // best candidate may be ambiguous only in the case of 2 or more arguments
                ranks.Count > 1)
            {
                Debug.Assert(bestCandidateRank != null); 

                // 
                // Search collection of composite ranks to see if there is an overload that would render the best candidate ambiguous 
                //
                isAmbiguous = ranks.Any(rank => 
                {
                    Debug.Assert(rank.Length == bestCandidateRank.Length, "composite ranks have different number of elements");

                    if (!Object.ReferenceEquals(bestCandidateRank, rank)) // do not compare best cadnidate against itself 
                    {
                        // All individual ranks of the best candidate must equal or better than the ranks of all other candidates, 
                        // otherwise we consider it ambigous, even though it has an unambigously best total rank. 
                        for (int i = 0; i < rank.Length; ++i)
                        { 
                            if (bestCandidateRank[i] < rank[i])
                            {
                                return true;
                            } 
                        }
                    } 
 
                    return false;
                }); 
            }

            return bestCandidate;
        } 

        ///  
        /// Check promotability, returns true if argument list is promotable to the overload and overload was successfully ranked, otherwise false. 
        /// Ranks the overload parameter types against the argument list.
        ///  
        /// list of argument types
        /// flattened list of argument types
        /// list of overload parameter types
        /// TypeUsage getter for the overload parameters 
        /// ParameterMode getter for the overload parameters
        /// returns total promotion rank of the overload, 0 if no arguments 
        /// returns individual promotion ranks of the overload parameters, empty array if no arguments 
        private static bool TryRankFunctionParameters(IList argumentList,
                                                                                  IList flatArgumentList, 
                                                                                  IList overloadParamList,
                                                                                  Func getParameterTypeUsage,
                                                                                  Func getParameterMode,
                                                                                  bool isGroupAggregateFunction, 
                                                                                  out int totalRank,
                                                                                  out int[] parameterRanks) 
        { 
            totalRank = 0;
            parameterRanks = null; 

            if (argumentList.Count != overloadParamList.Count)
            {
                return false; 
            }
 
            // 
            // Check promotability and flatten the parameter types
            // 
            List flatOverloadParamList = new List(flatArgumentList.Count);
            for (int i = 0; i < overloadParamList.Count; ++i)
            {
                TypeUsage argumentType = argumentList[i]; 
                TypeUsage parameterType = getParameterTypeUsage(overloadParamList[i]);
 
                // 
                // Parameter mode must match.
                // 
                ParameterMode parameterMode = getParameterMode(overloadParamList[i]);
                if (parameterMode != ParameterMode.In && parameterMode != ParameterMode.InOut)
                {
                    return false; 
                }
 
                // 
                // If function being ranked is a group aggregate, consider the element type.
                // 
                if (isGroupAggregateFunction)
                {
                    if (!TypeSemantics.IsCollectionType(parameterType))
                    { 
                        //
                        // Even though it is the job of metadata to ensure that the provider manifest is consistent. 
                        // Ensure that if a function is marked as aggregate, then the argument type must be of collection{GivenType}. 
                        //
                        throw EntityUtil.EntitySqlError(Strings.InvalidArgumentTypeForAggregateFunction); 
                    }
                    parameterType = TypeHelpers.GetElementTypeUsage(parameterType);
                }
 
                //
                // If argument is not promotable - reject the overload. 
                // 
                if (!TypeSemantics.IsPromotableTo(argumentType, parameterType))
                { 
                    return false;
                }

                if (TypeSemantics.IsNullType(argumentType)) 
                {
                    // 
                    // NULL type is promotable regardless of target type structure, so do not flatten the target (parameter) type. 
                    //
                    flatOverloadParamList.Add(parameterType); 
                }
                else
                {
                    // 
                    // Flatten the parameter type.
                    // 
                    flatOverloadParamList.AddRange(TypeSemantics.FlattenType(parameterType)); 
                }
            } 

            Debug.Assert(flatArgumentList.Count == flatOverloadParamList.Count, "flatArgumentList.Count == flatOverloadParamList.Count");

            // 
            // Rank argument promotions
            // 
            parameterRanks = new int[flatOverloadParamList.Count]; 
            for (int i = 0; i < parameterRanks.Length; ++i)
            { 
                int rank = GetPromotionRank(flatArgumentList[i], flatOverloadParamList[i]);
                totalRank += rank;
                parameterRanks[i] = rank;
            } 

            return true; 
        } 

        ///  
        /// Ranks the  ->  promotion.
        /// Range of values: 0 to negative infinity, with 0 as the best rank (promotion to self).
        ///  must be promotable to , otherwise internal error is thrown.
        ///  
        private static int GetPromotionRank(TypeUsage fromType, TypeUsage toType)
        { 
            // 
            // Only promotable types are allowed at this point.
            // 
            Debug.Assert(TypeSemantics.IsPromotableTo(fromType, toType), "TypeSemantics.IsPromotableTo(fromType, toType)");
            //
            // NULL type in toType can only be coming from metadata which does not allow it in definitions.
            // 
            Debug.Assert(!TypeSemantics.IsNullType(toType), "!TypeSemantics.IsNullType(toType)");
 
            // 
            // If both types are the same or if fromType is NULL (compatible with any type except collection) -
            // return rank 0 - best match. 
            //
            if (TypeSemantics.IsStructurallyEqual(fromType, toType) || TypeSemantics.IsNullType(fromType))
            {
                return 0; 
            }
 
            // 
            // Handle primitive types
            // 
            PrimitiveType primitiveFromType = fromType.EdmType as PrimitiveType;
            PrimitiveType primitiveToType = toType.EdmType as PrimitiveType;
            if (primitiveFromType != null && primitiveToType != null)
            { 
                IList promotions = EdmProviderManifest.Instance.GetPromotionTypes(primitiveFromType);
 
                int promotionIndex = promotions.IndexOf(primitiveToType); 

                if (promotionIndex < 0) 
                {
                    throw EntityUtil.InternalError(EntityUtil.InternalErrorCode.FailedToGeneratePromotionRank, 1);
                }
 
                return -promotionIndex;
            } 
 
            //
            // Handle entity/relship types 
            //
            EntityTypeBase entityBaseFromType = fromType.EdmType as EntityTypeBase;
            EntityTypeBase entityBaseToType = toType.EdmType as EntityTypeBase;
            if (entityBaseFromType != null && entityBaseToType != null) 
            {
                int promotionIndex = 0; 
                EdmType t; 
                for (t = entityBaseFromType; t != entityBaseToType && t != null; t = t.BaseType, ++promotionIndex);
 
                if (t == null)
                {
                    throw EntityUtil.InternalError(EntityUtil.InternalErrorCode.FailedToGeneratePromotionRank, 2);
                } 

                return -promotionIndex; 
            } 

            throw EntityUtil.InternalError(EntityUtil.InternalErrorCode.FailedToGeneratePromotionRank, 3); 
        }
    }
}

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.

                        

Link Menu

Network programming in C#, Network Programming in VB.NET, Network Programming in .NET
This book is available now!
Buy at Amazon US or
Buy at Amazon UK