private Node arrayComprehension(String arrayName, Node expr)
            throws IOException, ParserException
    {
        if (nextToken() != Token.FOR)
            throw Kit.codeBug(); // shouldn't be here if next token isn't 'for'
        decompiler.addName(" "); // space after array literal expr
        decompiler.addToken(Token.FOR);
        boolean isForEach = false;
        if (matchToken(Token.NAME)) {
            decompiler.addName(ts.getString());
            if (ts.getString().equals("each")) {
                isForEach = true;
            }
            else {
                reportError("msg.no.paren.for");
            }
        }
        mustMatchToken(Token.LP, "msg.no.paren.for");
        decompiler.addToken(Token.LP);
        String name;
        int tt = peekToken();
        if (tt == Token.LB || tt == Token.LC) {
            // handle destructuring assignment
            name = currentScriptOrFn.getNextTempName();
            defineSymbol(Token.LP, name);
            expr = nf.createBinary(Token.COMMA, nf.createAssignment(
                    Token.ASSIGN, primaryExpr(), nf.createName(name)), expr);
        }
        else if (tt == Token.NAME) {
            consumeToken();
            name = ts.getString();
            decompiler.addName(name);
        }
        else {
            reportError("msg.bad.var");
            return nf.createNumber(0);
        }

        Node init = nf.createName(name);
        // Define as a let since we want the scope of the variable to
        // be restricted to the array comprehension
        defineSymbol(Token.LET, name);

        mustMatchToken(Token.IN, "msg.in.after.for.name");
        decompiler.addToken(Token.IN);
        Node iterator = expr(false);
        mustMatchToken(Token.RP, "msg.no.paren.for.ctrl");
        decompiler.addToken(Token.RP);

        Node body;
        tt = peekToken();
        if (tt == Token.FOR) {
            body = arrayComprehension(arrayName, expr);
        }
        else {

            Node call = nf.createCallOrNew(Token.CALL, nf.createPropertyGet(nf
                    .createName(arrayName), null, "push", 0));
            call.addChildToBack(expr);
            body = new Node(Token.EXPR_VOID, call, ts.getLineno());
            if (tt == Token.IF) {
                consumeToken();
                decompiler.addToken(Token.IF);
                int lineno = ts.getLineno();
                Node cond = condition();
                body = nf.createIf(cond, body, null, lineno);
            }
            mustMatchToken(Token.RB, "msg.no.bracket.arg");
            decompiler.addToken(Token.RB);
        }

        Node loop = enterLoop(null, true);
        try {
            return nf.createForIn(Token.LET, loop, init, iterator, body,
                    isForEach);
        }
        finally {
            exitLoop(false);
        }
    }