The dynamic call site binder that participates in the DynamicMetaObject binding protocol.
The CallSiteBinder performs the binding of the dynamic operation using the runtime values as input. On the other hand, the DynamicMetaObjectBinder participates in the DynamicMetaObject binding protocol.
Inheritance: System.Runtime.CompilerServices.CallSiteBinder
Example #1
0
        /*!*/
        public static DynamicMetaObject TypeError(DynamicMetaObjectBinder/*!*/ action, string message, params DynamicMetaObject[] types)
        {
            if (action is ITotemSite)
            {
                ITotemSite site = (ITotemSite)action;

                message = String.Format(message, ArrayUtils.ConvertAll(types, x => {
                    var t = site.Context.GetTypeHandler(x.LimitType);
                    if (t != null)
                        return t.Name;

                    return x.LimitType.Name;
                }));

                Expression error = action.Throw(
                    Ast.Call(
                        AstMethods.SimpleTypeError,
                        Ast.Constant(message)
                    ),
                    typeof(object)
                );

                return new DynamicMetaObject(
                    error,
                    BindingRestrictions.Combine(types)
                );
            }

            return GenericFallback(action, types);
        }
Example #2
0
        internal static DynamicMetaObject ConvertToString(DynamicMetaObjectBinder conversion, DynamicMetaObject self)
        {
            Assert.NotNull(conversion, self);

            TotemType ltype = MetaTotemObject.GetTotemType(self);
            var matches = ltype.GetOperatorFunctions(TotemOperationKind.ToString).ToList();

            var overloadResolver = GetTotemContext(conversion).SharedOverloadResolverFactory.CreateOverloadResolver(new[] { self }, new CallSignature(1), CallTypes.None);
            var ret = overloadResolver.ResolveOverload("ToString", ArrayUtils.ToArray(matches, m => CreateOverloadInfo(m)), NarrowingLevel.None, NarrowingLevel.All);

            if (!ret.Success)
            {
                return new DynamicMetaObject(
                    Expression.Throw(
                        Expression.Call(
                            AstMethods.TypeError,
                            Utils.Constant("No toString found on type {1}."),
                            Expression.NewArrayInit(
                                typeof(string),
                                Expression.Constant(ltype.Name)
                            )
                        )
                    ),
                    BindingRestrictions.Combine(new[] { self })
                );
            }
            return new DynamicMetaObject(ret.MakeExpression(), ret.RestrictedArguments.GetAllRestrictions());
        }
Example #3
0
        internal DynamicMetaObject/*!*/ CreateMetaObject(DynamicMetaObjectBinder/*!*/ action) {
            Debug.Assert(ControlFlowBuilder == null, "Control flow required but not built");

            var expr = _error ? Ast.Throw(_result) : _result;

            if (_condition != null) {
                var deferral = action.GetUpdateExpression(typeof(object));
                expr = Ast.Condition(_condition, AstUtils.Convert(expr, typeof(object)), deferral);
            }

            if (_temps != null) {
                expr = Ast.Block(_temps, expr);
            }

#if DEBUG && !SILVERLIGHT && !SYSTEM_CORE
            if (RubyOptions.ShowRules) {
                var oldColor = Console.ForegroundColor;
                try {
                    Console.ForegroundColor = ConsoleColor.Cyan;
                    Console.WriteLine("Rule #{0}: {1}", Interlocked.Increment(ref _ruleCounter), action);
                    Console.ForegroundColor = ConsoleColor.DarkGray;
                    var d = (_restrictions != BindingRestrictions.Empty) ? Ast.IfThen(_restrictions.ToExpression(), expr) : expr;
                    d.DumpExpression(null, Console.Out);
                } finally {
                    Console.ForegroundColor = oldColor;
                }
            }
#endif

            return new DynamicMetaObject(expr, _restrictions);
        }
		public CSharpBinder (DynamicMetaObjectBinder binder, Compiler.Expression expr, DynamicMetaObject errorSuggestion)
		{
			this.binder = binder;
			this.expr = expr;
			this.restrictions = BindingRestrictions.Empty;
			this.errorSuggestion = errorSuggestion;
		}
