Exemple #1
0
        private void AddBasicMethodTargets(MethodBase method)
        {
            List <ParameterWrapper> parameters = new List <ParameterWrapper>();
            int        argIndex = 0;
            ArgBuilder instanceBuilder;
            bool       hasDefaults = false;

            if (!CompilerHelpers.IsStatic(method))
            {
                parameters.Add(new ParameterWrapper(_binder, method.DeclaringType, true));
                instanceBuilder = new SimpleArgBuilder(argIndex++, parameters[0].Type);
            }
            else
            {
                instanceBuilder = new NullArgBuilder();
            }

            ParameterInfo[]   methodParams    = method.GetParameters();
            List <ArgBuilder> argBuilders     = new List <ArgBuilder>(methodParams.Length);
            List <ArgBuilder> defaultBuilders = new List <ArgBuilder>();
            bool hasByRefOrOut = false;

            foreach (ParameterInfo pi in methodParams)
            {
                if (pi.ParameterType == typeof(CodeContext) && argBuilders.Count == 0)
                {
                    argBuilders.Add(new ContextArgBuilder());
                    continue;
                }

                int newIndex, kwIndex = GetKeywordIndex(pi);
                if (kwIndex == -1)
                {
                    if (!CompilerHelpers.IsMandatoryParameter(pi))
                    {
                        defaultBuilders.Add(new DefaultArgBuilder(pi.ParameterType, pi.DefaultValue));
                        hasDefaults = true;
                    }
                    else if (defaultBuilders.Count > 0)
                    {
                        defaultBuilders.Add(null);
                    }
                    newIndex = argIndex++;
                }
                else
                {
                    defaultBuilders.Add(null);
                    newIndex = 0;
                }

                ArgBuilder ab;
                if (pi.ParameterType.IsByRef)
                {
                    hasByRefOrOut = true;
                    Type             refType = typeof(StrongBox <>).MakeGenericType(pi.ParameterType.GetElementType());
                    ParameterWrapper param   = new ParameterWrapper(_binder, refType, true, SymbolTable.StringToId(pi.Name));
                    parameters.Add(param);
                    ab = new ReferenceArgBuilder(newIndex, param.Type);
                }
                else
                {
                    hasByRefOrOut |= CompilerHelpers.IsOutParameter(pi);
                    ParameterWrapper param = new ParameterWrapper(_binder, pi);
                    parameters.Add(param);
                    ab = new SimpleArgBuilder(newIndex, param.Type, pi);
                }

                if (kwIndex == -1)
                {
                    argBuilders.Add(ab);
                }
                else
                {
                    argBuilders.Add(new KeywordArgBuilder(ab, _kwArgs.Length, kwIndex));
                }
            }

            ReturnBuilder returnBuilder = MakeKeywordReturnBuilder(
                new ReturnBuilder(CompilerHelpers.GetReturnType(method)),
                methodParams,
                parameters);

            if (hasDefaults)
            {
                for (int defaultsUsed = 1; defaultsUsed < defaultBuilders.Count + 1; defaultsUsed++)
                {
                    // if the left most default we'll use is not present then don't add a default.  This happens in cases such as:
                    // a(a=1, b=2, c=3) and then call with a(a=5, c=3).  We'll come through once for c (no default, skip),
                    // once for b (default present, emit) and then a (no default, skip again).  W/o skipping we'd generate the same
                    // method multiple times.  This also happens w/ non-contigious default values, e.g. foo(a, b=3, c) where we don't want
                    // to generate a default candidate for just c which matches the normal method.
                    if (defaultBuilders[defaultBuilders.Count - defaultsUsed] != null)
                    {
                        AddTarget(MakeDefaultCandidate(
                                      method,
                                      parameters,
                                      instanceBuilder,
                                      argBuilders,
                                      defaultBuilders,
                                      returnBuilder,
                                      defaultsUsed));
                    }
                }
            }

            if (hasByRefOrOut)
            {
                AddSimpleTarget(MakeByRefReducedMethodTarget(method));
            }
            AddSimpleTarget(MakeMethodCandidate(method, parameters, instanceBuilder, argBuilders, returnBuilder));
        }
