Beispiel #1
0
        public override DynamicMetaObject Bind(DynamicMetaObject target, DynamicMetaObject[] args)
        {
            DynamicMetaObject self = target;

            DynamicMetaObject res = null;

            if (self.NeedsDeferral())
            {
                return(MyDefer(self));
            }


            IPythonConvertible convertible = target as IPythonConvertible;

            if (convertible != null)
            {
                res = convertible.BindConvert(this);
            }
            else if (res == null)
            {
                res = BindConvert(self);
            }

            if (_retObject)
            {
                res = new DynamicMetaObject(
                    AstUtils.Convert(res.Expression, typeof(object)),
                    res.Restrictions
                    );
            }

            return(res);
        }
Beispiel #2
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
                                          ));
        }
        public override DynamicMetaObject FallbackDeleteMember(DynamicMetaObject self, DynamicMetaObject errorSuggestion) {
            if (self.NeedsDeferral()) {
                return Defer(self);
            }

            return Context.Binder.DeleteMember(Name, self, new PythonOverloadResolverFactory(_context.Binder, AstUtils.Constant(Context.SharedContext)));
        }
        public override DynamicMetaObject FallbackDeleteMember(DynamicMetaObject self, DynamicMetaObject errorSuggestion) {
            if (self.NeedsDeferral()) {
                return Defer(self);
            }

            return Binder.Binder.DeleteMember(Name, self, AstUtils.Constant(Binder.Context));
        }
Beispiel #5
0
        public override DynamicMetaObject FallbackDeleteMember(DynamicMetaObject self, DynamicMetaObject errorSuggestion)
        {
            if (self.NeedsDeferral())
            {
                return(Defer(self));
            }

            return(Context.Binder.DeleteMember(Name, self, new PythonOverloadResolverFactory(_context.Binder, AstUtils.Constant(Context.SharedContext)), errorSuggestion));
        }
Beispiel #6
0
        /// <summary>
        /// Fallback - performs the default binding operation if the object isn't recognized
        /// as being invokable.
        /// </summary>
        internal DynamicMetaObject /*!*/ Fallback(Expression codeContext, DynamicMetaObject target, DynamicMetaObject /*!*/[] /*!*/ args)
        {
            if (target.NeedsDeferral())
            {
                return(Defer(args));
            }

            return(PythonProtocol.Call(this, target, args) ??
                   Context.Binder.Create(Signature, target, args, codeContext) ??
                   Context.Binder.Call(Signature, new PythonOverloadResolverFactory(Context.Binder, codeContext), target, args));
        }
        public override DynamicMetaObject FallbackSetMember(DynamicMetaObject self, DynamicMetaObject value, DynamicMetaObject onBindingError) {
            if (self.NeedsDeferral()) {
                return Defer(self, value);
            }
#if !SILVERLIGHT
            DynamicMetaObject com;
            if (System.Dynamic.ComBinder.TryBindSetMember(this, self, value, out com)) {
                return com;
            }
#endif
            return Binder.Binder.SetMember(Name, self, value, Ast.Constant(Binder.Context));
        }
        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 = 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 FallbackSetMember(DynamicMetaObject self, DynamicMetaObject value, DynamicMetaObject errorSuggestion)
        {
            if (self.NeedsDeferral())
            {
                return(Defer(self, value));
            }
#if FEATURE_COM
            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 static DynamicMetaObject/*!*/ Operation(UnaryOperationBinder/*!*/ operation, DynamicMetaObject arg, DynamicMetaObject errorSuggestion) {
            PerfTrack.NoteEvent(PerfTrack.Categories.Binding, "Fallback UnaryOperator " + " " + operation.Operation + " " + arg.LimitType.FullName);
            PerfTrack.NoteEvent(PerfTrack.Categories.BindingTarget, operation.Operation.ToString());

            DynamicMetaObject[] args = new[] { arg };
            if (arg.NeedsDeferral()) {
                return operation.Defer(arg);
            }

            ValidationInfo valInfo = BindingHelpers.GetValidationInfo(args);

            DynamicMetaObject res = null;
            Type retType = typeof(object);
            switch (operation.Operation) {
                case ExpressionType.UnaryPlus:
                    res = BindingHelpers.AddPythonBoxing(MakeUnaryOperation(operation, arg, "__pos__", errorSuggestion));
                    break;
                case ExpressionType.Negate:
                    res = BindingHelpers.AddPythonBoxing(MakeUnaryOperation(operation, arg, "__neg__", errorSuggestion));
                    break;
                case ExpressionType.OnesComplement:
                    res = BindingHelpers.AddPythonBoxing(MakeUnaryOperation(operation, arg, "__invert__", errorSuggestion));
                    break;
                case ExpressionType.Not:
                    res = MakeUnaryNotOperation(operation, arg, typeof(object), errorSuggestion);
                    break;
                case ExpressionType.IsFalse:
                    res = MakeUnaryNotOperation(operation, arg, typeof(bool), errorSuggestion);
                    retType = typeof(bool);
                    break;
                case ExpressionType.IsTrue:
                    res = PythonProtocol.ConvertToBool(operation, arg);
                    retType = typeof(bool);
                    break;
                default:
                    res = TypeError(operation, "unknown operation: " + operation.ToString(), args);
                    break;

            }

            return BindingHelpers.AddDynamicTestAndDefer(operation, res, args, valInfo, retType);
        }
        public static DynamicMetaObject Operation(UnaryOperationBinder operation, DynamicMetaObject arg, DynamicMetaObject errorSuggestion)
        {
            PerfTrack.NoteEvent(PerfTrack.Categories.Binding, "Fallback UnaryOperator " + " " + operation.Operation + " " + arg.LimitType.FullName);
            PerfTrack.NoteEvent(PerfTrack.Categories.BindingTarget, operation.Operation.ToString());

            DynamicMetaObject[] args = new[] { arg };
            if (arg.NeedsDeferral())
                return operation.Defer(arg);

            ValidationInfo valInfo = BindingHelpers.GetValidationInfo(args);

            TotemOperationKind? toOperator = null;
            Type retType = typeof(object);
            bool box = true;
            bool inverse = false;
            switch (operation.Operation)
            {
                case ExpressionType.UnaryPlus: toOperator = TotemOperationKind.Positive; break;
                case ExpressionType.Negate: toOperator = TotemOperationKind.Negate; break;
                case ExpressionType.OnesComplement: toOperator = TotemOperationKind.OnesComplement; break;
                case ExpressionType.Not: toOperator = TotemOperationKind.Not; box = false; break;
                case ExpressionType.IsFalse: toOperator = TotemOperationKind.IsFalse; box = false; retType = typeof(bool); break;
                case ExpressionType.IsTrue: toOperator = TotemOperationKind.IsFalse; box = false; retType = typeof(bool); inverse = true; break;
            }

            DynamicMetaObject res = null;
            if (toOperator != null)
                res = MakeUnaryOperation(operation, args[0], toOperator.Value, errorSuggestion, retType);
            else
                res = operation.FallbackUnaryOperation(arg);

            if (inverse)
            {
                res = new DynamicMetaObject(
                    Expression.Condition(
                        res.Expression,
                        Utils.Constant(ScriptingRuntimeHelpers.False),
                        Utils.Constant(ScriptingRuntimeHelpers.True)
                    ),
                    res.Restrictions
                );
            }

            if (box)
            {
                res = BindingHelpers.AddTotemBoxing(res);
            }

            return BindingHelpers.AddDynamicTestAndDefer(operation, res, args, valInfo, retType);
        }
Beispiel #12
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);
        }
