Beispiel #1
0
        private DynamicMetaObject TryPythonConversion(DynamicMetaObjectBinder conversion, Type type)
        {
            if (!type.IsEnum)
            {
                switch (type.GetTypeCode())
                {
                case TypeCode.Object:
                    if (type == typeof(Complex))
                    {
                        return(MakeConvertRuleForCall(conversion, type, this, "__complex__", "ConvertToComplex",
                                                      (() => MakeConvertRuleForCall(conversion, type, this, "__float__", "ConvertToFloat",
                                                                                    (() => FallbackConvert(conversion)),
                                                                                    (x) => Ast.Call(null, typeof(PythonOps).GetMethod(nameof(PythonOps.ConvertFloatToComplex)), x))),
                                                      (x) => x));
                    }
                    else if (type == typeof(BigInteger))
                    {
                        return(MakeConvertRuleForCall(conversion, type, this, "__long__", "ConvertToLong"));
                    }
                    else if (type == typeof(IEnumerable))
                    {
                        return(PythonConversionBinder.ConvertToIEnumerable(conversion, Restrict(Value.GetType())));
                    }
                    else if (type == typeof(IEnumerator))
                    {
                        return(PythonConversionBinder.ConvertToIEnumerator(conversion, Restrict(Value.GetType())));
                    }
                    else if (type.IsSubclassOf(typeof(Delegate)))
                    {
                        return(MakeDelegateTarget(conversion, type, Restrict(Value.GetType())));
                    }
                    break;

                case TypeCode.Int32:
                    if (!typeof(Extensible <int>).IsAssignableFrom(LimitType))
                    {
                        return(MakeConvertRuleForCall(conversion, type, this, "__int__", "ConvertToInt"));
                    }
                    break;

                case TypeCode.Double:
                    return(MakeConvertRuleForCall(conversion, type, this, "__float__", "ConvertToFloat"));

                case TypeCode.Boolean:
                    return(PythonProtocol.ConvertToBool(
                               conversion,
                               this
                               ));

                case TypeCode.String:
                    if (!typeof(Extensible <string>).IsAssignableFrom(LimitType))
                    {
                        return(MakeConvertRuleForCall(conversion, type, this, "__str__", "ConvertToString"));
                    }
                    break;
                }
            }

            return(null);
        }
Beispiel #2
0
        private DynamicMetaObject /*!*/ MakeToBoolConversion(DynamicMetaObject /*!*/ self)
        {
            DynamicMetaObject res;

            if (self.HasValue)
            {
                self = self.Restrict(self.GetRuntimeType());
            }

            // Optimization: if we already boxed it to a bool, and now
            // we're unboxing it, remove the unnecessary box.
            if (self.Expression.NodeType == ExpressionType.Convert && self.Expression.Type == typeof(object))
            {
                var convert = (UnaryExpression)self.Expression;
                if (convert.Operand.Type == typeof(bool))
                {
                    return(new DynamicMetaObject(convert.Operand, self.Restrictions));
                }
            }

            if (self.GetLimitType() == typeof(DynamicNull))
            {
                // None has no __nonzero__ and no __len__ but it's always false
                res = MakeNoneToBoolConversion(self);
            }
            else if (self.GetLimitType() == typeof(bool))
            {
                // nothing special to convert from bool to bool
                res = self;
            }
            else if (typeof(IStrongBox).IsAssignableFrom(self.GetLimitType()))
            {
                // Explictly block conversion of References to bool
                res = MakeStrongBoxToBoolConversionError(self);
            }
            else if (self.GetLimitType().IsPrimitive || self.GetLimitType().IsEnum)
            {
                // optimization - rather than doing a method call for primitives and enums generate
                // the comparison to zero directly.
                res = MakePrimitiveToBoolComparison(self);
            }
            else
            {
                // anything non-null that doesn't fall under one of the above rules is true.  So we
                // fallback to the base Python conversion which will check for __nonzero__ and
                // __len__.  The fallback is handled by our ConvertTo site binder.
                return
                    (PythonProtocol.ConvertToBool(this, self) ??
                     new DynamicMetaObject(
                         AstUtils.Constant(true),
                         self.Restrictions
                         ));
            }

            return(res);
        }