private Expression ConversionFallback(ConvertBinder/*!*/ convertToAction) { ConversionBinder cb = convertToAction as ConversionBinder; if (cb != null) { return GetConversionFailedReturnValue(cb, this); } return convertToAction.Defer(this).Expression; }
private DynamicMetaObject/*!*/ MakeConvertRuleForCall(ConvertBinder/*!*/ convertToAction, DynamicMetaObject/*!*/ self, SymbolId symbolId, string returner) { PythonType pt = ((IPythonObject)self.Value).PythonType; PythonTypeSlot pts; CodeContext context = BinderState.GetBinderState(convertToAction).Context; if (pt.TryResolveSlot(context, symbolId, out pts) && !IsBuiltinConversion(context, pts, symbolId, pt)) { ParameterExpression tmp = Ast.Variable(typeof(object), "func"); Expression callExpr = Ast.Call( PythonOps.GetConversionHelper(returner, GetResultKind(convertToAction)), Ast.Dynamic( new PythonInvokeBinder( BinderState.GetBinderState(convertToAction), new CallSignature(0) ), typeof(object), BinderState.GetCodeContext(convertToAction), tmp ) ); if (typeof(Extensible<>).MakeGenericType(convertToAction.Type).IsAssignableFrom(self.GetLimitType())) { // if we're doing a conversion to the underlying type and we're an // Extensible<T> of that type: // if an extensible type returns it's self in a conversion, then we need // to actually return the underlying value. If an extensible just keeps // returning more instances of it's self a stack overflow occurs - both // behaviors match CPython. callExpr = AstUtils.Convert(AddExtensibleSelfCheck(convertToAction, self, callExpr), typeof(object)); } return new DynamicMetaObject( Ast.Block( new ParameterExpression[] { tmp }, Ast.Condition( BindingHelpers.CheckTypeVersion( self.Expression, pt.Version ), Ast.Condition( MakeTryGetTypeMember( BinderState.GetBinderState(convertToAction), pts, self.Expression, tmp ), callExpr, AstUtils.Convert( ConversionFallback(convertToAction), typeof(object) ) ), convertToAction.Defer(this).Expression ) ), self.Restrict(self.GetRuntimeType()).Restrictions ); } return convertToAction.FallbackConvert(this); }