Example #5
0
            public static DynamicMetaObject/*!*/ Bind(string/*!*/ methodName, CallInfo/*!*/ callInfo,
                DynamicMetaObjectBinder/*!*/ binder, DynamicMetaObject/*!*/ target, DynamicMetaObject/*!*/[]/*!*/ args,
                Func<DynamicMetaObject, DynamicMetaObject[], DynamicMetaObject>/*!*/ fallback)
            {
                Debug.Assert(fallback != null);

                //create DMO
                var phpInvokeBinder = Binder.MethodCall(methodName, 0, callInfo.ArgumentCount, null, Types.Object[0]) as PhpBaseInvokeMemberBinder;

                if (phpInvokeBinder != null)
                {

                    //Add ScriptContext.CurrentContext
                    var context = new DynamicMetaObject(Expression.Call(Methods.ScriptContext.GetCurrentContext), BindingRestrictions.Empty);

                    var restrictions = BinderHelper.GetSimpleInvokeRestrictions(target, args);

                    //Value type arguments have to be boxed
                    DynamicMetaObject[] arguments = new DynamicMetaObject[1 + args.Length];
                    arguments[0] = context;
                    for (int i = 0; i < args.Length; ++i)
                        arguments[1 + i] = new DynamicMetaObject(WrapDynamic(args[i].Expression),
                                                                 args[i].Restrictions);
                    var result = phpInvokeBinder.Bind(target, arguments);

                    //Unwrap result
                    var res = new DynamicMetaObject(Unwrap(result.Expression), restrictions);

                    return res;
                }
                else
                    return fallback(target, args);//this will never happen
            }
Example #6
0
 /// <summary>
 /// Constror 
 /// </summary>
 /// <param name="target">Be weaved object.</param>
 /// <param name="binder">Dynamic object binder <see cref="DynamicMetaObjectBinder"/></param>
 /// <param name="argumentValues">To store Arguement values of calling method.</param>
 /// <param name="returnValue">To store  return value of the calling method, if it has one.</param>
 public WeavingContext(object target, DynamicMetaObjectBinder binder, object[] argumentValues=null, object returnValue=null)
 {
     this.Target = target;
     this.binder = binder;
     this.ArgumentValues = argumentValues;
     this.ReturnValue = returnValue;
 }
Example #7
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 (var 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);
            TotemType tt = DynamicHelpers.GetTotemType(target.Value);
            TotemContext toContext = GetTotemContext(call);

            throw new NotImplementedException();
        }
Example #8
0
        internal static bool IsNoThrow(DynamicMetaObjectBinder action) {
            PythonGetMemberBinder gmb = action as PythonGetMemberBinder;
            if (gmb != null) {
                return gmb.IsNoThrow;
            }

            return false;
        }
Example #9
0
        public DynamicMetaObject FallbackConvert(DynamicMetaObjectBinder binder)
        {
            TotemConversionBinder toBinder = binder as TotemConversionBinder;
            if (toBinder != null)
                return toBinder.FallbackConvert(binder.ReturnType, this, null);

            return ((ConvertBinder)binder).FallbackConvert(this);
        }
Example #10
0
        public DynamicMetaObject/*!*/ FallbackConvert(DynamicMetaObjectBinder/*!*/ binder) {
            PythonConversionBinder pyBinder = binder as PythonConversionBinder;
            if (pyBinder != null) {
                return pyBinder.FallbackConvert(binder.ReturnType, this, null);
            }

            return ((ConvertBinder)binder).FallbackConvert(this);
        }
Example #11
0
        public static BinderState/*!*/ GetBinderState(DynamicMetaObjectBinder/*!*/ action) {
            IPythonSite pySite = action as IPythonSite;
            if (pySite != null) {
                return pySite.Binder;
            }

            Debug.Assert(Default != null);
            return Default;
        }
Example #12
0
 internal static BindingRestrictions GetOptionalVersionAndLanguageCheckForType(DynamicMetaObjectBinder binder, Type targetType, int expectedVersionNumber)
 {
     BindingRestrictions empty = BindingRestrictions.Empty;
     if (CoreTypes.Contains(targetType))
     {
         return empty;
     }
     if (expectedVersionNumber != -1)
     {
         empty = empty.Merge(GetVersionCheck(binder, expectedVersionNumber));
     }
     return empty.Merge(GetLanguageModeCheckIfHasEverUsedConstrainedLanguage());
 }
Example #13
0
 public BinaryRetTypeBinder(DynamicMetaObjectBinder operationBinder, PythonConversionBinder conversionBinder) :
     base(new BinderMappingInfo(
             operationBinder,
             ParameterMappingInfo.Parameter(0),
             ParameterMappingInfo.Parameter(1)
         ),
         new BinderMappingInfo(
             conversionBinder,
             ParameterMappingInfo.Action(0)
         )
     ) {
     _opBinder = operationBinder;
     _convBinder = conversionBinder;
 }
