Search in sources :

Example 16 with Scope

use of org.mozilla.javascript.ast.Scope in project HL4A by HL4A.

the class Parser method forLoop.

private Loop forLoop() throws IOException {
    if (currentToken != Token.FOR)
        codeBug();
    consumeToken();
    int forPos = ts.tokenBeg, lineno = ts.lineno;
    boolean isForEach = false, isForIn = false, isForOf = false;
    int eachPos = -1, inPos = -1, lp = -1, rp = -1;
    // init is also foo in 'foo in object'
    AstNode init = null;
    // cond is also object in 'foo in object'
    AstNode cond = null;
    AstNode incr = null;
    Loop pn = null;
    Scope tempScope = new Scope();
    // decide below what AST class to use
    pushScope(tempScope);
    try {
        // See if this is a for each () instead of just a for ()
        if (matchToken(Token.NAME)) {
            if ("each".equals(ts.getString())) {
                isForEach = true;
                eachPos = ts.tokenBeg - forPos;
            } else {
                reportError("msg.no.paren.for");
            }
        }
        if (mustMatchToken(Token.LP, "msg.no.paren.for"))
            lp = ts.tokenBeg - forPos;
        int tt = peekToken();
        init = forLoopInit(tt);
        if (matchToken(Token.IN)) {
            isForIn = true;
            inPos = ts.tokenBeg - forPos;
            // object over which we're iterating
            cond = expr();
        } else if (compilerEnv.getLanguageVersion() >= Context.VERSION_ES6 && matchToken(Token.NAME) && "of".equals(ts.getString())) {
            isForOf = true;
            inPos = ts.tokenBeg - forPos;
            // object over which we're iterating
            cond = expr();
        } else {
            // ordinary for-loop
            mustMatchToken(Token.SEMI, "msg.no.semi.for");
            if (peekToken() == Token.SEMI) {
                // no loop condition
                cond = new EmptyExpression(ts.tokenBeg, 1);
                cond.setLineno(ts.lineno);
            } else {
                cond = expr();
            }
            mustMatchToken(Token.SEMI, "msg.no.semi.for.cond");
            int tmpPos = ts.tokenEnd;
            if (peekToken() == Token.RP) {
                incr = new EmptyExpression(tmpPos, 1);
                incr.setLineno(ts.lineno);
            } else {
                incr = expr();
            }
        }
        if (mustMatchToken(Token.RP, "msg.no.paren.for.ctrl"))
            rp = ts.tokenBeg - forPos;
        if (isForIn || isForOf) {
            ForInLoop fis = new ForInLoop(forPos);
            if (init instanceof VariableDeclaration) {
                // check that there was only one variable given
                if (((VariableDeclaration) init).getVariables().size() > 1) {
                    reportError("msg.mult.index");
                }
            }
            if (isForOf && isForEach) {
                reportError("msg.invalid.for.each");
            }
            fis.setIterator(init);
            fis.setIteratedObject(cond);
            fis.setInPosition(inPos);
            fis.setIsForEach(isForEach);
            fis.setEachPosition(eachPos);
            fis.setIsForOf(isForOf);
            pn = fis;
        } else {
            ForLoop fl = new ForLoop(forPos);
            fl.setInitializer(init);
            fl.setCondition(cond);
            fl.setIncrement(incr);
            pn = fl;
        }
        // replace temp scope with the new loop object
        currentScope.replaceWith(pn);
        popScope();
        // We have to parse the body -after- creating the loop node,
        // so that the loop node appears in the loopSet, allowing
        // break/continue statements to find the enclosing loop.
        enterLoop(pn);
        try {
            AstNode body = statement();
            pn.setLength(getNodeEnd(body) - forPos);
            pn.setBody(body);
        } finally {
            exitLoop();
        }
    } finally {
        if (currentScope == tempScope) {
            popScope();
        }
    }
    pn.setParens(lp, rp);
    pn.setLineno(lineno);
    return pn;
}
Also used : WhileLoop(org.mozilla.javascript.ast.WhileLoop) ForLoop(org.mozilla.javascript.ast.ForLoop) GeneratorExpressionLoop(org.mozilla.javascript.ast.GeneratorExpressionLoop) ArrayComprehensionLoop(org.mozilla.javascript.ast.ArrayComprehensionLoop) Loop(org.mozilla.javascript.ast.Loop) ForInLoop(org.mozilla.javascript.ast.ForInLoop) DoLoop(org.mozilla.javascript.ast.DoLoop) ForInLoop(org.mozilla.javascript.ast.ForInLoop) Scope(org.mozilla.javascript.ast.Scope) ForLoop(org.mozilla.javascript.ast.ForLoop) VariableDeclaration(org.mozilla.javascript.ast.VariableDeclaration) AstNode(org.mozilla.javascript.ast.AstNode) EmptyExpression(org.mozilla.javascript.ast.EmptyExpression)

