示例#1
0
        /////////////////////////////////////////////////////////////////////////////////

        private static Expression ConvertResult(Expression binding, ICSharpBinder action)
        {
            // Need to handle the following cases:
            //   (1) Call to a constructor: no conversions.
            //   (2) Call to a void-returning method: return null iff result is discarded.
            //   (3) Call to a value-type returning method: box to object.
            //
            // In all other cases, binding.Type should be equivalent or
            // reference assignable to resultType.

            // No conversions needed for , the call site has the correct type.
            if (action is CSharpInvokeConstructorBinder)
            {
                return(binding);
            }

            if (binding.Type == typeof(void))
            {
                if (action is ICSharpInvokeOrInvokeMemberBinder invoke && invoke.ResultDiscarded)
                {
                    Debug.Assert(action.ReturnType == typeof(object));
                    return(Expression.Block(binding, Expression.Default(action.ReturnType)));
                }

                throw Error.BindToVoidMethodButExpectResult();
            }

            if (binding.Type.IsValueType && !action.ReturnType.IsValueType)
            {
                Debug.Assert(action.ReturnType == typeof(object));
                return(Expression.Convert(binding, action.ReturnType));
            }

            return(binding);
        }
示例#2
0
        /////////////////////////////////////////////////////////////////////////////////

        private static Type GetTypeForErrorMetaObject(ICSharpBinder action, DynamicMetaObject[] args)
        {
            // This is similar to ConvertResult but has fewer things to worry about.

            if (action is CSharpInvokeConstructorBinder)
            {
                Debug.Assert(args != null);
                Debug.Assert(args.Length != 0);
                Debug.Assert(args[0].Value is Type);
                return(args[0].Value as Type);
            }

            return(action.ReturnType);
        }
示例#3
0
        public bool IsEquivalentTo(ICSharpBinder other)
        {
            var otherBinder = other as CSharpIsEventBinder;

            if (otherBinder == null)
            {
                return(false);
            }

            if (_callingContext != otherBinder._callingContext ||
                Name != otherBinder.Name)
            {
                return(false);
            }

            return(true);
        }
示例#4
0
        public bool IsEquivalentTo(ICSharpBinder other)
        {
            var otherBinder = other as CSharpGetIndexBinder;

            if (otherBinder == null)
            {
                return(false);
            }

            if (_callingContext != otherBinder._callingContext ||
                _argumentInfo.Length != otherBinder._argumentInfo.Length)
            {
                return(false);
            }

            return(BinderHelper.CompareArgInfos(_argumentInfo, otherBinder._argumentInfo));
        }
        public bool IsEquivalentTo(ICSharpBinder other)
        {
            var otherBinder = other as CSharpUnaryOperationBinder;

            if (otherBinder == null)
            {
                return(false);
            }

            if (Operation != otherBinder.Operation ||
                IsChecked != otherBinder.IsChecked ||
                _callingContext != otherBinder._callingContext)
            {
                return(false);
            }

            return(BinderHelper.CompareArgInfos(_argumentInfo, otherBinder._argumentInfo));
        }
示例#6
0
        public bool IsEquivalentTo(ICSharpBinder other)
        {
            var otherBinder = other as CSharpConvertBinder;

            if (otherBinder == null)
            {
                return(false);
            }

            if (ConversionKind != otherBinder.ConversionKind ||
                IsChecked != otherBinder.IsChecked ||
                _callingContext != otherBinder._callingContext ||
                Type != otherBinder.Type)
            {
                return(false);
            }

            return(true);
        }
示例#7
0
        public bool IsEquivalentTo(ICSharpBinder other)
        {
            var otherBinder = other as CSharpInvokeMemberBinder;

            if (otherBinder == null)
            {
                return(false);
            }

            if (Flags != otherBinder.Flags ||
                CallingContext != otherBinder.CallingContext ||
                Name != otherBinder.Name ||
                TypeArguments.Length != otherBinder.TypeArguments.Length ||
                _argumentInfo.Length != otherBinder._argumentInfo.Length)
            {
                return(false);
            }

            return(BinderHelper.CompareArgInfos(TypeArguments, otherBinder.TypeArguments, _argumentInfo, otherBinder._argumentInfo));
        }
示例#8
0
        public bool IsEquivalentTo(ICSharpBinder other)
        {
            var otherBinder = other as CSharpSetMemberBinder;

            if (otherBinder == null)
            {
                return(false);
            }

            if (Name != otherBinder.Name ||
                _callingContext != otherBinder._callingContext ||
                IsChecked != otherBinder.IsChecked ||
                IsCompoundAssignment != otherBinder.IsCompoundAssignment ||
                _argumentInfo.Length != otherBinder._argumentInfo.Length)
            {
                return(false);
            }

            return(BinderHelper.CompareArgInfos(_argumentInfo, otherBinder._argumentInfo));
        }
