Ejemplo n.º 1
0
        public override bool CanConvertFrom(Type fromType, DynamicMetaObject fromArg, ParameterWrapper toParameter, NarrowingLevel level) {
            if ((fromType == typeof(List) || fromType.IsSubclassOf(typeof(List)))) {
                if (toParameter.Type.IsGenericType() &&
                    toParameter.Type.GetGenericTypeDefinition() == typeof(IList<>) &&
                    (toParameter.ParameterInfo.IsDefined(typeof(BytesConversionAttribute), false) ||
                     toParameter.ParameterInfo.IsDefined(typeof(BytesConversionNoStringAttribute), false))) {
                    return false;
                }
            } else if (fromType == typeof(string)) {
                if (toParameter.Type == typeof(IList<byte>) &&
                    !Binder.Context.PythonOptions.Python30 &&
                    toParameter.ParameterInfo.IsDefined(typeof(BytesConversionAttribute), false)) {
                    // string -> byte array, we allow this in Python 2.6
                    return true;
                }
            } else if (fromType == typeof(Bytes)) {
                if (toParameter.Type == typeof(string) &&
                    !Binder.Context.PythonOptions.Python30 &&
                    toParameter.ParameterInfo.IsDefined(typeof(BytesConversionAttribute), false)) {
                    return true;
                }
            }

            return base.CanConvertFrom(fromType, fromArg, toParameter, level);
        }
Ejemplo n.º 2
0
        public override bool CanConvertFrom(Type fromType, DynamicMetaObject fromArgument, ParameterWrapper toParameter, NarrowingLevel level)
        {
            if (toParameter.Type == typeof(string) && (level == NarrowingLevel.Three || level == NarrowingLevel.All))
                return true;

            if (toParameter.IsParamsArray == true && typeof(IList<object>).IsAssignableFrom(fromType))
            {
                var toType = toParameter.Type.GetElementType();
                var list = (IList<object>)fromArgument.Value;
                for(var i = 0; i < list.Count; i++)
                {
                    var itm = list[i];
                    var argExp = Expression.Call(
                        Expression.Convert(fromArgument.Expression, fromArgument.LimitType),
                        (typeof(IList<object>).GetMethod("get_Item")),
                        Expression.Constant(i, typeof(int))
                    );
                    var arg = new DynamicMetaObject(
                        argExp,
                        fromArgument.Restrictions,
                        itm
                    );
                    if(!CanConvertFrom(itm.GetType(), arg, new ParameterWrapper(null, toType, null, ParameterBindingFlags.None), level))
                        return false;
                }
                return true;
            }

            return base.CanConvertFrom(fromType, fromArgument, toParameter, level);
        }
Ejemplo n.º 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(int count, IList<string> names) {
            Debug.Assert(_overload.IsVariadic);

            List<ParameterWrapper> newParameters = new List<ParameterWrapper>(count);
            
            // keep track of which named args map to a real argument, and which ones
            // map to the params dictionary.
            List<string> unusedNames = new List<string>(names);
            List<int> unusedNameIndexes = new List<int>();
            for (int i = 0; i < unusedNames.Count; i++) {
                unusedNameIndexes.Add(i);
            }

            // if we don't have a param array we'll have a param dict which is type object
            ParameterWrapper paramsArrayParameter = null;
            int paramsArrayIndex = -1;

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

                if (parameter.IsParamsArray) {
                    paramsArrayParameter = parameter;
                    paramsArrayIndex = i;
                } else {
                    int j = unusedNames.IndexOf(parameter.Name);
                    if (j != -1) {
                        unusedNames.RemoveAt(j);
                        unusedNameIndexes.RemoveAt(j);
                    }
                    newParameters.Add(parameter);
                }
            }

            if (paramsArrayIndex != -1) {
                ParameterWrapper expanded = paramsArrayParameter.Expand();
                while (newParameters.Count < (count - unusedNames.Count)) {
                    newParameters.Insert(System.Math.Min(paramsArrayIndex, newParameters.Count), expanded);
                }
            }

            if (_paramsDict != null) {
                var flags = (_overload.ProhibitsNullItems(_paramsDict.ParameterInfo.Position) ? ParameterBindingFlags.ProhibitNull : 0) |
                            (_paramsDict.IsHidden ? ParameterBindingFlags.IsHidden : 0);

                foreach (string name in unusedNames) {
                    newParameters.Add(new ParameterWrapper(_paramsDict.ParameterInfo, typeof(object), name, flags));
                }
            } 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 MakeParamsExtended(unusedNames.ToArray(), unusedNameIndexes.ToArray(), newParameters);
        }
