예제 #1
0
        /// <summary>
        /// Transforms an invoke member into a Python GetMember/Invoke.  The caller should
        /// verify that the given attribute is not resolved against a normal .NET class
        /// before calling this.  If it is a normal .NET member then a fallback InvokeMember
        /// is preferred.
        /// </summary>
        internal static DynamicMetaObject /*!*/ GenericInvokeMember(InvokeMemberBinder /*!*/ action, ValidationInfo valInfo, DynamicMetaObject target, DynamicMetaObject /*!*/[] /*!*/ args)
        {
            if (target.NeedsDeferral())
            {
                return(action.Defer(args));
            }

            return(AddDynamicTestAndDefer(action,
                                          action.FallbackInvoke(
                                              new DynamicMetaObject(
                                                  Binders.Get(
                                                      PythonContext.GetCodeContext(action),
                                                      PythonContext.GetPythonContext(action),
                                                      typeof(object),
                                                      action.Name,
                                                      target.Expression
                                                      ),
                                                  BindingRestrictionsHelpers.GetRuntimeTypeRestriction(target)
                                                  ),
                                              args,
                                              null
                                              ),
                                          args,
                                          valInfo
                                          ));
        }
예제 #2
0
        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;

            // 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[] newArgs = ArrayUtils.Insert(GetMetaFunction(self), GetMetaSelf(self), args);
            var newSig = new CallSignature(ArrayUtils.Insert(new Argument(ArgumentType.Simple), signature.GetArgumentInfos()));

            var 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)
                           ));
            }
        }
예제 #3
0
 private static Expression /*!*/ CheckSelf(DynamicMetaObjectBinder /*!*/ binder, Expression /*!*/ method, Expression /*!*/ inst)
 {
     return(Ast.Call(
                typeof(PythonOps).GetMethod(nameof(PythonOps.MethodCheckSelf)),
                PythonContext.GetCodeContext(binder),
                method,
                AstUtils.Convert(inst, typeof(object))
                ));
 }
예제 #4
0
        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());
        }
예제 #5
0
 public override DynamicMetaObject /*!*/ BindInvoke(InvokeBinder /*!*/ invoke, params DynamicMetaObject /*!*/[] /*!*/ args)
 {
     return(InvokeWorker(invoke, PythonContext.GetCodeContext(invoke), args));
 }
예제 #6
0
 public override DynamicMetaObject /*!*/ BindInvoke(InvokeBinder /*!*/ call, params DynamicMetaObject /*!*/[] /*!*/ args)
 {
     return(InvokeWorker(call, args, PythonContext.GetCodeContext(call)));
 }
예제 #7
0
 public override DynamicMetaObject /*!*/ BindGetMember(GetMemberBinder /*!*/ member)
 {
     return(GetMemberWorker(member, PythonContext.GetCodeContext(member)));
 }
예제 #8
0
        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);

                callSlot.MakeGetExpression(
                    pyContext.Binder,
                    PythonContext.GetCodeContext(call),
                    self,
                    GetPythonType(self),
                    cb
                    );

                if (!cb.IsFinal)
                {
                    cb.FinishCondition(GetCallError(call, self));
                }

                Expression[] callArgs = ArrayUtils.Insert(
                    PythonContext.GetCodeContext(call),
                    cb.GetMetaObject().Expression,
                    DynamicUtils.GetExpressions(args)
                    );

                Expression body = DynamicExpression.Dynamic(
                    PythonContext.GetPythonContext(call).Invoke(
                        BindingHelpers.GetCallSignature(call)
                        ),
                    typeof(object),
                    callArgs
                    );

                body = Ast.TryFinally(
                    Ast.Block(
                        Ast.Call(typeof(PythonOps).GetMethod(nameof(PythonOps.FunctionPushFrame)), Ast.Constant(pyContext)),
                        body
                        ),
                    Ast.Call(typeof(PythonOps).GetMethod(nameof(PythonOps.FunctionPopFrame)))
                    );

                return(BindingHelpers.AddDynamicTestAndDefer(
                           call,
                           new DynamicMetaObject(body, self.Restrictions.Merge(BindingRestrictions.Combine(args))),
                           args,
                           valInfo
                           ));
            }

            return(null);
        }
예제 #9
0
 public override DynamicMetaObject /*!*/ BindInvoke(InvokeBinder /*!*/ call, params DynamicMetaObject /*!*/[] /*!*/ args)
 {
     // TODO: Context should come from BuiltinFunction
     return(InvokeWorker(call, PythonContext.GetCodeContext(call), args));
 }
예제 #10
0
        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(nameof(PythonOps.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(nameof(PythonOps.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)
                           ));
            }
        }