private void CheckForItemInArrayLoop(ForStatement node)
{
ArrayType enumeratorType = GetExpressionType(node.Iterator) as ArrayType;
if (enumeratorType == null || enumeratorType.GetArrayRank() > 1) return;
IType elementType = enumeratorType.GetElementType();
if (elementType is InternalCallableType) return;
Block body = new Block(node.LexicalInfo);
InternalLocal indexVariable = DeclareTempLocal(TypeSystemServices.IntType);
Expression indexReference = CodeBuilder.CreateReference(indexVariable);
// __num = 0
body.Add(
CodeBuilder.CreateAssignment(
indexReference,
CodeBuilder.CreateIntegerLiteral(0)));
InternalLocal arrayVar = DeclareTempLocal(node.Iterator.ExpressionType);
ReferenceExpression arrayRef = CodeBuilder.CreateReference(arrayVar);
// __arr = <arr>
body.Add(
CodeBuilder.CreateAssignment(
arrayRef,
node.Iterator));
InternalLocal endVar = CodeBuilder.DeclareTempLocal(
_currentMethod,
TypeSystemServices.IntType);
ReferenceExpression endRef = CodeBuilder.CreateReference(endVar);
// __end = __arr.Length
body.Add(
CodeBuilder.CreateAssignment(
node.Iterator.LexicalInfo,
endRef,
CodeBuilder.CreateMethodInvocation(
arrayRef,
Array_get_Length)));
// while __num < __end:
WhileStatement ws = new WhileStatement(node.LexicalInfo);
ws.Condition = CodeBuilder.CreateBoundBinaryExpression(
TypeSystemServices.BoolType,
BinaryOperatorType.LessThan,
indexReference,
endRef);
if (1 == node.Declarations.Count)
{
IEntity loopVariable = node.Declarations[0].Entity;
node.Block.ReplaceNodes(
new NodePredicate(new EntityPredicate(loopVariable).Matches),
CreateRawArraySlicing(arrayRef, indexReference, elementType));
}
else
{
// alpha, bravo, charlie = arr[__num]
UnpackExpression(
ws.Block,
CreateRawArraySlicing(arrayRef, indexReference, elementType),
node.Declarations);
}
// <block>
ws.Block.Add(node.Block);
FixContinueStatements(node, ws);
// __num += 1
BinaryExpression assignment = CodeBuilder.CreateAssignment(
indexReference,
CodeBuilder.CreateBoundBinaryExpression(
TypeSystemServices.IntType,
BinaryOperatorType.Addition,
indexReference,
CodeBuilder.CreateIntegerLiteral(1)));
AstAnnotations.MarkUnchecked(assignment);
ws.Block.Add(assignment);
ws.OrBlock = node.OrBlock;
ws.ThenBlock = node.ThenBlock;
body.Add(ws);
ReplaceCurrentNode(body);
}