Search in sources :

Example 11 with Jump

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

the class IRFactory method addSwitchCase.

/**
 * If caseExpression argument is null it indicates a default label.
 */
private void addSwitchCase(Node switchBlock, Node caseExpression, Node statements) {
    if (switchBlock.getType() != Token.BLOCK)
        throw Kit.codeBug();
    Jump switchNode = (Jump) switchBlock.getFirstChild();
    if (switchNode.getType() != Token.SWITCH)
        throw Kit.codeBug();
    Node gotoTarget = Node.newTarget();
    if (caseExpression != null) {
        Jump caseNode = new Jump(Token.CASE, caseExpression);
        caseNode.target = gotoTarget;
        switchNode.addChildToBack(caseNode);
    } else {
        switchNode.setDefault(gotoTarget);
    }
    switchBlock.addChildToBack(gotoTarget);
    switchBlock.addChildToBack(statements);
}
Also used : ScriptNode(org.mozilla.javascript.ast.ScriptNode) AstNode(org.mozilla.javascript.ast.AstNode) LetNode(org.mozilla.javascript.ast.LetNode) FunctionNode(org.mozilla.javascript.ast.FunctionNode) Jump(org.mozilla.javascript.ast.Jump)

Example 12 with Jump

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

the class IRFactory method createForIn.

/**
 * Generate IR for a for..in loop.
 */
private Node createForIn(int declType, Node loop, Node lhs, Node obj, Node body, boolean isForEach, boolean isForOf) {
    int destructuring = -1;
    int destructuringLen = 0;
    Node lvalue;
    int type = lhs.getType();
    if (type == Token.VAR || type == Token.LET) {
        Node kid = lhs.getLastChild();
        int kidType = kid.getType();
        if (kidType == Token.ARRAYLIT || kidType == Token.OBJECTLIT) {
            type = destructuring = kidType;
            lvalue = kid;
            destructuringLen = 0;
            if (kid instanceof ArrayLiteral)
                destructuringLen = ((ArrayLiteral) kid).getDestructuringLength();
        } else if (kidType == Token.NAME) {
            lvalue = Node.newString(Token.NAME, kid.getString());
        } else {
            reportError("msg.bad.for.in.lhs");
            return null;
        }
    } else if (type == Token.ARRAYLIT || type == Token.OBJECTLIT) {
        destructuring = type;
        lvalue = lhs;
        destructuringLen = 0;
        if (lhs instanceof ArrayLiteral)
            destructuringLen = ((ArrayLiteral) lhs).getDestructuringLength();
    } else {
        lvalue = makeReference(lhs);
        if (lvalue == null) {
            reportError("msg.bad.for.in.lhs");
            return null;
        }
    }
    Node localBlock = new Node(Token.LOCAL_BLOCK);
    int initType = isForEach ? Token.ENUM_INIT_VALUES : isForOf ? Token.ENUM_INIT_VALUES_IN_ORDER : (destructuring != -1 ? Token.ENUM_INIT_ARRAY : Token.ENUM_INIT_KEYS);
    Node init = new Node(initType, obj);
    init.putProp(Node.LOCAL_BLOCK_PROP, localBlock);
    Node cond = new Node(Token.ENUM_NEXT);
    cond.putProp(Node.LOCAL_BLOCK_PROP, localBlock);
    Node id = new Node(Token.ENUM_ID);
    id.putProp(Node.LOCAL_BLOCK_PROP, localBlock);
    Node newBody = new Node(Token.BLOCK);
    Node assign;
    if (destructuring != -1) {
        assign = createDestructuringAssignment(declType, lvalue, id);
        if (!isForEach && !isForOf && (destructuring == Token.OBJECTLIT || destructuringLen != 2)) {
            // destructuring assignment is only allowed in for..each or
            // with an array type of length 2 (to hold key and value)
            reportError("msg.bad.for.in.destruct");
        }
    } else {
        assign = simpleAssignment(lvalue, id);
    }
    newBody.addChildToBack(new Node(Token.EXPR_VOID, assign));
    newBody.addChildToBack(body);
    loop = createLoop((Jump) loop, LOOP_WHILE, newBody, cond, null, null);
    loop.addChildToFront(init);
    if (type == Token.VAR || type == Token.LET)
        loop.addChildToFront(lhs);
    localBlock.addChildToBack(loop);
    return localBlock;
}
Also used : ScriptNode(org.mozilla.javascript.ast.ScriptNode) AstNode(org.mozilla.javascript.ast.AstNode) LetNode(org.mozilla.javascript.ast.LetNode) FunctionNode(org.mozilla.javascript.ast.FunctionNode) ArrayLiteral(org.mozilla.javascript.ast.ArrayLiteral) Jump(org.mozilla.javascript.ast.Jump)

