@Override
public void endVisit(ForeachStatement x, BlockScope scope) {
try {
SourceInfo info = makeSourceInfo(x);
JBlock body = popBlock(info, x.action);
JExpression collection = pop(x.collection);
JDeclarationStatement elementDecl = pop(x.elementVariable);
assert (elementDecl.initializer == null);
JLocal elementVar = (JLocal) curMethod.locals.get(x.elementVariable.binding);
String elementVarName = elementVar.getName();
JForStatement result;
if (x.collectionVariable != null) {
/**
* <pre>
* for (final T[] i$array = collection,
* int i$index = 0,
* final int i$max = i$array.length;
* i$index < i$max; ++i$index) {
* T elementVar = i$array[i$index];
* // user action
* }
* </pre>
*/
JLocal arrayVar =
JProgram.createLocal(info, elementVarName + "$array", collection.getType(), true,
curMethod.body);
JLocal indexVar =
JProgram.createLocal(info, elementVarName + "$index", JPrimitiveType.INT, false,
curMethod.body);
JLocal maxVar =
JProgram.createLocal(info, elementVarName + "$max", JPrimitiveType.INT, true,
curMethod.body);
List<JStatement> initializers = Lists.newArrayListWithCapacity(3);
// T[] i$array = arr
initializers.add(makeDeclaration(info, arrayVar, collection));
// int i$index = 0
initializers.add(makeDeclaration(info, indexVar, JIntLiteral.get(0)));
// int i$max = i$array.length
initializers.add(makeDeclaration(info, maxVar, new JArrayLength(info, new JLocalRef(info,
arrayVar))));
// i$index < i$max
JExpression condition =
new JBinaryOperation(info, JPrimitiveType.BOOLEAN, JBinaryOperator.LT, new JLocalRef(
info, indexVar), new JLocalRef(info, maxVar));
// ++i$index
JExpression increments = new JPrefixOperation(info, JUnaryOperator.INC,
new JLocalRef(info, indexVar));
// T elementVar = i$array[i$index];
elementDecl.initializer =
new JArrayRef(info, new JLocalRef(info, arrayVar), new JLocalRef(info, indexVar));
body.addStmt(0, elementDecl);
result = new JForStatement(info, initializers, condition, increments, body);
} else {
/**
* <pre>
* for (Iterator<T> i$iterator = collection.iterator(); i$iterator.hasNext();) {
* T elementVar = i$iterator.next();
* // user action
* }
* </pre>
*/
CompilationUnitScope cudScope = scope.compilationUnitScope();
ReferenceBinding javaUtilIterator = scope.getJavaUtilIterator();
ReferenceBinding javaLangIterable = scope.getJavaLangIterable();
MethodBinding iterator = javaLangIterable.getExactMethod(ITERATOR, NO_TYPES, cudScope);
MethodBinding hasNext = javaUtilIterator.getExactMethod(HAS_NEXT, NO_TYPES, cudScope);
MethodBinding next = javaUtilIterator.getExactMethod(NEXT, NO_TYPES, cudScope);
JLocal iteratorVar =
JProgram.createLocal(info, (elementVarName + "$iterator"), typeMap
.get(javaUtilIterator), false, curMethod.body);
List<JStatement> initializers = Lists.newArrayListWithCapacity(1);
// Iterator<T> i$iterator = collection.iterator()
initializers.add(makeDeclaration(info, iteratorVar, new JMethodCall(info, collection,
typeMap.get(iterator))));
// i$iterator.hasNext()
JExpression condition =
new JMethodCall(info, new JLocalRef(info, iteratorVar), typeMap.get(hasNext));
// T elementVar = (T) i$iterator.next();
elementDecl.initializer =
new JMethodCall(info, new JLocalRef(info, iteratorVar), typeMap.get(next));
// Perform any implicit reference type casts (due to generics).
// Note this occurs before potential unboxing.
if (elementVar.getType() != javaLangObject) {
TypeBinding collectionElementType = (TypeBinding) collectionElementTypeField.get(x);
JType toType = typeMap.get(collectionElementType);
assert (toType instanceof JReferenceType);
elementDecl.initializer = maybeCast(toType, elementDecl.initializer);
}
body.addStmt(0, elementDecl);
result = new JForStatement(info, initializers, condition,
null, body);
}