示例#9
0
        /////////////////////////////////////////////////////////////////////////////////

        private static bool IsIncrementOrDecrementActionOnLocal(ICSharpBinder action) =>
        action is CSharpUnaryOperationBinder operatorPayload &&
示例#10
0
        internal static DynamicMetaObject Bind(
            ICSharpBinder action,
            RuntimeBinder binder,
            DynamicMetaObject[] args,
            IEnumerable <CSharpArgumentInfo> arginfos,
            DynamicMetaObject onBindingError)
        {
            Expression[]        parameters   = new Expression[args.Length];
            BindingRestrictions restrictions = BindingRestrictions.Empty;
            ICSharpInvokeOrInvokeMemberBinder callPayload = action as ICSharpInvokeOrInvokeMemberBinder;
            ParameterExpression tempForIncrement          = null;
            IEnumerator <CSharpArgumentInfo> arginfosEnum = (arginfos ?? Array.Empty <CSharpArgumentInfo>()).GetEnumerator();

            for (int index = 0; index < args.Length; ++index)
            {
                DynamicMetaObject o = args[index];
                // Our contract with the DLR is such that we will not enter a bind unless we have
                // values for the meta-objects involved.

                Debug.Assert(o.HasValue);

                CSharpArgumentInfo info = arginfosEnum.MoveNext() ? arginfosEnum.Current : null;

                if (index == 0 && IsIncrementOrDecrementActionOnLocal(action))
                {
                    // We have an inc or a dec operation. Insert the temp local instead.
                    //
                    // We need to do this because for value types, the object will come
                    // in boxed, and we'd need to unbox it to get the original type in order
                    // to increment. The only way to do that is to create a new temporary.
                    object value = o.Value;
                    tempForIncrement = Expression.Variable(value != null ? value.GetType() : typeof(object), "t0");
                    parameters[0]    = tempForIncrement;
                }
                else
                {
                    parameters[index] = o.Expression;
                }

                BindingRestrictions r = DeduceArgumentRestriction(index, callPayload, o, info);
                restrictions = restrictions.Merge(r);

                // Here we check the argument info. If the argument info shows that the current argument
                // is a literal constant, then we also add an instance restriction on the value of
                // the constant.
                if (info != null && info.LiteralConstant)
                {
                    if (o.Value is double && double.IsNaN((double)o.Value))
                    {
                        MethodInfo isNaN = s_DoubleIsNaN ?? (s_DoubleIsNaN = typeof(double).GetMethod("IsNaN"));
                        Expression e     = Expression.Call(null, isNaN, o.Expression);
                        restrictions = restrictions.Merge(BindingRestrictions.GetExpressionRestriction(e));
                    }
                    else if (o.Value is float && float.IsNaN((float)o.Value))
                    {
                        MethodInfo isNaN = s_SingleIsNaN ?? (s_SingleIsNaN = typeof(float).GetMethod("IsNaN"));
                        Expression e     = Expression.Call(null, isNaN, o.Expression);
                        restrictions = restrictions.Merge(BindingRestrictions.GetExpressionRestriction(e));
                    }
                    else
                    {
                        Expression e = Expression.Equal(o.Expression, Expression.Constant(o.Value, o.Expression.Type));
                        r            = BindingRestrictions.GetExpressionRestriction(e);
                        restrictions = restrictions.Merge(r);
                    }
                }
            }

            // Get the bound expression.
            try
            {
                Expression expression = binder.Bind(action, parameters, args, out DynamicMetaObject deferredBinding);

                if (deferredBinding != null)
                {
                    expression   = ConvertResult(deferredBinding.Expression, action);
                    restrictions = deferredBinding.Restrictions.Merge(restrictions);
                    return(new DynamicMetaObject(expression, restrictions));
                }

                if (tempForIncrement != null)
                {
                    // If we have a ++ or -- payload, we need to do some temp rewriting.
                    // We rewrite to the following:
                    //
                    // temp = (type)o;
                    // temp++;
                    // o = temp;
                    // return o;

                    DynamicMetaObject arg0 = args[0];

                    expression = Expression.Block(
                        new[] { tempForIncrement },
                        Expression.Assign(tempForIncrement, Expression.Convert(arg0.Expression, arg0.Value.GetType())),
                        expression,
                        Expression.Assign(arg0.Expression, Expression.Convert(tempForIncrement, arg0.Expression.Type)));
                }

                expression = ConvertResult(expression, action);

                return(new DynamicMetaObject(expression, restrictions));
            }
            catch (RuntimeBinderException e)
            {
                if (onBindingError != null)
                {
                    return(onBindingError);
                }

                return(new DynamicMetaObject(
                           Expression.Throw(
                               Expression.New(
                                   typeof(RuntimeBinderException).GetConstructor(new Type[] { typeof(string) }),
                                   Expression.Constant(e.Message)
                                   ),
                               GetTypeForErrorMetaObject(action, args)
                               ),
                           restrictions
                           ));
            }
        }