Search in sources :

Example 11 with Scope

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

the class Parser method block.

private AstNode block() throws IOException {
    if (currentToken != Token.LC)
        codeBug();
    consumeToken();
    int pos = ts.tokenBeg;
    Scope block = new Scope(pos);
    block.setLineno(ts.lineno);
    pushScope(block);
    try {
        statements(block);
        mustMatchToken(Token.RC, "msg.no.brace.block");
        block.setLength(ts.tokenEnd - pos);
        return block;
    } finally {
        popScope();
    }
}
Also used : Scope(org.mozilla.javascript.ast.Scope)

Example 12 with Scope

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

the class NodeTransformer method visitLet.

protected Node visitLet(boolean createWith, Node parent, Node previous, Node scopeNode) {
    Node vars = scopeNode.getFirstChild();
    Node body = vars.getNext();
    scopeNode.removeChild(vars);
    scopeNode.removeChild(body);
    boolean isExpression = scopeNode.getType() == Token.LETEXPR;
    Node result;
    Node newVars;
    if (createWith) {
        result = new Node(isExpression ? Token.WITHEXPR : Token.BLOCK);
        result = replaceCurrent(parent, previous, scopeNode, result);
        ArrayList<Object> list = new ArrayList<Object>();
        Node objectLiteral = new Node(Token.OBJECTLIT);
        for (Node v = vars.getFirstChild(); v != null; v = v.getNext()) {
            Node current = v;
            if (current.getType() == Token.LETEXPR) {
                // destructuring in let expr, e.g. let ([x, y] = [3, 4]) {}
                List<?> destructuringNames = (List<?>) current.getProp(Node.DESTRUCTURING_NAMES);
                Node c = current.getFirstChild();
                if (c.getType() != Token.LET)
                    throw Kit.codeBug();
                // Add initialization code to front of body
                if (isExpression) {
                    body = new Node(Token.COMMA, c.getNext(), body);
                } else {
                    body = new Node(Token.BLOCK, new Node(Token.EXPR_VOID, c.getNext()), body);
                }
                // defined in the destructuring assignment
                if (destructuringNames != null) {
                    list.addAll(destructuringNames);
                    for (int i = 0; i < destructuringNames.size(); i++) {
                        objectLiteral.addChildToBack(new Node(Token.VOID, Node.newNumber(0.0)));
                    }
                }
                // should be a NAME, checked below
                current = c.getFirstChild();
            }
            if (current.getType() != Token.NAME)
                throw Kit.codeBug();
            list.add(ScriptRuntime.getIndexObject(current.getString()));
            Node init = current.getFirstChild();
            if (init == null) {
                init = new Node(Token.VOID, Node.newNumber(0.0));
            }
            objectLiteral.addChildToBack(init);
        }
        objectLiteral.putProp(Node.OBJECT_IDS_PROP, list.toArray());
        newVars = new Node(Token.ENTERWITH, objectLiteral);
        result.addChildToBack(newVars);
        result.addChildToBack(new Node(Token.WITH, body));
        result.addChildToBack(new Node(Token.LEAVEWITH));
    } else {
        result = new Node(isExpression ? Token.COMMA : Token.BLOCK);
        result = replaceCurrent(parent, previous, scopeNode, result);
        newVars = new Node(Token.COMMA);
        for (Node v = vars.getFirstChild(); v != null; v = v.getNext()) {
            Node current = v;
            if (current.getType() == Token.LETEXPR) {
                // destructuring in let expr, e.g. let ([x, y] = [3, 4]) {}
                Node c = current.getFirstChild();
                if (c.getType() != Token.LET)
                    throw Kit.codeBug();
                // Add initialization code to front of body
                if (isExpression) {
                    body = new Node(Token.COMMA, c.getNext(), body);
                } else {
                    body = new Node(Token.BLOCK, new Node(Token.EXPR_VOID, c.getNext()), body);
                }
                // We're removing the LETEXPR, so move the symbols
                Scope.joinScopes((Scope) current, (Scope) scopeNode);
                // should be a NAME, checked below
                current = c.getFirstChild();
            }
            if (current.getType() != Token.NAME)
                throw Kit.codeBug();
            Node stringNode = Node.newString(current.getString());
            stringNode.setScope((Scope) scopeNode);
            Node init = current.getFirstChild();
            if (init == null) {
                init = new Node(Token.VOID, Node.newNumber(0.0));
            }
            newVars.addChildToBack(new Node(Token.SETVAR, stringNode, init));
        }
        if (isExpression) {
            result.addChildToBack(newVars);
            scopeNode.setType(Token.COMMA);
            result.addChildToBack(scopeNode);
            scopeNode.addChildToBack(body);
            if (body instanceof Scope) {
                Scope scopeParent = ((Scope) body).getParentScope();
                ((Scope) body).setParentScope((Scope) scopeNode);
                ((Scope) scopeNode).setParentScope(scopeParent);
            }
        } else {
            result.addChildToBack(new Node(Token.EXPR_VOID, newVars));
            scopeNode.setType(Token.BLOCK);
            result.addChildToBack(scopeNode);
            scopeNode.addChildrenToBack(body);
            if (body instanceof Scope) {
                Scope scopeParent = ((Scope) body).getParentScope();
                ((Scope) body).setParentScope((Scope) scopeNode);
                ((Scope) scopeNode).setParentScope(scopeParent);
            }
        }
    }
    return result;
}
Also used : Scope(org.mozilla.javascript.ast.Scope) ScriptNode(org.mozilla.javascript.ast.ScriptNode) FunctionNode(org.mozilla.javascript.ast.FunctionNode) ArrayList(java.util.ArrayList) List(java.util.List) ArrayList(java.util.ArrayList)

Example 13 with Scope

use of org.mozilla.javascript.ast.Scope in project hackpad by dropbox.

the class Node method toString.

private void toString(ObjToIntMap printIds, StringBuffer 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 14 with Scope

use of org.mozilla.javascript.ast.Scope in project hackpad by dropbox.

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)

Example 15 with Scope

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

the class IRFactory method createFor.

private Node createFor(Scope loop, Node init, Node test, Node incr, Node body) {
    if (init.getType() == Token.LET) {
        // rewrite "for (let i=s; i < N; i++)..." as
        // "let (i=s) { for (; i < N; i++)..." so that "s" is evaluated
        // outside the scope of the for.
        Scope let = Scope.splitScope(loop);
        let.setType(Token.LET);
        let.addChildrenToBack(init);
        let.addChildToBack(createLoop(loop, LOOP_FOR, body, test, new Node(Token.EMPTY), incr));
        return let;
    }
    return createLoop(loop, LOOP_FOR, body, test, init, incr);
}
Also used : Scope(org.mozilla.javascript.ast.Scope) ScriptNode(org.mozilla.javascript.ast.ScriptNode) AstNode(org.mozilla.javascript.ast.AstNode) LetNode(org.mozilla.javascript.ast.LetNode) FunctionNode(org.mozilla.javascript.ast.FunctionNode)

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