⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 irfactory.java

📁 這是一個javascript 的 interpreter是了解 web browser的好材料
💻 JAVA
📖 第 1 页 / 共 4 页
字号:
    /**     * Add a child to the back of the given node.  This function     * breaks the Factory abstraction, but it removes a requirement     * from implementors of Node.     */    void addChildToBack(Node parent, Node child)    {        parent.addChildToBack(child);    }    /**     * Create a node that can be used to hold lexically scoped variable     * definitions (via let declarations).     *      * @param token the token of the node to create     * @param lineno line number of source     * @return the created node     */    Node createScopeNode(int token, int lineno) {        return new Node.Scope(token, lineno);    }    /**     * Create loop node. The parser will later call     * createWhile|createDoWhile|createFor|createForIn     * to finish loop generation.     */    Node createLoopNode(Node loopLabel, int lineno)    {        Node.Jump result = new Node.Scope(Token.LOOP, lineno);        if (loopLabel != null) {            ((Node.Jump)loopLabel).setLoop(result);        }        return result;    }    /**     * While     */    Node createWhile(Node loop, Node cond, Node body)    {        return createLoop((Node.Jump)loop, LOOP_WHILE, body, cond,                          null, null);    }    /**     * DoWhile     */    Node createDoWhile(Node loop, Node body, Node cond)    {        return createLoop((Node.Jump)loop, LOOP_DO_WHILE, body, cond,                          null, null);    }    /**     * For     */    Node createFor(Node 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.            Node.Scope let = Node.Scope.splitScope((Node.Scope)loop);            let.setType(Token.LET);            let.addChildrenToBack(init);            let.addChildToBack(createLoop((Node.Jump)loop, LOOP_FOR, body, test,                new Node(Token.EMPTY), incr));            return let;        }        return createLoop((Node.Jump)loop, LOOP_FOR, body, test, init, incr);    }    private Node createLoop(Node.Jump loop, int loopType, Node body, Node cond,                            Node init, Node incr)    {        Node bodyTarget = Node.newTarget();        Node condTarget = Node.newTarget();        if (loopType == LOOP_FOR && cond.getType() == Token.EMPTY) {            cond = new Node(Token.TRUE);        }        Node.Jump IFEQ = new Node.Jump(Token.IFEQ, cond);        IFEQ.target = bodyTarget;        Node breakTarget = Node.newTarget();        loop.addChildToBack(bodyTarget);        loop.addChildrenToBack(body);        if (loopType == LOOP_WHILE || loopType == LOOP_FOR) {            // propagate lineno to condition            loop.addChildrenToBack(new Node(Token.EMPTY, loop.getLineno()));        }        loop.addChildToBack(condTarget);        loop.addChildToBack(IFEQ);        loop.addChildToBack(breakTarget);        loop.target = breakTarget;        Node continueTarget = condTarget;        if (loopType == LOOP_WHILE || loopType == LOOP_FOR) {            // Just add a GOTO to the condition in the do..while            loop.addChildToFront(makeJump(Token.GOTO, condTarget));            if (loopType == LOOP_FOR) {                int initType = init.getType();                if (initType != Token.EMPTY) {                    if (initType != Token.VAR && initType != Token.LET) {                        init = new Node(Token.EXPR_VOID, init);                    }                    loop.addChildToFront(init);                }                Node incrTarget = Node.newTarget();                loop.addChildAfter(incrTarget, body);                if (incr.getType() != Token.EMPTY) {                    incr = new Node(Token.EXPR_VOID, incr);                    loop.addChildAfter(incr, incrTarget);                }                continueTarget = incrTarget;            }        }        loop.setContinue(continueTarget);        return loop;    }    /**     * For .. In     *     */    Node createForIn(int declType, Node loop, Node lhs, Node obj, Node body,                     boolean isForEach)    {        int destructuring = -1;        int destructuringLen = 0;        Node lvalue;        int type = lhs.getType();        if (type == Token.VAR || type == Token.LET) {            Node lastChild = lhs.getLastChild();            if (lhs.getFirstChild() != lastChild) {                /*                 * check that there was only one variable given.                 * we can't do this in the parser, because then the                 * parser would have to know something about the                 * 'init' node of the for-in loop.                 */                parser.reportError("msg.mult.index");            }            if (lastChild.getType() == Token.ARRAYLIT ||                lastChild.getType() == Token.OBJECTLIT)            {                type = destructuring = lastChild.getType();                lvalue = lastChild;                destructuringLen = lastChild.getIntProp(                    Node.DESTRUCTURING_ARRAY_LENGTH, 0);            } else if (lastChild.getType() == Token.NAME) {                lvalue = Node.newString(Token.NAME, lastChild.getString());            } else {                parser.reportError("msg.bad.for.in.lhs");                return obj;            }        } else if (type == Token.ARRAYLIT || type == Token.OBJECTLIT) {            destructuring = type;            lvalue = lhs;            destructuringLen = lhs.getIntProp(Node.DESTRUCTURING_ARRAY_LENGTH, 0);        } else {            lvalue = makeReference(lhs);            if (lvalue == null) {                parser.reportError("msg.bad.for.in.lhs");                return obj;            }        }        Node localBlock = new Node(Token.LOCAL_BLOCK);        int initType = (isForEach)           ? Token.ENUM_INIT_VALUES :                       (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 && (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)                parser.reportError("msg.bad.for.in.destruct");            }        } else {            assign = simpleAssignment(lvalue, id);        }        newBody.addChildToBack(new Node(Token.EXPR_VOID, assign));        newBody.addChildToBack(body);        loop = createWhile(loop, cond, newBody);        loop.addChildToFront(init);        if (type == Token.VAR || type == Token.LET)            loop.addChildToFront(lhs);        localBlock.addChildToBack(loop);        return localBlock;    }    /**     * 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.     */    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);        Node.Jump pn = new Node.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;    }    /**     * Throw, Return, Label, Break and Continue are defined in ASTFactory.     */    /**     * With     */    Node createWith(Node obj, Node body, int lineno)

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -