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