package bsh;
// Just testing...
import java.util.*;
/**
Implementation of the enhanced for(:) statement.
This statement uses BshIterable to support iteration over a wide variety
of iterable types. Under JDK 1.1 this statement supports primitive and
Object arrays, Vectors, and enumerations. Under JDK 1.2 and later it
additionally supports collections.
@author Daniel Leuck
@author Pat Niemeyer
*/
class
BSHEnhancedForStatement extends
SimpleNode implements
ParserConstants
{
String varName;
BSHEnhancedForStatement(int
id) { super(
id); }
public
Object eval(
CallStack callstack ,
Interpreter interpreter )
throws
EvalError
{
Class elementType = null;
SimpleNode expression,
statement=null;
NameSpace enclosingNameSpace =
callstack.
top();
SimpleNode firstNode =((
SimpleNode)
jjtGetChild(0));
int
nodeCount =
jjtGetNumChildren();
if (
firstNode instanceof
BSHType )
{
elementType=((
BSHType)
firstNode).
getType(
callstack,
interpreter );
expression=((
SimpleNode)
jjtGetChild(1));
if (
nodeCount>2 )
statement=((
SimpleNode)
jjtGetChild(2));
} else
{
expression=
firstNode;
if (
nodeCount>1 )
statement=((
SimpleNode)
jjtGetChild(1));
}
BlockNameSpace eachNameSpace = new
BlockNameSpace(
enclosingNameSpace );
callstack.
swap(
eachNameSpace );
final
Object iteratee =
expression.
eval(
callstack,
interpreter );
if (
iteratee ==
Primitive.
NULL )
throw new
EvalError("The collection, array, map, iterator, or " +
"enumeration portion of a for statement cannot be null.",
this,
callstack );
CollectionManager cm =
CollectionManager.
getCollectionManager();
if ( !
cm.
isBshIterable(
iteratee ) )
throw new
EvalError("Can't iterate over type: "
+
iteratee.
getClass(), this,
callstack );
BshIterator iterator =
cm.
getBshIterator(
iteratee );
Object returnControl =
Primitive.
VOID;
while(
iterator.
hasNext() )
{
try {
if (
elementType != null )
eachNameSpace.
setTypedVariable(
varName/*name*/,
elementType/*type*/,
iterator.
next()/*value*/, new
Modifiers()/*none*/ );
else
eachNameSpace.
setVariable(
varName,
iterator.
next(), false );
} catch (
UtilEvalError e ) {
throw
e.
toEvalError(
"for loop iterator variable:"+
varName, this,
callstack );
}
boolean
breakout = false; // switch eats a multi-level break here?
if (
statement != null ) // not empty statement
{
Object ret =
statement.
eval(
callstack,
interpreter );
if (
ret instanceof
ReturnControl)
{
switch(((
ReturnControl)
ret).
kind)
{
case
RETURN:
returnControl =
ret;
breakout = true;
break;
case
CONTINUE:
break;
case
BREAK:
breakout = true;
break;
}
}
}
if (
breakout)
break;
}
callstack.
swap(
enclosingNameSpace);
return
returnControl;
}
}