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); }
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); }