Ejemplo n.º 4
0
        internal static Candidate GetPreferredCandidate(MethodCandidate one, MethodCandidate two, CallTypes callType, MetaObject[] actualTypes)
        {
            Candidate cmpParams = ParameterWrapper.GetPreferredParameters(one.Parameters, two.Parameters, actualTypes);

            if (cmpParams.Chosen())
            {
                return(cmpParams);
            }

            Candidate ret = MethodTarget.CompareEquivalentParameters(one.Target, two.Target);

            if (ret.Chosen())
            {
                return(ret);
            }

            if (CompilerHelpers.IsStatic(one.Target.Method) && !CompilerHelpers.IsStatic(two.Target.Method))
            {
                return(callType == CallTypes.ImplicitInstance ? Candidate.Two : Candidate.One);
            }
            else if (!CompilerHelpers.IsStatic(one.Target.Method) && CompilerHelpers.IsStatic(two.Target.Method))
            {
                return(callType == CallTypes.ImplicitInstance ? Candidate.One : Candidate.Two);
            }

            return(Candidate.Equivalent);
        }
Ejemplo n.º 5
0
        public override bool CanConvertFrom(Type fromType, DynamicMetaObject fromArgument, ParameterWrapper toParameter, NarrowingLevel level)
        {
            if (level >= NarrowingLevel.Two)
            {
                if (toParameter.Type == typeof(string))
                    return true;
            }

            return base.CanConvertFrom(fromType, fromArgument, toParameter, level);
        }
Ejemplo n.º 6
0
        public override bool CanConvertFrom(Type fromType, ParameterWrapper toParameter, NarrowingLevel level) {
            if ((fromType == typeof(List) || fromType.IsSubclassOf(typeof(List))) && 
                toParameter.Type.IsGenericType && 
                toParameter.Type.GetGenericTypeDefinition() == typeof(IList<>)) {
                if (toParameter.ParameterInfo.IsDefined(typeof(ProhibitGenericListConversionAttribute), false)) {
                    return false;
                }
            }

            return base.CanConvertFrom(fromType, toParameter, level);
        }
Ejemplo n.º 7
0
        private SimpleArgBuilder AddSimpleParameterMapping(ParameterInfo info, int index)
        {
            var param = CreateParameterWrapper(info);

            if (param.IsParamsDict)
            {
                _paramsDict = param;
            }
            else
            {
                _parameters.Add(param);
            }

            return(new SimpleArgBuilder(info, info.ParameterType, index, param.IsParamsArray, param.IsParamsDict));
        }
Ejemplo n.º 8
0
        private static Candidate GetPreferredParameter(ParameterWrapper candidateOne, ParameterWrapper candidateTwo)
        {
            Assert.NotNull(candidateOne, candidateTwo);

            if (candidateOne._binder.ParametersEquivalent(candidateOne, candidateTwo))
            {
                return(Candidate.Equivalent);
            }

            Type t1 = candidateOne.Type;
            Type t2 = candidateTwo.Type;

            if (candidateOne._binder.CanConvertFrom(t2, candidateOne, NarrowingLevel.None))
            {
                if (candidateOne._binder.CanConvertFrom(t1, candidateTwo, NarrowingLevel.None))
                {
                    return(Candidate.Ambiguous);
                }
                else
                {
                    return(Candidate.Two);
                }
            }

            if (candidateOne._binder.CanConvertFrom(t1, candidateTwo, NarrowingLevel.None))
            {
                return(Candidate.One);
            }

            // Special additional rules to order numeric value types
            Candidate preferred = candidateOne._binder.PreferConvert(t1, t2);

            if (preferred.Chosen())
            {
                return(preferred);
            }

            preferred = candidateOne._binder.PreferConvert(t2, t1).TheOther();
            if (preferred.Chosen())
            {
                return(preferred);
            }

            return(Candidate.Ambiguous);
        }
