Пример #1
0
        public int?CompareTo(ParameterWrapper other, Type actualType)
        {
            //+1 if t1, -1 if t2, null if no resolution

            Type t1 = Type;
            Type t2 = other.Type;

            if (t1 == t2)
            {
                return(0);
            }
            int?ret = null;

            ret = SelectBestConversionFor(actualType, t1, t2, NarrowingLevel.None);
            if (ret != null)
            {
                return(ret);
            }

            ret = SelectBestConversionFor(actualType, t1, t2, NarrowingLevel.Preferred);
            if (ret != null)
            {
                return(ret);
            }

            ret = SelectBestConversionFor(actualType, t1, t2, NarrowingLevel.All);
            if (ret != null)
            {
                return(ret);
            }

            return(CompareTo(other));
        }
Пример #2
0
        private ReturnBuilder MakeKeywordReturnBuilder(ReturnBuilder returnBuilder, ParameterInfo[] methodParams, List <ParameterWrapper> parameters)
        {
            if (_binderType == BinderType.Constructor)
            {
                List <SymbolId>   unusedNames     = GetUnusedKeywordParameters(methodParams);
                List <MemberInfo> bindableMembers = GetBindableMembers(returnBuilder, unusedNames);
                List <int>        kwArgIndexs     = new List <int>();
                if (unusedNames.Count == bindableMembers.Count)
                {
                    foreach (MemberInfo mi in bindableMembers)
                    {
                        ParameterWrapper pw = new ParameterWrapper(
                            _binder,
                            mi.MemberType == MemberTypes.Property ?
                            ((PropertyInfo)mi).PropertyType :
                            ((FieldInfo)mi).FieldType,
                            false,
                            SymbolTable.StringToId(mi.Name));
                        parameters.Add(pw);
                        kwArgIndexs.Add(GetKeywordIndex(mi.Name));
                    }

                    KeywordConstructorReturnBuilder kwBuilder = new KeywordConstructorReturnBuilder(returnBuilder,
                                                                                                    _kwArgs.Length,
                                                                                                    kwArgIndexs.ToArray(),
                                                                                                    bindableMembers.ToArray());

                    return(kwBuilder);
                }
            }
            return(returnBuilder);
        }
Пример #3
0
        public static int?CompareParameters(IList <ParameterWrapper> parameters1, IList <ParameterWrapper> parameters2, Type[] actualTypes)
        {
            Debug.Assert(parameters1.Count == parameters2.Count);
            Debug.Assert(parameters1.Count == actualTypes.Length);

            int?ret = 0;

            for (int i = 0; i < parameters1.Count; i++)
            {
                ParameterWrapper p1 = parameters1[i];
                ParameterWrapper p2 = parameters2[i];
                int?cmp             = p1.CompareTo(p2, actualTypes[i]);

                switch (ret)
                {
                case 0:
                    ret = cmp; break;

                case +1:
                    if (cmp == -1)
                    {
                        return(null);
                    }
                    break;

                case -1:
                    if (cmp == +1)
                    {
                        return(null);
                    }
                    break;

                case null:
                    if (cmp != 0)
                    {
                        ret = cmp;
                    }
                    break;

                default:
                    throw new InvalidOperationException();
                }
            }

            return(ret);
        }
Пример #4
0
        public int?CompareTo(ParameterWrapper other)
        {
            Type t1 = Type;
            Type t2 = other.Type;

            if (t1 == t2)
            {
                return(0);
            }
            if (_binder.CanConvertFrom(t2, t1, NarrowingLevel.None))
            {
                if (_binder.CanConvertFrom(t1, t2, NarrowingLevel.None))
                {
                    return(null);
                }
                else
                {
                    return(-1);
                }
            }
            if (_binder.CanConvertFrom(t1, t2, NarrowingLevel.None))
            {
                return(+1);
            }

            // Special additional rules to order numeric value types
            if (_binder.PreferConvert(t1, t2))
            {
                return(-1);
            }
            else if (_binder.PreferConvert(t2, t1))
            {
                return(+1);
            }

            return(null);
        }