Exemple #2
0
        private MethodCandidate MakeByRefReducedMethodTarget(MethodBase method)
        {
            List <ParameterWrapper> parameters = new List <ParameterWrapper>();
            int        argIndex = 0;
            ArgBuilder instanceBuilder;

            if (!CompilerHelpers.IsStatic(method))
            {
                parameters.Add(new ParameterWrapper(_binder, method.DeclaringType, true));
                instanceBuilder = new SimpleArgBuilder(argIndex++, parameters[0].Type);
            }
            else
            {
                instanceBuilder = new NullArgBuilder();
            }

            List <ArgBuilder> argBuilders = new List <ArgBuilder>();

            List <int> returnArgs = new List <int>();

            if (CompilerHelpers.GetReturnType(method) != typeof(void))
            {
                returnArgs.Add(-1);
            }

            int paramCount = 0;

            foreach (ParameterInfo pi in method.GetParameters())
            {
                if (pi.ParameterType == typeof(CodeContext) && paramCount == 0)
                {
                    argBuilders.Add(new ContextArgBuilder());
                    continue;
                }
                paramCount++;

                int newIndex = 0, kwIndex = -1;
                if (!CompilerHelpers.IsOutParameter(pi))
                {
                    kwIndex = GetKeywordIndex(pi);
                    if (kwIndex == -1)
                    {
                        newIndex = argIndex++;
                    }
                }

                ArgBuilder ab;
                if (CompilerHelpers.IsOutParameter(pi))
                {
                    returnArgs.Add(argBuilders.Count);
                    ab = new OutArgBuilder(pi);
                }
                else if (pi.ParameterType.IsByRef)
                {
                    returnArgs.Add(argBuilders.Count);
                    ParameterWrapper param = new ParameterWrapper(_binder, pi.ParameterType.GetElementType(), SymbolTable.StringToId(pi.Name));
                    parameters.Add(param);
                    ab = new ReturnReferenceArgBuilder(newIndex, pi.ParameterType.GetElementType());
                }
                else
                {
                    ParameterWrapper param = new ParameterWrapper(_binder, pi);
                    parameters.Add(param);
                    ab = new SimpleArgBuilder(newIndex, param.Type, pi);
                }

                if (kwIndex == -1)
                {
                    argBuilders.Add(ab);
                }
                else
                {
                    argBuilders.Add(new KeywordArgBuilder(ab, _kwArgs.Length, kwIndex));
                }
            }

            ReturnBuilder returnBuilder = MakeKeywordReturnBuilder(
                new ByRefReturnBuilder(_binder, returnArgs),
                method.GetParameters(),
                parameters);

            return(MakeMethodCandidate(method, parameters, instanceBuilder, argBuilders, returnBuilder));
        }
Exemple #3
0
        /// <summary>
        /// Performs late-bound invocation - used by ReflectedMethod's and
        /// for keyword argument calls.
        /// </summary>
        protected static object Invoke(MethodBinding binding)
        {
            object result;

            try {
                if (binding.method is ConstructorInfo)
                {
                    result = ((ConstructorInfo)binding.method).Invoke(binding.arguments);
                }
                else
                {
                    result = binding.method.Invoke(binding.instance, binding.arguments);
                }
            } catch (TargetInvocationException tie) {
                throw ExceptionConverter.UpdateForRethrow(tie.InnerException);
            }

            MethodBase info = binding.method;

            ParameterInfo[] parameters = info.GetParameters();
            int             results    = 0;

            for (int parm = 0; parm < parameters.Length; parm++)
            {
                if (parameters[parm].ParameterType.IsByRef)
                {
                    results++;
                }
            }
            if (results == 0)
            {
                return(Ops.ToPython(CompilerHelpers.GetReturnType(info), result));
            }

            object[] retValues;
            int      retValueIndex = 0;

            if (info is MethodInfo && ((MethodInfo)info).ReturnType != typeof(void))
            {
                retValues = new object[results + 1];
                retValues[retValueIndex++] = Ops.ToPython(CompilerHelpers.GetReturnType(info), result);
            }
            else
            {
                retValues = new object[results];
            }

            for (int parm = 0; parm < parameters.Length; parm++)
            {
                Type parmType = parameters[parm].ParameterType;
                if (parmType.IsByRef)
                {
                    retValues[retValueIndex++] = Ops.ToPython(parmType, binding.arguments[parm]);
                }
            }
            if (retValues.Length == 1)
            {
                return(retValues[0]);
            }
            else
            {
                return(Tuple.MakeTuple(retValues));
            }
        }