Ejemplo n.º 9
0
        internal MethodCandidate(OverloadResolver resolver, MethodBase method, List<ParameterWrapper> parameters, ParameterWrapper paramsDict,
            ReturnBuilder returnBuilder, ArgBuilder instanceBuilder, IList<ArgBuilder> argBuilders) {

            Assert.NotNull(resolver, method, instanceBuilder, returnBuilder);
            Assert.NotNullItems(parameters);
            Assert.NotNullItems(argBuilders);

            _resolver = resolver;
            _method = method;
            _instanceBuilder = instanceBuilder;
            _argBuilders = argBuilders;
            _returnBuilder = returnBuilder;
            _parameters = parameters;
            _paramsDict = paramsDict;

            _paramsArrayIndex = ParameterWrapper.IndexOfParamsArray(parameters);

            parameters.TrimExcess();
        }
Ejemplo n.º 10
0
        internal MethodCandidate(OverloadResolver resolver, OverloadInfo method, List <ParameterWrapper> parameters, ParameterWrapper paramsDict,
                                 ReturnBuilder returnBuilder, InstanceBuilder instanceBuilder, IList <ArgBuilder> argBuilders, Dictionary <DynamicMetaObject, BindingRestrictions> restrictions)
        {
            Assert.NotNull(resolver, method, instanceBuilder, returnBuilder);
            Assert.NotNullItems(parameters);
            Assert.NotNullItems(argBuilders);

            Resolver         = resolver;
            Overload         = method;
            _instanceBuilder = instanceBuilder;
            ArgBuilders      = argBuilders;
            ReturnBuilder    = returnBuilder;
            _parameters      = parameters;
            _paramsDict      = paramsDict;
            Restrictions     = restrictions;

            ParamsArrayIndex = ParameterWrapper.IndexOfParamsArray(parameters);

            parameters.TrimExcess();
        }
Ejemplo n.º 11
0
        private static Candidate GetPreferredParameter(ParameterWrapper candidateOne, ParameterWrapper candidateTwo, MetaObject actualType)
        {
            Assert.NotNull(candidateOne, candidateTwo, actualType);

            if (candidateOne._binder.ParametersEquivalent(candidateOne, candidateTwo))
            {
                return(Candidate.Equivalent);
            }

            for (NarrowingLevel curLevel = NarrowingLevel.None; curLevel <= NarrowingLevel.All; curLevel++)
            {
                Candidate candidate = candidateOne._binder.SelectBestConversionFor(actualType.LimitType, candidateOne, candidateTwo, curLevel);
                if (candidate.Chosen())
                {
                    return(candidate);
                }
            }

            return(GetPreferredParameter(candidateOne, candidateTwo));
        }
Ejemplo n.º 12
0
        internal MethodCandidate(OverloadResolver resolver, OverloadInfo method, List<ParameterWrapper> parameters, ParameterWrapper paramsDict,
            ReturnBuilder returnBuilder, InstanceBuilder instanceBuilder, IList<ArgBuilder> argBuilders, Dictionary<DynamicMetaObject, BindingRestrictions> restrictions) {

            Assert.NotNull(resolver, method, instanceBuilder, returnBuilder);
            Assert.NotNullItems(parameters);
            Assert.NotNullItems(argBuilders);

            _resolver = resolver;
            _overload = method;
            _instanceBuilder = instanceBuilder;
            _argBuilders = argBuilders;
            _returnBuilder = returnBuilder;
            _parameters = parameters;
            _paramsDict = paramsDict;
            _restrictions = restrictions;

            _paramsArrayIndex = ParameterWrapper.IndexOfParamsArray(parameters);

            parameters.TrimExcess();
        }
Ejemplo n.º 13
0
        /// <summary>
        /// Creates a new list of ParameterWrappers for the generic method replacing the old parameters with the new ones.
        /// </summary>
        private static List <ParameterWrapper> CreateNewWrappers(MethodCandidate candidate, OverloadInfo newOverload, OverloadInfo oldOverload)
        {
            List <ParameterWrapper> newWrappers = new List <ParameterWrapper>();

            for (int i = 0; i < candidate.ParameterCount; i++)
            {
                ParameterWrapper oldWrap = candidate.GetParameter(i);
                ParameterInfo    pi      = null;
                Type             newType = oldWrap.Type;
                if (oldWrap.ParameterInfo != null)
                {
                    pi = newOverload.Parameters[oldWrap.ParameterInfo.Position];
                    ParameterInfo oldParam = oldOverload.Parameters[oldWrap.ParameterInfo.Position];

                    if (oldParam.ParameterType == oldWrap.Type)
                    {
                        newType = pi.ParameterType;
                    }
                    else if (pi.ParameterType.IsByRef)
                    {
                        newType = pi.ParameterType.GetElementType();
                        if (oldParam.ParameterType.GetElementType() != oldWrap.Type)
                        {
                            Debug.Assert(CompilerHelpers.IsStrongBox(oldWrap.Type));
                            newType = typeof(StrongBox <>).MakeGenericType(newType);
                        }
                    }
                    else
                    {
                        Debug.Assert(oldParam.ParameterType.GetElementType() == oldWrap.Type);
                        newType = pi.ParameterType.GetElementType();
                    }
                }

                newWrappers.Add(new ParameterWrapper(pi, newType, oldWrap.Name, oldWrap.Flags));
            }
            return(newWrappers);
        }