Пример #5
0
        public int? CompareTo(ParameterWrapper other, Type actualType) {
            //+1 if t1, -1 if t2, null if no resolution

            Type t1 = Type;
            Type t2 = other.Type;
            if (t1 == t2) return 0;
            int? ret = null;

            ret = SelectBestConversionFor(actualType, t1, t2, NarrowingLevel.None);
            if (ret != null) {
                return ret;
            }

            ret = SelectBestConversionFor(actualType, t1, t2, NarrowingLevel.Preferred);
            if (ret != null) {
                return ret;
            }

            ret = SelectBestConversionFor(actualType, t1, t2, NarrowingLevel.All);
            if (ret != null) {
                return ret;
            }

            return CompareTo(other);
        }
Пример #6
0
        public int? CompareTo(ParameterWrapper other) {
            Type t1 = Type;
            Type t2 = other.Type;
            if (t1 == t2) return 0;
            if (_binder.CanConvertFrom(t2, t1, NarrowingLevel.None)) {
                if (_binder.CanConvertFrom(t1, t2, NarrowingLevel.None)) {
                    return null;
                } else {
                    return -1;
                }
            }
            if (_binder.CanConvertFrom(t1, t2, NarrowingLevel.None)) {
                return +1;
            }

            // Special additional rules to order numeric value types
            if (_binder.PreferConvert(t1, t2)) return -1;
            else if (_binder.PreferConvert(t2, t1)) return +1;

            return null;
        }
Пример #7
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));
        }
Пример #8
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));
        }
Пример #9
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>
        public MethodCandidate MakeParamsExtended(ActionBinder binder, int count, SymbolId[] names)
        {
            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].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);
                    newParameters.Insert(System.Math.Min(index, newParameters.Count), param);
                }
            }

            if (kwIndex != -1)
            {
                foreach (SymbolId si in unusedNames)
                {
                    ParameterWrapper pw = new ParameterWrapper(binder, typeof(object), si);
                    newParameters.Add(pw);
                }
            }
            else if (unusedNames.Count != 0)
            {
                // unbound kw args and no where to put them, can't call...
                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));
        }
Пример #10
0
 public int?CompareParameters(MethodCandidate other, Type[] actualTypes)
 {
     return(ParameterWrapper.CompareParameters(this._parameters, other._parameters, actualTypes));
 }
Пример #11
0
        private ReturnBuilder MakeKeywordReturnBuilder(ReturnBuilder returnBuilder, ParameterInfo[] methodParams, List<ParameterWrapper> parameters) {
            if (_binderType == BinderType.Constructor) {
                List<SymbolId> unusedNames = GetUnusedKeywordParameters(methodParams);
                List<MemberInfo> bindableMembers = GetBindableMembers(returnBuilder, unusedNames);
                List<int> kwArgIndexs = new List<int>();
                if (unusedNames.Count == bindableMembers.Count) {
                    foreach (MemberInfo mi in bindableMembers) {
                        ParameterWrapper pw = new ParameterWrapper(
                            _binder,
                            mi.MemberType == MemberTypes.Property ?
                                ((PropertyInfo)mi).PropertyType :
                                ((FieldInfo)mi).FieldType,
                            false,
                            SymbolTable.StringToId(mi.Name));
                        parameters.Add(pw);
                        kwArgIndexs.Add(GetKeywordIndex(mi.Name));
                    }

                    KeywordConstructorReturnBuilder kwBuilder = new KeywordConstructorReturnBuilder(returnBuilder,
                        _kwArgs.Length,
                        kwArgIndexs.ToArray(),
                        bindableMembers.ToArray());

                    return kwBuilder;
                }

            }
            return returnBuilder;
        }
Пример #12
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);
        }
Пример #13
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));
        }