internal AssignBinaryDynamicCSharpExpression(Type context, CSharpBinderFlags binderFlags, CSharpExpressionType binaryType, DynamicCSharpArgument left, DynamicCSharpArgument right)
     : base(context, binderFlags)
 {
     OperationNodeType = binaryType;
     Left = left;
     Right = right;
 }
Example #2
0
        private static AssignUnaryCSharpExpression MakeUnaryAssignCore(CSharpExpressionType unaryType, Expression operand, MethodInfo method)
        {
            RequiresCanRead(operand, nameof(operand));
            Helpers.RequiresCanWrite(operand, nameof(operand));

            return(AssignUnaryCSharpExpression.Make(unaryType, operand, method));
        }
 internal WithConversions(CSharpExpressionType binaryType, Expression left, Expression right, MethodInfo method, LambdaExpression leftConversion, LambdaExpression finalConversion)
     : base(binaryType, left, right)
 {
     Method          = method;
     LeftConversion  = leftConversion;
     FinalConversion = finalConversion;
 }
Example #4
0
 internal EventAssignCSharpExpression(CSharpExpressionType type, Expression @object, EventInfo @event, Expression handler)
 {
     CSharpNodeType = type;
     Object         = @object;
     Event          = @event;
     Handler        = handler;
 }
 internal AssignBinaryDynamicCSharpExpression(Type context, CSharpBinderFlags binderFlags, CSharpExpressionType binaryType, DynamicCSharpArgument left, DynamicCSharpArgument right)
     : base(context, binderFlags)
 {
     OperationNodeType = binaryType;
     Left  = left;
     Right = right;
 }
Example #6
0
        /// <summary>
        /// Creates an expression representing a unary assignment operation.
        /// </summary>
        /// <param name="unaryType">The type of assignment represented.</param>
        /// <param name="operand">The operand of the assignment operation, i.e. the assignment target.</param>
        /// <param name="method">The method implementing the assignment operation.</param>
        /// <returns>A new <see cref="AssignUnaryCSharpExpression"/> instance representing the unary assignment.</returns>
        public static AssignUnaryCSharpExpression MakeUnaryAssign(CSharpExpressionType unaryType, Expression operand, MethodInfo method)
        {
            switch (unaryType)
            {
            case CSharpExpressionType.PreIncrementAssign:
                return(PreIncrementAssign(operand, method));

            case CSharpExpressionType.PreIncrementAssignChecked:
                return(PreIncrementAssignChecked(operand, method));

            case CSharpExpressionType.PreDecrementAssign:
                return(PreDecrementAssign(operand, method));

            case CSharpExpressionType.PreDecrementAssignChecked:
                return(PreDecrementAssignChecked(operand, method));

            case CSharpExpressionType.PostIncrementAssign:
                return(PostIncrementAssign(operand, method));

            case CSharpExpressionType.PostIncrementAssignChecked:
                return(PostIncrementAssignChecked(operand, method));

            case CSharpExpressionType.PostDecrementAssign:
                return(PostDecrementAssign(operand, method));

            case CSharpExpressionType.PostDecrementAssignChecked:
                return(PostDecrementAssignChecked(operand, method));
            }

            throw LinqError.UnhandledUnary(unaryType);
        }
Example #7
0
        private static void ValidateCustomUnaryAssign(CSharpExpressionType unaryType, Expression operand, ref MethodInfo method)
        {
            var operandType = operand.Type;

            // NB: Just leverage LINQ to do the dirty work to check everything.This could produce mysterious error
            //     messages. (TODO: Review what's most appropriate here.)

            var resultType = operandType;

            if (!IsCSharpSpecificUnaryAssignNumeric(operandType))
            {
                var operandDummy = Expression.Parameter(operandType, "__operand");
                var functionalOp = FunctionalOp(unaryType, operandDummy, method);

                if (method == null)
                {
                    method = functionalOp.Method;
                }

                resultType = functionalOp.Type;
            }

            if (!TypeUtils.AreEquivalent(resultType, operand.Type))
            {
                throw Error.InvalidUnaryAssignmentWithOperands(unaryType, operand.Type);
            }
        }
Example #8
0
        internal static AssignUnaryCSharpExpression Make(CSharpExpressionType unaryType, Expression operand, MethodInfo method)
        {
            ValidateCustomUnaryAssign(unaryType, operand, ref method);

            // TODO: Add optimized layouts

            return(new Custom(unaryType, operand, method));
        }
        internal static AssignBinaryCSharpExpression Make(CSharpExpressionType binaryType, Expression left, Expression right, MethodInfo method, LambdaExpression leftConversion, LambdaExpression finalConversion)
        {
            ValidateCustomBinaryAssign(binaryType, left, right, ref method, leftConversion, finalConversion);

            // TODO: Add optimized layouts

            return(new WithConversions(binaryType, left, right, method, leftConversion, finalConversion));
        }
        private static bool IsCheckedBinary(CSharpExpressionType type)
        {
            switch (type)
            {
            case CSharpExpressionType.AddAssignChecked:
            case CSharpExpressionType.MultiplyAssignChecked:
            case CSharpExpressionType.SubtractAssignChecked:
                return(true);
            }

            return(false);
        }
        /// <summary>
        /// Creates an expression representing a binary assignment operation.
        /// </summary>
        /// <param name="binaryType">The type of assignment represented.</param>
        /// <param name="left">The left operand of the assignment operation, i.e. the assignment target.</param>
        /// <param name="right">The right operation of the assignment operation.</param>
        /// <param name="method">The method implementing the assignment operation.</param>
        /// <param name="leftConversion">The conversion function used to convert the left hand side of the compound assignment prior to use by the underlying operation.</param>
        /// <param name="finalConversion">The conversion function used to convert the result of the underlying operation prior to assignment to the left hand side of the compound assignment operation.</param>
        /// <returns>A new <see cref="AssignBinaryCSharpExpression"/> instance representing the binary assignment.</returns>
        public static AssignBinaryCSharpExpression MakeBinaryAssign(CSharpExpressionType binaryType, Expression left, Expression right, MethodInfo method, LambdaExpression leftConversion, LambdaExpression finalConversion)
        {
            switch (binaryType)
            {
            case CSharpExpressionType.Assign:
                return(Assign(left, right));

            case CSharpExpressionType.AddAssign:
                return(AddAssign(left, right, method, leftConversion, finalConversion));

            case CSharpExpressionType.AndAssign:
                return(AndAssign(left, right, method, leftConversion, finalConversion));

            case CSharpExpressionType.DivideAssign:
                return(DivideAssign(left, right, method, leftConversion, finalConversion));

            case CSharpExpressionType.ExclusiveOrAssign:
                return(ExclusiveOrAssign(left, right, method, leftConversion, finalConversion));

            case CSharpExpressionType.LeftShiftAssign:
                return(LeftShiftAssign(left, right, method, leftConversion, finalConversion));

            case CSharpExpressionType.ModuloAssign:
                return(ModuloAssign(left, right, method, leftConversion, finalConversion));

            case CSharpExpressionType.MultiplyAssign:
                return(MultiplyAssign(left, right, method, leftConversion, finalConversion));

            case CSharpExpressionType.OrAssign:
                return(OrAssign(left, right, method, leftConversion, finalConversion));

            case CSharpExpressionType.RightShiftAssign:
                return(RightShiftAssign(left, right, method, leftConversion, finalConversion));

            case CSharpExpressionType.SubtractAssign:
                return(SubtractAssign(left, right, method, leftConversion, finalConversion));

            case CSharpExpressionType.AddAssignChecked:
                return(AddAssignChecked(left, right, method, leftConversion, finalConversion));

            case CSharpExpressionType.MultiplyAssignChecked:
                return(MultiplyAssignChecked(left, right, method, leftConversion, finalConversion));

            case CSharpExpressionType.SubtractAssignChecked:
                return(SubtractAssignChecked(left, right, method, leftConversion, finalConversion));
            }

            throw LinqError.UnhandledBinary(binaryType);
        }
        internal static BinaryExpression FunctionalOp(CSharpExpressionType binaryType, Expression left, Expression right, MethodInfo method)
        {
            switch (binaryType)
            {
            case CSharpExpressionType.Assign:
                return(Expression.Assign(left, right));

            case CSharpExpressionType.AddAssign:
                return(Expression.Add(left, right, method));

            case CSharpExpressionType.AndAssign:
                return(Expression.And(left, right, method));

            case CSharpExpressionType.DivideAssign:
                return(Expression.Divide(left, right, method));

            case CSharpExpressionType.ExclusiveOrAssign:
                return(Expression.ExclusiveOr(left, right, method));

            case CSharpExpressionType.LeftShiftAssign:
                return(Expression.LeftShift(left, right, method));

            case CSharpExpressionType.ModuloAssign:
                return(Expression.Modulo(left, right, method));

            case CSharpExpressionType.MultiplyAssign:
                return(Expression.Multiply(left, right, method));

            case CSharpExpressionType.OrAssign:
                return(Expression.Or(left, right, method));

            case CSharpExpressionType.RightShiftAssign:
                return(Expression.RightShift(left, right, method));

            case CSharpExpressionType.SubtractAssign:
                return(Expression.Subtract(left, right, method));

            case CSharpExpressionType.AddAssignChecked:
                return(Expression.AddChecked(left, right, method));

            case CSharpExpressionType.MultiplyAssignChecked:
                return(Expression.MultiplyChecked(left, right, method));

            case CSharpExpressionType.SubtractAssignChecked:
                return(Expression.SubtractChecked(left, right, method));
            }

            throw LinqError.UnhandledBinary(binaryType);
        }
		private static ExpressionType ConvertNodeType(CSharpExpressionType nodeType)
        {
			switch (nodeType)
			{
				case CSharpExpressionType.PreIncrementAssign: return ExpressionType.PreIncrementAssign;
				case CSharpExpressionType.PreIncrementAssignChecked: return ExpressionType.PreIncrementAssign;
				case CSharpExpressionType.PreDecrementAssign: return ExpressionType.PreDecrementAssign;
				case CSharpExpressionType.PreDecrementAssignChecked: return ExpressionType.PreDecrementAssign;
				case CSharpExpressionType.PostIncrementAssign: return ExpressionType.PostIncrementAssign;
				case CSharpExpressionType.PostIncrementAssignChecked: return ExpressionType.PostIncrementAssign;
				case CSharpExpressionType.PostDecrementAssign: return ExpressionType.PostDecrementAssign;
				case CSharpExpressionType.PostDecrementAssignChecked: return ExpressionType.PostDecrementAssign;
				default:
					throw ContractUtils.Unreachable;
			}
        }
        private static Type ValidateConversion(CSharpExpressionType nodeType, Type inputType, LambdaExpression conversion)
        {
            var invoke = conversion.Type.GetMethod("Invoke");

            var invokeParameters = invoke.GetParametersCached();

            if (invokeParameters.Length != 1)
            {
                throw LinqError.IncorrectNumberOfMethodCallArguments(conversion);
            }

            if (!TypeUtils.AreEquivalent(invokeParameters[0].ParameterType, inputType))
            {
                throw LinqError.OperandTypesDoNotMatchParameters(nodeType, conversion.ToString());
            }

            return(invoke.ReturnType);
        }
        public static AssignBinaryDynamicCSharpExpression MakeDynamicBinaryAssign(CSharpExpressionType binaryType, DynamicCSharpArgument left, DynamicCSharpArgument right, CSharpBinderFlags binderFlags, Type context)
        {
            ContractUtils.RequiresNotNull(left, nameof(left));
            ContractUtils.RequiresNotNull(right, nameof(right));

            RequiresCanWrite(left.Expression, nameof(left));
            RequiresCanRead(right.Expression, nameof(right));

            CheckBinaryAssign(binaryType);

            switch (binaryType)
            {
            case CSharpExpressionType.AddAssignChecked:
            case CSharpExpressionType.SubtractAssignChecked:
            case CSharpExpressionType.MultiplyAssignChecked:
                binderFlags |= CSharpBinderFlags.CheckedContext;
                break;
            }

            return(new AssignBinaryDynamicCSharpExpression(context, binderFlags, binaryType, left, right));
        }
Example #16
0
        public static AssignUnaryDynamicCSharpExpression MakeDynamicUnaryAssign(CSharpExpressionType unaryType, DynamicCSharpArgument operand, CSharpBinderFlags binderFlags, Type context)
        {
            RequiresNotNull(operand, nameof(operand));

            RequiresCanRead(operand.Expression, nameof(operand));
            RequiresCanWrite(operand.Expression, nameof(operand));

            CheckUnaryAssign(unaryType);

            switch (unaryType)
            {
            case CSharpExpressionType.PreIncrementAssignChecked:
            case CSharpExpressionType.PreDecrementAssignChecked:
            case CSharpExpressionType.PostIncrementAssignChecked:
            case CSharpExpressionType.PostDecrementAssignChecked:
                binderFlags |= CSharpBinderFlags.CheckedContext;
                break;
            }

            return(new AssignUnaryDynamicCSharpExpression(context, binderFlags, unaryType, operand));
        }
        private static void ValidateCustomBinaryAssign(CSharpExpressionType binaryType, Expression left, Expression right, ref MethodInfo method, LambdaExpression leftConversion, LambdaExpression finalConversion)
        {
            var leftType  = left.Type;
            var rightType = right.Type;

            if (leftConversion != null)
            {
                leftType = ValidateConversion(binaryType, leftType, leftConversion);
            }

            // NB: Just leverage LINQ to do the dirty work to check everything. Note that this assumes that the
            //     left conversion performed widening if that's required for the underlying operation. However,
            //     the use of FunctionalOp below will widen the right operand to match the left operand's type,
            //     which is what we do during Reduce as well (see remarks in FunctionalOp). This could produce
            //     mysterious error messages. (TODO: Review what's most appropriate here.)
            //
            // NB: We can't have it check the final conversion, because it doesn't allow these without the use of
            //     a custom method, so we check that ourselves further down.

            var leftDummy    = Expression.Parameter(leftType, "__left");
            var rightDummy   = Expression.Parameter(rightType, "__right");
            var functionalOp = FunctionalOp(binaryType, leftDummy, rightDummy, method);

            if (method == null)
            {
                method = functionalOp.Method;
            }

            var resultType = functionalOp.Type;

            if (finalConversion != null)
            {
                resultType = ValidateConversion(binaryType, resultType, finalConversion);
            }

            if (!TypeUtils.AreEquivalent(resultType, left.Type))
            {
                throw Error.InvalidCompoundAssignmentWithOperands(binaryType, left.Type, right.Type);
            }
        }
