Пример #1
0
        /// <summary>
        /// Given a list of arguments, it looks at the types and tries to find out which function
        /// in this list is the best match.
        /// </summary>
        /// <param name="list"></param>
        /// <param name="funcs"></param>
        /// <returns></returns>
        public FunctionValue FindBestMatch(List <FunctionValue> list, HeronValue[] args)
        {
            // Each iteration removes candidates. This list holds all of the matches
            // Necessary, because removing items from a list while we iterate it is hard.
            List <FunctionValue> tmp = new List <FunctionValue>(list);

            for (int pos = 0; pos < args.Length; ++pos)
            {
                // On each iteration, update the main list, to only contain the remaining items
                list = new List <FunctionValue>(tmp);
                HeronValue arg = args[pos];
                HeronType  argType;
                if (arg is AnyValue)
                {
                    argType = (arg as AnyValue).GetHeldType();
                }
                else
                {
                    argType = arg.Type;
                }
                for (int i = 0; i < list.Count; ++i)
                {
                    FunctionValue fo         = list[i];
                    HeronType     formalType = fo.GetFormalType(pos);
                    if (!formalType.Equals(argType))
                    {
                        tmp.Remove(fo);
                    }
                }
                if (tmp.Count == 0)
                {
                    throw new Exception("Could not resolve function " + name + " no function matches perfectly");
                }

                // We found a single best match
                if (tmp.Count == 1)
                {
                    return(tmp[0]);
                }
            }

            Debug.Assert(tmp.Count > 1);

            // There are multiple functions
            // Choose the function which is the most derived type.
            // This is a pretty awful hack to make up for a bad design.
            int           n    = 0;
            FunctionValue best = null;

            foreach (FunctionValue fv in list)
            {
                int depth = fv.GetDefn().parent.GetHierarchyDepth();
                if (depth > n)
                {
                    n    = depth;
                    best = fv;
                }
                else if (depth == n)
                {
                    // Ambiguous match at this depth.
                    best = null;
                }
            }

            if (best == null)
            {
                throw new Exception("Ambiguous function match");
            }

            return(best);
        }