SimpleArgBuilder produces the value produced by the user as the argument value. It also tracks information about the original parameter and is used to create extended methods for params arrays and param dictionary functions.
Inheritance: ArgBuilder
Example #1
0
        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));
        }
Example #2
0
 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;
 }
Example #3
0
        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);
        }
Example #4
0
        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));
            }
        }
Example #5
0
        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));
        }