private void generateForeachIterator(final ForeachStatement node) {
            Expression range = node.getRange();
            Statement init = node.getInitializer();
            Statement body = node.getBody();

            // Allow Maps and Sets to be reverse iterable - Wrap it in an ArrayList
            // This is a stack optimization to avoid creating a local variable
            if (! "java.util.List".equals(range.getType().getNaturalClass().getName()) &&
                    node.isReverse()) {
                mBuilder.newObject(makeDesc(java.util.ArrayList.class));
                mBuilder.dup();
            }

            // Put the range onto the stack
            generate(range);

            // Convert the Map to a Set
            if ("java.util.Map".equals(range.getType().getNaturalClass().getName()))
                mBuilder.invokeInterface("java.util.Map", "keySet",
                    makeDesc(java.util.Set.class));


            // Allow Maps and Sets to be reverse iterable - invoke constructor on ArrayList.
            // The overall cost for this is only incurred for Sets/Maps
            if (! "java.util.List".equals(range.getType().getNaturalClass().getName()) &&
                    node.isReverse()) {
                mBuilder.invokeConstructor("java.util.ArrayList",
                    new TypeDesc[] { makeDesc(java.util.Collection.class) });
            }

            // Generate init right after the range is evaluated.
            if (init != null) {
                generate(init);
            }

            Label endLabel = mBuilder.createLabel();
            Label notNullLabel = mBuilder.createLabel();

            if (range.getType().isNullable()) {
                // If range is null, just skip past the loop, avoiding a
                // NullPointerException.
                mBuilder.dup();
                mBuilder.ifNullBranch(notNullLabel, false);
                mBuilder.pop();
                mBuilder.branch(endLabel);
            }

            notNullLabel.setLocation();

            // TODO: if array, this fails to iterate

            TypeDesc td;
            if (!node.isReverse()) {
                td = makeDesc(Iterator.class);
                mBuilder.invokeInterface
                    ("java.lang.Iterable", "iterator", td);
            }
            else {
                mBuilder.dup();
                mBuilder.invokeInterface
                    ("java.util.Collection", "size", TypeDesc.INT);
                td = makeDesc(ListIterator.class);
                mBuilder.invokeInterface
                    ("java.util.List", "listIterator", td, cIntParam);
            }

            final LocalVariable iteratorLocal =
                mBuilder.createLocalVariable(null, td);
            mBuilder.storeLocal(iteratorLocal);

            Label checkLabel = mBuilder.createLabel();
            mBuilder.branch(checkLabel);

            // Loop body begins here.
            Label startLabel = mBuilder.createLabel().setLocation();
            Label continueLabel = mBuilder.createLabel();
            saveContinueLabel(continueLabel);

            // Feed the loop variable with a value.
            final VariableRef loopVarRef = node.getLoopVariable();
            final Class<?> loopVarClass = loopVarRef.getType().getNaturalClass();

            storeToVariable(loopVarRef.getVariable(), new Runnable() {
                public void run() {
                    mBuilder.loadLocal(iteratorLocal);
                    if (!node.isReverse()) {
                        mBuilder.invokeInterface("java.util.Iterator", "next",
                                                 TypeDesc.OBJECT);
                    }
                    else {
                        mBuilder.invokeInterface("java.util.ListIterator",
                                                 "previous",
                                                 TypeDesc.OBJECT);
                    }
                    if (loopVarClass != Object.class) {
                        mBuilder.checkCast(makeDesc(loopVarRef.getType()));
                    }
                }
            });

            if (body != null) {
                generate(body);
            }

            // set entry point for continue
            continueLabel.setLocation();

            checkLabel.setLocation();
            mBuilder.loadLocal(iteratorLocal);

            td = TypeDesc.BOOLEAN;

            if (!node.isReverse()) {
                mBuilder.invokeInterface("java.util.Iterator",
                                         "hasNext", td);
            }
            else {
                mBuilder.invokeInterface("java.util.ListIterator",
                                         "hasPrevious", td);
            }

            mBuilder.ifZeroComparisonBranch(startLabel, "!=");

            endLabel.setLocation();
        }