Ejemplo n.º 14
0
        /// <summary>
        /// Returns a mapping from generic type parameter to the input DMOs which map to it.
        /// </summary>
        private static Dictionary <Type /*!*/, ArgumentInputs /*!*/> /*!*/ GetArgumentToInputMapping(MethodCandidate /*!*/ candidate, IList <DynamicMetaObject /*!*/> /*!*/ args)
        {
            Dictionary <Type, ArgumentInputs> inputs = new Dictionary <Type, ArgumentInputs>();

            for (int curParam = 0; curParam < candidate.ParameterCount; curParam++)
            {
                ParameterWrapper param = candidate.GetParameter(curParam);
                if (param.IsParamsArray)
                {
                    AddOneInput(inputs, args[curParam], param.Type.GetElementType());
                }
                else if (param.IsByRef)
                {
                    AddOneInput(inputs, args[curParam], param.ParameterInfo.ParameterType);
                }
                else
                {
                    AddOneInput(inputs, args[curParam], param.Type);
                }
            }

            return(inputs);
        }
Ejemplo n.º 15
0
        private static Candidate GetPreferredParameter(ParameterWrapper candidateOne, ParameterWrapper candidateTwo) {
            Assert.NotNull(candidateOne, candidateTwo);

            if (candidateOne._binder.ParametersEquivalent(candidateOne, candidateTwo)) {
                return Candidate.Equivalent;
            }

            Type t1 = candidateOne.Type;
            Type t2 = candidateTwo.Type;

            if (candidateOne._binder.CanConvertFrom(t2, candidateOne, NarrowingLevel.None)) {
                if (candidateOne._binder.CanConvertFrom(t1, candidateTwo, NarrowingLevel.None)) {
                    return Candidate.Ambiguous;
                } else {
                    return Candidate.Two;
                }
            }

            if (candidateOne._binder.CanConvertFrom(t1, candidateTwo, NarrowingLevel.None)) {
                return Candidate.One;
            }

            // Special additional rules to order numeric value types
            Candidate preferred = candidateOne._binder.PreferConvert(t1, t2);
            if (preferred.Chosen()) {
                return preferred;
            }

            preferred = candidateOne._binder.PreferConvert(t2, t1).TheOther();
            if (preferred.Chosen()) {
                return preferred;
            }

            return Candidate.Ambiguous;
        }
Ejemplo n.º 16
0
        public override Candidate SelectBestConversionFor(DynamicMetaObject/*!*/ arg, ParameterWrapper/*!*/ candidateOne, 
            ParameterWrapper/*!*/ candidateTwo, NarrowingLevel level) {

            Type typeOne = candidateOne.Type;
            Type typeTwo = candidateTwo.Type;
            Type actualType = arg.GetLimitType();

            // if nil is passed as a block argument prefer BlockParam over missing block:
            if (actualType == typeof(DynamicNull)) {
                if (typeOne == typeof(BlockParam) && typeTwo == typeof(MissingBlockParam)) {
                    Debug.Assert(!candidateOne.ProhibitNull);
                    return Candidate.One;
                }

                if (typeOne == typeof(MissingBlockParam) && typeTwo == typeof(BlockParam)) {
                    Debug.Assert(!candidateTwo.ProhibitNull);
                    return Candidate.Two;
                }
            } else if (actualType == typeof(MissingBlockParam)) {
                if (typeOne == typeof(BlockParam) && typeTwo == typeof(MissingBlockParam)) {
                    return Candidate.Two;
                }

                if (typeOne == typeof(MissingBlockParam) && typeTwo == typeof(BlockParam)) {
                    return Candidate.One;
                }
            } else if (actualType == typeof(BlockParam)) {
                if (typeOne == typeof(BlockParam) && typeTwo == typeof(MissingBlockParam)) {
                    return Candidate.One;
                }

                if (typeOne == typeof(MissingBlockParam) && typeTwo == typeof(BlockParam)) {
                    return Candidate.Two;
                }

                if (typeOne == typeof(BlockParam) && typeTwo == typeof(BlockParam)) {
                    if (candidateOne.ProhibitNull) {
                        return Candidate.One;
                    } else if (candidateTwo.ProhibitNull) {
                        return Candidate.Two;
                    }
                }
            }
            return base.SelectBestConversionFor(arg, candidateOne, candidateTwo, level);
        }