Example 13 with Jump

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

the class IRFactory method createTryCatchFinally.

/**
 * Try/Catch/Finally
 *
 * The IRFactory tries to express as much as possible in the tree;
 * the responsibilities remaining for Codegen are to add the Java
 * handlers: (Either (but not both) of TARGET and FINALLY might not
 * be defined)
 *
 * - a catch handler for javascript exceptions that unwraps the
 * exception onto the stack and GOTOes to the catch target
 *
 * - a finally handler
 *
 * ... and a goto to GOTO around these handlers.
 */
private Node createTryCatchFinally(Node tryBlock, Node catchBlocks, Node finallyBlock, int lineno) {
    boolean hasFinally = (finallyBlock != null) && (finallyBlock.getType() != Token.BLOCK || finallyBlock.hasChildren());
    // short circuit
    if (tryBlock.getType() == Token.BLOCK && !tryBlock.hasChildren() && !hasFinally) {
        return tryBlock;
    }
    boolean hasCatch = catchBlocks.hasChildren();
    // short circuit
    if (!hasFinally && !hasCatch) {
        // bc finally might be an empty block...
        return tryBlock;
    }
    Node handlerBlock = new Node(Token.LOCAL_BLOCK);
    Jump pn = new Jump(Token.TRY, tryBlock, lineno);
    pn.putProp(Node.LOCAL_BLOCK_PROP, handlerBlock);
    if (hasCatch) {
        // jump around catch code
        Node endCatch = Node.newTarget();
        pn.addChildToBack(makeJump(Token.GOTO, endCatch));
        // make a TARGET for the catch that the tcf node knows about
        Node catchTarget = Node.newTarget();
        pn.target = catchTarget;
        // mark it
        pn.addChildToBack(catchTarget);
        // 
        // Given
        // 
        // try {
        // tryBlock;
        // } catch (e if condition1) {
        // something1;
        // ...
        // 
        // } catch (e if conditionN) {
        // somethingN;
        // } catch (e) {
        // somethingDefault;
        // }
        // 
        // rewrite as
        // 
        // try {
        // tryBlock;
        // goto after_catch:
        // } catch (x) {
        // with (newCatchScope(e, x)) {
        // if (condition1) {
        // something1;
        // goto after_catch;
        // }
        // }
        // ...
        // with (newCatchScope(e, x)) {
        // if (conditionN) {
        // somethingN;
        // goto after_catch;
        // }
        // }
        // with (newCatchScope(e, x)) {
        // somethingDefault;
        // goto after_catch;
        // }
        // }
        // after_catch:
        // 
        // If there is no default catch, then the last with block
        // arround  "somethingDefault;" is replaced by "rethrow;"
        // It is assumed that catch handler generation will store
        // exeception object in handlerBlock register
        // Block with local for exception scope objects
        Node catchScopeBlock = new Node(Token.LOCAL_BLOCK);
        // expects catchblocks children to be (cond block) pairs.
        Node cb = catchBlocks.getFirstChild();
        boolean hasDefault = false;
        int scopeIndex = 0;
        while (cb != null) {
            int catchLineNo = cb.getLineno();
            Node name = cb.getFirstChild();
            Node cond = name.getNext();
            Node catchStatement = cond.getNext();
            cb.removeChild(name);
            cb.removeChild(cond);
            cb.removeChild(catchStatement);
            // Add goto to the catch statement to jump out of catch
            // but prefix it with LEAVEWITH since try..catch produces
            // "with"code in order to limit the scope of the exception
            // object.
            catchStatement.addChildToBack(new Node(Token.LEAVEWITH));
            catchStatement.addChildToBack(makeJump(Token.GOTO, endCatch));
            // Create condition "if" when present
            Node condStmt;
            if (cond.getType() == Token.EMPTY) {
                condStmt = catchStatement;
                hasDefault = true;
            } else {
                condStmt = createIf(cond, catchStatement, null, catchLineNo);
            }
            // Generate code to create the scope object and store
            // it in catchScopeBlock register
            Node catchScope = new Node(Token.CATCH_SCOPE, name, createUseLocal(handlerBlock));
            catchScope.putProp(Node.LOCAL_BLOCK_PROP, catchScopeBlock);
            catchScope.putIntProp(Node.CATCH_SCOPE_PROP, scopeIndex);
            catchScopeBlock.addChildToBack(catchScope);
            // Add with statement based on catch scope object
            catchScopeBlock.addChildToBack(createWith(createUseLocal(catchScopeBlock), condStmt, catchLineNo));
            // move to next cb
            cb = cb.getNext();
            ++scopeIndex;
        }
        pn.addChildToBack(catchScopeBlock);
        if (!hasDefault) {
            // Generate code to rethrow if no catch clause was executed
            Node rethrow = new Node(Token.RETHROW);
            rethrow.putProp(Node.LOCAL_BLOCK_PROP, handlerBlock);
            pn.addChildToBack(rethrow);
        }
        pn.addChildToBack(endCatch);
    }
    if (hasFinally) {
        Node finallyTarget = Node.newTarget();
        pn.setFinally(finallyTarget);
        // add jsr finally to the try block
        pn.addChildToBack(makeJump(Token.JSR, finallyTarget));
        // jump around finally code
        Node finallyEnd = Node.newTarget();
        pn.addChildToBack(makeJump(Token.GOTO, finallyEnd));
        pn.addChildToBack(finallyTarget);
        Node fBlock = new Node(Token.FINALLY, finallyBlock);
        fBlock.putProp(Node.LOCAL_BLOCK_PROP, handlerBlock);
        pn.addChildToBack(fBlock);
        pn.addChildToBack(finallyEnd);
    }
    handlerBlock.addChildToBack(pn);
    return handlerBlock;
}
Also used : ScriptNode(org.mozilla.javascript.ast.ScriptNode) AstNode(org.mozilla.javascript.ast.AstNode) LetNode(org.mozilla.javascript.ast.LetNode) FunctionNode(org.mozilla.javascript.ast.FunctionNode) Jump(org.mozilla.javascript.ast.Jump)

