internal CallFailure(MethodCandidate candidate, string[] keywordArgs, int[] positionalArgs) { Candidate = candidate; Reason = CallFailureReason.DuplicateKeyword; _keywordArgs = keywordArgs; _positionalArgs = positionalArgs ?? EmptyArray <int> .Instance; }
private readonly int _actualArgs; // gets the actual number of arguments provided /// <summary> /// Creates a new BindingTarget when the method binding has succeeded. /// </summary> internal BindingTarget(string name, int actualArgumentCount, MethodCandidate candidate, NarrowingLevel level, RestrictedArguments restrictedArgs) { _name = name; _candidate = candidate; _restrictedArgs = restrictedArgs; _level = level; _actualArgs = actualArgumentCount; }
internal CallFailure(MethodCandidate candidate, string[] keywordArgs) { Candidate = candidate; Reason = CallFailureReason.UnassignableKeyword; _keywordArgs = keywordArgs; _positionalArgs = EmptyArray <int> .Instance; }
/// <summary> /// Creates a new set of arg builders for the given generic method definition which target the new /// parameters. /// </summary> private static List <ArgBuilder> CreateNewArgBuilders(MethodCandidate candidate, OverloadInfo newOverload) { List <ArgBuilder> argBuilders = new List <ArgBuilder>(); foreach (ArgBuilder oldArgBuilder in candidate.ArgBuilders) { var pi = oldArgBuilder.ParameterInfo; if (pi != null && (pi.ParameterType.IsGenericParameter || pi.ParameterType.ContainsGenericParameters())) { ArgBuilder replacement = oldArgBuilder.Clone(newOverload.Parameters[pi.Position]); if (replacement == null) { return(null); } argBuilders.Add(replacement); } else { argBuilders.Add(oldArgBuilder); } } return(argBuilders); }
internal static Candidate GetPreferredCandidate(MethodCandidate one, MethodCandidate two, CallTypes callType, MetaObject[] actualTypes) { Candidate cmpParams = ParameterWrapper.GetPreferredParameters(one.Parameters, two.Parameters, actualTypes); if (cmpParams.Chosen()) { return(cmpParams); } Candidate ret = MethodTarget.CompareEquivalentParameters(one.Target, two.Target); if (ret.Chosen()) { return(ret); } if (CompilerHelpers.IsStatic(one.Target.Method) && !CompilerHelpers.IsStatic(two.Target.Method)) { return(callType == CallTypes.ImplicitInstance ? Candidate.Two : Candidate.One); } else if (!CompilerHelpers.IsStatic(one.Target.Method) && CompilerHelpers.IsStatic(two.Target.Method)) { return(callType == CallTypes.ImplicitInstance ? Candidate.One : Candidate.Two); } return(Candidate.Equivalent); }
private readonly int _actualArgs; // gets the actual number of arguments provided /// <summary> /// Creates a new BindingTarget when the method binding has succeeded. /// </summary> internal BindingTarget(string name, int actualArgumentCount, MethodCandidate candidate, NarrowingLevel level, RestrictedArguments restrictedArgs) { _name = name; _candidate = candidate; _restrictedArgs = restrictedArgs; _level = level; _actualArgs = actualArgumentCount; }
private readonly int[] _expectedArgs; // gets the acceptable number of parameters which can be passed to the method. /// <summary> /// Creates a new BindingTarget when the method binding has succeeded. /// </summary> internal BindingTarget(string name, int actualArgumentCount, MethodCandidate candidate, NarrowingLevel level, RestrictedArguments restrictedArgs) { Name = name; MethodCandidate = candidate; RestrictedArguments = restrictedArgs; NarrowingLevel = level; ActualArgumentCount = actualArgumentCount; }
internal CallFailure(MethodCandidate candidate, CallFailureReason reason) { Debug.Assert(reason != CallFailureReason.ConversionFailure); // use first overload Debug.Assert(reason != CallFailureReason.UnassignableKeyword); // use second overload Debug.Assert(reason != CallFailureReason.DuplicateKeyword); // use third overload Candidate = candidate; Reason = reason; }
/// <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; }
/// <summary> /// Gets an Expression which calls the binding target if the method binding succeeded. /// /// Throws InvalidOperationException if the binding failed. /// </summary> public Expression MakeExpression() { if (MethodCandidate == null) { throw new InvalidOperationException("An expression cannot be produced because the method binding was unsuccessful."); } if (RestrictedArguments == null) { throw new InvalidOperationException("An expression cannot be produced because the method binding was done with Expressions, not MetaObject's"); } return(MethodCandidate.MakeExpression(RestrictedArguments)); }
/// <summary> /// Creates a new list of ParameterWrappers for the generic method replacing the old parameters with the new ones. /// </summary> private static List <ParameterWrapper> CreateNewWrappers(MethodCandidate candidate, OverloadInfo newOverload, OverloadInfo oldOverload) { List <ParameterWrapper> newWrappers = new List <ParameterWrapper>(); for (int i = 0; i < candidate.ParameterCount; i++) { ParameterWrapper oldWrap = candidate.GetParameter(i); ParameterInfo pi = null; Type newType = oldWrap.Type; if (oldWrap.ParameterInfo != null) { pi = newOverload.Parameters[oldWrap.ParameterInfo.Position]; ParameterInfo oldParam = oldOverload.Parameters[oldWrap.ParameterInfo.Position]; if (oldParam.ParameterType == oldWrap.Type) { newType = pi.ParameterType; } else if (pi.ParameterType.IsByRef) { newType = pi.ParameterType.GetElementType(); if (oldParam.ParameterType.GetElementType() != oldWrap.Type) { Debug.Assert(CompilerHelpers.IsStrongBox(oldWrap.Type)); newType = typeof(StrongBox <>).MakeGenericType(newType); } } else { Debug.Assert(oldParam.ParameterType.GetElementType() == oldWrap.Type); newType = pi.ParameterType.GetElementType(); } } newWrappers.Add(new ParameterWrapper(pi, newType, oldWrap.Name, oldWrap.Flags)); } return(newWrappers); }
private void AddTarget(MethodCandidate target) { int count = target.ParameterCount; CandidateSet set; if (!_candidateSets.TryGetValue(count, out set)) { set = new CandidateSet(count); _candidateSets[count] = set; } set.Add(target); }
/// <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); }
/// <summary> /// Returns a mapping from generic type parameter to the input DMOs which map to it. /// </summary> private static Dictionary<Type/*!*/, ArgumentInputs/*!*/>/*!*/ GetArgumentToInputMapping(MethodCandidate/*!*/ wrappers, IList<DynamicMetaObject/*!*/>/*!*/ args) { Dictionary<Type, ArgumentInputs> inputs = new Dictionary<Type, ArgumentInputs>(); for (int curParam = 0; curParam < wrappers.ParameterCount; curParam++) { if (wrappers.GetParameter(curParam).IsParamsArray) { AddOneInput(inputs, args[curParam], wrappers.GetParameter(curParam).Type.GetElementType()); } else { AddOneInput(inputs, args[curParam], wrappers.GetParameter(curParam).Type); } } return inputs; }
/// <summary> /// Creates a new list of ParameterWrappers for the generic method replacing the old parameters with the new ones. /// </summary> private static List<ParameterWrapper> CreateNewWrappers(MethodCandidate candidate, ParameterInfo[] newParams, ParameterInfo[] oldParams) { List<ParameterWrapper> newWrappers = new List<ParameterWrapper>(); for (int i = 0; i < candidate.ParameterCount; i++) { ParameterWrapper oldWrap = candidate.GetParameter(i); ParameterInfo pi = null; Type newType = oldWrap.Type; if (oldWrap.ParameterInfo != null) { pi = newParams[oldWrap.ParameterInfo.Position]; ParameterInfo oldParam = oldParams[oldWrap.ParameterInfo.Position]; if (oldParam.ParameterType == oldWrap.Type) { newType = pi.ParameterType; } else { Debug.Assert(oldParam.ParameterType.GetElementType() == oldWrap.Type); newType = pi.ParameterType.GetElementType(); } } newWrappers.Add(new ParameterWrapper(pi, newType, oldWrap.Name, oldWrap.ProhibitNull, oldWrap.IsParamsArray, oldWrap.IsParamsDict, oldWrap.IsHidden)); } return newWrappers; }
internal void Add(MethodCandidate target) { Debug.Assert(target.ParameterCount == _arity); _candidates.Add(target); }
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; }
private BindingTarget MakeAmbiguousBindingTarget(List<ApplicableCandidate> result) { var methods = new MethodCandidate[result.Count]; for (int i = 0; i < result.Count; i++) { methods[i] = result[i].Method; } return new BindingTarget(_methodName, _actualArguments.VisibleCount, methods); }
internal ApplicableCandidate(MethodCandidate method, ArgumentBinding argBinding) { Assert.NotNull(method, argBinding); Method = method; ArgumentBinding = argBinding; }
internal MethodCandidate(MethodCandidate previous, NarrowingLevel narrowingLevel) { this._target = previous.Target; this._parameters = previous._parameters; _narrowingLevel = narrowingLevel; }
internal CallFailure(MethodCandidate candidate, ConversionResult[] results) { _candidate = candidate; _results = results; _reason = CallFailureReason.ConversionFailure; }
/// <summary> /// Returns a mapping from generic type parameter to the input DMOs which map to it. /// </summary> private static Dictionary <Type /*!*/, ArgumentInputs /*!*/> /*!*/ GetArgumentToInputMapping(MethodCandidate /*!*/ candidate, IList <DynamicMetaObject /*!*/> /*!*/ args) { Dictionary <Type, ArgumentInputs> inputs = new Dictionary <Type, ArgumentInputs>(); for (int curParam = 0; curParam < candidate.ParameterCount; curParam++) { ParameterWrapper param = candidate.GetParameter(curParam); if (param.IsParamsArray) { AddOneInput(inputs, args[curParam], param.Type.GetElementType()); } else if (param.IsByRef) { AddOneInput(inputs, args[curParam], param.ParameterInfo.ParameterType); } else { AddOneInput(inputs, args[curParam], param.Type); } } return(inputs); }
internal CallFailure(MethodCandidate candidate, CallFailureReason reason) { _candidate = candidate; _reason = reason; }
internal CallFailure(MethodCandidate candidate, ConversionResult[] results) { _candidate = candidate; _results = results; _reason = CallFailureReason.ConversionFailure; }
internal ApplicableCandidate(MethodCandidate method, ArgumentBinding argBinding) { Assert.NotNull(method, argBinding); Method = method; ArgumentBinding = argBinding; }
private void AddSimpleTarget(MethodCandidate target) { AddTarget(target); if (BinderHelpers.IsParamsMethod(target.Method)) { if (_paramsCandidates == null) { _paramsCandidates = new List<MethodCandidate>(); } _paramsCandidates.Add(target); } }
private void AddSimpleTarget(MethodCandidate target) { if (target.HasParamsArray || target.HasParamsDictionary) { if (BindToUnexpandedParams(target)) { AddTarget(target); } if (_paramsCandidates == null) { _paramsCandidates = new List<MethodCandidate>(); } _paramsCandidates.Add(target); } else { AddTarget(target); } }
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; }
/// <summary> /// Creates a new set of arg builders for the given generic method definition which target the new /// parameters. /// </summary> private static List<ArgBuilder> CreateNewArgBuilders(MethodCandidate candidate, OverloadInfo newOverload) { List<ArgBuilder> argBuilders = new List<ArgBuilder>(); foreach (ArgBuilder oldArgBuilder in candidate.ArgBuilders) { var pi = oldArgBuilder.ParameterInfo; if (pi != null && (pi.ParameterType.IsGenericParameter || pi.ParameterType.ContainsGenericParameters)) { ArgBuilder replacement = oldArgBuilder.Clone(newOverload.Parameters[pi.Position]); if (replacement == null) { return null; } argBuilders.Add(replacement); } else { argBuilders.Add(oldArgBuilder); } } return argBuilders; }
internal Candidate CompareEquivalentParameters(MethodCandidate one, MethodCandidate two) { // Prefer normal methods over explicit interface implementations if (two.Method.IsPrivate && !one.Method.IsPrivate) return Candidate.One; if (one.Method.IsPrivate && !two.Method.IsPrivate) return Candidate.Two; // Prefer non-generic methods over generic methods if (one.Method.IsGenericMethod) { if (!two.Method.IsGenericMethod) { return Candidate.Two; } else { //!!! Need to support selecting least generic method here return Candidate.Equivalent; } } else if (two.Method.IsGenericMethod) { return Candidate.One; } // prefer methods without out params over those with them switch (Compare(one.ReturnBuilder.CountOutParams, two.ReturnBuilder.CountOutParams)) { case 1: return Candidate.Two; case -1: return Candidate.One; } // prefer methods using earlier conversions rules to later ones for (int i = Int32.MaxValue; i >= 0; ) { int maxPriorityThis = FindMaxPriority(one.ArgBuilders, i); int maxPriorityOther = FindMaxPriority(two.ArgBuilders, i); if (maxPriorityThis < maxPriorityOther) return Candidate.One; if (maxPriorityOther < maxPriorityThis) return Candidate.Two; i = maxPriorityThis - 1; } // prefer methods whose name exactly matches the call site name: if (one.Method.Name != two.Method.Name) { if (one.Method.Name == _methodName) { return Candidate.One; } if (two.Method.Name == _methodName) { return Candidate.Two; } } return Candidate.Equivalent; }
/// <summary> /// Creates a new list of ParameterWrappers for the generic method replacing the old parameters with the new ones. /// </summary> private static List<ParameterWrapper> CreateNewWrappers(MethodCandidate candidate, OverloadInfo newOverload, OverloadInfo oldOverload) { List<ParameterWrapper> newWrappers = new List<ParameterWrapper>(); for (int i = 0; i < candidate.ParameterCount; i++) { ParameterWrapper oldWrap = candidate.GetParameter(i); ParameterInfo pi = null; Type newType = oldWrap.Type; if (oldWrap.ParameterInfo != null) { pi = newOverload.Parameters[oldWrap.ParameterInfo.Position]; ParameterInfo oldParam = oldOverload.Parameters[oldWrap.ParameterInfo.Position]; if (oldParam.ParameterType == oldWrap.Type) { newType = pi.ParameterType; } else if (pi.ParameterType.IsByRef) { newType = pi.ParameterType.GetElementType(); if (oldParam.ParameterType.GetElementType() != oldWrap.Type) { Debug.Assert(CompilerHelpers.IsStrongBox(oldWrap.Type)); newType = typeof(StrongBox<>).MakeGenericType(newType); } } else { Debug.Assert(oldParam.ParameterType.GetElementType() == oldWrap.Type); newType = pi.ParameterType.GetElementType(); } } newWrappers.Add(new ParameterWrapper(pi, newType, oldWrap.Name, oldWrap.Flags)); } return newWrappers; }
/// <summary> /// We expand params arrays for library methods. Splat operator needs to be used to pass content of an array/list into params array method. /// </summary> protected override bool BindToUnexpandedParams(MethodCandidate/*!*/ candidate) { // TODO: separate flag? return _implicitProtocolConversions; }
/// <summary> /// Returns a mapping from generic type parameter to the input DMOs which map to it. /// </summary> private static Dictionary<Type/*!*/, ArgumentInputs/*!*/>/*!*/ GetArgumentToInputMapping(MethodCandidate/*!*/ candidate, IList<DynamicMetaObject/*!*/>/*!*/ args) { Dictionary<Type, ArgumentInputs> inputs = new Dictionary<Type, ArgumentInputs>(); for (int curParam = 0; curParam < candidate.ParameterCount; curParam++) { ParameterWrapper param = candidate.GetParameter(curParam); if (param.IsParamsArray) { AddOneInput(inputs, args[curParam], param.Type.GetElementType()); } else if (param.IsByRef) { AddOneInput(inputs, args[curParam], param.ParameterInfo.ParameterType); } else { AddOneInput(inputs, args[curParam], param.Type); } } return inputs; }
internal CallFailure(MethodCandidate candidate, string[] keywordArgs, bool unassignable) { _reason = unassignable ? CallFailureReason.UnassignableKeyword : CallFailureReason.DuplicateKeyword; _candidate = candidate; _keywordArgs = keywordArgs; }
internal CallFailure(MethodCandidate candidate, string[] keywordArgs, bool unassignable) { _reason = unassignable ? CallFailureReason.UnassignableKeyword : CallFailureReason.DuplicateKeyword; _candidate = candidate; _keywordArgs = keywordArgs; }
internal void Add(MethodCandidate target) { Debug.Assert(target.ParameterCount == _arity); _candidates.Add(target); }
internal CallFailure(MethodCandidate candidate, CallFailureReason reason) { _candidate = candidate; _reason = reason; }
/// <summary> /// Creates a new BindingTarget when the match was ambiguous /// </summary> internal BindingTarget(string name, int actualArgumentCount, MethodCandidate[] ambiguousMatches) { _name = name; _result = BindingResult.AmbiguousMatch; _ambiguousMatches = ambiguousMatches; _actualArgs = actualArgumentCount; }
/// <summary> /// Allow to bind an array/dictionary instance or a null reference to params array/dictionary parameter. /// </summary> protected virtual bool BindToUnexpandedParams(MethodCandidate candidate) { return true; }