Beispiel #1
0
        /// <summary>
        /// Binds named arguments to the parameters. Returns a permutation of indices that captures the relationship between 
        /// named arguments and their corresponding parameters. Checks for duplicate and unbound named arguments.
        /// 
        /// Ensures that for all i: namedArgs[i] binds to parameters[args.Length + bindingPermutation[i]] 
        /// </summary>
        internal bool TryBindNamedArguments(MethodCandidate method, out ArgumentBinding binding, out CallFailure failure) {
            if (_namedArgs.Count == 0) {
                binding = new ArgumentBinding(_args.Count);
                failure = null;
                return true;
            }

            var permutation = new int[_namedArgs.Count];
            var boundParameters = new BitArray(_namedArgs.Count);

            for (int i = 0; i < permutation.Length; i++) {
                permutation[i] = -1;
            }

            List<string> unboundNames = null;
            List<string> duppedNames = null;

            int positionalArgCount = _args.Count;

            for (int i = 0; i < _names.Count; i++) {
                int paramIndex = method.IndexOfParameter(_names[i]);
                if (paramIndex >= 0) {
                    int nameIndex = paramIndex - positionalArgCount;

                    // argument maps to already bound parameter:
                    if (paramIndex < positionalArgCount || boundParameters[nameIndex]) {
                        if (duppedNames == null) {
                            duppedNames = new List<string>();
                        }
                        duppedNames.Add(_names[i]);
                    } else {
                        permutation[i] = nameIndex;
                        boundParameters[nameIndex] = true;
                    }
                } else {
                    if (unboundNames == null) {
                        unboundNames = new List<string>();
                    }
                    unboundNames.Add(_names[i]);
                }
            }

            binding = new ArgumentBinding(positionalArgCount, permutation);

            if (unboundNames != null) {
                failure = new CallFailure(method, unboundNames.ToArray(), true);
                return false;
            } else if (duppedNames != null) {
                failure = new CallFailure(method, duppedNames.ToArray(), false);
                return false;
            }

            failure = null;
            return true;
        }
Beispiel #2
0
 /// <summary>
 /// Creates a new BindingTarget when the method binding has failued due to 
 /// one or more parameters which could not be converted.
 /// </summary>
 internal BindingTarget(string name, int actualArgumentCount, CallFailure[] failures)
 {
     _name = name;
     _result = BindingResult.CallFailure;
     _callFailures = failures;
     _actualArgs = actualArgumentCount;
 }
Beispiel #3
0
 private BindingTarget MakeFailedBindingTarget(CallFailure[] failures) {
     return new BindingTarget(_methodName, _actualArguments.VisibleCount, failures);
 }
Beispiel #4
0
        private bool TryConvertCollapsedArguments(MethodCandidate candidate, NarrowingLevel narrowingLevel, out CallFailure failure) {
            Debug.Assert(_actualArguments.CollapsedCount > 0);

            // There must be at least one expanded parameter preceding splat index (see MethodBinder.GetSplatLimits):
            ParameterWrapper parameter = candidate.GetParameter(_actualArguments.SplatIndex - 1);
            Debug.Assert(parameter.ParameterInfo != null && CompilerHelpers.IsParamArray(parameter.ParameterInfo));

            for (int i = 0; i < _actualArguments.CollapsedCount; i++) {
                object value = GetCollapsedArgumentValue(i);
                Type argType = CompilerHelpers.GetType(value);

                if (!CanConvertFrom(argType, null, parameter, narrowingLevel)) {
                    failure = new CallFailure(candidate, new[] { new ConversionResult(value, argType, parameter.Type, false) });
                    return false;
                }
            }

            failure = null;
            return true;
        }
Beispiel #5
0
        private bool TryConvertArguments(MethodCandidate candidate, ArgumentBinding namesBinding, NarrowingLevel narrowingLevel, out CallFailure failure) {
            Debug.Assert(_actualArguments.Count == candidate.ParameterCount);

            BitArray hasConversion = new BitArray(_actualArguments.Count);

            bool success = true;
            for (int i = 0; i < _actualArguments.Count; i++) {
                success &= (hasConversion[i] = CanConvertFrom(_actualArguments[i].GetLimitType(), _actualArguments[i], candidate.GetParameter(i, namesBinding), narrowingLevel));
            }

            if (!success) {
                var conversionResults = new ConversionResult[_actualArguments.Count];
                for (int i = 0; i < _actualArguments.Count; i++) {
                    conversionResults[i] = new ConversionResult(_actualArguments[i].Value, _actualArguments[i].GetLimitType(), candidate.GetParameter(i, namesBinding).Type, !hasConversion[i]);
                }
                failure = new CallFailure(candidate, conversionResults);
            } else {
                failure = null;
            }

            return success;
        }
