in src/main/java/org/apache/commons/jexl3/internal/Interpreter.java [694:769]
private Object forIterator(final ASTForeachStatement node, final Object data) {
Object result = null;
/* first objectNode is the loop variable */
final ASTReference loopReference = (ASTReference) node.jjtGetChild(0);
final ASTIdentifier loopVariable = (ASTIdentifier) loopReference.jjtGetChild(0);
final int symbol = loopVariable.getSymbol();
final boolean lexical = loopVariable.isLexical() || options.isLexical();
final LexicalFrame locals = lexical? new LexicalFrame(frame, block) : null;
final boolean loopSymbol = symbol >= 0 && loopVariable instanceof ASTVar;
if (lexical) {
// create lexical frame
// it may be a local previously declared
if (loopSymbol && !defineVariable((ASTVar) loopVariable, locals)) {
return redefinedVariable(node, loopVariable.getName());
}
block = locals;
}
Object forEach = null;
try {
/* second objectNode is the variable to iterate */
final Object iterableValue = node.jjtGetChild(1).jjtAccept(this, data);
// make sure there is a value to iterate upon
if (iterableValue == null) {
return null;
}
/* last child node is the statement to execute */
final int numChildren = node.jjtGetNumChildren();
final JexlNode statement = numChildren >= 3 ? node.jjtGetChild(numChildren - 1) : null;
// get an iterator for the collection/array/etc. via the introspector.
forEach = operators.tryOverload(node, JexlOperator.FOR_EACH, iterableValue);
final Iterator<?> itemsIterator = forEach instanceof Iterator
? (Iterator<?>) forEach
: uberspect.getIterator(iterableValue);
if (itemsIterator == null) {
return null;
}
int cnt = 0;
while (itemsIterator.hasNext()) {
cancelCheck(node);
// reset loop variable
if (lexical && cnt++ > 0) {
// clean up but remain current
block.pop();
// unlikely to fail
if (loopSymbol && !defineVariable((ASTVar) loopVariable, locals)) {
return redefinedVariable(node, loopVariable.getName());
}
}
// set loopVariable to value of iterator
final Object value = itemsIterator.next();
if (symbol < 0) {
setContextVariable(node, loopVariable.getName(), value);
} else {
frame.set(symbol, value);
}
if (statement != null) {
try {
// execute statement
result = statement.jjtAccept(this, data);
} catch (final JexlException.Break stmtBreak) {
break;
} catch (final JexlException.Continue stmtContinue) {
//continue;
}
}
}
} finally {
// closeable iterator handling
closeIfSupported(forEach);
// restore lexical frame
if (lexical) {
block = block.pop();
}
}
return result;
}