Ejemplo n.º 17
0
        private SimpleArgBuilder AddSimpleParameterMapping(ParameterInfo info, int index) {
            var param = CreateParameterWrapper(info);
            if (param.IsParamsDict) {
                _paramsDict = param;
            } else {
                _parameters.Add(param);
            }

            return new SimpleArgBuilder(info, info.ParameterType, index, param.IsParamsArray, param.IsParamsDict);
        }
Ejemplo n.º 18
0
 private bool HasExplicitProtocolConversion(ParameterWrapper/*!*/ parameter) {
     return
         parameter.ParameterInfo != null &&
         parameter.ParameterInfo.IsDefined(typeof(DefaultProtocolAttribute), false) &&
         !parameter.IsParamsArray; // default protocol doesn't apply on param-array/dict itself, only on the expanded parameters
 }
Ejemplo n.º 19
0
        public override Candidate SelectBestConversionFor(DynamicMetaObject/*!*/ arg, ParameterWrapper/*!*/ candidateOne, 
            ParameterWrapper/*!*/ candidateTwo, NarrowingLevel level) {

            Type typeOne = candidateOne.Type;
            Type typeTwo = candidateTwo.Type;
            Type actualType = arg.GetLimitType();

            if (actualType == typeof(DynamicNull)) {
                // if nil is passed as a block argument prefers BlockParam over a missing block:
                if (typeOne == typeof(BlockParam) && typeTwo == typeof(MissingBlockParam)) {
                    Debug.Assert(!candidateOne.ProhibitNull);
                    return Candidate.One;
                }

                if (typeOne == typeof(MissingBlockParam) && typeTwo == typeof(BlockParam)) {
                    Debug.Assert(!candidateTwo.ProhibitNull);
                    return Candidate.Two;
                }
            } else {
                if (typeOne == actualType) {
                    if (typeTwo == actualType) {
                        // prefer non-nullable reference type over nullable:
                        if (!actualType.IsValueType) {
                            if (candidateOne.ProhibitNull) {
                                return Candidate.One;
                            } else if (candidateTwo.ProhibitNull) {
                                return Candidate.Two;
                            }
                        }
                    } else {
                        return Candidate.One;
                    }
                } else if (typeTwo == actualType) {
                    return Candidate.Two;
                }
            }

            // prefer integer type over enum:
            if (typeOne.IsEnum && Enum.GetUnderlyingType(typeOne) == typeTwo) {
                return Candidate.Two;
            }

            if (typeTwo.IsEnum && Enum.GetUnderlyingType(typeTwo) == typeOne) {
                return Candidate.One;
            }

            return base.SelectBestConversionFor(arg, candidateOne, candidateTwo, level);
        }
Ejemplo n.º 20
0
 /// <summary>
 /// Returns true if fromArg of type fromType can be assigned to toParameter with a conversion on given narrowing level.
 /// </summary>
 public override bool CanConvertFrom(Type/*!*/ fromType, DynamicMetaObject fromArg, ParameterWrapper/*!*/ toParameter, NarrowingLevel level) {
     return Converter.CanConvertFrom(fromArg, fromType, toParameter.Type, toParameter.ProhibitNull, level, 
         HasExplicitProtocolConversion(toParameter), _implicitProtocolConversions
     );
 }
Ejemplo n.º 21
0
 public override bool CanConvertFrom(ParameterWrapper/*!*/ fromParameter, ParameterWrapper/*!*/ toParameter) {
     return Converter.CanConvertFrom(null, fromParameter.Type, toParameter.Type, toParameter.ProhibitNull, NarrowingLevel.None, false, false);
 }
Ejemplo n.º 22
0
        internal Candidate GetPreferredParameter(ParameterWrapper candidateOne, ParameterWrapper candidateTwo, Type argType) {
            Assert.NotNull(candidateOne, candidateTwo, argType);

            if (ParametersEquivalent(candidateOne, candidateTwo)) {
                return Candidate.Equivalent;
            }

            for (NarrowingLevel curLevel = NarrowingLevel.None; curLevel <= NarrowingLevel.All; curLevel++) {
                Candidate candidate = SelectBestConversionFor(argType, candidateOne, candidateTwo, curLevel);
                if (candidate.Chosen()) {
                    return candidate;
                }
            }

            return GetPreferredParameter(candidateOne, candidateTwo);
        }
Ejemplo n.º 23
0
        /// <summary>
        /// Returns true if fromArg of type fromType can be assigned to toParameter with a conversion on given narrowing level.
        /// </summary>
        public override bool CanConvertFrom(Type/*!*/ fromType, DynamicMetaObject fromArg, ParameterWrapper/*!*/ toParameter, NarrowingLevel level) {
            var result = Converter.CanConvertFrom(fromArg, fromType, toParameter.Type, toParameter.ProhibitNull, level, 
                HasExplicitProtocolConversion(toParameter), _implicitProtocolConversions
            );

            if (result.Assumption != null) {
                if (_argumentAssumptions == null) {
                    _argumentAssumptions = new List<Key<int, NarrowingLevel, Ast>>();
                }

                if (_argumentAssumptions.FindIndex((k) => k.First == toParameter.ParameterInfo.Position && k.Second == level) < 0) {
                    _argumentAssumptions.Add(Key.Create(toParameter.ParameterInfo.Position, level, result.Assumption));
                }
            }

            return result.IsConvertible;
        }
Ejemplo n.º 24
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 (!CompilerHelpers.IsMandatoryParameter(pi)) {
                // 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) {
                _hasByRefOrOut = true;
                Type refType = typeof(StrongBox<>).MakeGenericType(pi.ParameterType.GetElementType());
                _parameters.Add(new ParameterWrapper(pi, refType, pi.Name, true, false, false, false));
                ab = new ReferenceArgBuilder(pi, refType, indexForArgBuilder);
            } else if (BinderHelpers.IsParamDictionary(pi)) {
                _paramsDict = new ParameterWrapper(pi);
                ab = new SimpleArgBuilder(pi, indexForArgBuilder);
            } else if (pi.Position == 0 && CompilerHelpers.IsExtension(pi.Member)) {
                _parameters.Add(new ParameterWrapper(pi, pi.ParameterType, pi.Name, true, false, false, true));
                ab = new SimpleArgBuilder(pi, indexForArgBuilder);
            } else {
                _hasByRefOrOut |= CompilerHelpers.IsOutParameter(pi);
                _parameters.Add(new ParameterWrapper(pi));
                ab = new SimpleArgBuilder(pi, indexForArgBuilder);
            }

            if (nameIndex == -1) {
                _arguments.Add(ab);
            } else {
                Debug.Assert(KeywordArgBuilder.BuilderExpectsSingleParameter(ab));
                _arguments.Add(new KeywordArgBuilder(ab, _argNames.Count, nameIndex));
            }
        }
Ejemplo n.º 25
0
 public void AddParameter(ParameterWrapper parameter)
 {
     _parameters.Add(parameter);
 }
Ejemplo n.º 26
0
        public override bool CanConvertFrom(Type/*!*/ fromType, ParameterWrapper/*!*/ toParameter, NarrowingLevel level) {
            Type toType = toParameter.Type;

            if (toType == fromType) {
                return true;
            }

            if (fromType == typeof(DynamicNull)) {
                if (toParameter.ProhibitNull) {
                    return false;
                }

                if (toType.IsGenericType && toType.GetGenericTypeDefinition() == typeof(Nullable<>)) {
                    return true;
                }

                if (!toType.IsValueType) {
                    return true;
                }
            }

            // blocks:
            if (fromType == typeof(MissingBlockParam)) {
                return toType == typeof(BlockParam) && !toParameter.ProhibitNull;
            }

            if (fromType == typeof(BlockParam) && toType == typeof(MissingBlockParam)) {
                return true;
            }

            // protocol conversions:
            if (toParameter.ParameterInfo != null && toParameter.ParameterInfo.IsDefined(typeof(DefaultProtocolAttribute), false) &&
                // default protocol doesn't apply on param-array/dict itself, only on the expanded parameters:
                !toParameter.IsParamsArray) {

                // any type is potentially convertible, except for nil if [NotNull] is used or the target type is a value type:
                return fromType != typeof(DynamicNull) || !(toParameter.ProhibitNull || toType.IsValueType);
            }

            if (Converter.CanConvertFrom(fromType, toType, level, _implicitProtocolConversions)) {
                return true;
            }

            return false;
        }
