public override DynamicMetaObject FallbackGetIndex(DynamicMetaObject target, DynamicMetaObject[] indexes, DynamicMetaObject errorSuggestion) { #if FEATURE_COM DynamicMetaObject com; if (Microsoft.Scripting.ComInterop.ComBinder.TryBindGetIndex(this, target, BindingHelpers.GetComArguments(indexes), out com)) { return(com); } #endif return(PythonProtocol.Index(this, PythonIndexType.GetItem, ArrayUtils.Insert(target, indexes), errorSuggestion)); }
private DynamicMetaObject /*!*/ MakeSetMember(SetMemberBinder /*!*/ member, DynamicMetaObject /*!*/ value) { PythonContext state = PythonContext.GetPythonContext(member); DynamicMetaObject self = Restrict(Value.GetType()); if (Value.GetType() != typeof(PythonType) && DynamicHelpers.GetPythonType(Value).IsSystemType) { // built-in subclass of .NET type. Usually __setattr__ is handled by MetaUserObject // but we can have a built-in subtype that's not a user type. PythonTypeSlot pts; if (Value.TryGetCustomSetAttr(state.SharedContext, out pts)) { Debug.Assert(pts.GetAlwaysSucceeds); ParameterExpression tmp = Ast.Variable(typeof(object), "boundVal"); return(BindingHelpers.AddDynamicTestAndDefer( member, new DynamicMetaObject( Ast.Block( new[] { tmp }, Ast.Dynamic( state.Invoke(new CallSignature(2)), typeof(object), AstUtils.Constant(state.SharedContext), Ast.Block( Ast.Call( typeof(PythonOps).GetMethod("SlotTryGetValue"), AstUtils.Constant(state.SharedContext), AstUtils.Convert(AstUtils.WeakConstant(pts), typeof(PythonTypeSlot)), AstUtils.Convert(Expression, typeof(object)), AstUtils.Convert(AstUtils.WeakConstant(DynamicHelpers.GetPythonType(Value)), typeof(PythonType)), tmp ), tmp ), Ast.Constant(member.Name), value.Expression ) ), self.Restrictions ), new DynamicMetaObject[] { this, value }, TestUserType() )); } } return(BindingHelpers.AddDynamicTestAndDefer( member, new DynamicMetaObject( Ast.Call( typeof(PythonOps).GetMethod("PythonTypeSetCustomMember"), AstUtils.Constant(PythonContext.GetPythonContext(member).SharedContext), self.Expression, AstUtils.Constant(member.Name), AstUtils.Convert( value.Expression, typeof(object) ) ), self.Restrictions.Merge(value.Restrictions) ), new DynamicMetaObject[] { this, value }, TestUserType() )); }
private DynamicMetaObject /*!*/ MakeMemberAccess(DynamicMetaObjectBinder /*!*/ member, string name, MemberAccess access, params DynamicMetaObject /*!*/[] /*!*/ args) { DynamicMetaObject self = Restrict(typeof(OldInstance)); CustomInstanceDictionaryStorage dict; int key = GetCustomStorageSlot(name, out dict); if (key == -1) { PerfTrack.NoteEvent(PerfTrack.Categories.Binding, "OldInstance " + access + " NoOptimized"); return(MakeDynamicMemberAccess(member, name, access, args)); } ParameterExpression tmp = Ast.Variable(typeof(object), "dict"); Expression target; ValidationInfo test = new ValidationInfo( Ast.NotEqual( Ast.Assign( tmp, Ast.Call( typeof(PythonOps).GetMethod("OldInstanceGetOptimizedDictionary"), self.Expression, AstUtils.Constant(dict.KeyVersion) ) ), AstUtils.Constant(null) ) ); PerfTrack.NoteEvent(PerfTrack.Categories.Binding, "OldInstance " + access + " Optimized"); switch (access) { case MemberAccess.Invoke: ParameterExpression value = Ast.Variable(typeof(object), "value"); target = Ast.Block( new[] { value }, Ast.Condition( Ast.Call( typeof(PythonOps).GetMethod("TryOldInstanceDictionaryGetValueHelper"), tmp, Ast.Constant(key), AstUtils.Convert(Expression, typeof(object)), value ), AstUtils.Convert( ((InvokeMemberBinder)member).FallbackInvoke(new DynamicMetaObject(value, BindingRestrictions.Empty), args, null).Expression, typeof(object) ), AstUtils.Convert( ((InvokeMemberBinder)member).FallbackInvokeMember(self, args).Expression, typeof(object) ) ) ); break; case MemberAccess.Get: // BUG: There's a missing Fallback path here that's always been present even // in the version that used rules. target = Ast.Call( typeof(PythonOps).GetMethod("OldInstanceDictionaryGetValueHelper"), tmp, AstUtils.Constant(key), AstUtils.Convert(Expression, typeof(object)) ); break; case MemberAccess.Set: target = Ast.Call( typeof(PythonOps).GetMethod("OldInstanceDictionarySetExtraValue"), tmp, AstUtils.Constant(key), AstUtils.Convert(args[1].Expression, typeof(object)) ); break; case MemberAccess.Delete: target = Ast.Call( typeof(PythonOps).GetMethod("OldInstanceDeleteCustomMember"), AstUtils.Constant(PythonContext.GetPythonContext(member).SharedContext), AstUtils.Convert(Expression, typeof(OldInstance)), AstUtils.Constant(name) ); break; default: throw new InvalidOperationException(); } return(BindingHelpers.AddDynamicTestAndDefer( member, new DynamicMetaObject( target, BindingRestrictions.Combine(args).Merge(self.Restrictions) ), args, test, tmp )); }
private DynamicMetaObject /*!*/ MakeSelfCall(DynamicMetaObjectBinder /*!*/ call, Expression /*!*/ codeContext, DynamicMetaObject /*!*/[] /*!*/ args) { BindingRestrictions selfRestrict = Restrictions.Merge( BindingRestrictionsHelpers.GetRuntimeTypeRestriction( Expression, LimitType ) ).Merge( BindingRestrictions.GetExpressionRestriction( Value.MakeBoundFunctionTest( AstUtils.Convert(Expression, typeof(BuiltinFunction)) ) ) ); Expression instance = Ast.Call( typeof(PythonOps).GetMethod("GetBuiltinFunctionSelf"), AstUtils.Convert( Expression, typeof(BuiltinFunction) ) ); DynamicMetaObject self = GetInstance(instance, CompilerHelpers.GetType(Value.BindingSelf)); return(Value.MakeBuiltinFunctionCall( call, codeContext, this, ArrayUtils.Insert(self, args), true, // has self selfRestrict, (newArgs) => { CallSignature signature = BindingHelpers.GetCallSignature(call); DynamicMetaObject res; PythonContext state = PythonContext.GetPythonContext(call); BindingTarget target; PythonOverloadResolver resolver; if (Value.IsReversedOperator) { resolver = new PythonOverloadResolver( state.Binder, newArgs, GetReversedSignature(signature), codeContext ); } else { resolver = new PythonOverloadResolver( state.Binder, self, args, signature, codeContext ); } res = state.Binder.CallMethod( resolver, Value.Targets, self.Restrictions, Value.Name, NarrowingLevel.None, Value.IsBinaryOperator ? PythonNarrowing.BinaryOperator : NarrowingLevel.All, out target ); return BindingHelpers.CheckLightThrow(call, res, target); } )); }
internal static DynamicMetaObject Call(DynamicMetaObjectBinder /*!*/ call, DynamicMetaObject target, DynamicMetaObject /*!*/[] /*!*/ args) { Assert.NotNull(call, args); Assert.NotNullItems(args); if (target.NeedsDeferral()) { return(call.Defer(ArrayUtils.Insert(target, args))); } foreach (DynamicMetaObject mo in args) { if (mo.NeedsDeferral()) { RestrictTypes(args); return(call.Defer( ArrayUtils.Insert(target, args) )); } } DynamicMetaObject self = target.Restrict(target.GetLimitType()); ValidationInfo valInfo = BindingHelpers.GetValidationInfo(target); PythonType pt = DynamicHelpers.GetPythonType(target.Value); PythonContext pyContext = PythonContext.GetPythonContext(call); // look for __call__, if it's present dispatch to it. Otherwise fall back to the // default binder PythonTypeSlot callSlot; if (!typeof(Delegate).IsAssignableFrom(target.GetLimitType()) && pt.TryResolveSlot(pyContext.SharedContext, "__call__", out callSlot)) { ConditionalBuilder cb = new ConditionalBuilder(call); Expression body; callSlot.MakeGetExpression( pyContext.Binder, PythonContext.GetCodeContext(call), self, GetPythonType(self), cb ); if (!cb.IsFinal) { cb.FinishCondition(GetCallError(self)); } Expression[] callArgs = ArrayUtils.Insert( PythonContext.GetCodeContext(call), cb.GetMetaObject().Expression, DynamicUtils.GetExpressions(args) ); body = Ast.Dynamic( PythonContext.GetPythonContext(call).Invoke( BindingHelpers.GetCallSignature(call) ), typeof(object), callArgs ); body = Ast.TryFinally( Ast.Block( Ast.Call(typeof(PythonOps).GetMethod("FunctionPushFrame"), Ast.Constant(pyContext)), body ), Ast.Call(typeof(PythonOps).GetMethod("FunctionPopFrame")) ); return(BindingHelpers.AddDynamicTestAndDefer( call, new DynamicMetaObject(body, self.Restrictions.Merge(BindingRestrictions.Combine(args))), args, valInfo )); } return(null); }
private DynamicMetaObject InvokeWorker(DynamicMetaObjectBinder /*!*/ callAction, DynamicMetaObject /*!*/[] args) { PerfTrack.NoteEvent(PerfTrack.Categories.Binding, "Method Invoke " + args.Length); PerfTrack.NoteEvent(PerfTrack.Categories.BindingTarget, "Method"); CallSignature signature = BindingHelpers.GetCallSignature(callAction); DynamicMetaObject self = Restrict(typeof(Method)); BindingRestrictions restrictions = self.Restrictions; DynamicMetaObject func = GetMetaFunction(self); DynamicMetaObject call; if (Value.im_self == null) { // restrict to null self (Method is immutable so this is an invariant test) restrictions = restrictions.Merge( BindingRestrictions.GetExpressionRestriction( Ast.Equal( GetSelfExpression(self), AstUtils.Constant(null) ) ) ); if (args.Length == 0) { // this is an error, we pass null which will throw the normal error call = new DynamicMetaObject( Ast.Call( typeof(PythonOps).GetMethod("MethodCheckSelf"), PythonContext.GetCodeContext(callAction), self.Expression, AstUtils.Constant(null) ), restrictions ); } else { // this may or may not be an error call = new DynamicMetaObject( Ast.Block( MakeCheckSelf(callAction, signature, args), DynamicExpression.Dynamic( PythonContext.GetPythonContext(callAction).Invoke( BindingHelpers.GetCallSignature(callAction) ).GetLightExceptionBinder(callAction.SupportsLightThrow()), typeof(object), ArrayUtils.Insert(PythonContext.GetCodeContext(callAction), DynamicUtils.GetExpressions(ArrayUtils.Insert(func, args))) ) ), BindingRestrictions.Empty ); /*call = func.Invoke(callAction, ArrayUtils.Insert(func, args)); * call = new MetaObject( * Ast.Comma( * Ast.Call( * typeof(PythonOps).GetMethod("MethodCheckSelf"), * self.Expression, * args[0].Expression * ), * call.Expression * ), * call.Restrictions * );*/ } } else { // restrict to non-null self (Method is immutable so this is an invariant test) restrictions = restrictions.Merge( BindingRestrictions.GetExpressionRestriction( Ast.NotEqual( GetSelfExpression(self), AstUtils.Constant(null) ) ) ); DynamicMetaObject im_self = GetMetaSelf(self); DynamicMetaObject[] newArgs = ArrayUtils.Insert(func, im_self, args); CallSignature newSig = new CallSignature(ArrayUtils.Insert(new Argument(ArgumentType.Simple), signature.GetArgumentInfos())); call = new DynamicMetaObject( DynamicExpression.Dynamic( PythonContext.GetPythonContext(callAction).Invoke( newSig ).GetLightExceptionBinder(callAction.SupportsLightThrow()), typeof(object), ArrayUtils.Insert(PythonContext.GetCodeContext(callAction), DynamicUtils.GetExpressions(newArgs)) ), BindingRestrictions.Empty ); /* * call = func.Invoke( * new CallBinder( * PythonContext.GetBinderState(callAction), * newSig * ), * newArgs * );*/ } if (call.HasValue) { return(new DynamicMetaObject( call.Expression, restrictions.Merge(call.Restrictions), call.Value )); } else { return(new DynamicMetaObject( call.Expression, restrictions.Merge(call.Restrictions) )); } }
public override DynamicMetaObject /*!*/ FallbackCreateInstance(DynamicMetaObject /*!*/ target, DynamicMetaObject /*!*/[] /*!*/ args, DynamicMetaObject errorSuggestion) { return(_fallback.InvokeFallback(target, args, BindingHelpers.GetCallSignature(this), errorSuggestion)); }
private DynamicMetaObject /*!*/ InvokeWorker(DynamicMetaObjectBinder /*!*/ invoke, Expression /*!*/ codeContext, DynamicMetaObject /*!*/[] args) { PerfTrack.NoteEvent(PerfTrack.Categories.Binding, "OldClass Invoke"); DynamicMetaObject self = Restrict(typeof(OldInstance)); Expression[] exprArgs = new Expression[args.Length + 1]; for (int i = 0; i < args.Length; i++) { exprArgs[i + 1] = args[i].Expression; } ParameterExpression tmp = Ast.Variable(typeof(object), "callFunc"); exprArgs[0] = tmp; return(new DynamicMetaObject( // we could get better throughput w/ a more specific rule against our current custom old class but // this favors less code generation. Ast.Block( new ParameterExpression[] { tmp }, Ast.Condition( Expression.Not( Expression.TypeIs( Expression.Assign( tmp, Ast.Call( typeof(PythonOps).GetMethod("OldInstanceTryGetBoundCustomMember"), codeContext, self.Expression, AstUtils.Constant("__call__") ) ), typeof(OperationFailed) ) ), Ast.Block( Utils.Try( Ast.Call(typeof(PythonOps).GetMethod("FunctionPushFrameCodeContext"), codeContext), Ast.Assign( tmp, DynamicExpression.Dynamic( PythonContext.GetPythonContext(invoke).Invoke( BindingHelpers.GetCallSignature(invoke) ), typeof(object), ArrayUtils.Insert(codeContext, exprArgs) ) ) ).Finally( Ast.Call(typeof(PythonOps).GetMethod("FunctionPopFrame")) ), tmp ), Utils.Convert( BindingHelpers.InvokeFallback(invoke, codeContext, this, args).Expression, typeof(object) ) ) ), self.Restrictions.Merge(BindingRestrictions.Combine(args)) )); }
/// <summary> /// Creating a Python type involves calling __new__ and __init__. We resolve them /// and generate calls to either the builtin funcions directly or embed sites which /// call the slots at runtime. /// </summary> private DynamicMetaObject /*!*/ MakePythonTypeCall(DynamicMetaObjectBinder /*!*/ call, Expression /*!*/ codeContext, DynamicMetaObject /*!*/[] /*!*/ args) { ValidationInfo valInfo = MakeVersionCheck(); DynamicMetaObject self = new RestrictedMetaObject( AstUtils.Convert(Expression, LimitType), BindingRestrictionsHelpers.GetRuntimeTypeRestriction(Expression, LimitType), Value ); CallSignature sig = BindingHelpers.GetCallSignature(call); ArgumentValues ai = new ArgumentValues(sig, self, args); NewAdapter newAdapter; InitAdapter initAdapter; if (TooManyArgsForDefaultNew(call, args)) { return(MakeIncorrectArgumentsForCallError(call, ai, valInfo)); } else if (Value.UnderlyingSystemType.IsGenericTypeDefinition()) { return(MakeGenericTypeDefinitionError(call, ai, valInfo)); } else if (Value.HasAbstractMethods(PythonContext.GetPythonContext(call).SharedContext)) { return(MakeAbstractInstantiationError(call, ai, valInfo)); } DynamicMetaObject translated = BuiltinFunction.TranslateArguments(call, codeContext, self, args, false, Value.Name); if (translated != null) { return(translated); } GetAdapters(ai, call, codeContext, out newAdapter, out initAdapter); PythonContext state = PythonContext.GetPythonContext(call); // get the expression for calling __new__ DynamicMetaObject createExpr = newAdapter.GetExpression(state.Binder); if (createExpr.Expression.Type == typeof(void)) { return(BindingHelpers.AddDynamicTestAndDefer( call, createExpr, args, valInfo )); } Expression res; BindingRestrictions additionalRestrictions = BindingRestrictions.Empty; if (!Value.IsSystemType && (!(newAdapter is DefaultNewAdapter) || HasFinalizer(call))) { // we need to dynamically check the return value to see if it's a subtype of // the type that we are calling. If it is then we need to call __init__/__del__ // for the actual returned type. res = DynamicExpression.Dynamic( Value.GetLateBoundInitBinder(sig), typeof(object), ArrayUtils.Insert( codeContext, Expression.Convert(createExpr.Expression, typeof(object)), DynamicUtils.GetExpressions(args) ) ); additionalRestrictions = createExpr.Restrictions; } else { // just call the __init__ method, built-in types currently have // no wacky return values which don't return the derived type. // then get the statement for calling __init__ ParameterExpression allocatedInst = Ast.Variable(createExpr.GetLimitType(), "newInst"); Expression tmpRead = allocatedInst; DynamicMetaObject initCall = initAdapter.MakeInitCall( state.Binder, new RestrictedMetaObject( AstUtils.Convert(allocatedInst, Value.UnderlyingSystemType), createExpr.Restrictions ) ); List <Expression> body = new List <Expression>(); Debug.Assert(!HasFinalizer(call)); // add the call to init if we need to if (initCall.Expression != tmpRead) { // init can fail but if __new__ returns a different type // no exception is raised. DynamicMetaObject initStmt = initCall; if (body.Count == 0) { body.Add( Ast.Assign(allocatedInst, createExpr.Expression) ); } if (!Value.UnderlyingSystemType.IsAssignableFrom(createExpr.Expression.Type)) { // return type of object, we need to check the return type before calling __init__. body.Add( AstUtils.IfThen( Ast.TypeIs(allocatedInst, Value.UnderlyingSystemType), initStmt.Expression ) ); } else { // just call the __init__ method, no type check necessary (TODO: need null check?) body.Add(initStmt.Expression); } } // and build the target from everything we have if (body.Count == 0) { res = createExpr.Expression; } else { body.Add(allocatedInst); res = Ast.Block(body); } res = Ast.Block(new ParameterExpression[] { allocatedInst }, res); additionalRestrictions = initCall.Restrictions; } return(BindingHelpers.AddDynamicTestAndDefer( call, new DynamicMetaObject( res, self.Restrictions.Merge(additionalRestrictions) ), ArrayUtils.Insert(this, args), valInfo )); }
public override DynamicMetaObject FallbackSetMember(DynamicMetaObject self, DynamicMetaObject value, DynamicMetaObject errorSuggestion) { if (self.NeedsDeferral()) { return(Defer(self, value)); } #if !SILVERLIGHT DynamicMetaObject com; if (Microsoft.Scripting.ComInterop.ComBinder.TryBindSetMember(this, self, BindingHelpers.GetComArgument(value), out com)) { return(com); } #endif return(Context.Binder.SetMember(Name, self, value, errorSuggestion, new PythonOverloadResolverFactory(_context.Binder, AstUtils.Constant(Context.SharedContext)))); }
public override DynamicMetaObject FallbackSetIndex(DynamicMetaObject target, DynamicMetaObject[] indexes, DynamicMetaObject value, DynamicMetaObject errorSuggestion) { #if FEATURE_COM DynamicMetaObject com; if (Microsoft.Scripting.ComInterop.ComBinder.TryBindSetIndex(this, target, BindingHelpers.GetComArguments(indexes), BindingHelpers.GetComArgument(value), out com)) { return(com); } #endif DynamicMetaObject[] finalArgs = new DynamicMetaObject[indexes.Length + 2]; finalArgs[0] = target; for (int i = 0; i < indexes.Length; i++) { finalArgs[i + 1] = indexes[i]; } finalArgs[finalArgs.Length - 1] = value; return(PythonProtocol.Index(this, PythonIndexType.SetItem, finalArgs, errorSuggestion)); }
private DynamicMetaObject /*!*/ MakeConvertRuleForCall(DynamicMetaObjectBinder /*!*/ convertToAction, Type toType, DynamicMetaObject /*!*/ self, string name, string returner, Func <DynamicMetaObject> fallback, Func <Expression, Expression> resultConverter) { PythonType pt = ((IPythonObject)self.Value).PythonType; PythonTypeSlot pts; CodeContext context = PythonContext.GetPythonContext(convertToAction).SharedContext; ValidationInfo valInfo = BindingHelpers.GetValidationInfo(this, pt); if (pt.TryResolveSlot(context, name, out pts) && !IsBuiltinConversion(context, pts, name, pt)) { ParameterExpression tmp = Ast.Variable(typeof(object), "func"); Expression callExpr = resultConverter( Ast.Call( PythonOps.GetConversionHelper(returner, GetResultKind(convertToAction)), Ast.Dynamic( PythonContext.GetPythonContext(convertToAction).InvokeNone, typeof(object), PythonContext.GetCodeContext(convertToAction), tmp ) ) ); if (typeof(Extensible <>).MakeGenericType(toType).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, toType, self, callExpr), typeof(object)); } return(BindingHelpers.AddDynamicTestAndDefer( convertToAction, new DynamicMetaObject( Ast.Condition( MakeTryGetTypeMember( PythonContext.GetPythonContext(convertToAction), pts, self.Expression, tmp ), callExpr, AstUtils.Convert( ConversionFallback(convertToAction), typeof(object) ) ), self.Restrict(self.GetRuntimeType()).Restrictions ), new DynamicMetaObject[] { this }, valInfo, tmp )); } return(fallback()); }
internal static DynamicMetaObject FallbackWorker(PythonContext context, DynamicMetaObject /*!*/ self, DynamicMetaObject /*!*/ codeContext, string name, GetMemberOptions options, DynamicMetaObjectBinder action, DynamicMetaObject errorSuggestion) { if (self.NeedsDeferral()) { return(action.Defer(self)); } PythonOverloadResolverFactory resolverFactory = new PythonOverloadResolverFactory(context.Binder, codeContext.Expression); PerfTrack.NoteEvent(PerfTrack.Categories.BindingTarget, "FallbackGet"); bool isNoThrow = ((options & GetMemberOptions.IsNoThrow) != 0) ? true : false; Type limitType = self.GetLimitType(); if (limitType == typeof(DynamicNull) || PythonBinder.IsPythonType(limitType)) { // look up in the PythonType so that we can // get our custom method names (e.g. string.startswith) PythonType argType = DynamicHelpers.GetPythonTypeFromType(limitType); // if the name is defined in the CLS context but not the normal context then // we will hide it. if (argType.IsHiddenMember(name)) { DynamicMetaObject baseRes = PythonContext.GetPythonContext(action).Binder.GetMember( name, self, resolverFactory, isNoThrow, errorSuggestion ); Expression failure = GetFailureExpression(limitType, self, name, isNoThrow, action); return(BindingHelpers.FilterShowCls(codeContext, action, baseRes, failure)); } } if (self.GetLimitType() == typeof(OldInstance)) { if ((options & GetMemberOptions.IsNoThrow) != 0) { return(new DynamicMetaObject( Ast.Field( null, typeof(OperationFailed).GetField("Value") ), self.Restrictions.Merge(BindingRestrictionsHelpers.GetRuntimeTypeRestriction(self.Expression, typeof(OldInstance))) )); } else { return(new DynamicMetaObject( Ast.Throw( Ast.Call( typeof(PythonOps).GetMethod("AttributeError"), AstUtils.Constant("{0} instance has no attribute '{1}'"), Ast.NewArrayInit( typeof(object), AstUtils.Constant(((OldInstance)self.Value)._class._name), AstUtils.Constant(name) ) ) ), self.Restrictions.Merge(BindingRestrictionsHelpers.GetRuntimeTypeRestriction(self.Expression, typeof(OldInstance))) )); } } var res = PythonContext.GetPythonContext(action).Binder.GetMember(name, self, resolverFactory, isNoThrow, errorSuggestion); // Default binder can return something typed to boolean or int. // If that happens, we need to apply Python's boxing rules. if (res.Expression.Type.IsValueType) { res = new DynamicMetaObject( AstUtils.Convert(res.Expression, typeof(object)), res.Restrictions ); } return(res); }
public override DynamicMetaObject /*!*/ BindInvokeMember(InvokeMemberBinder /*!*/ action, DynamicMetaObject /*!*/[] /*!*/ args) { return(BindingHelpers.GenericInvokeMember(action, null, this, args)); }
/// <summary> /// Tries to get a MethodBinder associated with the slot for the specified type. /// /// If a method is found the binder is set and true is returned. /// If nothing is found binder is null and true is returned. /// If something other than a method is found false is returned. /// /// TODO: Remove rop /// </summary> internal static bool TryGetBinder(PythonContext /*!*/ state, DynamicMetaObject /*!*/[] /*!*/ types, string op, string rop, out SlotOrFunction /*!*/ res, out PythonType declaringType) { declaringType = null; DynamicMetaObject xType = types[0]; BuiltinFunction xBf; if (!BindingHelpers.TryGetStaticFunction(state, op, xType, out xBf)) { res = SlotOrFunction.Empty; return(false); } xBf = CheckAlwaysNotImplemented(xBf); BindingTarget bt; DynamicMetaObject binder; DynamicMetaObject yType = null; BuiltinFunction yBf = null; if (types.Length > 1) { yType = types[1]; if (!BindingHelpers.IsSubclassOf(xType, yType) && !BindingHelpers.TryGetStaticFunction(state, rop, yType, out yBf)) { res = SlotOrFunction.Empty; return(false); } yBf = CheckAlwaysNotImplemented(yBf); } if (yBf == xBf) { yBf = null; } else if (yBf != null && BindingHelpers.IsSubclassOf(yType, xType)) { xBf = null; } var mc = new PythonOverloadResolver( state.Binder, types, new CallSignature(types.Length), AstUtils.Constant(state.SharedContext) ); if (xBf == null) { if (yBf == null) { binder = null; bt = null; } else { declaringType = DynamicHelpers.GetPythonTypeFromType(yBf.DeclaringType); binder = state.Binder.CallMethod(mc, yBf.Targets, BindingRestrictions.Empty, null, PythonNarrowing.None, PythonNarrowing.BinaryOperator, out bt); } } else { if (yBf == null) { declaringType = DynamicHelpers.GetPythonTypeFromType(xBf.DeclaringType); binder = state.Binder.CallMethod(mc, xBf.Targets, BindingRestrictions.Empty, null, PythonNarrowing.None, PythonNarrowing.BinaryOperator, out bt); } else { List <MethodBase> targets = new List <MethodBase>(); targets.AddRange(xBf.Targets); foreach (MethodBase mb in yBf.Targets) { if (!ContainsMethodSignature(targets, mb)) { targets.Add(mb); } } binder = state.Binder.CallMethod(mc, targets.ToArray(), BindingRestrictions.Empty, null, PythonNarrowing.None, PythonNarrowing.BinaryOperator, out bt); foreach (MethodBase mb in yBf.Targets) { if (bt.Overload.ReflectionInfo == mb) { declaringType = DynamicHelpers.GetPythonTypeFromType(yBf.DeclaringType); break; } } if (declaringType == null) { declaringType = DynamicHelpers.GetPythonTypeFromType(xBf.DeclaringType); } } } if (binder != null) { res = new SlotOrFunction(bt, binder); } else { res = SlotOrFunction.Empty; } Debug.Assert(res != null); return(true); }
private DynamicMetaObject /*!*/ InvokeWorker(DynamicMetaObjectBinder /*!*/ call, Expression /*!*/ codeContext, DynamicMetaObject /*!*/[] /*!*/ args) { PerfTrack.NoteEvent(PerfTrack.Categories.Binding, "BuiltinFunc Invoke " + Value.DeclaringType.FullName + "." + Value.Name + " with " + args.Length + " args " + Value.IsUnbound); PerfTrack.NoteEvent(PerfTrack.Categories.BindingTarget, "BuiltinFunction " + Value.Targets.Count + ", " + Value.Targets[0].GetParameters().Length); PerfTrack.NoteEvent(PerfTrack.Categories.BindingSlow, "BuiltinFunction " + BindingHelpers.GetCallSignature(call)); if (this.NeedsDeferral()) { return(call.Defer(ArrayUtils.Insert(this, args))); } for (int i = 0; i < args.Length; i++) { if (args[i].NeedsDeferral()) { return(call.Defer(ArrayUtils.Insert(this, args))); } } if (Value.IsUnbound) { return(MakeSelflessCall(call, codeContext, args)); } else { return(MakeSelfCall(call, codeContext, args)); } }
internal static DynamicMetaObject FallbackWorker(PythonContext context, DynamicMetaObject /*!*/ self, DynamicMetaObject /*!*/ codeContext, string name, GetMemberOptions options, DynamicMetaObjectBinder action, DynamicMetaObject errorSuggestion) { if (self.NeedsDeferral()) { return(action.Defer(self)); } PythonOverloadResolverFactory resolverFactory = new PythonOverloadResolverFactory(context.Binder, codeContext.Expression); PerfTrack.NoteEvent(PerfTrack.Categories.BindingTarget, "FallbackGet"); bool isNoThrow = ((options & GetMemberOptions.IsNoThrow) != 0) ? true : false; Type limitType = self.GetLimitType(); if (limitType == typeof(DynamicNull) || PythonBinder.IsPythonType(limitType)) { // look up in the PythonType so that we can // get our custom method names (e.g. string.startswith) PythonType argType = DynamicHelpers.GetPythonTypeFromType(limitType); // if the name is defined in the CLS context but not the normal context then // we will hide it. if (argType.IsHiddenMember(name)) { DynamicMetaObject baseRes = PythonContext.GetPythonContext(action).Binder.GetMember( name, self, resolverFactory, isNoThrow, errorSuggestion ); Expression failure = GetFailureExpression(limitType, self, name, isNoThrow, action); return(BindingHelpers.FilterShowCls(codeContext, action, baseRes, failure)); } } var res = context.Binder.GetMember(name, self, resolverFactory, isNoThrow, errorSuggestion); if (res is ErrorMetaObject) { // see if we can bind to any extension methods... var codeCtx = (CodeContext)codeContext.Value; var extMethods = codeCtx.ModuleContext.ExtensionMethods; if (extMethods != null) { // try again w/ the extension method binder res = extMethods.GetBinder(context).GetMember(name, self, resolverFactory, isNoThrow, errorSuggestion); } // and add any restrictions (we need an empty restriction even if it's an error so later adds work) res = new DynamicMetaObject( res.Expression, res.Restrictions.Merge(extMethods.GetRestriction(codeContext.Expression)) ); } // Default binder can return something typed to boolean or int. // If that happens, we need to apply Python's boxing rules. if (res.Expression.Type.IsValueType()) { res = new DynamicMetaObject( AstUtils.Convert(res.Expression, typeof(object)), res.Restrictions ); } return(res); }