Example 17 with Scope

use of org.mozilla.javascript.ast.Scope in project HL4A by HL4A.

the class Node method toString.

private void toString(ObjToIntMap printIds, StringBuilder sb) {
    if (Token.printTrees) {
        sb.append(Token.name(type));
        if (this instanceof Name) {
            sb.append(' ');
            sb.append(getString());
            Scope scope = getScope();
            if (scope != null) {
                sb.append("[scope: ");
                appendPrintId(scope, printIds, sb);
                sb.append("]");
            }
        } else if (this instanceof Scope) {
            if (this instanceof ScriptNode) {
                ScriptNode sof = (ScriptNode) this;
                if (this instanceof FunctionNode) {
                    FunctionNode fn = (FunctionNode) this;
                    sb.append(' ');
                    sb.append(fn.getName());
                }
                sb.append(" [source name: ");
                sb.append(sof.getSourceName());
                sb.append("] [encoded source length: ");
                sb.append(sof.getEncodedSourceEnd() - sof.getEncodedSourceStart());
                sb.append("] [base line: ");
                sb.append(sof.getBaseLineno());
                sb.append("] [end line: ");
                sb.append(sof.getEndLineno());
                sb.append(']');
            }
            if (((Scope) this).getSymbolTable() != null) {
                sb.append(" [scope ");
                appendPrintId(this, printIds, sb);
                sb.append(": ");
                Iterator<String> iter = ((Scope) this).getSymbolTable().keySet().iterator();
                while (iter.hasNext()) {
                    sb.append(iter.next());
                    sb.append(" ");
                }
                sb.append("]");
            }
        } else if (this instanceof Jump) {
            Jump jump = (Jump) this;
            if (type == Token.BREAK || type == Token.CONTINUE) {
                sb.append(" [label: ");
                appendPrintId(jump.getJumpStatement(), printIds, sb);
                sb.append(']');
            } else if (type == Token.TRY) {
                Node catchNode = jump.target;
                Node finallyTarget = jump.getFinally();
                if (catchNode != null) {
                    sb.append(" [catch: ");
                    appendPrintId(catchNode, printIds, sb);
                    sb.append(']');
                }
                if (finallyTarget != null) {
                    sb.append(" [finally: ");
                    appendPrintId(finallyTarget, printIds, sb);
                    sb.append(']');
                }
            } else if (type == Token.LABEL || type == Token.LOOP || type == Token.SWITCH) {
                sb.append(" [break: ");
                appendPrintId(jump.target, printIds, sb);
                sb.append(']');
                if (type == Token.LOOP) {
                    sb.append(" [continue: ");
                    appendPrintId(jump.getContinue(), printIds, sb);
                    sb.append(']');
                }
            } else {
                sb.append(" [target: ");
                appendPrintId(jump.target, printIds, sb);
                sb.append(']');
            }
        } else if (type == Token.NUMBER) {
            sb.append(' ');
            sb.append(getDouble());
        } else if (type == Token.TARGET) {
            sb.append(' ');
            appendPrintId(this, printIds, sb);
        }
        if (lineno != -1) {
            sb.append(' ');
            sb.append(lineno);
        }
        for (PropListItem x = propListHead; x != null; x = x.next) {
            int type = x.type;
            sb.append(" [");
            sb.append(propToString(type));
            sb.append(": ");
            String value;
            switch(type) {
                case // can't add this as it recurses
                TARGETBLOCK_PROP:
                    value = "target block property";
                    break;
                case // can't add this as it is dull
                LOCAL_BLOCK_PROP:
                    value = "last local block";
                    break;
                case ISNUMBER_PROP:
                    switch(x.intValue) {
                        case BOTH:
                            value = "both";
                            break;
                        case RIGHT:
                            value = "right";
                            break;
                        case LEFT:
                            value = "left";
                            break;
                        default:
                            throw Kit.codeBug();
                    }
                    break;
                case SPECIALCALL_PROP:
                    switch(x.intValue) {
                        case SPECIALCALL_EVAL:
                            value = "eval";
                            break;
                        case SPECIALCALL_WITH:
                            value = "with";
                            break;
                        default:
                            // NON_SPECIALCALL should not be stored
                            throw Kit.codeBug();
                    }
                    break;
                case OBJECT_IDS_PROP:
                    {
                        Object[] a = (Object[]) x.objectValue;
                        value = "[";
                        for (int i = 0; i < a.length; i++) {
                            value += a[i].toString();
                            if (i + 1 < a.length)
                                value += ", ";
                        }
                        value += "]";
                        break;
                    }
                default:
                    Object obj = x.objectValue;
                    if (obj != null) {
                        value = obj.toString();
                    } else {
                        value = String.valueOf(x.intValue);
                    }
                    break;
            }
            sb.append(value);
            sb.append(']');
        }
    }
}
Also used : Scope(org.mozilla.javascript.ast.Scope) ScriptNode(org.mozilla.javascript.ast.ScriptNode) FunctionNode(org.mozilla.javascript.ast.FunctionNode) FunctionNode(org.mozilla.javascript.ast.FunctionNode) Iterator(java.util.Iterator) ScriptNode(org.mozilla.javascript.ast.ScriptNode) Jump(org.mozilla.javascript.ast.Jump) Name(org.mozilla.javascript.ast.Name)

