예제 #1
0
        private static List <DynamicMetaObject> GetAllArguments(ApplicableCandidate candidate, ActualArguments actualArgs)
        {
            List <DynamicMetaObject> args = new List <DynamicMetaObject>();

            for (int i = 0; i < actualArgs.Count; i++)
            {
                int index = candidate.ArgumentBinding.ArgumentToParameter(i);
                if (index < actualArgs.Arguments.Count)
                {
                    args.Add(actualArgs.Arguments[index]);
                }
                else
                {
                    args.Add(actualArgs.NamedArguments[index - actualArgs.Arguments.Count]);
                }
            }
            return(args);
        }
예제 #2
0
        internal static MethodCandidate InferGenericMethod(ApplicableCandidate /*!*/ candidate, ActualArguments /*!*/ actualArgs)
        {
            OverloadInfo target = candidate.Method.Overload;

            Assert.NotNull(target);
            Debug.Assert(target.IsGenericMethodDefinition);
            Debug.Assert(target.IsGenericMethod && target.ContainsGenericParameters);

            List <DynamicMetaObject /*!*/> args = GetAllArguments(candidate, actualArgs);

            if (args == null)
            {
                return(null);
            }

            Dictionary <Type, List <Type> > dependencies = GetDependencyMapping(target);

            Type[] genArgs = GetSortedGenericArguments(target, dependencies);
            Dictionary <Type, ArgumentInputs> inputs = GetArgumentToInputMapping(candidate.Method, args);

            // now process the inputs
            var  binding      = new Dictionary <Type, Type>();
            var  restrictions = new Dictionary <DynamicMetaObject, BindingRestrictions>();
            bool noMethod     = false;

            foreach (Type t in genArgs)
            {
                if (!inputs.TryGetValue(t, out ArgumentInputs inps))
                {
                    continue;
                }

                Type bestType = inps.GetBestType(candidate.Method.Resolver, binding, restrictions);
                if (bestType == null)
                {
                    // we conflict with possible constraints
                    noMethod = true;
                    break;
                }
            }

            if (!noMethod)
            {
                // finally build a new MethodCandidate for the generic method
                genArgs = GetGenericArgumentsForInferedMethod(target, binding);
                if (genArgs == null)
                {
                    // not all types we're inferred
                    return(null);
                }

                OverloadInfo newMethod = target.MakeGenericMethod(genArgs);

                List <ParameterWrapper> newWrappers = CreateNewWrappers(candidate.Method, newMethod, target);

                List <ArgBuilder> argBuilders = CreateNewArgBuilders(candidate.Method, newMethod);
                if (argBuilders == null)
                {
                    // one or more arg builders don't support type inference
                    return(null);
                }

                if (restrictions.Count == 0)
                {
                    restrictions = null;
                }

                // create the new method candidate
                return(candidate.Method.ReplaceMethod(newMethod, newWrappers, argBuilders, restrictions));
            }

            return(null);
        }
예제 #3
0
        private BindingTarget MakeSuccessfulBindingTarget(ApplicableCandidate result, List<ApplicableCandidate> potentialCandidates,
            NarrowingLevel level, CandidateSet targetSet) {

            return new BindingTarget(
                _methodName,
                _actualArguments.VisibleCount,
                result.Method,
                level,
                GetRestrictedArgs(result, potentialCandidates, targetSet.Arity)
            );
        }
예제 #4
0
        internal protected virtual Candidate CompareEquivalentCandidates(ApplicableCandidate one, ApplicableCandidate two) {
            Candidate ret = CompareEquivalentParameters(one.Method, two.Method);
            if (ret.Chosen()) {
                return ret;
            }

            return Candidate.Equivalent;
        }
예제 #5
0
        private Candidate GetPreferredParameters(ApplicableCandidate one, ApplicableCandidate two, NarrowingLevel level) {
            Debug.Assert(one.Method.ParameterCount == two.Method.ParameterCount);
            var args = GetActualArguments();

            Candidate result = Candidate.Equivalent;
            for (int i = 0; i < args.Count; i++) {
                Candidate preferred = GetPreferredParameter(one.GetParameter(i), two.GetParameter(i), args[i], level);

                switch (result) {
                    case Candidate.Equivalent:
                        result = preferred;
                        break;

                    case Candidate.One:
                        if (preferred == Candidate.Two) return Candidate.Ambiguous;
                        break;

                    case Candidate.Two:
                        if (preferred == Candidate.One) return Candidate.Ambiguous;
                        break;

                    case Candidate.Ambiguous:
                        if (preferred != Candidate.Equivalent) {
                            result = preferred;
                        }
                        break;

                    default:
                        throw new InvalidOperationException();
                }
            }

            // TODO: process collapsed arguments:

            return result;
        }
예제 #6
0
        private bool IsBest(ApplicableCandidate candidate, List<ApplicableCandidate> candidates, NarrowingLevel level) {
            foreach (ApplicableCandidate other in candidates) {
                if (candidate == other) {
                    continue;
                }

                if (GetPreferredCandidate(candidate, other, level) != Candidate.One) {
                    return false;
                }
            }
            return true;
        }
예제 #7
0
        internal Candidate GetPreferredCandidate(ApplicableCandidate one, ApplicableCandidate two, NarrowingLevel level) {
            Candidate cmpParams = GetPreferredParameters(one, two, level);
            if (cmpParams.Chosen()) {
                return cmpParams;
            }

            return CompareEquivalentCandidates(one, two);
        }
