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(call, 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);
        }
Example #2
0
        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 },
                                       DynamicExpression.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()
                       ));
        }
        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);
        }
Example #4
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("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)
                           ));
            }
        }
        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(nameof(PythonOps.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);
                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
                        );
                }

                DynamicMetaObject 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);
            }
                       ));
        }
Example #6
0
                public override DynamicMetaObject BindInvoke(InvokeBinder binder, DynamicMetaObject[] args)
                {
                    CodeContext context = PythonContext.GetPythonContext(binder).SharedContext;

                    ArgumentMarshaller[] signature = GetArgumentMarshallers(args);

                    BindingRestrictions restrictions = BindingRestrictions.GetTypeRestriction(
                        Expression,
                        Value.GetType()
                        ).Merge(
                        BindingRestrictions.GetExpressionRestriction(
                            Expression.Call(
                                typeof(ModuleOps).GetMethod("CheckFunctionId"),
                                Expression.Convert(Expression, typeof(_CFuncPtr)),
                                Expression.Constant(Value.Id)
                                )
                            )
                        );

                    foreach (var arg in signature)
                    {
                        restrictions = restrictions.Merge(arg.GetRestrictions());
                    }

                    int argCount = args.Length;

                    if (Value._comInterfaceIndex != -1)
                    {
                        argCount--;
                    }
                    // need to verify we have the correct # of args
                    if (Value._argtypes != null)
                    {
                        if (argCount < Value._argtypes.Count || (Value.CallingConvention != CallingConvention.Cdecl && argCount > Value._argtypes.Count))
                        {
                            return(IncorrectArgCount(binder, restrictions, Value._argtypes.Count, argCount));
                        }
                    }
                    else
                    {
                        CFuncPtrType funcType = ((CFuncPtrType)Value.NativeType);
                        if (funcType._argtypes != null &&
                            (argCount < funcType._argtypes.Length || (Value.CallingConvention != CallingConvention.Cdecl && argCount > funcType._argtypes.Length)))
                        {
                            return(IncorrectArgCount(binder, restrictions, funcType._argtypes.Length, argCount));
                        }
                    }

                    if (Value._comInterfaceIndex != -1 && args.Length == 0)
                    {
                        return(NoThisParam(binder, restrictions));
                    }

                    Expression        call  = MakeCall(signature, GetNativeReturnType(), Value.Getrestype() == null, GetFunctionAddress(args));
                    List <Expression> block = new List <Expression>();
                    Expression        res;

                    if (call.Type != typeof(void))
                    {
                        ParameterExpression tmp = Expression.Parameter(call.Type, "ret");
                        block.Add(Expression.Assign(tmp, call));
                        AddKeepAlives(signature, block);
                        block.Add(tmp);
                        res = Expression.Block(new[] { tmp }, block);
                    }
                    else
                    {
                        block.Add(call);
                        AddKeepAlives(signature, block);
                        res = Expression.Block(block);
                    }

                    res = AddReturnChecks(context, args, res);

                    return(new DynamicMetaObject(Utils.Convert(res, typeof(object)), restrictions));
                }