protected internal override Expression VisitIndexerAccess(IndexerAccessCSharpExpression node)
        {
            var obj = Visit(node.Object);
            var arg = Visit(node.Argument);

            return(Push(node, new XAttribute(nameof(node.LengthOrCount), node.LengthOrCount), new XAttribute(nameof(node.IndexOrSlice), node.IndexOrSlice), new XElement(nameof(node.Object), obj), new XElement(nameof(node.Argument), arg)));
        }
        private static Expression GetIntIndexExpression(Expression array, Expression index)
        {
            //
            // NB: The Roslyn compiler also allows the array.Length expression to be evaluated after evaluating the index expression,
            //     so we follow suit here. This is different from IndexerAccess behavior where, when needed, the length is evaluated
            //     prior to evaluating the index. Arguably, the only side-effect that can take place here is a NullReferenceException
            //     when the array is null.
            //

            return(IndexerAccessCSharpExpression.GetIndexOffset(index, Expression.ArrayLength(array), out _));
        }
        /// <summary>
        /// Reduces the expression node to a simpler expression.
        /// </summary>
        /// <returns>The reduced expression.</returns>
        public override Expression Reduce()
        {
            var left = MakeWriteable(Left);

            if (CSharpNodeType == CSharpExpressionType.NullCoalescingAssign)
            {
                // NB: NullCoalescingAssign is handled by the Reduce implementation on the derived type.

                throw ContractUtils.Unreachable;
            }

            if (CSharpNodeType == CSharpExpressionType.Assign)
            {
                // NB: We still use `ReduceAssignment` here to deal with IndexCSharpExpression which is not
                //     a valid LHS to Expression.Assign.

                return(left switch
                {
                    IndexCSharpExpression indexCSharp => indexCSharp.ReduceAssign(lhs => Expression.Assign(lhs, Right)),
                    ArrayAccessCSharpExpression arrayAccessCSharp => arrayAccessCSharp.ReduceAssign(lhs => Expression.Assign(lhs, Right)),
                    IndexerAccessCSharpExpression indexerAccessCSharp => indexerAccessCSharp.ReduceAssign(lhs => Expression.Assign(lhs, Right)),
                    _ => Expression.Assign(left, Right)
                });