Example #14
0
        private DynamicMetaObject/*!*/ InvokeWorker(DynamicMetaObjectBinder/*!*/ call, Expression/*!*/ codeContext, DynamicMetaObject/*!*/[]/*!*/ args) {
            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);
            }
        }
        private DynamicMetaObject/*!*/ InvokeWorker(DynamicMetaObjectBinder/*!*/ call, Expression/*!*/ codeContext, DynamicMetaObject/*!*/[] args) {
            CallSignature signature = BindingHelpers.GetCallSignature(call);
            BindingRestrictions selfRestrict = BindingRestrictions.GetInstanceRestriction(Expression, Value).Merge(Restrictions);

            selfRestrict = selfRestrict.Merge(
                BindingRestrictions.GetExpressionRestriction(
                    MakeFunctionTest(
                        Ast.Call(
                            typeof(PythonOps).GetMethod("GetBuiltinMethodDescriptorTemplate"),
                            Ast.Convert(Expression, typeof(BuiltinMethodDescriptor))
                        )
                    )
                )
            );

            return Value.Template.MakeBuiltinFunctionCall(
                call,
                codeContext,
                this,
                args,
                false,  // no self
                true,
                selfRestrict,
                (newArgs) => {
                    BindingTarget target;

                    BinderState state = BinderState.GetBinderState(call);

                    DynamicMetaObject res = state.Binder.CallMethod(
                        new ParameterBinderWithCodeContext(state.Binder, codeContext),
                        Value.Template.Targets,
                        newArgs,
                        signature,
                        selfRestrict,
                        NarrowingLevel.None,
                        Value.Template.IsBinaryOperator ?
                            PythonNarrowing.BinaryOperator :
                            NarrowingLevel.All,
                        Value.Template.Name,
                        out target
                    );

                    return new BuiltinFunction.BindingResult(target, res);
                });            
        }
Example #16
0
        internal static DynamicMetaObject/*!*/ FilterShowCls(DynamicMetaObject/*!*/ codeContext, DynamicMetaObjectBinder/*!*/ action, DynamicMetaObject/*!*/ res, Expression/*!*/ failure) {
            if (action is IPythonSite) {
                return new DynamicMetaObject(
                    Ast.Condition(
                        Ast.Call(
                            typeof(PythonOps).GetMethod("IsClsVisible"),
                            codeContext.Expression
                        ),
                        AstUtils.Convert(res.Expression, typeof(object)),
                        AstUtils.Convert(failure, typeof(object))

                    ),
                    res.Restrictions
                );
            }

            return res;
        }
Example #17
0
        /// <summary>
        /// Gets a MetaObject which converts the provided object to a bool using __nonzero__ or __len__
        /// protocol methods.  This code is shared between both our fallback for a site and our MetaObject
        /// for user defined objects.
        /// </summary>
        internal static DynamicMetaObject ConvertToBool(DynamicMetaObjectBinder/*!*/ conversion, DynamicMetaObject/*!*/ self) {
            Assert.NotNull(conversion, self);

            SlotOrFunction sf = SlotOrFunction.GetSlotOrFunction(
                BinderState.GetBinderState(conversion),
                Symbols.NonZero,
                self);

            if (sf.Success) {
                if (sf.Target.Expression.Type != typeof(bool)) {
                    return new DynamicMetaObject(
                        Ast.Call(
                            typeof(PythonOps).GetMethod("ThrowingConvertToNonZero"),
                            sf.Target.Expression
                        ),
                        sf.Target.Restrictions
                    );
                }

                return sf.Target;
            }

            sf = SlotOrFunction.GetSlotOrFunction(
                BinderState.GetBinderState(conversion),
                Symbols.Length,
                self);

            if (sf.Success) {
                return new DynamicMetaObject(
                    GetConvertByLengthBody(
                        BinderState.GetBinderState(conversion),
                        sf.Target.Expression
                    ),
                    sf.Target.Restrictions
                );
            }

            return null;
        }