Beispiel #13
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(
                            BinderState.GetCodeContext(action),
                            BinderState.GetBinderState(action),
                            typeof(object),
                            action.Name,
                            target.Expression
                        ),
                        BindingRestrictionsHelpers.GetRuntimeTypeRestriction(target)
                    ),
                    args,
                    null
                ),
                args,
                valInfo
            );
        }
Beispiel #14
0
        /// <summary>
        /// Fallback - performs the default binding operation if the object isn't recognized
        /// as being invokable.
        /// </summary>
        internal DynamicMetaObject/*!*/ Fallback(Expression codeContext, DynamicMetaObject target, DynamicMetaObject/*!*/[]/*!*/ args) {
            if (target.NeedsDeferral()) {
                return Defer(args);
            }

            return PythonProtocol.Call(this, target, args) ??
                Binder.Binder.Create(Signature, new ParameterBinderWithCodeContext(Binder.Binder, codeContext), target, args) ??
                Binder.Binder.Call(Signature, new ParameterBinderWithCodeContext(Binder.Binder, codeContext), target, args);
        }
Beispiel #15
0
        /// <summary>
        /// Transforms a call into a Python GetMember/Invoke.  This isn't quite the correct semantic as
        /// we shouldn't be returning Python members (e.g. object.__repr__) to non-Python callers.  This
        /// can go away as soon as all of the classes implement the full fidelity of the protocol
        /// </summary>
        internal static DynamicMetaObject/*!*/ GenericCall(InvokeMemberBinder/*!*/ action, DynamicMetaObject target, DynamicMetaObject/*!*/[]/*!*/ args) {
            if (target.NeedsDeferral()) {
                return action.Defer(args);
            }

            return new DynamicMetaObject(
                Invoke(
                    BinderState.GetCodeContext(action),
                    BinderState.GetBinderState(action),
                    typeof(object),
                    GetCallSignature(action),
                    ArrayUtils.Insert(
                        Binders.Get(
                            BinderState.GetCodeContext(action),
                            BinderState.GetBinderState(action),
                            typeof(object),
                            action.Name,
                            target.Expression
                        ),
                        DynamicUtils.GetExpressions(args)
                    )
                ),
                BindingRestrictions.Combine(args).Merge(target.Restrict(target.GetLimitType()).Restrictions)
            );
        }