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

📄 irfactory.java

📁 java中比较著名的js引擎当属mozilla开源的rhino
💻 JAVA
📖 第 1 页 / 共 4 页
字号:
                FunctionNode fn = fnNode.getFunctionNode(i);                // nested function expression statements overrides var                if (fn.getFunctionType()                        == FunctionNode.FUNCTION_EXPRESSION_STATEMENT)                {                    String name = fn.getFunctionName();                    if (name != null && name.length() != 0) {                        fnNode.removeParamOrVar(name);                    }                }            }        }        if (functionType == FunctionNode.FUNCTION_EXPRESSION) {            String name = fnNode.getFunctionName();            if (name != null && name.length() != 0                && !fnNode.hasParamOrVar(name))            {                // A function expression needs to have its name as a                // variable (if it isn't already allocated as a variable).                // See ECMA Ch. 13.  We add code to the beginning of the                // function to initialize a local variable of the                // function's name to the function value.                fnNode.addVar(name);                Node setFn = new Node(Token.EXPR_VOID,                                 new Node(Token.SETNAME,                                     Node.newString(Token.BINDNAME, name),                                     new Node(Token.THISFN)));                statements.addChildrenToFront(setFn);            }        }        // Add return to end if needed.        Node lastStmt = statements.getLastChild();        if (lastStmt == null || lastStmt.getType() != Token.RETURN) {            statements.addChildToBack(new Node(Token.RETURN));        }        Node result = Node.newString(Token.FUNCTION,                                     fnNode.getFunctionName());        result.putIntProp(Node.FUNCTION_PROP, functionIndex);        return result;    }    /**     * 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 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.Jump(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)    {        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) {                if (init.getType() != Token.EMPTY) {                    if (init.getType() != Token.VAR) {                        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(Node loop, Node lhs, Node obj, Node body,                     boolean isForEach)    {        String name;        int type = lhs.getType();        Node lvalue;        if (type == Token.VAR) {            /*             * 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.             */            Node lastChild = lhs.getLastChild();            if (lhs.getFirstChild() != lastChild) {                parser.reportError("msg.mult.index");            }            lvalue = Node.newString(Token.NAME, lastChild.getString());        } 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                                   : 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 = 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)            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);

⌨️ 快捷键说明

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