static void CheckOperand(Expression operand, string paramName, ref int operandCount, ref bool lifted)
            {
                if (operand == null)
                {
                    return;
                }

                operandCount++;

                ExpressionStubs.RequiresCanRead(operand, paramName);

                if (operand.Type != typeof(Index) && operand.Type != typeof(Index?))
                {
                    throw Error.InvalidRangeOperandType(operand.Type);
                }

                if (operand.Type.IsNullableType())
                {
                    lifted = true;
                }
            }
Beispiel #2
0
        public static void RequiresCanWrite(Expression expression, string paramName)
        {
            // NB: This does not account for dynamic member and index nodes; to make dynamically bound assignments,
            //     one should use the appropriate methods on DynamicCSharpExpression, which require the use of
            //     dynamic arguments and also allow to separate the dynamic API from the rest of the nodes without
            //     having a strange circular dependency.

            if (expression is DiscardCSharpExpression)
            {
                return;
            }
            else if (expression is IndexCSharpExpression index)
            {
                EnsureCanWrite(index, paramName);
            }
            else
            {
                // NB: Our current modification of the Roslyn compiler can emit these nodes as the LHS of an
                //     assignment. We can deal with this in reduction steps by rewriting it to ArrayAccess
                //     using MakeWriteable below.

                if (expression.NodeType == ExpressionType.ArrayIndex)
                {
                    return;
                }

                if (expression.NodeType == ExpressionType.Call)
                {
                    var call = (MethodCallExpression)expression;
                    if (IsArrayAssignment(call))
                    {
                        return;
                    }
                }

                ExpressionStubs.RequiresCanWrite(expression, paramName);
            }
        }
        /// <summary>
        /// Creates a <see cref="FromEndIndexCSharpExpression"/> that represents an index from the end of an indexable object.
        /// </summary>
        /// <param name="operand">The expression representing the index value.</param>
        /// <param name="method">The method or constructor used to instantiate the index.</param>
        /// <param name="type">The index type, either <see cref="System.Index"/> or <see cref="System.Index?"/>.</param>
        /// <returns>The created <see cref="FromEndIndexCSharpExpression"/>.</returns>
        public static FromEndIndexCSharpExpression FromEndIndex(Expression operand, MethodBase method, Type type)
        {
            ExpressionStubs.RequiresCanRead(operand, nameof(operand));

            if (operand.Type != typeof(int) && operand.Type != typeof(int?))
            {
                throw Error.InvalidFromEndIndexOperandType(operand.Type);
            }

            if (method != null)
            {
                if (method.IsGenericMethodDefinition || method.GetReturnType() != typeof(Index))
                {
                    throw Error.InvalidFromEndIndexMethod();
                }

                if (method.MemberType == MemberTypes.Method && !method.IsStatic)
                {
                    throw Error.InvalidFromEndIndexMethod();
                }

                var parameters = method.GetParametersCached();

                switch (parameters.Length)
                {
                case 1:
                    if (parameters[0].ParameterType != typeof(int))
                    {
                        throw Error.InvalidFromEndIndexMethod();
                    }
                    break;

                case 2:
                    if (parameters[0].ParameterType != typeof(int) || parameters[1].ParameterType != typeof(bool))
                    {
                        throw Error.InvalidFromEndIndexMethod();
                    }
                    break;

                default:
                    throw Error.InvalidFromEndIndexMethod();
                }
            }

            if (type != null)
            {
                if (type == typeof(Index))
                {
                    if (operand.Type != typeof(int))
                    {
                        throw Error.InvalidIndexType(type);
                    }
                }
                else if (type == typeof(Index?))
                {
                    if (operand.Type != typeof(int?))
                    {
                        throw Error.InvalidIndexType(type);
                    }
                }
                else
                {
                    throw Error.InvalidIndexType(type);
                }
            }

            return(new FromEndIndexCSharpExpression(operand, method, type));
        }
 public static void RequiresCanRead(Expression expression, string paramName)
 {
     ExpressionStubs.RequiresCanRead(expression, paramName);
 }