Example #18
0
        private static UnaryExpression FunctionalOp(CSharpExpressionType unaryType, Expression operand, MethodInfo method)
        {
            switch (unaryType)
            {
            case CSharpExpressionType.PreDecrementAssign:
            case CSharpExpressionType.PreDecrementAssignChecked:
                return(Expression.PreDecrementAssign(operand, method));

            case CSharpExpressionType.PreIncrementAssign:
            case CSharpExpressionType.PreIncrementAssignChecked:
                return(Expression.PreIncrementAssign(operand, method));

            case CSharpExpressionType.PostDecrementAssign:
            case CSharpExpressionType.PostDecrementAssignChecked:
                return(Expression.PostDecrementAssign(operand, method));

            case CSharpExpressionType.PostIncrementAssign:
            case CSharpExpressionType.PostIncrementAssignChecked:
                return(Expression.PostIncrementAssign(operand, method));
            }

            throw LinqError.UnhandledUnary(unaryType);
        }
		private static ExpressionType ConvertNodeType(CSharpExpressionType nodeType)
        {
            // NB: Only used for ToCSharp pretty printing; maybe we can remove it?

			switch (nodeType)
			{
				case CSharpExpressionType.Assign: return ExpressionType.Assign;
				case CSharpExpressionType.AddAssign: return ExpressionType.AddAssign;
				case CSharpExpressionType.SubtractAssign: return ExpressionType.SubtractAssign;
				case CSharpExpressionType.MultiplyAssign: return ExpressionType.MultiplyAssign;
				case CSharpExpressionType.DivideAssign: return ExpressionType.DivideAssign;
				case CSharpExpressionType.ModuloAssign: return ExpressionType.ModuloAssign;
				case CSharpExpressionType.AndAssign: return ExpressionType.AndAssign;
				case CSharpExpressionType.OrAssign: return ExpressionType.OrAssign;
				case CSharpExpressionType.ExclusiveOrAssign: return ExpressionType.ExclusiveOrAssign;
				case CSharpExpressionType.LeftShiftAssign: return ExpressionType.LeftShiftAssign;
				case CSharpExpressionType.RightShiftAssign: return ExpressionType.RightShiftAssign;
				case CSharpExpressionType.AddAssignChecked: return ExpressionType.AddAssignChecked;
				case CSharpExpressionType.MultiplyAssignChecked: return ExpressionType.MultiplyAssignChecked;
				case CSharpExpressionType.SubtractAssignChecked: return ExpressionType.SubtractAssignChecked;
				default:
					throw ContractUtils.Unreachable;
			}
        }
        private static ExpressionType ConvertNodeType(CSharpExpressionType nodeType)
        {
            switch (nodeType)
            {
            case CSharpExpressionType.PreIncrementAssign: return(ExpressionType.PreIncrementAssign);

            case CSharpExpressionType.PreIncrementAssignChecked: return(ExpressionType.PreIncrementAssign);

            case CSharpExpressionType.PreDecrementAssign: return(ExpressionType.PreDecrementAssign);

            case CSharpExpressionType.PreDecrementAssignChecked: return(ExpressionType.PreDecrementAssign);

            case CSharpExpressionType.PostIncrementAssign: return(ExpressionType.PostIncrementAssign);

            case CSharpExpressionType.PostIncrementAssignChecked: return(ExpressionType.PostIncrementAssign);

            case CSharpExpressionType.PostDecrementAssign: return(ExpressionType.PostDecrementAssign);

            case CSharpExpressionType.PostDecrementAssignChecked: return(ExpressionType.PostDecrementAssign);

            default:
                throw ContractUtils.Unreachable;
            }
        }
        private static UnaryExpression FunctionalOp(CSharpExpressionType unaryType, Expression operand, MethodInfo method)
        {
            switch (unaryType)
            {
                case CSharpExpressionType.PreDecrementAssign:
                case CSharpExpressionType.PreDecrementAssignChecked:
                    return Expression.PreDecrementAssign(operand, method);
                case CSharpExpressionType.PreIncrementAssign:
                case CSharpExpressionType.PreIncrementAssignChecked:
                    return Expression.PreIncrementAssign(operand, method);
                case CSharpExpressionType.PostDecrementAssign:
                case CSharpExpressionType.PostDecrementAssignChecked:
                    return Expression.PostDecrementAssign(operand, method);
                case CSharpExpressionType.PostIncrementAssign:
                case CSharpExpressionType.PostIncrementAssignChecked:
                    return Expression.PostIncrementAssign(operand, method);
            }

            throw LinqError.UnhandledUnary(unaryType);
        }
