Beispiel #1
0
        internal MSAst Call(string methodName, MSAst instance = null, Type type = null, params MSAst[] arguments)
        {
            if (((instance == null) && (type == null)) || ((instance != null) && (type != null)))
            {
                throw new ArgumentException("Either 'instance' or 'type' must be specified, but not both.");
            }

            List <MethodBase> candidates;

            var isCandidate =
                (Func <MethodBase, bool>)
                    (m => (m.Name == methodName) &&
                    ((m.GetParameters().Length == arguments.Length) ||
                     (BinderHelpers.IsParamsMethod(m) && ((m.GetParameters().Length + 1) <= arguments.Length))));

            if (type != null)
            {
                candidates = type
                             .GetMethods(BindingFlags.Public | BindingFlags.Static)
                             .Where(isCandidate)
                             .Cast <MethodBase>()
                             .ToList();
            }
            else
            {
                candidates = instance.Type
                             .GetMethods(BindingFlags.Public | BindingFlags.Static)
                             .Where(isCandidate)
                             .Cast <MethodBase>()
                             .ToList();
            }

            return(_binder.Binder.CallMethod(
                       _sxeContext.OverloadResolver.CreateOverloadResolver(
                           arguments.Select(o => DynamicUtils.ObjectToMetaObject(null, o)).ToList(),
                           new CallSignature(arguments.Length),
                           CallTypes.None),
                       candidates).Expression);
        }
Beispiel #2
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));
        }
Beispiel #3
0
        /// <summary>
        /// Builds a new MethodCandidate which takes count arguments and the provided list of keyword arguments.
        ///
        /// The basic idea here is to figure out which parameters map to params or a dictionary params and
        /// fill in those spots w/ extra ParameterWrapper's.
        /// </summary>
        internal MethodCandidate MakeParamsExtended(ActionBinder binder, int count, SymbolId[] names)
        {
            Debug.Assert(BinderHelpers.IsParamsMethod(_target.Method));

            List <ParameterWrapper> newParameters = new List <ParameterWrapper>(count);
            // if we don't have a param array we'll have a param dict which is type object
            Type elementType = null;
            int  index = -1, kwIndex = -1;

            // keep track of which kw args map to a real argument, and which ones
            // map to the params dictionary.
            List <SymbolId> unusedNames       = new List <SymbolId>(names);
            List <int>      unusedNameIndexes = new List <int>();

            for (int i = 0; i < unusedNames.Count; i++)
            {
                unusedNameIndexes.Add(i);
            }

            for (int i = 0; i < _parameters.Count; i++)
            {
                ParameterWrapper pw = _parameters[i];

                if (_parameters[i].IsParamsDict)
                {
                    kwIndex = i;
                }
                else if (_parameters[i].IsParamsArray)
                {
                    elementType = pw.Type.GetElementType();
                    index       = i;
                }
                else
                {
                    for (int j = 0; j < unusedNames.Count; j++)
                    {
                        if (unusedNames[j] == _parameters[i].Name)
                        {
                            unusedNames.RemoveAt(j);
                            unusedNameIndexes.RemoveAt(j);
                            break;
                        }
                    }
                    newParameters.Add(pw);
                }
            }

            if (index != -1)
            {
                while (newParameters.Count < (count - unusedNames.Count))
                {
                    ParameterWrapper param = new ParameterWrapper(binder, elementType, SymbolId.Empty, false);
                    newParameters.Insert(System.Math.Min(index, newParameters.Count), param);
                }
            }

            if (kwIndex != -1)
            {
                foreach (SymbolId si in unusedNames)
                {
                    newParameters.Add(new ParameterWrapper(binder, typeof(object), si, false));
                }
            }
            else if (unusedNames.Count != 0)
            {
                // unbound kw args and no where to put them, can't call...
                // TODO: We could do better here because this results in an incorrect arg # error message.
                return(null);
            }

            // if we have too many or too few args we also can't call
            if (count != newParameters.Count)
            {
                return(null);
            }

            return(new MethodCandidate(_target.MakeParamsExtended(count, unusedNames.ToArray(), unusedNameIndexes.ToArray()), newParameters));
        }