private Expression ReduceIndex()
{
// left[a0, a1, ... aN] (op)= r
//
// ... is reduced into ...
//
// tempObj = left
// tempArg0 = a0
// ...
// tempArgN = aN
// tempValue = tempObj[tempArg0, ... tempArgN] (op) r
// tempObj[tempArg0, ... tempArgN] = tempValue
var index = (IndexExpression)Left;
var vars = new ArrayBuilder<ParameterExpression>(index.ArgumentCount + 2);
var exprs = new ArrayBuilder<Expression>(index.ArgumentCount + 3);
ParameterExpression tempObj = Expression.Variable(index.Object.Type, "tempObj");
vars.UncheckedAdd(tempObj);
exprs.UncheckedAdd(Expression.Assign(tempObj, index.Object));
int n = index.ArgumentCount;
var tempArgs = new ArrayBuilder<Expression>(n);
for (var i = 0; i < n; i++)
{
Expression arg = index.GetArgument(i);
ParameterExpression tempArg = Expression.Variable(arg.Type, "tempArg" + i);
vars.UncheckedAdd(tempArg);
tempArgs.UncheckedAdd(tempArg);
exprs.UncheckedAdd(Expression.Assign(tempArg, arg));
}
IndexExpression tempIndex = Expression.MakeIndex(tempObj, index.Indexer, tempArgs.ToReadOnly());
// tempValue = tempObj[tempArg0, ... tempArgN] (op) r
ExpressionType binaryOp = GetBinaryOpFromAssignmentOp(NodeType);
Expression op = Expression.MakeBinary(binaryOp, tempIndex, Right, false, Method);
LambdaExpression conversion = GetConversion();
if (conversion != null)
{
op = Expression.Invoke(conversion, op);
}
ParameterExpression tempValue = Expression.Variable(op.Type, "tempValue");
vars.UncheckedAdd(tempValue);
exprs.UncheckedAdd(Expression.Assign(tempValue, op));
// tempObj[tempArg0, ... tempArgN] = tempValue
exprs.UncheckedAdd(Expression.Assign(tempIndex, tempValue));
return Expression.Block(vars.ToReadOnly(), exprs.ToReadOnly());
}