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) });