Ejemplo n.º 27
0
 public virtual bool ParametersEquivalent(ParameterWrapper parameter1, ParameterWrapper parameter2) {
     return parameter1.Type == parameter2.Type && parameter1.ProhibitNull == parameter2.ProhibitNull;
 }
Ejemplo n.º 28
0
        private Candidate GetPreferredParameter(ParameterWrapper candidateOne, ParameterWrapper candidateTwo, DynamicMetaObject arg, NarrowingLevel level) {
            Assert.NotNull(candidateOne, candidateTwo);

            if (ParametersEquivalent(candidateOne, candidateTwo)) {
                return Candidate.Equivalent;
            }

            Candidate candidate = SelectBestConversionFor(arg, candidateOne, candidateTwo, level);
            if (candidate.Chosen()) {
                return candidate;
            }

            if (CanConvertFrom(candidateTwo, candidateOne)) {
                if (CanConvertFrom(candidateOne, candidateTwo)) {
                    return Candidate.Ambiguous;
                } else {
                    return Candidate.Two;
                }
            } else if (CanConvertFrom(candidateOne, candidateTwo)) {
                return Candidate.One;
            }

            // Special additional rules to order numeric value types
            Type t1 = candidateOne.Type;
            Type t2 = candidateTwo.Type;

            Candidate preferred = PreferConvert(t1, t2);
            if (preferred.Chosen()) {
                return preferred;
            }

            preferred = PreferConvert(t2, t1).TheOther();
            if (preferred.Chosen()) {
                return preferred;
            }

            // consider the actual argument type:
            Type argType = arg.GetLimitType();
            NarrowingLevel levelOne = NarrowingLevel.None;
            while (levelOne < level && !CanConvertFrom(argType, arg, candidateOne, levelOne)) {
                if (levelOne == NarrowingLevel.All) {
                    Debug.Assert(false, "Each argument should be convertible to the corresponding parameter");
                    break;
                }
                levelOne++;
            }

            NarrowingLevel levelTwo = NarrowingLevel.None;
            while (levelTwo < level && !CanConvertFrom(argType, arg, candidateTwo, levelTwo)) {
                if (levelTwo == NarrowingLevel.All) {
                    Debug.Assert(false, "Each argument should be convertible to the corresponding parameter");
                    break;
                }
                levelTwo++;
            }

            if (levelOne < levelTwo) {
                return Candidate.One;
            } else if (levelOne > levelTwo) {
                return Candidate.Two;
            } else {
                return Candidate.Ambiguous;
            }
        }
Ejemplo n.º 29
0
 private DynamicMetaObject RestrictArgument(DynamicMetaObject arg, ParameterWrapper parameter) {
     if (parameter.Type == typeof(object)) {
         // don't use Restrict as it'll box & unbox.
         return new DynamicMetaObject(arg.Expression, BindingRestrictionsHelpers.GetRuntimeTypeRestriction(arg.Expression, arg.GetLimitType()));
     } else {
         return arg.Restrict(arg.GetLimitType());
     }
 }
Ejemplo n.º 30
0
        public override Candidate SelectBestConversionFor(Type/*!*/ actualType, ParameterWrapper/*!*/ candidateOne, ParameterWrapper/*!*/ candidateTwo, NarrowingLevel level) {
            Type typeOne = candidateOne.Type;
            Type typeTwo = candidateTwo.Type;

            if (actualType == typeof(DynamicNull)) {
                // if nil is passed as a block argument prefer BlockParam over missing block;
                if (typeOne == typeof(BlockParam) && typeTwo == typeof(MissingBlockParam)) {
                    return Candidate.One;
                }

                if (typeOne == typeof(MissingBlockParam) && typeTwo == typeof(BlockParam)) {
                    return Candidate.Two;
                }
            } else {
                if (actualType == typeOne && candidateOne.ProhibitNull) {
                    return Candidate.One;
                }

                if (actualType == typeTwo && candidateTwo.ProhibitNull) {
                    return Candidate.Two;
                }
            }

            if (actualType == typeOne) {
                return Candidate.One;
            }

            if (actualType == typeTwo) {
                return Candidate.Two;
            }


            return Candidate.Equivalent;
        }
Ejemplo n.º 31
0
 public void AddParameter(ParameterWrapper parameter) {
     _parameters.Add(parameter);
 }