Example #18
0
        internal DynamicMetaObject/*!*/ CreateMetaObject(DynamicMetaObjectBinder/*!*/ action) {
            Debug.Assert(ControlFlowBuilder == null, "Control flow required but not built");

            var expr = _error ? Ast.Throw(_result) : _result;

            if (_condition != null) {
                var deferral = action.GetUpdateExpression(typeof(object));
                expr = Ast.Condition(_condition, AstUtils.Convert(expr, typeof(object)), deferral);
            }

            if (_temps != null) {
                expr = Ast.Block(_temps, expr);
            }

            BindingRestrictions restrictions;
            if (_restriction != null) {
                restrictions = BindingRestrictions.GetExpressionRestriction(_restriction);
            } else {
                restrictions = BindingRestrictions.Empty;
            }

            return new DynamicMetaObject(expr, restrictions);
        }
Example #19
0
            public static DynamicMetaObject/*!*/ Bind(DynamicMetaObject/*!*/ context, string/*!*/ methodName, CallInfo/*!*/ callInfo, 
                DynamicMetaObjectBinder/*!*/ binder, DynamicMetaObject/*!*/ target, DynamicMetaObject/*!*/[]/*!*/ args,
                Func<DynamicMetaObject, DynamicMetaObject[], DynamicMetaObject>/*!*/ fallback) {
                Debug.Assert(fallback != null);

                var callArgs = new CallArguments(context, target, args, RubyCallSignature.Interop(callInfo.ArgumentCount));
                var metaBuilder = new MetaObjectBuilder(target, args);

                if (!RubyCallAction.BuildCall(metaBuilder, methodName, callArgs, false, false)) {
                    metaBuilder.SetMetaResult(fallback(target, args), false);
                }
                return metaBuilder.CreateMetaObject(binder);
            }
            /// <summary>
            /// Helper method for generating a MetaObject which calls a
            /// specific method on DynamicObject that returns a result.
            /// 
            /// args is either an array of arguments to be passed
            /// to the method as an object[] or NoArgs to signify that
            /// the target method takes no parameters.
            /// </summary>
            private DynamicMetaObject BuildCallMethodWithResult(string methodName, DynamicMetaObjectBinder binder, Expression[] args, DynamicMetaObject fallbackResult, Fallback fallbackInvoke) {
                if (!IsOverridden(methodName)) {
                    return fallbackResult;
                }

                //
                // Build a new expression like:
                // {
                //   object result;
                //   TryGetMember(payload, out result) ? fallbackInvoke(result) : fallbackResult
                // }
                //
                var result = Expression.Parameter(typeof(object), null);
                ParameterExpression callArgs = methodName != "TryBinaryOperation" ? Expression.Parameter(typeof(object[]), null) : Expression.Parameter(typeof(object), null);
                var callArgsValue = GetConvertedArgs(args);

                var resultMO = new DynamicMetaObject(result, BindingRestrictions.Empty);

                // Need to add a conversion if calling TryConvert
                if (binder.ReturnType != typeof(object)) {
                    Debug.Assert(binder is ConvertBinder && fallbackInvoke == null);

                    var convert = Expression.Convert(resultMO.Expression, binder.ReturnType);
                    // will always be a cast or unbox
                    Debug.Assert(convert.Method == null);

#if !SILVERLIGHT
                    // Prepare a good exception message in case the convert will fail
                    string convertFailed = Strings.DynamicObjectResultNotAssignable(
                        "{0}",
                        this.Value.GetType(),
                        binder.GetType(),
                        binder.ReturnType
                    );

                    Expression condition;
                    // If the return type can not be assigned null then just check for type assignablity otherwise allow null.
                    if (binder.ReturnType.IsValueType && Nullable.GetUnderlyingType(binder.ReturnType) == null) {
                        condition = Expression.TypeIs(resultMO.Expression, binder.ReturnType);
                    }
                    else {
                        condition = Expression.OrElse(
                                        Expression.Equal(resultMO.Expression, Expression.Constant(null)),
                                        Expression.TypeIs(resultMO.Expression, binder.ReturnType));
                    }

                    var checkedConvert = Expression.Condition(
                        condition,
                        convert,
                        Expression.Throw(
                            Expression.New(typeof(InvalidCastException).GetConstructor(new Type[]{typeof(string)}),
                                Expression.Call(
                                    typeof(string).GetMethod("Format", new Type[] {typeof(string), typeof(object[])}),
                                    Expression.Constant(convertFailed),
                                    Expression.NewArrayInit(typeof(object), 
                                        Expression.Condition(
                                            Expression.Equal(resultMO.Expression, Expression.Constant(null)),
                                            Expression.Constant("null"),
                                            Expression.Call(
                                                resultMO.Expression,
                                                typeof(object).GetMethod("GetType")
                                            ),
                                            typeof(object)
                                        )
                                    )
                                )
                            ),
                            binder.ReturnType
                        ),
                        binder.ReturnType
                    );
#else
                    var checkedConvert = convert;
#endif

                    resultMO = new DynamicMetaObject(checkedConvert, resultMO.Restrictions);
                }

                if (fallbackInvoke != null) {
                    resultMO = fallbackInvoke(resultMO);
                }

                var callDynamic = new DynamicMetaObject(
                    Expression.Block(
                        new[] { result, callArgs },
                        methodName != "TryBinaryOperation" ? Expression.Assign(callArgs, Expression.NewArrayInit(typeof(object), callArgsValue)) : Expression.Assign(callArgs, callArgsValue[0]),
                        Expression.Condition(
                            Expression.Call(
                                GetLimitedSelf(),
                                typeof(DynamicObject).GetMethod(methodName),
                                BuildCallArgs(
                                    binder,
                                    args,
                                    callArgs,
                                    result
                                )
                            ),
                            Expression.Block(
                                methodName != "TryBinaryOperation" ? ReferenceArgAssign(callArgs, args) : Expression.Empty(),
                                resultMO.Expression
                            ),
                            fallbackResult.Expression,
                            binder.ReturnType
                        )
                    ),
                    GetRestrictions().Merge(resultMO.Restrictions).Merge(fallbackResult.Restrictions)
                );
                return callDynamic;
            }
            /// <summary>
            /// Helper method for generating a MetaObject which calls a
            /// specific method on Dynamic, but uses one of the arguments for
            /// the result.
            /// 
            /// args is either an array of arguments to be passed
            /// to the method as an object[] or NoArgs to signify that
            /// the target method takes no parameters.
            /// </summary>
            private DynamicMetaObject CallMethodNoResult(string methodName, DynamicMetaObjectBinder binder, Expression[] args, Fallback fallback) {
                //
                // First, call fallback to do default binding
                // This produces either an error or a call to a .NET member
                //
                DynamicMetaObject fallbackResult = fallback(null);
                var callArgs = Expression.Parameter(typeof(object[]), null);
                var callArgsValue = GetConvertedArgs(args);

                //
                // Build a new expression like:
                //   if (TryDeleteMember(payload)) { } else { fallbackResult }
                //
                var callDynamic = new DynamicMetaObject(
                    Expression.Block(
                        new[] { callArgs },
                        Expression.Assign(callArgs, Expression.NewArrayInit(typeof(object), callArgsValue)),
                        Expression.Condition(
                            Expression.Call(
                                GetLimitedSelf(),
                                typeof(DynamicObject).GetMethod(methodName),
                                BuildCallArgs(
                                    binder,
                                    args,
                                    callArgs,
                                    null
                                )
                            ),
                            Expression.Block(
                                ReferenceArgAssign(callArgs, args),
                                Expression.Empty()
                            ),
                            fallbackResult.Expression,
                            typeof(void)
                        )
                    ),
                    GetRestrictions().Merge(fallbackResult.Restrictions)
                );

                //
                // Now, call fallback again using our new MO as the error
                // When we do this, one of two things can happen:
                //   1. Binding will succeed, and it will ignore our call to
                //      the dynamic method, OR
                //   2. Binding will fail, and it will use the MO we created
                //      above.
                //
                return fallback(callDynamic);
            }
 /// <summary>
 /// Helper method for generating a MetaObject which calls a
 /// specific method on Dynamic that returns a result
 /// </summary>
 private DynamicMetaObject CallMethodWithResult(string methodName, DynamicMetaObjectBinder binder, Expression[] args, Fallback fallback) {
     return CallMethodWithResult(methodName, binder, args, fallback, null);
 }
            /// <summary>
            /// Helper method for generating a MetaObject which calls a
            /// specific method on Dynamic that returns a result
            /// </summary>
            private DynamicMetaObject CallMethodWithResult(string methodName, DynamicMetaObjectBinder binder, Expression[] args, Fallback fallback, Fallback fallbackInvoke) {
                //
                // First, call fallback to do default binding
                // This produces either an error or a call to a .NET member
                //
                DynamicMetaObject fallbackResult = fallback(null);

                var callDynamic = BuildCallMethodWithResult(methodName, binder, args, fallbackResult, fallbackInvoke);
                
                //
                // Now, call fallback again using our new MO as the error
                // When we do this, one of two things can happen:
                //   1. Binding will succeed, and it will ignore our call to
                //      the dynamic method, OR
                //   2. Binding will fail, and it will use the MO we created
                //      above.
                //
                return fallback(callDynamic);
            }
 /// <summary>
 /// Helper method for generating arguments for calling methods
 /// on DynamicObject.  parameters is either a list of ParameterExpressions
 /// to be passed to the method as an object[], or NoArgs to signify that
 /// the target method takes no object[] parameter.
 /// </summary>
 private static Expression[] BuildCallArgs(DynamicMetaObjectBinder binder, Expression[] parameters, Expression arg0, Expression arg1) {
     if (!object.ReferenceEquals(parameters, NoArgs))
         return arg1 != null ? new Expression[] { Constant(binder), arg0, arg1 } : new Expression[] { Constant(binder), arg0 };
     else
         return arg1 != null ? new Expression[] { Constant(binder), arg1 } : new Expression[] { Constant(binder) };
 }
 private static ConstantExpression Constant(DynamicMetaObjectBinder binder) {
     Type t = binder.GetType();
     while (!t.IsVisible) {
         t = t.BaseType;
     }
     return Expression.Constant(binder, t);
 }
