Search in sources :

Example 1 with Scope

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

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 2 with Scope

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

the class IRFactory method transformBlock.

private Node transformBlock(AstNode node) {
    if (node instanceof Scope) {
        pushScope((Scope) node);
    }
    try {
        List<Node> kids = new ArrayList<Node>();
        for (Node kid : node) {
            kids.add(transform((AstNode) kid));
        }
        node.removeChildren();
        for (Node kid : kids) {
            node.addChildToBack(kid);
        }
        return node;
    } finally {
        if (node instanceof Scope) {
            popScope();
        }
    }
}
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) ArrayList(java.util.ArrayList) AstNode(org.mozilla.javascript.ast.AstNode)

Example 3 with Scope

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

the class IRFactory method arrayCompTransformHelper.

private Node arrayCompTransformHelper(ArrayComprehension node, String arrayName) {
    decompiler.addToken(Token.LB);
    int lineno = node.getLineno();
    Node expr = transform(node.getResult());
    List<ArrayComprehensionLoop> loops = node.getLoops();
    int numLoops = loops.size();
    // Walk through loops, collecting and defining their iterator symbols.
    Node[] iterators = new Node[numLoops];
    Node[] iteratedObjs = new Node[numLoops];
    for (int i = 0; i < numLoops; i++) {
        ArrayComprehensionLoop acl = loops.get(i);
        decompiler.addName(" ");
        decompiler.addToken(Token.FOR);
        if (acl.isForEach()) {
            decompiler.addName("each ");
        }
        decompiler.addToken(Token.LP);
        AstNode iter = acl.getIterator();
        String name = null;
        if (iter.getType() == Token.NAME) {
            name = iter.getString();
            decompiler.addName(name);
        } else {
            // destructuring assignment
            decompile(iter);
            name = currentScriptOrFn.getNextTempName();
            defineSymbol(Token.LP, name, false);
            expr = createBinary(Token.COMMA, createAssignment(Token.ASSIGN, iter, createName(name)), expr);
        }
        Node init = 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, false);
        iterators[i] = init;
        if (acl.isForOf()) {
            decompiler.addName("of ");
        } else {
            decompiler.addToken(Token.IN);
        }
        iteratedObjs[i] = transform(acl.getIteratedObject());
        decompiler.addToken(Token.RP);
    }
    // generate code for tmpArray.push(body)
    Node call = createCallOrNew(Token.CALL, createPropertyGet(createName(arrayName), null, "push", 0));
    Node body = new Node(Token.EXPR_VOID, call, lineno);
    if (node.getFilter() != null) {
        decompiler.addName(" ");
        decompiler.addToken(Token.IF);
        decompiler.addToken(Token.LP);
        body = createIf(transform(node.getFilter()), body, null, lineno);
        decompiler.addToken(Token.RP);
    }
    // Now walk loops in reverse to build up the body statement.
    int pushed = 0;
    try {
        for (int i = numLoops - 1; i >= 0; i--) {
            ArrayComprehensionLoop acl = loops.get(i);
            Scope loop = createLoopNode(// no label
            null, acl.getLineno());
            pushScope(loop);
            pushed++;
            body = createForIn(Token.LET, loop, iterators[i], iteratedObjs[i], body, acl.isForEach(), acl.isForOf());
        }
    } finally {
        for (int i = 0; i < pushed; i++) {
            popScope();
        }
    }
    decompiler.addToken(Token.RB);
    // Now that we've accumulated any destructuring forms,
    // add expr to the call node; it's pushed on each iteration.
    call.addChildToBack(expr);
    return body;
}
Also used : Scope(org.mozilla.javascript.ast.Scope) ArrayComprehensionLoop(org.mozilla.javascript.ast.ArrayComprehensionLoop) ScriptNode(org.mozilla.javascript.ast.ScriptNode) AstNode(org.mozilla.javascript.ast.AstNode) LetNode(org.mozilla.javascript.ast.LetNode) FunctionNode(org.mozilla.javascript.ast.FunctionNode) XmlString(org.mozilla.javascript.ast.XmlString) AstNode(org.mozilla.javascript.ast.AstNode)

Example 4 with Scope

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

the class IRFactory method transformArrayComp.