Ejemplo n.º 32
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));
        }
Ejemplo n.º 33
0
        private void MapParameterReduceByRef(ParameterInfo pi) {
            Debug.Assert(_returnArgs != null);

            // See KeywordArgBuilder.BuilderExpectsSingleParameter
            int indexForArgBuilder = 0;

            int nameIndex = -1;
            if (!CompilerHelpers.IsOutParameter(pi)) {
                nameIndex = _argNames.IndexOf(pi.Name);
                if (nameIndex == -1) {
                    indexForArgBuilder = _argIndex++;
                }
            }

            ArgBuilder ab;
            if (CompilerHelpers.IsOutParameter(pi)) {
                _returnArgs.Add(_arguments.Count);
                ab = new OutArgBuilder(pi);
            } else if (pi.ParameterType.IsByRef) {
                // if the parameter is marked as [In] it is not returned.
                if ((pi.Attributes & (ParameterAttributes.In | ParameterAttributes.Out)) != ParameterAttributes.In) {
                    _returnArgs.Add(_arguments.Count);
                }
                _parameters.Add(new ParameterWrapper(pi, pi.ParameterType.GetElementType(), pi.Name, false, false, false, false));
                ab = new ReturnReferenceArgBuilder(pi, indexForArgBuilder);
            } else if (BinderHelpers.IsParamDictionary(pi)) {
                _paramsDict = new ParameterWrapper(pi);
                ab = new SimpleArgBuilder(pi, indexForArgBuilder);
            } else {
                _parameters.Add(new ParameterWrapper(pi));
                ab = new SimpleArgBuilder(pi, indexForArgBuilder);
            }

            if (nameIndex == -1) {
                _arguments.Add(ab);
            } else {
                Debug.Assert(KeywordArgBuilder.BuilderExpectsSingleParameter(ab));
                _arguments.Add(new KeywordArgBuilder(ab, _argNames.Count, nameIndex));
            }
        }
Ejemplo n.º 34
0
 /// <summary>
 /// Selects the best (of two) candidates for conversion from actualType
 /// </summary>
 public virtual Candidate SelectBestConversionFor(DynamicMetaObject arg, ParameterWrapper candidateOne, ParameterWrapper candidateTwo, NarrowingLevel level) {
     return Candidate.Equivalent;
 }
Ejemplo n.º 35
0
 public virtual bool CanConvertFrom(ParameterWrapper parameter1, ParameterWrapper parameter2) {
     return CanConvertFrom(parameter1.Type, null, parameter2, NarrowingLevel.None);
 }
Ejemplo n.º 36
0
 /// <summary>
 /// Selects the best (of two) candidates for conversion from actualType
 /// </summary>
 public virtual Candidate SelectBestConversionFor(Type actualType, ParameterWrapper candidateOne, ParameterWrapper candidateTwo, NarrowingLevel level) {
     return Candidate.Equivalent;
 }
Ejemplo n.º 37
0
        private static Candidate GetPreferredParameter(ParameterWrapper candidateOne, ParameterWrapper candidateTwo, MetaObject actualType) {
            Assert.NotNull(candidateOne, candidateTwo, actualType);

            if (candidateOne._binder.ParametersEquivalent(candidateOne, candidateTwo)) {
                return Candidate.Equivalent;
            }

            for (NarrowingLevel curLevel = NarrowingLevel.None; curLevel <= NarrowingLevel.All; curLevel++) {
                Candidate candidate = candidateOne._binder.SelectBestConversionFor(actualType.LimitType, candidateOne, candidateTwo, curLevel);
                if (candidate.Chosen()) {
                    return candidate;
                }
            }

            return GetPreferredParameter(candidateOne, candidateTwo);
        }
Ejemplo n.º 38
0
        public virtual bool CanConvertFrom(Type fromType, DynamicMetaObject fromArgument, ParameterWrapper toParameter, NarrowingLevel level) {
            Assert.NotNull(fromType, toParameter);

            Type toType = toParameter.Type;

            if (fromType == typeof(DynamicNull)) {
                if (toParameter.ProhibitNull) {
                    return false;
                }

                if (toType.IsGenericType && toType.GetGenericTypeDefinition() == typeof(Nullable<>)) {
                    return true;
                }

                if (!toType.IsValueType) {
                    return true;
                }
            }

            if (fromType == toType) {
                return true;
            }

            return _binder.CanConvertFrom(fromType, toType, toParameter.ProhibitNull, level);
        }