protected override Expression VisitIndex(IndexExpression node) { int yields = _yields.Count; Expression o = Visit(node.Object); ReadOnlyCollection <Expression> a = Visit(node.Arguments); if (o == node.Object && a == node.Arguments) { return(node); } if (yields == _yields.Count) { return(Expression.MakeIndex(o, node.Indexer, a)); } return(Expression.Block( ToTemp(ref o), ToTemp(ref a), Expression.MakeIndex(o, node.Indexer, a) )); }
private Expression VisitAssign(BinaryExpression node) { int yields = _yields.Count; Expression left = Visit(node.Left); Expression right = Visit(node.Right); if (left == node.Left && right == node.Right) { return(node); } if (yields == _yields.Count) { return(Expression.Assign(left, right)); } var block = new List <Expression>(); // If the left hand side did not rewrite itself, we may still need // to rewrite to ensure proper evaluation order. Essentially, we // want all of the left side evaluated first, then the value, then // the assignment if (left == node.Left) { switch (left.NodeType) { case ExpressionType.MemberAccess: var member = (MemberExpression)node.Left; Expression e = Visit(member.Expression); block.Add(ToTemp(ref e)); left = Expression.MakeMemberAccess(e, member.Member); break; case ExpressionType.Index: var index = (IndexExpression)node.Left; Expression o = Visit(index.Object); ReadOnlyCollection <Expression> a = Visit(index.Arguments); if (o == index.Object && a == index.Arguments) { return(index); } block.Add(ToTemp(ref o)); block.Add(ToTemp(ref a)); left = Expression.MakeIndex(o, index.Indexer, a); break; case ExpressionType.Parameter: // no action needed break; default: // Extension should've been reduced by Visit above, // and returned a different node throw Assert.Unreachable; } } else { // Get the last expression of the rewritten left side var leftBlock = (BlockExpression)left; left = leftBlock.Expressions[leftBlock.Expressions.Count - 1]; block.AddRange(leftBlock.Expressions); block.RemoveAt(block.Count - 1); } if (right != node.Right) { block.Add(ToTemp(ref right)); } block.Add(Expression.Assign(left, right)); return(Expression.Block(block)); }