예제 #8
0
        private RestrictedArguments GetRestrictedArgs(ApplicableCandidate selectedCandidate, IList<ApplicableCandidate> candidates, int targetSetSize) {
            Debug.Assert(selectedCandidate.Method.ParameterCount == _actualArguments.Count);

            int argCount = _actualArguments.Count;
            var restrictedArgs = new DynamicMetaObject[argCount];
            var types = new Type[argCount];
            bool hasAdditionalRestrictions = false;
            for (int i = 0; i < argCount; i++) {
                var arg = _actualArguments[i];

                if (targetSetSize > 0 && IsOverloadedOnParameter(i, argCount, candidates) ||
                    !selectedCandidate.GetParameter(i).Type.IsAssignableFrom(arg.Expression.Type)) {

                    restrictedArgs[i] = RestrictArgument(arg, selectedCandidate.GetParameter(i));
                    types[i] = arg.GetLimitType();
                } else {
                    restrictedArgs[i] = arg;
                }

                BindingRestrictions additionalRestrictions;
                if (selectedCandidate.Method.Restrictions != null && selectedCandidate.Method.Restrictions.TryGetValue(arg, out additionalRestrictions)) {
                    hasAdditionalRestrictions = true;
                    restrictedArgs[i] = new DynamicMetaObject(restrictedArgs[i].Expression, restrictedArgs[i].Restrictions.Merge(additionalRestrictions));
                }
            }

            return new RestrictedArguments(restrictedArgs, types, hasAdditionalRestrictions);
        }
예제 #9
0
        internal static MethodCandidate InferGenericMethod(ApplicableCandidate/*!*/ candidate, ActualArguments/*!*/ actualArgs) {
            OverloadInfo target = candidate.Method.Overload;
            Assert.NotNull(target);
            Debug.Assert(target.IsGenericMethodDefinition);
            Debug.Assert(target.IsGenericMethod && target.ContainsGenericParameters);

            List<DynamicMetaObject/*!*/> args = GetAllArguments(candidate, actualArgs);
            if (args == null) {
                return null;
            }

            Dictionary<Type, List<Type>> dependencies = GetDependencyMapping(target);
            Type[] genArgs = GetSortedGenericArguments(target, dependencies);
            Dictionary<Type, ArgumentInputs> inputs = GetArgumentToInputMapping(candidate.Method, args);

            // now process the inputs
            var binding = new Dictionary<Type, Type>();
            var restrictions = new Dictionary<DynamicMetaObject, BindingRestrictions>();
            bool noMethod = false;
            foreach (Type t in genArgs) {
                ArgumentInputs inps;
                if (!inputs.TryGetValue(t, out inps)) {
                    continue;
                }

                Type bestType = inps.GetBestType(candidate.Method.Resolver, binding, restrictions);
                if (bestType == null) {
                    // we conflict with possible constraints
                    noMethod = true;
                    break;
                }
            }

            if (!noMethod) {
                // finally build a new MethodCandidate for the generic method
                genArgs = GetGenericArgumentsForInferedMethod(target, binding);
                if (genArgs == null) {
                    // not all types we're inferred
                    return null;
                }
                
                OverloadInfo newMethod = target.MakeGenericMethod(genArgs);

                List<ParameterWrapper> newWrappers = CreateNewWrappers(candidate.Method, newMethod, target);

                List<ArgBuilder> argBuilders = CreateNewArgBuilders(candidate.Method, newMethod);
                if (argBuilders == null) {
                    // one or more arg builders don't support type inference
                    return null;
                }

                if (restrictions.Count == 0) {
                    restrictions = null;
                }

                // create the new method candidate
                return candidate.Method.ReplaceMethod(newMethod, newWrappers, argBuilders, restrictions);
            }

            return null;
        }
예제 #10
0
 private static List<DynamicMetaObject> GetAllArguments(ApplicableCandidate candidate, ActualArguments actualArgs) {
     List<DynamicMetaObject> args = new List<DynamicMetaObject>();
     for (int i = 0; i < actualArgs.Count; i++) {
         int index = candidate.ArgumentBinding.ArgumentToParameter(i);
         if (index < actualArgs.Arguments.Count) {
             args.Add(actualArgs.Arguments[index]);
         } else {
             args.Add(actualArgs.NamedArguments[index - actualArgs.Arguments.Count]);
         }
     }
     return args;
 }
예제 #11
0
        internal protected override Candidate CompareEquivalentCandidates(ApplicableCandidate one, ApplicableCandidate two) {
            var result = base.CompareEquivalentCandidates(one, two);
            if (result.Chosen()) {
                return result;
            }

            if (one.Method.Overload.IsStatic && !two.Method.Overload.IsStatic) {
                return _callType == CallTypes.ImplicitInstance ? Candidate.Two : Candidate.One;
            } else if (!one.Method.Overload.IsStatic && two.Method.Overload.IsStatic) {
                return _callType == CallTypes.ImplicitInstance ? Candidate.One : Candidate.Two;
            }

            return Candidate.Equivalent;
        }
예제 #12
0
        private RestrictedArguments GetRestrictedArgs(ApplicableCandidate selectedCandidate, IList<ApplicableCandidate> candidates, int targetSetSize) {
            Debug.Assert(selectedCandidate.Method.ParameterCount == _actualArguments.Count);

            int argCount = _actualArguments.Count;
            var restrictedArgs = new DynamicMetaObject[argCount];
            var types = new Type[argCount];

            for (int i = 0; i < argCount; i++) {
                var arg = _actualArguments[i];

                if (targetSetSize > 0 && IsOverloadedOnParameter(i, argCount, candidates) ||
                    !selectedCandidate.GetParameter(i).Type.IsAssignableFrom(arg.Expression.Type)) {

                    restrictedArgs[i] = RestrictArgument(arg, selectedCandidate.GetParameter(i));
                    types[i] = arg.GetLimitType();
                } else {
                    restrictedArgs[i] = arg;
                }
            }

            return new RestrictedArguments(restrictedArgs, types);
        }