Example 18 with Scope

use of org.mozilla.javascript.ast.Scope in project HL4A by HL4A.

the class NodeTransformer method transformCompilationUnit_r.

private void transformCompilationUnit_r(final ScriptNode tree, final Node parent, Scope scope, boolean createScopeObjects, boolean inStrictMode) {
    Node node = null;
    siblingLoop: for (; ; ) {
        Node previous = null;
        if (node == null) {
            node = parent.getFirstChild();
        } else {
            previous = node;
            node = node.getNext();
        }
        if (node == null) {
            break;
        }
        int type = node.getType();
        if (createScopeObjects && (type == Token.BLOCK || type == Token.LOOP || type == Token.ARRAYCOMP) && (node instanceof Scope)) {
            Scope newScope = (Scope) node;
            if (newScope.getSymbolTable() != null) {
                // transform to let statement so we get a with statement
                // created to contain scoped let variables
                Node let = new Node(type == Token.ARRAYCOMP ? Token.LETEXPR : Token.LET);
                Node innerLet = new Node(Token.LET);
                let.addChildToBack(innerLet);
                for (String name : newScope.getSymbolTable().keySet()) {
                    innerLet.addChildToBack(Node.newString(Token.NAME, name));
                }
                // so we don't transform again
                newScope.setSymbolTable(null);
                Node oldNode = node;
                node = replaceCurrent(parent, previous, node, let);
                type = node.getType();
                let.addChildToBack(oldNode);
            }
        }
        switch(type) {
            case Token.LABEL:
            case Token.SWITCH:
            case Token.LOOP:
                loops.push(node);
                loopEnds.push(((Jump) node).target);
                break;
            case Token.WITH:
                {
                    loops.push(node);
                    Node leave = node.getNext();
                    if (leave.getType() != Token.LEAVEWITH) {
                        Kit.codeBug();
                    }
                    loopEnds.push(leave);
                    break;
                }
            case Token.TRY:
                {
                    Jump jump = (Jump) node;
                    Node finallytarget = jump.getFinally();
                    if (finallytarget != null) {
                        hasFinally = true;
                        loops.push(node);
                        loopEnds.push(finallytarget);
                    }
                    break;
                }
            case Token.TARGET:
            case Token.LEAVEWITH:
                if (!loopEnds.isEmpty() && loopEnds.peek() == node) {
                    loopEnds.pop();
                    loops.pop();
                }
                break;
            case Token.YIELD:
                ((FunctionNode) tree).addResumptionPoint(node);
                break;
            case Token.RETURN:
                {
                    boolean isGenerator = tree.getType() == Token.FUNCTION && ((FunctionNode) tree).isGenerator();
                    if (isGenerator) {
                        node.putIntProp(Node.GENERATOR_END_PROP, 1);
                    }
                    /* If we didn't support try/finally, it wouldn't be
                 * necessary to put LEAVEWITH nodes here... but as
                 * we do need a series of JSR FINALLY nodes before
                 * each RETURN, we need to ensure that each finally
                 * block gets the correct scope... which could mean
                 * that some LEAVEWITH nodes are necessary.
                 */
                    if (!hasFinally)
                        // skip the whole mess.
                        break;
                    Node unwindBlock = null;
                    for (int i = loops.size() - 1; i >= 0; i--) {
                        Node n = (Node) loops.get(i);
                        int elemtype = n.getType();
                        if (elemtype == Token.TRY || elemtype == Token.WITH) {
                            Node unwind;
                            if (elemtype == Token.TRY) {
                                Jump jsrnode = new Jump(Token.JSR);
                                Node jsrtarget = ((Jump) n).getFinally();
                                jsrnode.target = jsrtarget;
                                unwind = jsrnode;
                            } else {
                                unwind = new Node(Token.LEAVEWITH);
                            }
                            if (unwindBlock == null) {
                                unwindBlock = new Node(Token.BLOCK, node.getLineno());
                            }
                            unwindBlock.addChildToBack(unwind);
                        }
                    }
                    if (unwindBlock != null) {
                        Node returnNode = node;
                        Node returnExpr = returnNode.getFirstChild();
                        node = replaceCurrent(parent, previous, node, unwindBlock);
                        if (returnExpr == null || isGenerator) {
                            unwindBlock.addChildToBack(returnNode);
                        } else {
                            Node store = new Node(Token.EXPR_RESULT, returnExpr);
                            unwindBlock.addChildToFront(store);
                            returnNode = new Node(Token.RETURN_RESULT);
                            unwindBlock.addChildToBack(returnNode);
                            // transform return expression
                            transformCompilationUnit_r(tree, store, scope, createScopeObjects, inStrictMode);
                        }
                        // skip transformCompilationUnit_r to avoid infinite loop
                        continue siblingLoop;
                    }
                    break;
                }
            case Token.BREAK:
            case Token.CONTINUE:
                {
                    Jump jump = (Jump) node;
                    Jump jumpStatement = jump.getJumpStatement();
                    if (jumpStatement == null)
                        Kit.codeBug();
                    for (int i = loops.size(); ; ) {
                        if (i == 0) {
                            // which should be found
                            throw Kit.codeBug();
                        }
                        --i;
                        Node n = (Node) loops.get(i);
                        if (n == jumpStatement) {
                            break;
                        }
                        int elemtype = n.getType();
                        if (elemtype == Token.WITH) {
                            Node leave = new Node(Token.LEAVEWITH);
                            previous = addBeforeCurrent(parent, previous, node, leave);
                        } else if (elemtype == Token.TRY) {
                            Jump tryNode = (Jump) n;
                            Jump jsrFinally = new Jump(Token.JSR);
                            jsrFinally.target = tryNode.getFinally();
                            previous = addBeforeCurrent(parent, previous, node, jsrFinally);
                        }
                    }
                    if (type == Token.BREAK) {
                        jump.target = jumpStatement.target;
                    } else {
                        jump.target = jumpStatement.getContinue();
                    }
                    jump.setType(Token.GOTO);
                    break;
                }
            case Token.CALL:
                visitCall(node, tree);
                break;
            case Token.NEW:
                visitNew(node, tree);
                break;
            case Token.LETEXPR:
            case Token.LET:
                {
                    Node child = node.getFirstChild();
                    if (child.getType() == Token.LET) {
                        // We have a let statement or expression rather than a
                        // let declaration
                        boolean createWith = tree.getType() != Token.FUNCTION || ((FunctionNode) tree).requiresActivation();
                        node = visitLet(createWith, parent, previous, node);
                        break;
                    } else {
                    // fall through to process let declaration...
                    }
                }
            /* fall through */
            case Token.CONST:
            case Token.VAR:
                {
                    Node result = new Node(Token.BLOCK);
                    for (Node cursor = node.getFirstChild(); cursor != null; ) {
                        // Move cursor to next before createAssignment gets chance
                        // to change n.next
                        Node n = cursor;
                        cursor = cursor.getNext();
                        if (n.getType() == Token.NAME) {
                            if (!n.hasChildren())
                                continue;
                            Node init = n.getFirstChild();
                            n.removeChild(init);
                            n.setType(Token.BINDNAME);
                            n = new Node(type == Token.CONST ? Token.SETCONST : Token.SETNAME, n, init);
                        } else {
                            // to a LETEXPR
                            if (n.getType() != Token.LETEXPR)
                                throw Kit.codeBug();
                        }
                        Node pop = new Node(Token.EXPR_VOID, n, node.getLineno());
                        result.addChildToBack(pop);
                    }
                    node = replaceCurrent(parent, previous, node, result);
                    break;
                }
            case Token.TYPEOFNAME:
                {
                    Scope defining = scope.getDefiningScope(node.getString());
                    if (defining != null) {
                        node.setScope(defining);
                    }
                }
                break;
            case Token.TYPEOF:
            case Token.IFNE:
                {
                    /* We want to suppress warnings for undefined property o.p
                   * for the following constructs: typeof o.p, if (o.p),
                   * if (!o.p), if (o.p == undefined), if (undefined == o.p)
                   */
                    Node child = node.getFirstChild();
                    if (type == Token.IFNE) {
                        while (child.getType() == Token.NOT) {
                            child = child.getFirstChild();
                        }
                        if (child.getType() == Token.EQ || child.getType() == Token.NE) {
                            Node first = child.getFirstChild();
                            Node last = child.getLastChild();
                            if (first.getType() == Token.NAME && first.getString().equals("undefined")) {
                                child = last;
                            } else if (last.getType() == Token.NAME && last.getString().equals("undefined")) {
                                child = first;
                            }
                        }
                    }
                    if (child.getType() == Token.GETPROP) {
                        child.setType(Token.GETPROPNOWARN);
                    }
                    break;
                }
            case Token.SETNAME:
                if (inStrictMode) {
                    node.setType(Token.STRICT_SETNAME);
                }
            /* fall through */
            case Token.NAME:
            case Token.SETCONST:
            case Token.DELPROP:
                {
                    // Turn name to var for faster access if possible
                    if (createScopeObjects) {
                        break;
                    }
                    Node nameSource;
                    if (type == Token.NAME) {
                        nameSource = node;
                    } else {
                        nameSource = node.getFirstChild();
                        if (nameSource.getType() != Token.BINDNAME) {
                            if (type == Token.DELPROP) {
                                break;
                            }
                            throw Kit.codeBug();
                        }
                    }
                    if (nameSource.getScope() != null) {
                        // already have a scope set
                        break;
                    }
                    String name = nameSource.getString();
                    Scope defining = scope.getDefiningScope(name);
                    if (defining != null) {
                        nameSource.setScope(defining);
                        if (type == Token.NAME) {
                            node.setType(Token.GETVAR);
                        } else if (type == Token.SETNAME || type == Token.STRICT_SETNAME) {
                            node.setType(Token.SETVAR);
                            nameSource.setType(Token.STRING);
                        } else if (type == Token.SETCONST) {
                            node.setType(Token.SETCONSTVAR);
                            nameSource.setType(Token.STRING);
                        } else if (type == Token.DELPROP) {
                            // Local variables are by definition permanent
                            Node n = new Node(Token.FALSE);
                            node = replaceCurrent(parent, previous, node, n);
                        } else {
                            throw Kit.codeBug();
                        }
                    }
                    break;
                }
        }
        transformCompilationUnit_r(tree, node, node instanceof Scope ? (Scope) node : scope, createScopeObjects, inStrictMode);
    }
}
Also used : Scope(org.mozilla.javascript.ast.Scope) ScriptNode(org.mozilla.javascript.ast.ScriptNode) FunctionNode(org.mozilla.javascript.ast.FunctionNode) Jump(org.mozilla.javascript.ast.Jump)