Example 14 with Jump

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

the class IRFactory method createIf.

private Node createIf(Node cond, Node ifTrue, Node ifFalse, int lineno) {
    int condStatus = isAlwaysDefinedBoolean(cond);
    if (condStatus == ALWAYS_TRUE_BOOLEAN) {
        return ifTrue;
    } else if (condStatus == ALWAYS_FALSE_BOOLEAN) {
        if (ifFalse != null) {
            return ifFalse;
        }
        // Replace if (false) xxx by empty block
        return new Node(Token.BLOCK, lineno);
    }
    Node result = new Node(Token.BLOCK, lineno);
    Node ifNotTarget = Node.newTarget();
    Jump IFNE = new Jump(Token.IFNE, cond);
    IFNE.target = ifNotTarget;
    result.addChildToBack(IFNE);
    result.addChildrenToBack(ifTrue);
    if (ifFalse != null) {
        Node endTarget = Node.newTarget();
        result.addChildToBack(makeJump(Token.GOTO, endTarget));
        result.addChildToBack(ifNotTarget);
        result.addChildrenToBack(ifFalse);
        result.addChildToBack(endTarget);
    } else {
        result.addChildToBack(ifNotTarget);
    }
    return result;
}
Also used : ScriptNode(org.mozilla.javascript.ast.ScriptNode) AstNode(org.mozilla.javascript.ast.AstNode) LetNode(org.mozilla.javascript.ast.LetNode) FunctionNode(org.mozilla.javascript.ast.FunctionNode) Jump(org.mozilla.javascript.ast.Jump)

Example 15 with Jump

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

the class IRFactory method makeJump.

private Jump makeJump(int type, Node target) {
    Jump n = new Jump(type);
    n.target = target;
    return n;
}
Also used : Jump(org.mozilla.javascript.ast.Jump)

Aggregations

Jump (org.mozilla.javascript.ast.Jump)18 FunctionNode (org.mozilla.javascript.ast.FunctionNode)16 ScriptNode (org.mozilla.javascript.ast.ScriptNode)16 AstNode (org.mozilla.javascript.ast.AstNode)6 LetNode (org.mozilla.javascript.ast.LetNode)6 Scope (org.mozilla.javascript.ast.Scope)4 Name (org.mozilla.javascript.ast.Name)3 Iterator (java.util.Iterator)2 ArrayLiteral (org.mozilla.javascript.ast.ArrayLiteral)1 BreakStatement (org.mozilla.javascript.ast.BreakStatement)1 LabeledStatement (org.mozilla.javascript.ast.LabeledStatement)1