Пример #1
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));
        }
Пример #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);
        }
Пример #3
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));
        }
Пример #4
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));
        }