Example #26
0
        internal DynamicMetaObject/*!*/ CreateMetaObject(DynamicMetaObjectBinder/*!*/ binder, Type/*!*/ returnType) {
            Debug.Assert(ControlFlowBuilder == null, "Control flow required but not built");

            var restrictions = _restrictions;
            var expr = _error ? Ast.Throw(_result, returnType) : AstUtils.Convert(_result, returnType);

            if (_condition != null) {
                var deferral = binder.GetUpdateExpression(returnType);
                expr = Ast.Condition(_condition, expr, deferral);
            }

            if (_temps != null || _initializations != null) {
                AddInitialization(expr);
                if (_temps != null) {
                    expr = Ast.Block(_temps, _initializations);
                } else {
                    expr = Ast.Block(_initializations);
                }
            }

            Clear();
            RubyBinder.DumpRule(binder, restrictions, expr);
            return new DynamicMetaObject(expr, restrictions);
        }
Example #27
0
 internal DynamicMetaObject/*!*/ CreateMetaObject(DynamicMetaObjectBinder/*!*/ action) {
     return CreateMetaObject(action, action.ReturnType);
 }
        internal static DynamicMetaObject FallbackWorker(DynamicMetaObject/*!*/ self, Expression/*!*/ codeContext, string name, GetMemberOptions options, DynamicMetaObjectBinder action) {
            if (self.NeedsDeferral()) {
                return action.Defer(self);
            }

            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 = BinderState.GetBinderState(action).Binder.GetMember(
                        name,
                        self,
                        codeContext,
                        isNoThrow
                    );
                    Expression failure = GetFailureExpression(limitType, 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"),
                                Ast.Constant("{0} instance has no attribute '{1}'"),
                                Ast.NewArrayInit(
                                    typeof(object),
                                    Ast.Constant(((OldInstance)self.Value)._class._name),
                                    Ast.Constant(name)
                                )
                            )
                        ),
                        self.Restrictions.Merge(BindingRestrictionsHelpers.GetRuntimeTypeRestriction(self.Expression, typeof(OldInstance)))
                    );
                }
            }

            var res = BinderState.GetBinderState(action).Binder.GetMember(name, self, codeContext, isNoThrow);

            // 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 == typeof(bool) || res.Expression.Type == typeof(int)) {
                res = new DynamicMetaObject(
                    AstUtils.Convert(res.Expression, typeof(object)),
                    res.Restrictions
                );
            }

            return res;
        }
 private static Expression/*!*/ GetFailureExpression(Type/*!*/ limitType, string name, bool isNoThrow, DynamicMetaObjectBinder action) {
     return isNoThrow ?
         Ast.Field(null, typeof(OperationFailed).GetField("Value")) :
         DefaultBinder.MakeError(
             BinderState.GetBinderState(action).Binder.MakeMissingMemberError(
                 limitType,
                 name
             )
         );
 }
Example #30
0
 public BinderMappingInfo(DynamicMetaObjectBinder binder, params ParameterMappingInfo[] mappingInfos)
     : this(binder, (IList<ParameterMappingInfo>)mappingInfos) {
 }