private MethodCandidate CreateDefaultCandidate(int defaultsUsed) { List <ArgBuilder> defaultArgBuilders = new List <ArgBuilder>(_arguments); List <ParameterWrapper> necessaryParams = _parameters.GetRange(0, _parameters.Count - defaultsUsed); for (int curDefault = 0; curDefault < defaultsUsed; curDefault++) { int readIndex = _defaultArguments.Count - defaultsUsed + curDefault; int writeIndex = defaultArgBuilders.Count - defaultsUsed + curDefault; if (_defaultArguments[readIndex] != null) { defaultArgBuilders[writeIndex] = _defaultArguments[readIndex]; } else { necessaryParams.Add(_parameters[_parameters.Count - defaultsUsed + curDefault]); } } // shift any arguments forward that need to be... int curArg = _overload.IsStatic ? 0 : 1; for (int i = 0; i < defaultArgBuilders.Count; i++) { SimpleArgBuilder sab = defaultArgBuilders[i] as SimpleArgBuilder; if (sab != null) { defaultArgBuilders[i] = sab.MakeCopy(curArg++); } } return(new MethodCandidate(_resolver, _overload, necessaryParams, _paramsDict, _returnBuilder, _instanceBuilder, defaultArgBuilders, null)); }
private int GetConsumedArguments() { int consuming = 0; foreach (ArgBuilder argb in _argBuilders) { SimpleArgBuilder sab = argb as SimpleArgBuilder; if (sab != null && !sab.IsParamsDict || argb is KeywordArgBuilder) { consuming++; } } return consuming; }
private MethodCandidate MakeParamsExtended(string[] names, int[] nameIndices, List<ParameterWrapper> parameters) { Debug.Assert(Overload.IsVariadic); List<ArgBuilder> newArgBuilders = new List<ArgBuilder>(_argBuilders.Count); // current argument that we consume, initially skip this if we have it. int curArg = _overload.IsStatic ? 0 : 1; int kwIndex = -1; ArgBuilder paramsDictBuilder = null; foreach (ArgBuilder ab in _argBuilders) { // TODO: define a virtual method on ArgBuilder implementing this functionality: SimpleArgBuilder sab = ab as SimpleArgBuilder; if (sab != null) { // we consume one or more incoming argument(s) if (sab.IsParamsArray) { // consume all the extra arguments int paramsUsed = parameters.Count - GetConsumedArguments() - names.Length + (_overload.IsStatic ? 1 : 0); newArgBuilders.Add(new ParamsArgBuilder( sab.ParameterInfo, sab.Type.GetElementType(), curArg, paramsUsed )); curArg += paramsUsed; } else if (sab.IsParamsDict) { // consume all the kw arguments kwIndex = newArgBuilders.Count; paramsDictBuilder = sab; } else { // consume the argument, adjust its position: newArgBuilders.Add(sab.MakeCopy(curArg++)); } } else if (ab is KeywordArgBuilder) { newArgBuilders.Add(ab); curArg++; } else { // CodeContext, null, default, etc... we don't consume an // actual incoming argument. newArgBuilders.Add(ab); } } if (kwIndex != -1) { newArgBuilders.Insert(kwIndex, new ParamsDictArgBuilder(paramsDictBuilder.ParameterInfo, curArg, names, nameIndices)); } return new MethodCandidate(_resolver, _overload, parameters, null, _returnBuilder, _instanceBuilder, newArgBuilders, null); }
public void MapParameter(ParameterInfo pi) { int indexForArgBuilder; int nameIndex = _argNames.IndexOf(pi.Name); if (nameIndex == -1) { // positional argument, we simply consume the next argument indexForArgBuilder = _argIndex++; } else { // keyword argument, we just tell the simple arg builder to consume arg 0. // KeywordArgBuilder will then pass in the correct single argument based // upon the actual argument number provided by the user. indexForArgBuilder = 0; } // if the parameter is default we need to build a default arg builder and then // build a reduced method at the end. if (!pi.IsMandatory()) { // We need to build the default builder even if we have a parameter for it already to // get good consistency of our error messages. But consider a method like // def foo(a=1, b=2) and the user calls it as foo(b=3). Then adding the default // value breaks an otherwise valid call. This is because we only generate MethodCandidates // filling in the defaults from right to left (so the method - 1 arg requires a, // and the method minus 2 args requires b). So we only add the default if it's // a positional arg or we don't already have a default value. if (nameIndex == -1 || !_hasDefaults) { _defaultArguments.Add(new DefaultArgBuilder(pi)); _hasDefaults = true; } else { _defaultArguments.Add(null); } } else if (_defaultArguments.Count > 0) { // non-contigious default parameter _defaultArguments.Add(null); } ArgBuilder ab; if (pi.ParameterType.IsByRef) { _hasByRef = true; Type elementType = pi.ParameterType.GetElementType(); Type refType = typeof(StrongBox <>).MakeGenericType(elementType); _parameters.Add(new ParameterWrapper(pi, refType, pi.Name, ParameterBindingFlags.ProhibitNull)); ab = new ReferenceArgBuilder(pi, elementType, refType, indexForArgBuilder); } else if (pi.Position == 0 && _overload.IsExtension) { _parameters.Add(new ParameterWrapper(pi, pi.ParameterType, pi.Name, ParameterBindingFlags.IsHidden)); ab = new SimpleArgBuilder(pi, pi.ParameterType, indexForArgBuilder, false, false); } else { ab = AddSimpleParameterMapping(pi, indexForArgBuilder); } if (nameIndex == -1) { _arguments.Add(ab); } else { Debug.Assert(KeywordArgBuilder.BuilderExpectsSingleParameter(ab)); _arguments.Add(new KeywordArgBuilder(ab, _argNames.Count, nameIndex)); } }
internal MethodTarget MakeParamsExtended(int argCount, SymbolId[] names, int[] nameIndexes) { Debug.Assert(BinderHelpers.IsParamsMethod(Method)); List <ArgBuilder> newArgBuilders = new List <ArgBuilder>(_argBuilders.Count); // current argument that we consume, initially skip this if we have it. int curArg = CompilerHelpers.IsStatic(_method) ? 0 : 1; int kwIndex = -1; ArgBuilder paramsDictBuilder = null; foreach (ArgBuilder ab in _argBuilders) { SimpleArgBuilder sab = ab as SimpleArgBuilder; if (sab != null) { // we consume one or more incoming argument(s) if (sab.IsParamsArray) { // consume all the extra arguments int paramsUsed = argCount - GetConsumedArguments() - names.Length + (CompilerHelpers.IsStatic(_method) ? 1 : 0); newArgBuilders.Add(new ParamsArgBuilder( sab.ParameterInfo, sab.Type.GetElementType(), curArg, paramsUsed )); curArg += paramsUsed; } else if (sab.IsParamsDict) { // consume all the kw arguments kwIndex = newArgBuilders.Count; paramsDictBuilder = sab; } else { // consume the argument, adjust its position: newArgBuilders.Add(sab.MakeCopy(curArg++)); } } else { // CodeContext, null, default, etc... we don't consume an // actual incoming argument. newArgBuilders.Add(ab); } } if (kwIndex != -1) { newArgBuilders.Insert(kwIndex, new ParamsDictArgBuilder(paramsDictBuilder.ParameterInfo, curArg, names, nameIndexes)); } return(new MethodTarget(_binder, Method, argCount, _instanceBuilder, newArgBuilders, _returnBuilder)); }