private Expression ReduceIndex()
{
// left[a0, a1, ... aN] (op)
//
// ... is reduced into ...
//
// tempObj = left
// tempArg0 = a0
// ...
// tempArgN = aN
// tempValue = tempObj[tempArg0, ... tempArgN]
// tempObj[tempArg0, ... tempArgN] = op(tempValue)
// tempValue
bool prefix = IsPrefix;
var index = (IndexExpression)Operand;
int count = index.ArgumentCount;
var block = new Expression[count + (prefix ? 2 : 4)];
var temps = new ParameterExpression[count + (prefix ? 1 : 2)];
var args = new ParameterExpression[count];
int i = 0;
temps[i] = Parameter(index.Object.Type, name: null);
block[i] = Assign(temps[i], index.Object);
i++;
while (i <= count)
{
Expression arg = index.GetArgument(i - 1);
args[i - 1] = temps[i] = Parameter(arg.Type, name: null);
block[i] = Assign(temps[i], arg);
i++;
}
index = MakeIndex(temps[0], index.Indexer, new TrueReadOnlyCollection<Expression>(args));
if (!prefix)
{
ParameterExpression lastTemp = temps[i] = Parameter(index.Type, name: null);
block[i] = Assign(temps[i], index);
i++;
Debug.Assert(i == temps.Length);
block[i++] = Assign(index, FunctionalOp(lastTemp));
block[i++] = lastTemp;
}
else
{
Debug.Assert(i == temps.Length);
block[i++] = Assign(index, FunctionalOp(index));
}
Debug.Assert(i == block.Length);
return Block(new TrueReadOnlyCollection<ParameterExpression>(temps), new TrueReadOnlyCollection<Expression>(block));
}