Beispiel #6
0
 private static void AddFailure(ref List<CallFailure> failures, CallFailure failure) {
     if (failures == null) {
         failures = new List<CallFailure>(1);
     }
     failures.Add(failure);
 }
Beispiel #7
0
        /// <summary>
        /// Binds named arguments to the parameters. Returns a permutation of indices that captures the relationship between
        /// named arguments and their corresponding parameters. Checks for duplicate and unbound named arguments.
        /// Ensures that for all i: namedArgs[i] binds to parameters[args.Length + bindingPermutation[i]]
        /// </summary>
        internal bool TryBindNamedArguments(MethodCandidate method, out ArgumentBinding binding, out CallFailure failure)
        {
            if (NamedArguments.Count == 0)
            {
                binding = new ArgumentBinding(Arguments.Count);
                failure = null;
                return(true);
            }

            var permutation     = new int[NamedArguments.Count];
            var boundParameters = new BitArray(NamedArguments.Count);

            for (int i = 0; i < permutation.Length; i++)
            {
                permutation[i] = -1;
            }

            List <string> unboundNames      = null;
            List <string> duppedNames       = null;
            List <int>    duppedPositionals = null;

            int positionalArgCount = Arguments.Count;

            for (int i = 0; i < ArgNames.Count; i++)
            {
                int paramIndex = method.IndexOfParameter(ArgNames[i]);
                if (paramIndex >= 0)
                {
                    int nameIndex = paramIndex - positionalArgCount;

                    if (paramIndex < positionalArgCount)
                    {
                        // argument maps to already bound positional parameter
                        duppedNames ??= new List <string>();
                        duppedPositionals ??= Enumerable.Repeat(0, duppedNames.Count).ToList();
                        duppedNames.Add(ArgNames[i]);
                        duppedPositionals.Add(method.PositionOfParameter(ArgNames[i]));
                    }
                    else if (boundParameters[nameIndex])
                    {
                        // argument maps to already bound named parameter
                        duppedNames ??= new List <string>();
                        duppedNames.Add(ArgNames[i]);
                        duppedPositionals?.Add(0);
                    }
                    else
                    {
                        permutation[i]             = nameIndex;
                        boundParameters[nameIndex] = true;
                    }
                }
                else
                {
                    unboundNames ??= new List <string>();
                    unboundNames.Add(ArgNames[i]);
                }
            }

            Debug.Assert(duppedPositionals == null || (duppedNames != null && duppedNames.Count == duppedPositionals.Count));

            binding = new ArgumentBinding(positionalArgCount, permutation);

            if (unboundNames != null)
            {
                failure = new CallFailure(method, unboundNames.ToArray());
                return(false);
            }

            if (duppedNames != null)
            {
                failure = new CallFailure(method, duppedNames.ToArray(), duppedPositionals?.ToArray());
                return(false);
            }

            failure = null;
            return(true);
        }
Beispiel #8
0
        internal bool TryGetNormalizedArguments <T>(T[] argTypes, SymbolId[] names, out T[] args, out CallFailure failure)
        {
            if (names.Length == 0)
            {
                // no named arguments, success!
                args    = argTypes;
                failure = null;
                return(true);
            }

            T[] res = new T[argTypes.Length];
            Array.Copy(argTypes, res, argTypes.Length - names.Length);
            List <SymbolId> unboundNames = null;
            List <SymbolId> duppedNames  = null;

            for (int i = 0; i < names.Length; i++)
            {
                bool found = false;
                for (int j = 0; j < _parameters.Count; j++)
                {
                    if (_parameters[j].Name == names[i])
                    {
                        found = true;

                        if (res[j] != null)
                        {
                            if (duppedNames == null)
                            {
                                duppedNames = new List <SymbolId>();
                            }
                            duppedNames.Add(names[i]);
                        }
                        else
                        {
                            res[j] = argTypes[i + argTypes.Length - names.Length];
                        }
                        break;
                    }
                }

                if (!found)
                {
                    if (unboundNames == null)
                    {
                        unboundNames = new List <SymbolId>();
                    }
                    unboundNames.Add(names[i]);
                }
            }

            if (unboundNames != null)
            {
                failure = new CallFailure(Target, unboundNames.ToArray(), true);
                args    = null;
                return(false);
            }
            else if (duppedNames != null)
            {
                failure = new CallFailure(Target, duppedNames.ToArray(), false);
                args    = null;
                return(false);
            }

            failure = null;
            args    = res;
            return(true);
        }