/// <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; }
internal ParameterWrapper GetParameter(int argumentIndex, ArgumentBinding namesBinding) { return _parameters[namesBinding.ArgumentToParameter(argumentIndex)]; }
internal ParameterWrapper GetParameter(int argumentIndex, ArgumentBinding namesBinding) { return(_parameters[namesBinding.ArgumentToParameter(argumentIndex)]); }
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; }
internal ApplicableCandidate(MethodCandidate method, ArgumentBinding argBinding) { Assert.NotNull(method, argBinding); Method = method; ArgumentBinding = argBinding; }
/// <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); }