Example #22
0
 /// <summary>
 /// Creates an expression representing an event assignment operation.
 /// </summary>
 /// <param name="type">The type of assignment represented.</param>
 /// <param name="object">The instance on which to access the event, or <c>null</c> if the event is static.</param>
 /// <param name="event">The event to add or remove a handler on.</param>
 /// <param name="handler">The handler to add to or remove from the event.</param>
 /// <returns>A new <see cref="EventAssignCSharpExpression"/> instance representing the event assignment.</returns>
 public static EventAssignCSharpExpression MakeEventAssign(CSharpExpressionType type, Expression @object, EventInfo @event, Expression handler) =>
 type switch
 {
 /// <summary>
 /// Creates a new expression representing a dynamically bound binary assignment operation with the specified binder flags.
 /// </summary>
 /// <param name="binaryType">The type of the binary operation to perform.</param>
 /// <param name="left">The dynamic argument representing the left operand of the operation.</param>
 /// <param name="right">The dynamic argument representing the right operand of the operation.</param>
 /// <param name="binderFlags">The binder flags to use for the dynamic operation.</param>
 /// <returns>A new expression representing a dynamically bound binary operation.</returns>
 public static AssignBinaryDynamicCSharpExpression MakeDynamicBinaryAssign(CSharpExpressionType binaryType, DynamicCSharpArgument left, DynamicCSharpArgument right, CSharpBinderFlags binderFlags)
 {
     return MakeDynamicBinaryAssign(binaryType, left, right, binderFlags, null);
 }
        /// <summary>
        /// Creates an expression representing a unary assignment operation.
        /// </summary>
        /// <param name="unaryType">The type of assignment represented.</param>
        /// <param name="operand">The operand of the assignment operation, i.e. the assignment target.</param>
        /// <param name="method">The method implementing the assignment operation.</param>
        /// <returns>A new <see cref="AssignUnaryCSharpExpression"/> instance representing the unary assignment.</returns>
        public static AssignUnaryCSharpExpression MakeUnaryAssign(CSharpExpressionType unaryType, Expression operand, MethodInfo method)
        {
            switch (unaryType)
            {
                case CSharpExpressionType.PreIncrementAssign:
                    return PreIncrementAssign(operand, method);
                case CSharpExpressionType.PreIncrementAssignChecked:
                    return PreIncrementAssignChecked(operand, method);
                case CSharpExpressionType.PreDecrementAssign:
                    return PreDecrementAssign(operand, method);
                case CSharpExpressionType.PreDecrementAssignChecked:
                    return PreDecrementAssignChecked(operand, method);
                case CSharpExpressionType.PostIncrementAssign:
                    return PostIncrementAssign(operand, method);
                case CSharpExpressionType.PostIncrementAssignChecked:
                    return PostIncrementAssignChecked(operand, method);
                case CSharpExpressionType.PostDecrementAssign:
                    return PostDecrementAssign(operand, method);
                case CSharpExpressionType.PostDecrementAssignChecked:
                    return PostDecrementAssignChecked(operand, method);
            }

            throw LinqError.UnhandledUnary(unaryType);
        }
Example #25
0
 /// <summary>
 /// Creates a new expression representing a dynamically bound unary assignment operation with the specified binder flags.
 /// </summary>
 /// <param name="unaryType">The type of the unary operation to perform.</param>
 /// <param name="operand">The dynamic argument representing the operand of the operation.</param>
 /// <param name="binderFlags">The binder flags to use for the dynamic operation.</param>
 /// <returns>A new expression representing a dynamically bound unary assignment operation.</returns>
 public static AssignUnaryDynamicCSharpExpression MakeDynamicUnaryAssign(CSharpExpressionType unaryType, DynamicCSharpArgument operand, CSharpBinderFlags binderFlags)
 {
     return(MakeDynamicUnaryAssign(unaryType, operand, binderFlags, null));
 }
        private static AssignUnaryCSharpExpression MakeUnaryAssignCore(CSharpExpressionType unaryType, Expression operand, MethodInfo method)
        {
            RequiresCanRead(operand, nameof(operand));
            Helpers.RequiresCanWrite(operand, nameof(operand));

            return AssignUnaryCSharpExpression.Make(unaryType, operand, method);
        }
        private static AssignBinaryCSharpExpression MakeBinaryAssignCore(CSharpExpressionType binaryType, Expression left, Expression right, MethodInfo method, LambdaExpression finalConversion, LambdaExpression leftConversion)
        {
            Helpers.RequiresCanWrite(left, nameof(left));
            RequiresCanRead(right, nameof(right));

            // NB: We could return a BinaryExpression in case the lhs is not one of our index nodes, but it'd change
            //     the return type to Expression which isn't nice to consume. Also, the Update method would either
            //     have to change to return Expression or we should have an AssignBinary node to hold a Binary node
            //     underneath it. This said, a specialized layout for the case where the custom node trivially wraps
            //     a LINQ node could be useful (just make Left virtual).

            if (binaryType != CSharpExpressionType.Assign)
            {
                var leftType = left.Type;
                var rightType = right.Type;

                if (leftType == typeof(string))
                {
                    if (method == null)
                    {
                        if (binaryType == CSharpExpressionType.AddAssign || binaryType == CSharpExpressionType.AddAssignChecked)
                        {
                            if (rightType == typeof(string))
                            {
                                method = typeof(string).GetMethod(nameof(string.Concat), new[] { typeof(string), typeof(string) });
                            }
                            else
                            {
                                method = typeof(string).GetMethod(nameof(string.Concat), new[] { typeof(string), typeof(object) });

                                if (!TypeUtils.AreReferenceAssignable(typeof(object), rightType))
                                {
                                    // DESIGN: Should our factory do this our just reject the input?
                                    right = Expression.Convert(right, typeof(object));
                                }
                            }
                        }
                        else
                        {
                            throw Error.InvalidCompoundAssignment(binaryType, typeof(string));
                        }
                    }
                }
                else if (typeof(MulticastDelegate).IsAssignableFrom(leftType))
                {
                    if (leftType == typeof(MulticastDelegate))
                    {
                        throw Error.InvalidCompoundAssignmentWithOperands(binaryType, leftType, rightType);
                    }

                    // NB: This checks for assignment with variance checks in mind, e.g.
                    //
                    //       Action<string> s = ...;
                    //       Action<object> o = ...;
                    //       s += o;

                    if (!TypeUtils.AreReferenceAssignable(leftType, rightType))
                    {
                        throw Error.InvalidCompoundAssignmentWithOperands(binaryType, leftType, rightType);
                    }

                    if (method == null)
                    {
                        if (binaryType == CSharpExpressionType.AddAssign || binaryType == CSharpExpressionType.AddAssignChecked)
                        {
                            method = typeof(Delegate).GetMethod(nameof(Delegate.Combine), new[] { typeof(Delegate), typeof(Delegate) });
                        }
                        else if (binaryType == CSharpExpressionType.SubtractAssign || binaryType == CSharpExpressionType.SubtractAssignChecked)
                        {
                            method = typeof(Delegate).GetMethod(nameof(Delegate.Remove), new[] { typeof(Delegate), typeof(Delegate) });
                        }
                        else
                        {
                            throw Error.InvalidCompoundAssignment(binaryType, leftType);
                        }

                        if (finalConversion == null)
                        {
                            var resultParameter = Expression.Parameter(typeof(Delegate), "__result");
                            var convertResult = Expression.Convert(resultParameter, leftType);
                            finalConversion = Expression.Lambda(convertResult, resultParameter);
                        }
                    }
                }
                else if (IsCSharpSpecificCompoundNumeric(leftType))
                {
                    // NB: If any of these are passed, we'll assume the types all line up. The call to
                    //     the ValidateCustomBinaryAssign method below will check that's indeed the case.

                    if (method == null && leftConversion == null && finalConversion == null)
                    {
                        var isChecked = IsCheckedBinary(binaryType);

                        var isNullabeLeftType = leftType.IsNullableType();
                        var nonNullLeftType = leftType.GetNonNullableType();
                        var intermediateType = nonNullLeftType.IsEnum ? nonNullLeftType.GetEnumUnderlyingType() : typeof(int);

                        var leftParameter = Expression.Parameter(leftType, "__left");
                        var convertType = isNullabeLeftType ? typeof(Nullable<>).MakeGenericType(intermediateType) : intermediateType;
                        var convertLeft = isChecked ? Expression.ConvertChecked(leftParameter, convertType) : Expression.Convert(leftParameter, convertType);
                        leftConversion = Expression.Lambda(convertLeft, leftParameter);

                        var resultParameter = Expression.Parameter(convertType, "__result");
                        var convertResult = isChecked ? Expression.ConvertChecked(resultParameter, leftType) : Expression.Convert(resultParameter, leftType);
                        finalConversion = Expression.Lambda(convertResult, resultParameter);

                        if (rightType != convertType)
                        {
                            // DESIGN: Should our factory do this our just reject the input? On the one hand,
                            //         C# allows e.g. byte += byte, so if this is a C#-specific API it may be
                            //         reasonable for the user to expect such a tree can be built. On the
                            //         other hand, it's very unlike the expression tree API to insert nodes
                            //         on behalf of the user in the factories. Note that Roslyn often models
                            //         conversions as properties on a node using a `Conversion` objects
                            //         which would be handy to keep the shape from the tree isomorphic to the
                            //         bound nodes in the compiler. Note though that the RHS of a compound
                            //         assignment doesn't have such a conversion and the compiler will insert
                            //         a convert node in this case, so this is really just a convenience in
                            //         our factory method to mimic that behavior.
                            right = Expression.Convert(right, convertType);
                        }
                    }
                }
            }

            return AssignBinaryCSharpExpression.Make(binaryType, left, right, method, leftConversion, finalConversion);
        }
        private static void ValidateCustomBinaryAssign(CSharpExpressionType binaryType, Expression left, Expression right, ref MethodInfo method, LambdaExpression leftConversion, LambdaExpression finalConversion)
        {
            var leftType = left.Type;
            var rightType = right.Type;

            if (leftConversion != null)
            {
                leftType = ValidateConversion(binaryType, leftType, leftConversion);
            }

            // NB: Just leverage LINQ to do the dirty work to check everything. Note that this assumes that the
            //     left conversion performed widening if that's required for the underlying operation. However,
            //     the use of FunctionalOp below will widen the right operand to match the left operand's type,
            //     which is what we do during Reduce as well (see remarks in FunctionalOp). This could produce
            //     mysterious error messages. (TODO: Review what's most appropriate here.)
            //
            // NB: We can't have it check the final conversion, because it doesn't allow these without the use of
            //     a custom method, so we check that ourselves further down.

            var leftDummy = Expression.Parameter(leftType, "__left");
            var rightDummy = Expression.Parameter(rightType, "__right");
            var functionalOp = FunctionalOp(binaryType, leftDummy, rightDummy, method);

            if (method == null)
            {
                method = functionalOp.Method;
            }

            var resultType = functionalOp.Type;

            if (finalConversion != null)
            {
                resultType = ValidateConversion(binaryType, resultType, finalConversion);
            }

            if (!TypeUtils.AreEquivalent(resultType, left.Type))
            {
                throw Error.InvalidCompoundAssignmentWithOperands(binaryType, left.Type, right.Type);
            }
        }
 private AssignBinaryCSharpExpression(CSharpExpressionType binaryType, Expression left, Expression right)
     : base(left, right)
 {
     CSharpNodeType = binaryType;
 }
        private static Type ValidateConversion(CSharpExpressionType nodeType, Type inputType, LambdaExpression conversion)
        {
            var invoke = conversion.Type.GetMethod("Invoke");

            var invokeParameters = invoke.GetParametersCached();
            if (invokeParameters.Length != 1)
            {
                throw LinqError.IncorrectNumberOfMethodCallArguments(conversion);
            }

            if (!TypeUtils.AreEquivalent(invokeParameters[0].ParameterType, inputType))
            {
                throw LinqError.OperandTypesDoNotMatchParameters(nodeType, conversion.ToString());
            }

            return invoke.ReturnType;
        }
Example #31
0
 public Custom(CSharpExpressionType unaryType, Expression operand, MethodInfo method)
     : base(unaryType, operand)
 {
     Method = method;
 }
 internal WithConversions(CSharpExpressionType binaryType, Expression left, Expression right, MethodInfo method, LambdaExpression leftConversion, LambdaExpression finalConversion)
     : base(binaryType, left, right)
 {
     Method = method;
     LeftConversion = leftConversion;
     FinalConversion = finalConversion;
 }
        /// <summary>
        /// Creates an expression representing a binary assignment operation.
        /// </summary>
        /// <param name="binaryType">The type of assignment represented.</param>
        /// <param name="left">The left operand of the assignment operation, i.e. the assignment target.</param>
        /// <param name="right">The right operation of the assignment operation.</param>
        /// <param name="method">The method implementing the assignment operation.</param>
        /// <param name="leftConversion">The conversion function used to convert the left hand side of the compound assignment prior to use by the underlying operation.</param>
        /// <param name="finalConversion">The conversion function used to convert the result of the underlying operation prior to assignment to the left hand side of the compound assignment operation.</param>
        /// <returns>A new <see cref="AssignBinaryCSharpExpression"/> instance representing the binary assignment.</returns>
        public static AssignBinaryCSharpExpression MakeBinaryAssign(CSharpExpressionType binaryType, Expression left, Expression right, MethodInfo method, LambdaExpression leftConversion, LambdaExpression finalConversion)
        {
            switch (binaryType)
            {
                case CSharpExpressionType.Assign:
                    return Assign(left, right);
                case CSharpExpressionType.AddAssign:
                    return AddAssign(left, right, method, leftConversion, finalConversion);
                case CSharpExpressionType.AndAssign:
                    return AndAssign(left, right, method, leftConversion, finalConversion);
                case CSharpExpressionType.DivideAssign:
                    return DivideAssign(left, right, method, leftConversion, finalConversion);
                case CSharpExpressionType.ExclusiveOrAssign:
                    return ExclusiveOrAssign(left, right, method, leftConversion, finalConversion);
                case CSharpExpressionType.LeftShiftAssign:
                    return LeftShiftAssign(left, right, method, leftConversion, finalConversion);
                case CSharpExpressionType.ModuloAssign:
                    return ModuloAssign(left, right, method, leftConversion, finalConversion);
                case CSharpExpressionType.MultiplyAssign:
                    return MultiplyAssign(left, right, method, leftConversion, finalConversion);
                case CSharpExpressionType.OrAssign:
                    return OrAssign(left, right, method, leftConversion, finalConversion);
                case CSharpExpressionType.RightShiftAssign:
                    return RightShiftAssign(left, right, method, leftConversion, finalConversion);
                case CSharpExpressionType.SubtractAssign:
                    return SubtractAssign(left, right, method, leftConversion, finalConversion);
                case CSharpExpressionType.AddAssignChecked:
                    return AddAssignChecked(left, right, method, leftConversion, finalConversion);
                case CSharpExpressionType.MultiplyAssignChecked:
                    return MultiplyAssignChecked(left, right, method, leftConversion, finalConversion);
                case CSharpExpressionType.SubtractAssignChecked:
                    return SubtractAssignChecked(left, right, method, leftConversion, finalConversion);
            }

            throw LinqError.UnhandledBinary(binaryType);
        }
 /// <summary>
 /// Creates a new expression representing a dynamically bound binary assignment operation with the specified binder flags.
 /// </summary>
 /// <param name="binaryType">The type of the binary operation to perform.</param>
 /// <param name="left">The dynamic argument representing the left operand of the operation.</param>
 /// <param name="right">The dynamic argument representing the right operand of the operation.</param>
 /// <param name="binderFlags">The binder flags to use for the dynamic operation.</param>
 /// <returns>A new expression representing a dynamically bound binary operation.</returns>
 public static AssignBinaryDynamicCSharpExpression MakeDynamicBinaryAssign(CSharpExpressionType binaryType, DynamicCSharpArgument left, DynamicCSharpArgument right, CSharpBinderFlags binderFlags)
 {
     return(MakeDynamicBinaryAssign(binaryType, left, right, binderFlags, null));
 }
 private AssignBinaryCSharpExpression(CSharpExpressionType binaryType, Expression left, Expression right)
     : base(left, right)
 {
     CSharpNodeType = binaryType;
 }
Example #36
0
 /// <summary>
 /// Creates a new expression representing a dynamically bound unary assignment operation.
 /// </summary>
 /// <param name="unaryType">The type of the unary operation to perform.</param>
 /// <param name="operand">The expression representing the operand of the operation.</param>
 /// <returns>A new expression representing a dynamically bound unary assignment operation.</returns>
 public static AssignUnaryDynamicCSharpExpression MakeDynamicUnaryAssign(CSharpExpressionType unaryType, Expression operand) =>
 MakeDynamicUnaryAssign(unaryType, DynamicArgument(operand), CSharpBinderFlags.None, context: null);
        internal static AssignBinaryCSharpExpression Make(CSharpExpressionType binaryType, Expression left, Expression right, MethodInfo method, LambdaExpression leftConversion, LambdaExpression finalConversion)
        {
            ValidateCustomBinaryAssign(binaryType, left, right, ref method, leftConversion, finalConversion);

            // TODO: Add optimized layouts

            return new WithConversions(binaryType, left, right, method, leftConversion, finalConversion);
        }
        internal static AssignUnaryCSharpExpression Make(CSharpExpressionType unaryType, Expression operand, MethodInfo method)
        {
            ValidateCustomUnaryAssign(unaryType, operand, ref method);

            // TODO: Add optimized layouts

            return new Custom(unaryType, operand, method);
        }
Example #39
0
 /// <summary>
 /// Creates a new expression representing a dynamically bound unary assignment operation.
 /// </summary>
 /// <param name="unaryType">The type of the unary operation to perform.</param>
 /// <param name="operand">The expression representing the operand of the operation.</param>
 /// <returns>A new expression representing a dynamically bound unary assignment operation.</returns>
 public static AssignUnaryDynamicCSharpExpression MakeDynamicUnaryAssign(CSharpExpressionType unaryType, Expression operand)
 {
     return(MakeDynamicUnaryAssign(unaryType, DynamicArgument(operand), CSharpBinderFlags.None, null));
 }
        internal static BinaryExpression FunctionalOp(CSharpExpressionType binaryType, Expression left, Expression right, MethodInfo method)
        {
            switch (binaryType)
            {
                case CSharpExpressionType.Assign:
                    return Expression.Assign(left, right);
                case CSharpExpressionType.AddAssign:
                    return Expression.Add(left, right, method);
                case CSharpExpressionType.AndAssign:
                    return Expression.And(left, right, method);
                case CSharpExpressionType.DivideAssign:
                    return Expression.Divide(left, right, method);
                case CSharpExpressionType.ExclusiveOrAssign:
                    return Expression.ExclusiveOr(left, right, method);
                case CSharpExpressionType.LeftShiftAssign:
                    return Expression.LeftShift(left, right, method);
                case CSharpExpressionType.ModuloAssign:
                    return Expression.Modulo(left, right, method);
                case CSharpExpressionType.MultiplyAssign:
                    return Expression.Multiply(left, right, method);
                case CSharpExpressionType.OrAssign:
                    return Expression.Or(left, right, method);
                case CSharpExpressionType.RightShiftAssign:
                    return Expression.RightShift(left, right, method);
                case CSharpExpressionType.SubtractAssign:
                    return Expression.Subtract(left, right, method);
                case CSharpExpressionType.AddAssignChecked:
                    return Expression.AddChecked(left, right, method);
                case CSharpExpressionType.MultiplyAssignChecked:
                    return Expression.MultiplyChecked(left, right, method);
                case CSharpExpressionType.SubtractAssignChecked:
                    return Expression.SubtractChecked(left, right, method);
            }

            throw LinqError.UnhandledBinary(binaryType);
        }
 private static ExpressionType ConvertNodeType(CSharpExpressionType nodeType) =>
 nodeType switch
 {
        public static AssignUnaryDynamicCSharpExpression MakeDynamicUnaryAssign(CSharpExpressionType unaryType, DynamicCSharpArgument operand, CSharpBinderFlags binderFlags, Type context)
        {
            ContractUtils.RequiresNotNull(operand, nameof(operand));

            RequiresCanRead(operand.Expression, nameof(operand));
            RequiresCanWrite(operand.Expression, nameof(operand));

            CheckUnaryAssign(unaryType);

            switch (unaryType)
            {
                case CSharpExpressionType.PreIncrementAssignChecked:
                case CSharpExpressionType.PreDecrementAssignChecked:
                case CSharpExpressionType.PostIncrementAssignChecked:
                case CSharpExpressionType.PostDecrementAssignChecked:
                    binderFlags |= CSharpBinderFlags.CheckedContext;
                    break;
            }

            return new AssignUnaryDynamicCSharpExpression(context, binderFlags, unaryType, operand);
        }
 /// <summary>
 /// Creates a new expression representing a dynamically bound binary assignment operation.
 /// </summary>
 /// <param name="binaryType">The type of the binary operation to perform.</param>
 /// <param name="left">The expression representing the left operand of the operation.</param>
 /// <param name="right">The expression representing the right operand of the operation.</param>
 /// <returns>A new expression representing a dynamically bound binary operation.</returns>
 public static AssignBinaryDynamicCSharpExpression MakeDynamicBinaryAssign(CSharpExpressionType binaryType, Expression left, Expression right)
 {
     return MakeDynamicBinaryAssign(binaryType, DynamicArgument(left), DynamicArgument(right), CSharpBinderFlags.None, null);
 }
 internal AssignUnaryDynamicCSharpExpression(Type context, CSharpBinderFlags binderFlags, CSharpExpressionType unaryType, DynamicCSharpArgument operand)
     : base(context, binderFlags)
 {
     OperationNodeType = unaryType;
     Operand = operand;
 }
        public static AssignBinaryDynamicCSharpExpression MakeDynamicBinaryAssign(CSharpExpressionType binaryType, DynamicCSharpArgument left, DynamicCSharpArgument right, CSharpBinderFlags binderFlags, Type context)
        {
            ContractUtils.RequiresNotNull(left, nameof(left));
            ContractUtils.RequiresNotNull(right, nameof(right));

            RequiresCanWrite(left.Expression, nameof(left));
            RequiresCanRead(right.Expression, nameof(right));

            CheckBinaryAssign(binaryType);

            switch (binaryType)
            {
                case CSharpExpressionType.AddAssignChecked:
                case CSharpExpressionType.SubtractAssignChecked:
                case CSharpExpressionType.MultiplyAssignChecked:
                    binderFlags |= CSharpBinderFlags.CheckedContext;
                    break;
            }

            return new AssignBinaryDynamicCSharpExpression(context, binderFlags, binaryType, left, right);
        }
 /// <summary>
 /// Creates a new expression representing a dynamically bound unary assignment operation with the specified binder flags.
 /// </summary>
 /// <param name="unaryType">The type of the unary operation to perform.</param>
 /// <param name="operand">The dynamic argument representing the operand of the operation.</param>
 /// <param name="binderFlags">The binder flags to use for the dynamic operation.</param>
 /// <returns>A new expression representing a dynamically bound unary assignment operation.</returns>
 public static AssignUnaryDynamicCSharpExpression MakeDynamicUnaryAssign(CSharpExpressionType unaryType, DynamicCSharpArgument operand, CSharpBinderFlags binderFlags)
 {
     return MakeDynamicUnaryAssign(unaryType, operand, binderFlags, null);
 }
 public Custom(CSharpExpressionType unaryType, Expression operand, MethodInfo method)
     : base(unaryType, operand)
 {
     Method = method;
 }
        private static AssignBinaryCSharpExpression MakeBinaryAssignCore(CSharpExpressionType binaryType, Expression left, Expression right, MethodInfo method, LambdaExpression finalConversion, LambdaExpression leftConversion)
        {
            Helpers.RequiresCanWrite(left, nameof(left));
            RequiresCanRead(right, nameof(right));

            // NB: We could return a BinaryExpression in case the lhs is not one of our index nodes, but it'd change
            //     the return type to Expression which isn't nice to consume. Also, the Update method would either
            //     have to change to return Expression or we should have an AssignBinary node to hold a Binary node
            //     underneath it. This said, a specialized layout for the case where the custom node trivially wraps
            //     a LINQ node could be useful (just make Left virtual).

            if (binaryType != CSharpExpressionType.Assign)
            {
                var leftType  = left.Type;
                var rightType = right.Type;

                if (leftType == typeof(string))
                {
                    if (method == null)
                    {
                        if (binaryType == CSharpExpressionType.AddAssign || binaryType == CSharpExpressionType.AddAssignChecked)
                        {
                            if (rightType == typeof(string))
                            {
                                method = typeof(string).GetMethod(nameof(string.Concat), new[] { typeof(string), typeof(string) });
                            }
                            else
                            {
                                method = typeof(string).GetMethod(nameof(string.Concat), new[] { typeof(string), typeof(object) });

                                if (!TypeUtils1.AreReferenceAssignable(typeof(object), rightType))
                                {
                                    // DESIGN: Should our factory do this our just reject the input?
                                    right = Expression.Convert(right, typeof(object));
                                }
                            }
                        }
                        else
                        {
                            throw Error.InvalidCompoundAssignment(binaryType, typeof(string));
                        }
                    }
                }
                else if (typeof(MulticastDelegate).IsAssignableFrom(leftType))
                {
                    if (leftType == typeof(MulticastDelegate))
                    {
                        throw Error.InvalidCompoundAssignmentWithOperands(binaryType, leftType, rightType);
                    }

                    // NB: This checks for assignment with variance checks in mind, e.g.
                    //
                    //       Action<string> s = ...;
                    //       Action<object> o = ...;
                    //       s += o;

                    if (!TypeUtils1.AreReferenceAssignable(leftType, rightType))
                    {
                        throw Error.InvalidCompoundAssignmentWithOperands(binaryType, leftType, rightType);
                    }

                    if (method == null)
                    {
                        if (binaryType == CSharpExpressionType.AddAssign || binaryType == CSharpExpressionType.AddAssignChecked)
                        {
                            method = typeof(Delegate).GetMethod(nameof(Delegate.Combine), new[] { typeof(Delegate), typeof(Delegate) });
                        }
                        else if (binaryType == CSharpExpressionType.SubtractAssign || binaryType == CSharpExpressionType.SubtractAssignChecked)
                        {
                            method = typeof(Delegate).GetMethod(nameof(Delegate.Remove), new[] { typeof(Delegate), typeof(Delegate) });
                        }
                        else
                        {
                            throw Error.InvalidCompoundAssignment(binaryType, leftType);
                        }

                        if (finalConversion == null)
                        {
                            var resultParameter = Expression.Parameter(typeof(Delegate), "__result");
                            var convertResult   = Expression.Convert(resultParameter, leftType);
                            finalConversion = Expression.Lambda(convertResult, resultParameter);
                        }
                    }
                }
                else if (IsCSharpSpecificCompoundNumeric(leftType))
                {
                    // NB: If any of these are passed, we'll assume the types all line up. The call to
                    //     the ValidateCustomBinaryAssign method below will check that's indeed the case.

                    if (method == null && leftConversion == null && finalConversion == null)
                    {
                        var isChecked = IsCheckedBinary(binaryType);

                        var isNullabeLeftType = leftType.IsNullableType();
                        var nonNullLeftType   = leftType.GetNonNullableType();
                        var intermediateType  = nonNullLeftType.IsEnum ? nonNullLeftType.GetEnumUnderlyingType() : typeof(int);

                        var leftParameter = Expression.Parameter(leftType, "__left");
                        var convertType   = isNullabeLeftType ? typeof(Nullable <>).MakeGenericType(intermediateType) : intermediateType;
                        var convertLeft   = isChecked ? Expression.ConvertChecked(leftParameter, convertType) : Expression.Convert(leftParameter, convertType);
                        leftConversion = Expression.Lambda(convertLeft, leftParameter);

                        var resultParameter = Expression.Parameter(convertType, "__result");
                        var convertResult   = isChecked ? Expression.ConvertChecked(resultParameter, leftType) : Expression.Convert(resultParameter, leftType);
                        finalConversion = Expression.Lambda(convertResult, resultParameter);

                        if (rightType != convertType)
                        {
                            // DESIGN: Should our factory do this or just reject the input? On the one hand,
                            //         C# allows e.g. byte += byte, so if this is a C#-specific API it may be
                            //         reasonable for the user to expect such a tree can be built. On the
                            //         other hand, it's very unlike the expression tree API to insert nodes
                            //         on behalf of the user in the factories. Note that Roslyn often models
                            //         conversions as properties on a node using a `Conversion` objects
                            //         which would be handy to keep the shape from the tree isomorphic to the
                            //         bound nodes in the compiler. Note though that the RHS of a compound
                            //         assignment doesn't have such a conversion and the compiler will insert
                            //         a convert node in this case, so this is really just a convenience in
                            //         our factory method to mimic that behavior.
                            right = Expression.Convert(right, convertType);
                        }
                    }
                }
            }

            return(AssignBinaryCSharpExpression.Make(binaryType, left, right, method, leftConversion, finalConversion));
        }
 /// <summary>
 /// Creates a new expression representing a dynamically bound binary assignment operation.
 /// </summary>
 /// <param name="binaryType">The type of the binary operation to perform.</param>
 /// <param name="left">The expression representing the left operand of the operation.</param>
 /// <param name="right">The expression representing the right operand of the operation.</param>
 /// <returns>A new expression representing a dynamically bound binary operation.</returns>
 public static AssignBinaryDynamicCSharpExpression MakeDynamicBinaryAssign(CSharpExpressionType binaryType, Expression left, Expression right)
 {
     return(MakeDynamicBinaryAssign(binaryType, DynamicArgument(left), DynamicArgument(right), CSharpBinderFlags.None, null));
 }
 /// <summary>
 /// Creates a new expression representing a dynamically bound unary assignment operation.
 /// </summary>
 /// <param name="unaryType">The type of the unary operation to perform.</param>
 /// <param name="operand">The expression representing the operand of the operation.</param>
 /// <returns>A new expression representing a dynamically bound unary assignment operation.</returns>
 public static AssignUnaryDynamicCSharpExpression MakeDynamicUnaryAssign(CSharpExpressionType unaryType, Expression operand)
 {
     return MakeDynamicUnaryAssign(unaryType, DynamicArgument(operand), CSharpBinderFlags.None, null);
 }
        private static void ValidateCustomUnaryAssign(CSharpExpressionType unaryType, Expression operand, ref MethodInfo method)
        {
            var operandType = operand.Type;

            // NB: Just leverage LINQ to do the dirty work to check everything.This could produce mysterious error
            //     messages. (TODO: Review what's most appropriate here.)

            var resultType = operandType;

            if (!IsCSharpSpecificUnaryAssignNumeric(operandType))
            {
                var operandDummy = Expression.Parameter(operandType, "__operand");
                var functionalOp = FunctionalOp(unaryType, operandDummy, method);

                if (method == null)
                {
                    method = functionalOp.Method;
                }

                resultType = functionalOp.Type;
            }

            if (!TypeUtils.AreEquivalent(resultType, operand.Type))
            {
                throw Error.InvalidUnaryAssignmentWithOperands(unaryType, operand.Type);
            }
        }
Example #52
0
 internal AssignUnaryCSharpExpression(CSharpExpressionType unaryType, Expression operand)
     : base(operand)
 {
     CSharpNodeType = unaryType;
 }
 private static void CheckBinaryAssign(CSharpExpressionType binaryType)
 {
     switch (binaryType)
     {
         case CSharpExpressionType.Assign:
         case CSharpExpressionType.AddAssign:
         case CSharpExpressionType.AndAssign:
         case CSharpExpressionType.DivideAssign:
         case CSharpExpressionType.ExclusiveOrAssign:
         case CSharpExpressionType.LeftShiftAssign:
         case CSharpExpressionType.ModuloAssign:
         case CSharpExpressionType.MultiplyAssign:
         case CSharpExpressionType.OrAssign:
         case CSharpExpressionType.RightShiftAssign:
         case CSharpExpressionType.SubtractAssign:
         case CSharpExpressionType.AddAssignChecked:
         case CSharpExpressionType.MultiplyAssignChecked:
         case CSharpExpressionType.SubtractAssignChecked:
             break;
         default:
             throw LinqError.NotSupported();
     }
 }
        private static bool IsCheckedBinary(CSharpExpressionType type)
        {
            switch (type)
            {
                case CSharpExpressionType.AddAssignChecked:
                case CSharpExpressionType.MultiplyAssignChecked:
                case CSharpExpressionType.SubtractAssignChecked:
                    return true;
            }

            return false;
        }
Example #55
0
 /// <summary>
 /// Creates a new expression representing a dynamically bound unary assignment operation with the specified binder flags.
 /// </summary>
 /// <param name="unaryType">The type of the unary operation to perform.</param>
 /// <param name="operand">The dynamic argument representing the operand of the operation.</param>
 /// <param name="binderFlags">The binder flags to use for the dynamic operation.</param>
 /// <returns>A new expression representing a dynamically bound unary assignment operation.</returns>
 public static AssignUnaryDynamicCSharpExpression MakeDynamicUnaryAssign(CSharpExpressionType unaryType, DynamicCSharpArgument operand, CSharpBinderFlags binderFlags) =>
 MakeDynamicUnaryAssign(unaryType, operand, binderFlags, context: null);
 private static void CheckUnaryAssign(CSharpExpressionType unaryType)
 {
     switch (unaryType)
     {
         case CSharpExpressionType.PreIncrementAssign:
         case CSharpExpressionType.PreDecrementAssign:
         case CSharpExpressionType.PostIncrementAssign:
         case CSharpExpressionType.PostDecrementAssign:
         case CSharpExpressionType.PreIncrementAssignChecked:
         case CSharpExpressionType.PreDecrementAssignChecked:
         case CSharpExpressionType.PostIncrementAssignChecked:
         case CSharpExpressionType.PostDecrementAssignChecked:
             break;
         default:
             throw LinqError.NotSupported();
     }
 }
Example #57
0
 internal AssignUnaryDynamicCSharpExpression(Type context, CSharpBinderFlags binderFlags, CSharpExpressionType unaryType, DynamicCSharpArgument operand)
     : base(context, binderFlags)
 {
     OperationNodeType = unaryType;
     Operand           = operand;
 }
 internal AssignUnaryCSharpExpression(CSharpExpressionType unaryType, Expression operand)
     : base(operand)
 {
     CSharpNodeType = unaryType;
 }