private Node transformArrayComp(ArrayComprehension node) {
    // An array comprehension expression such as
    // 
    // [expr for (x in foo) for each ([y, z] in bar) if (cond)]
    // 
    // is rewritten approximately as
    // 
    // new Scope(ARRAYCOMP) {
    // new Node(BLOCK) {
    // let tmp1 = new Array;
    // for (let x in foo) {
    // for each (let tmp2 in bar) {
    // if (cond) {
    // tmp1.push([y, z] = tmp2, expr);
    // }
    // }
    // }
    // }
    // createName(tmp1)
    // }
    int lineno = node.getLineno();
    Scope scopeNode = createScopeNode(Token.ARRAYCOMP, lineno);
    String arrayName = currentScriptOrFn.getNextTempName();
    pushScope(scopeNode);
    try {
        defineSymbol(Token.LET, arrayName, false);
        Node block = new Node(Token.BLOCK, lineno);
        Node newArray = createCallOrNew(Token.NEW, createName("Array"));
        Node init = new Node(Token.EXPR_VOID, createAssignment(Token.ASSIGN, createName(arrayName), newArray), lineno);
        block.addChildToBack(init);
        block.addChildToBack(arrayCompTransformHelper(node, arrayName));
        scopeNode.addChildToBack(block);
        scopeNode.addChildToBack(createName(arrayName));
        return scopeNode;
    } finally {
        popScope();
    }
}
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) XmlString(org.mozilla.javascript.ast.XmlString)

Example 5 with Scope

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

the class IRFactory method genExprTransformHelper.

private Node genExprTransformHelper(GeneratorExpression node) {
    decompiler.addToken(Token.LP);
    int lineno = node.getLineno();
    Node expr = transform(node.getResult());
    List<GeneratorExpressionLoop> loops = node.getLoops();
    int numLoops = loops.size();
    // Walk through loops, collecting and defining their iterator symbols.
    Node[] iterators = new Node[numLoops];
    Node[] iteratedObjs = new Node[numLoops];
    for (int i = 0; i < numLoops; i++) {
        GeneratorExpressionLoop acl = loops.get(i);
        decompiler.addName(" ");
        decompiler.addToken(Token.FOR);
        decompiler.addToken(Token.LP);
        AstNode iter = acl.getIterator();
        String name = null;
        if (iter.getType() == Token.NAME) {
            name = iter.getString();
            decompiler.addName(name);
        } else {
            // destructuring assignment
            decompile(iter);
            name = currentScriptOrFn.getNextTempName();
            defineSymbol(Token.LP, name, false);
            expr = createBinary(Token.COMMA, createAssignment(Token.ASSIGN, iter, createName(name)), expr);
        }
        Node init = 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, false);
        iterators[i] = init;
        if (acl.isForOf()) {
            decompiler.addName("of ");
        } else {
            decompiler.addToken(Token.IN);
        }
        iteratedObjs[i] = transform(acl.getIteratedObject());
        decompiler.addToken(Token.RP);
    }
    // generate code for tmpArray.push(body)
    Node yield = new Node(Token.YIELD, expr, node.getLineno());
    Node body = new Node(Token.EXPR_VOID, yield, lineno);
    if (node.getFilter() != null) {
        decompiler.addName(" ");
        decompiler.addToken(Token.IF);
        decompiler.addToken(Token.LP);
        body = createIf(transform(node.getFilter()), body, null, lineno);
        decompiler.addToken(Token.RP);
    }
    // Now walk loops in reverse to build up the body statement.
    int pushed = 0;
    try {
        for (int i = numLoops - 1; i >= 0; i--) {
            GeneratorExpressionLoop acl = loops.get(i);
            Scope loop = createLoopNode(// no label
            null, acl.getLineno());
            pushScope(loop);
            pushed++;
            body = createForIn(Token.LET, loop, iterators[i], iteratedObjs[i], body, acl.isForEach(), acl.isForOf());
        }
    } finally {
        for (int i = 0; i < pushed; i++) {
            popScope();
        }
    }
    decompiler.addToken(Token.RP);
    return body;
}
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) GeneratorExpressionLoop(org.mozilla.javascript.ast.GeneratorExpressionLoop) XmlString(org.mozilla.javascript.ast.XmlString) AstNode(org.mozilla.javascript.ast.AstNode)

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