/// <summary> Determine which of two signatures is the closer fit.
        /// Returns one of PREFERENCE_EQUAL, PREFERENCE_FIRST_ARG,
        /// PREFERENCE_SECOND_ARG, or PREFERENCE_AMBIGUOUS.
        /// </summary>
        private static int PreferSignature(object [] args, ParameterInfo [] sig1, ParameterInfo [] sig2)
        {
            int totalPreference = 0;

            for (int j = 0; j < args.Length; j++)
            {
                Type type1 = sig1 [j].ParameterType;
                Type type2 = sig2 [j].ParameterType;
                if (type1 == type2)
                {
                    continue;
                }
                object arg = args [j];

                // Determine which of type1, type2 is easier to convert from arg.

                int rank1 = CliObject.GetConversionWeight(arg, type1);
                int rank2 = CliObject.GetConversionWeight(arg, type2);

                int preference;
                if (rank1 < rank2)
                {
                    preference = PREFERENCE_FIRST_ARG;
                }
                else if (rank1 > rank2)
                {
                    preference = PREFERENCE_SECOND_ARG;
                }
                else
                {
                    // Equal ranks
                    if (rank1 == CliObject.CONVERSION_NONTRIVIAL)
                    {
                        if (type1.IsAssignableFrom(type2))
                        {
                            preference = PREFERENCE_SECOND_ARG;
                        }
                        else if (type2.IsAssignableFrom(type1))
                        {
                            preference = PREFERENCE_FIRST_ARG;
                        }
                        else
                        {
                            preference = PREFERENCE_AMBIGUOUS;
                        }
                    }
                    else
                    {
                        preference = PREFERENCE_AMBIGUOUS;
                    }
                }

                totalPreference |= preference;

                if (totalPreference == PREFERENCE_AMBIGUOUS)
                {
                    break;
                }
            }
            return(totalPreference);
        }
 private void Init()
 {
     m_CliObject = new CliObject(m_Type, m_Type);
 }
        /// <summary> Find the index of the correct function to call given the set of methods
        /// or constructors and the arguments.
        /// If no function can be found to call, return -1.
        /// </summary>
        internal static int FindFunction(Context cx, MethodBase [] methodsOrCtors, object [] args, bool [] paramsParameter)
        {
            if (methodsOrCtors.Length == 0)
            {
                return(-1);
            }
            else if (methodsOrCtors.Length == 1)
            {
                MethodBase       member = methodsOrCtors [0];
                ParameterInfo [] pis    = member.GetParameters();
                int alength             = pis.Length;

                if (alength != args.Length)
                {
                    if (!paramsParameter [0])
                    {
                        return(-1);
                    }
                }

                for (int j = 0; j != alength; ++j)
                {
                    object arg     = args [j];
                    Type   argType = null;

                    if (paramsParameter [0] && j >= pis.Length - 1)
                    {
                        // params[] arg is always an array type
                        argType = pis [pis.Length - 1].ParameterType.GetElementType();
                    }
                    else
                    {
                        argType = pis [j].ParameterType;
                    }

                    if (!CliObject.CanConvert(arg, argType))
                    {
                        //if (debug)
                        //	printDebug("Rejecting (args can't convert) ", member, args);
                        return(-1);
                    }
                }
                //if (debug)
                //	printDebug("Found ", member, args);
                return(0);
            }

            int firstBestFit = -1;

            int [] extraBestFits      = null;
            int    extraBestFitsCount = 0;

            for (int i = 0; i < methodsOrCtors.Length; i++)
            {
                MethodBase       member = methodsOrCtors [i];
                ParameterInfo [] pis    = member.GetParameters();
                if (pis.Length != args.Length)
                {
                    goto search;
                }
                for (int j = 0; j < pis.Length; j++)
                {
                    if (!CliObject.CanConvert(args [j], pis [j].ParameterType))
                    {
                        //if (debug)
                        //	printDebug("Rejecting (args can't convert) ", member, args);
                        goto search;
                    }
                }
                if (firstBestFit < 0)
                {
                    //if (debug)
                    //	printDebug("Found first applicable ", member, args);
                    firstBestFit = i;
                }
                else
                {
                    // Compare with all currently fit methods.
                    // The loop starts from -1 denoting firstBestFit and proceed
                    // until extraBestFitsCount to avoid extraBestFits allocation
                    // in the most common case of no ambiguity
                    int betterCount = 0; // number of times member was prefered over
                    // best fits
                    int worseCount = 0;  // number of times best fits were prefered
                    // over member
                    for (int j = -1; j != extraBestFitsCount; ++j)
                    {
                        int bestFitIndex;
                        if (j == -1)
                        {
                            bestFitIndex = firstBestFit;
                        }
                        else
                        {
                            bestFitIndex = extraBestFits [j];
                        }
                        MethodBase bestFit    = methodsOrCtors [bestFitIndex];
                        int        preference = PreferSignature(args, pis, bestFit.GetParameters());
                        if (preference == PREFERENCE_AMBIGUOUS)
                        {
                            break;
                        }
                        else if (preference == PREFERENCE_FIRST_ARG)
                        {
                            ++betterCount;
                        }
                        else if (preference == PREFERENCE_SECOND_ARG)
                        {
                            ++worseCount;
                        }
                        else
                        {
                            if (preference != PREFERENCE_EQUAL)
                            {
                                Context.CodeBug();
                            }
                            // This should not happen in theory
                            // but on some JVMs, Class.getMethods will return all
                            // static methods of the class heirarchy, even if
                            // a derived class's parameters match exactly.
                            // We want to call the dervied class's method.
                            if (bestFit.IsStatic && bestFit.DeclaringType.IsAssignableFrom(member.DeclaringType))
                            {
                                // On some JVMs, Class.getMethods will return all
                                // static methods of the class heirarchy, even if
                                // a derived class's parameters match exactly.
                                // We want to call the dervied class's method.
                                //if (debug)
                                //	printDebug("Substituting (overridden static)", member, args);
                                if (j == -1)
                                {
                                    firstBestFit = i;
                                }
                                else
                                {
                                    extraBestFits [j] = i;
                                }
                            }
                            else
                            {
                                //if (debug)
                                //	printDebug("Ignoring same signature member ", member, args);
                            }
                            goto search;
                        }
                    }
                    if (betterCount == 1 + extraBestFitsCount)
                    {
                        // member was prefered over all best fits
                        //if (debug)
                        //	printDebug("New first applicable ", member, args);
                        firstBestFit       = i;
                        extraBestFitsCount = 0;
                    }
                    else if (worseCount == 1 + extraBestFitsCount)
                    {
                        // all best fits were prefered over member, ignore it
                        //if (debug)
                        //	printDebug("Rejecting (all current bests better) ", member, args);
                    }
                    else
                    {
                        // some ambiguity was present, add member to best fit set
                        //if (debug)
                        //	printDebug("Added to best fit set ", member, args);
                        if (extraBestFits == null)
                        {
                            // Allocate maximum possible array
                            extraBestFits = new int [methodsOrCtors.Length - 1];
                        }
                        extraBestFits [extraBestFitsCount] = i;
                        ++extraBestFitsCount;
                    }
                }
                //UPGRADE_NOTE: Label 'search' was moved. 'ms-help://MS.VSCC.2003/commoner/redir/redirect.htm?keyword="jlca1014_3"'

search:
                ;
            }

            if (firstBestFit < 0)
            {
                // Nothing was found
                return(-1);
            }
            else if (extraBestFitsCount == 0)
            {
                // single best fit
                return(firstBestFit);
            }

            // report remaining ambiguity
            System.Text.StringBuilder buf = new System.Text.StringBuilder();
            for (int j = -1; j != extraBestFitsCount; ++j)
            {
                int bestFitIndex;
                if (j == -1)
                {
                    bestFitIndex = firstBestFit;
                }
                else
                {
                    bestFitIndex = extraBestFits [j];
                }
                buf.Append("\n    ");
                buf.Append(CliHelper.ToSignature(methodsOrCtors [bestFitIndex]));
            }

            MethodBase firstFitMember = methodsOrCtors [firstBestFit];
            string     memberName     = firstFitMember.Name;
            //UPGRADE_TODO: The equivalent in .NET for method 'java.lang.Class.getName' may return a different value. 'ms-help://MS.VSCC.2003/commoner/redir/redirect.htm?keyword="jlca1043_3"'
            string memberClass = firstFitMember.DeclaringType.FullName;

            if (methodsOrCtors [0] is MethodInfo)
            {
                throw Context.ReportRuntimeErrorById("msg.constructor.ambiguous", memberName, ScriptSignature(args), buf.ToString());
            }
            else
            {
                throw Context.ReportRuntimeErrorById("msg.method.ambiguous", memberClass, memberName, ScriptSignature(args), buf.ToString());
            }
        }
 private void Init()
 {
     m_CliObject = new CliObject (m_Type, m_Type);
 }