001: package bsh;
002:
003: // Just testing...
004: import java.util.*;
005:
006: /**
007: Implementation of the enhanced for(:) statement.
008: This statement uses BshIterable to support iteration over a wide variety
009: of iterable types. Under JDK 1.1 this statement supports primitive and
010: Object arrays, Vectors, and enumerations. Under JDK 1.2 and later it
011: additionally supports collections.
012:
013: @author Daniel Leuck
014: @author Pat Niemeyer
015: */
016: class BSHEnhancedForStatement extends SimpleNode implements
017: ParserConstants {
018: String varName;
019:
020: BSHEnhancedForStatement(int id) {
021: super (id);
022: }
023:
024: public Object eval(CallStack callstack, Interpreter interpreter)
025: throws EvalError {
026: Class elementType = null;
027: SimpleNode expression, statement = null;
028:
029: NameSpace enclosingNameSpace = callstack.top();
030: SimpleNode firstNode = ((SimpleNode) jjtGetChild(0));
031: int nodeCount = jjtGetNumChildren();
032:
033: if (firstNode instanceof BSHType) {
034: elementType = ((BSHType) firstNode).getType(callstack,
035: interpreter);
036: expression = ((SimpleNode) jjtGetChild(1));
037: if (nodeCount > 2)
038: statement = ((SimpleNode) jjtGetChild(2));
039: } else {
040: expression = firstNode;
041: if (nodeCount > 1)
042: statement = ((SimpleNode) jjtGetChild(1));
043: }
044:
045: BlockNameSpace eachNameSpace = new BlockNameSpace(
046: enclosingNameSpace);
047: callstack.swap(eachNameSpace);
048:
049: final Object iteratee = expression.eval(callstack, interpreter);
050:
051: if (iteratee == Primitive.NULL)
052: throw new EvalError(
053: "The collection, array, map, iterator, or "
054: + "enumeration portion of a for statement cannot be null.",
055: this , callstack);
056:
057: CollectionManager cm = CollectionManager.getCollectionManager();
058: if (!cm.isBshIterable(iteratee))
059: throw new EvalError("Can't iterate over type: "
060: + iteratee.getClass(), this , callstack);
061: BshIterator iterator = cm.getBshIterator(iteratee);
062:
063: Object returnControl = Primitive.VOID;
064: while (iterator.hasNext()) {
065: try {
066: if (elementType != null)
067: eachNameSpace
068: .setTypedVariable(varName/*name*/,
069: elementType/*type*/, iterator
070: .next()/*value*/,
071: new Modifiers()/*none*/);
072: else
073: eachNameSpace.setVariable(varName, iterator.next(),
074: false);
075: } catch (UtilEvalError e) {
076: throw e.toEvalError("for loop iterator variable:"
077: + varName, this , callstack);
078: }
079:
080: boolean breakout = false; // switch eats a multi-level break here?
081: if (statement != null) // not empty statement
082: {
083: Object ret = statement.eval(callstack, interpreter);
084:
085: if (ret instanceof ReturnControl) {
086: switch (((ReturnControl) ret).kind) {
087: case RETURN:
088: returnControl = ret;
089: breakout = true;
090: break;
091:
092: case CONTINUE:
093: break;
094:
095: case BREAK:
096: breakout = true;
097: break;
098: }
099: }
100: }
101:
102: if (breakout)
103: break;
104: }
105:
106: callstack.swap(enclosingNameSpace);
107: return returnControl;
108: }
109: }
|