Aggregations

Scope (org.mozilla.javascript.ast.Scope)18 FunctionNode (org.mozilla.javascript.ast.FunctionNode)13 ScriptNode (org.mozilla.javascript.ast.ScriptNode)13 AstNode (org.mozilla.javascript.ast.AstNode)8 LetNode (org.mozilla.javascript.ast.LetNode)7 ArrayList (java.util.ArrayList)4 Jump (org.mozilla.javascript.ast.Jump)4 XmlString (org.mozilla.javascript.ast.XmlString)4 ArrayComprehensionLoop (org.mozilla.javascript.ast.ArrayComprehensionLoop)3 GeneratorExpressionLoop (org.mozilla.javascript.ast.GeneratorExpressionLoop)3 Iterator (java.util.Iterator)2 List (java.util.List)2 DoLoop (org.mozilla.javascript.ast.DoLoop)2 ForInLoop (org.mozilla.javascript.ast.ForInLoop)2 ForLoop (org.mozilla.javascript.ast.ForLoop)2 Loop (org.mozilla.javascript.ast.Loop)2 Name (org.mozilla.javascript.ast.Name)2 WhileLoop (org.mozilla.javascript.ast.WhileLoop)2 ArrayLiteral (org.mozilla.javascript.ast.ArrayLiteral)1 EmptyExpression (org.mozilla.javascript.ast.EmptyExpression)1