public Object visit(ForeachStatement node) {

            ++mForeachCount;

            VariableRef loopVar = node.getLoopVariable();
            String varName = loopVar.getName();
            if(mLoopVariables.contains(varName)) {
                error("foreach.loopvar.noreuse", varName,
                      loopVar.getSourceInfo());
                return null;
            }
            mLoopVariables.push(varName);

            Expression range = node.getRange();
            Expression endRange = node.getEndRange();
            Block body = node.getBody();

            check(range);
            Type rangeType = range.getType();

            Type endRangeType;
            if (endRange == null) {
                endRangeType = null;
            }
            else {
                check(endRange);
                endRangeType = endRange.getType();
            }

            if (rangeType == null ||
                (endRange != null && endRangeType == null)) {

                // Some error must have been detected in the range, so just
                // check everything else possible and bail out.

                enterScope();
                check(body);
                exitScope();

                mLoopVariables.pop();
                --mForeachCount;
                return null;
            }

            Class<?> rangeClass = rangeType.getObjectClass();
            Type elementType;

            // If there is no end range, then range expression type must be
            // an array or Collection.

            if (endRangeType == null) {
                if (loopVar.getVariable() != null && loopVar.getVariable().isStaticallyTyped()) {
                    check(loopVar.getVariable().getTypeName());
                    try {
                        if (rangeType.getIterationElementType() == null)
                            error("foreach.as.collection.required", rangeType.getSimpleName(), range);
                    }
                    catch (IntrospectionException e) {
                        error(e.toString(), node);
                        return null;
                    }

                    elementType = loopVar.getVariable().getTypeName().getType();
                    if (rangeClass.isArray() && (!rangeClass.getComponentType().isAssignableFrom(
                            elementType.getNaturalClass())
                            && !elementType.getNaturalClass().isAssignableFrom(
                            rangeClass.getComponentType()))) {
                        try {
                            error("foreach.as.not.assignable", elementType.getSimpleName(),
                                rangeType.getArrayElementType().getSimpleName(), range);
                        }
                        catch (IntrospectionException e) {
                            error(e.toString(), node);
                            return null;
                        }
                    }
                }
                else {
                    try {
                        elementType = rangeType.getIterationElementType();
                    }
                    catch (IntrospectionException e) {
                        error(e.toString(), node);
                        return null;
                    }
                }
                // end mod

                if (elementType == null) {
                    error("foreach.iteration.not.supported",
                          rangeType.getSimpleName(), range);
                }
                else {
                    checkAccess(elementType.getNaturalClass(), range);

                    if (node.isReverse() &&
                        !rangeType.isReverseIterationSupported()) {
                        error("foreach.reverse.not.supported",
                              rangeType.getSimpleName(), range);
                    }
                }
            }
            else {
                elementType = Type.INT_TYPE;

                if (!Number.class.isAssignableFrom(rangeClass)) {
                    error("foreach.range.start",
                          rangeType.getSimpleName(), range);
                    range.setType(elementType);
                }
                else {
                    if (Long.class.isAssignableFrom(rangeClass)) {
                        elementType = Type.LONG_TYPE;
                    }
                }

                Class<?> endRangeClass = endRangeType.getObjectClass();
                if (!Number.class.isAssignableFrom(endRangeClass)) {
                    error("foreach.range.end",
                          endRangeType.getSimpleName(), endRange);
                    endRange.setType(elementType);
                }
                else {
                    if (Long.class.isAssignableFrom(endRangeClass)) {
                        elementType = Type.LONG_TYPE;
                    }
                }

                range.convertTo(elementType);
                endRange.convertTo(elementType);
            }

            // Enter a new scope because variable declarations local
            // to a foreach loop might never get a value assigned because
            // there is no guarantee that the body will ever execute.
            Scope bodyScope = enterScope();

            if (elementType != null) {
                defineVariable(loopVar, elementType);
            }

            check(body);
            exitScope();

            Variable[] vars = bodyScope.promote();

            if (vars.length > 0) {
                // Since the body can be executed multiple times, variables
                // must be of the correct type before entering the scope.
                node.setInitializer
                    (createConversions(mScope, vars, node.getSourceInfo()));

                // Apply any conversions at the end of the body as well in
                // order for the variables to be of the correct type when
                // accessed again at the start of the body.
                body.setFinalizer
                    (createConversions(bodyScope, vars, body.getSourceInfo()));

                // Declare all promoted variables outside body scope.
                mScope.declareVariables(vars);

                // Re-check body to account for variable declaration changes.
                if (mErrorCount == 0) {
                    bodyScope.delete();
                    bodyScope = enterScope();

                    if (elementType != null) {
                        defineVariable(loopVar, elementType);
                    }

                    check(body);
                    exitScope();
                }
            }

            mLoopVariables.pop();
            --mForeachCount;
            return null;
        }