📄 irfactory.java
字号:
/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- * * ***** BEGIN LICENSE BLOCK ***** * Version: MPL 1.1/GPL 2.0 * * The contents of this file are subject to the Mozilla Public License Version * 1.1 (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * http://www.mozilla.org/MPL/ * * Software distributed under the License is distributed on an "AS IS" basis, * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License * for the specific language governing rights and limitations under the * License. * * The Original Code is Rhino code, released * May 6, 1999. * * The Initial Developer of the Original Code is * Netscape Communications Corporation. * Portions created by the Initial Developer are Copyright (C) 1997-1999 * the Initial Developer. All Rights Reserved. * * Contributor(s): * Norris Boyd * Igor Bukanov * Ethan Hugg * Bob Jervis * Terry Lucas * Milen Nankov * * Alternatively, the contents of this file may be used under the terms of * the GNU General Public License Version 2 or later (the "GPL"), in which * case the provisions of the GPL are applicable instead of those above. If * you wish to allow use of your version of this file only under the terms of * the GPL and not to allow others to use your version of this file under the * MPL, indicate your decision by deleting the provisions above and replacing * them with the notice and other provisions required by the GPL. If you do * not delete the provisions above, a recipient may use your version of this * file under either the MPL or the GPL. * * ***** END LICENSE BLOCK ***** */package org.mozilla.javascript;import java.util.List;import java.util.ArrayList;/** * This class allows the creation of nodes, and follows the Factory pattern. * * @see Node * @author Mike McCabe * @author Norris Boyd */final class IRFactory{ IRFactory(Parser parser) { this.parser = parser; } ScriptOrFnNode createScript() { return new ScriptOrFnNode(Token.SCRIPT); } /** * Script (for associating file/url names with toplevel scripts.) */ void initScript(ScriptOrFnNode scriptNode, Node body) { Node children = body.getFirstChild(); if (children != null) { scriptNode.addChildrenToBack(children); } } /** * Leaf */ Node createLeaf(int nodeType) { return new Node(nodeType); } /** * Statement leaf nodes. */ Node createSwitch(Node expr, int lineno) { // // The switch will be rewritten from: // // switch (expr) { // case test1: statements1; // ... // default: statementsDefault; // ... // case testN: statementsN; // } // // to: // // { // switch (expr) { // case test1: goto label1; // ... // case testN: goto labelN; // } // goto labelDefault; // label1: // statements1; // ... // labelDefault: // statementsDefault; // ... // labelN: // statementsN; // breakLabel: // } // // where inside switch each "break;" without label will be replaced // by "goto breakLabel". // // If the original switch does not have the default label, then // the transformed code would contain after the switch instead of // goto labelDefault; // the following goto: // goto breakLabel; // Node.Jump switchNode = new Node.Jump(Token.SWITCH, expr, lineno); Node block = new Node(Token.BLOCK, switchNode); return block; } /** * If caseExpression argument is null it indicate default label. */ void addSwitchCase(Node switchBlock, Node caseExpression, Node statements) { if (switchBlock.getType() != Token.BLOCK) throw Kit.codeBug(); Node.Jump switchNode = (Node.Jump)switchBlock.getFirstChild(); if (switchNode.getType() != Token.SWITCH) throw Kit.codeBug(); Node gotoTarget = Node.newTarget(); if (caseExpression != null) { Node.Jump caseNode = new Node.Jump(Token.CASE, caseExpression); caseNode.target = gotoTarget; switchNode.addChildToBack(caseNode); } else { switchNode.setDefault(gotoTarget); } switchBlock.addChildToBack(gotoTarget); switchBlock.addChildToBack(statements); } void closeSwitch(Node switchBlock) { if (switchBlock.getType() != Token.BLOCK) throw Kit.codeBug(); Node.Jump switchNode = (Node.Jump)switchBlock.getFirstChild(); if (switchNode.getType() != Token.SWITCH) throw Kit.codeBug(); Node switchBreakTarget = Node.newTarget(); // switchNode.target is only used by NodeTransformer // to detect switch end switchNode.target = switchBreakTarget; Node defaultTarget = switchNode.getDefault(); if (defaultTarget == null) { defaultTarget = switchBreakTarget; } switchBlock.addChildAfter(makeJump(Token.GOTO, defaultTarget), switchNode); switchBlock.addChildToBack(switchBreakTarget); } Node createVariables(int token, int lineno) { return new Node(token, lineno); } Node createExprStatement(Node expr, int lineno) { int type; if (parser.insideFunction()) { type = Token.EXPR_VOID; } else { type = Token.EXPR_RESULT; } return new Node(type, expr, lineno); } Node createExprStatementNoReturn(Node expr, int lineno) { return new Node(Token.EXPR_VOID, expr, lineno); } Node createDefaultNamespace(Node expr, int lineno) { // default xml namespace requires activation setRequiresActivation(); Node n = createUnary(Token.DEFAULTNAMESPACE, expr); Node result = createExprStatement(n, lineno); return result; } /** * Name */ Node createName(String name) { checkActivationName(name, Token.NAME); return Node.newString(Token.NAME, name); } private Node createName(int type, String name, Node child) { Node result = createName(name); result.setType(type); if (child != null) result.addChildToBack(child); return result; } /** * String (for literals) */ Node createString(String string) { return Node.newString(string); } /** * Number (for literals) */ Node createNumber(double number) { return Node.newNumber(number); } /** * Catch clause of try/catch/finally * @param varName the name of the variable to bind to the exception * @param catchCond the condition under which to catch the exception. * May be null if no condition is given. * @param stmts the statements in the catch clause * @param lineno the starting line number of the catch clause */ Node createCatch(String varName, Node catchCond, Node stmts, int lineno) { if (catchCond == null) { catchCond = new Node(Token.EMPTY); } return new Node(Token.CATCH, createName(varName), catchCond, stmts, lineno); } /** * Throw */ Node createThrow(Node expr, int lineno) { return new Node(Token.THROW, expr, lineno); } /** * Return */ Node createReturn(Node expr, int lineno) { return expr == null ? new Node(Token.RETURN, lineno) : new Node(Token.RETURN, expr, lineno); } /** * Debugger */ Node createDebugger(int lineno) { return new Node(Token.DEBUGGER, lineno); } /** * Label */ Node createLabel(int lineno) { return new Node.Jump(Token.LABEL, lineno); } Node getLabelLoop(Node label) { return ((Node.Jump)label).getLoop(); } /** * Label */ Node createLabeledStatement(Node labelArg, Node statement) { Node.Jump label = (Node.Jump)labelArg; // Make a target and put it _after_ the statement // node. And in the LABEL node, so breaks get the // right target. Node breakTarget = Node.newTarget(); Node block = new Node(Token.BLOCK, label, statement, breakTarget); label.target = breakTarget; return block; } /** * Break (possibly labeled) */ Node createBreak(Node breakStatement, int lineno) { Node.Jump n = new Node.Jump(Token.BREAK, lineno); Node.Jump jumpStatement; int t = breakStatement.getType(); if (t == Token.LOOP || t == Token.LABEL) { jumpStatement = (Node.Jump)breakStatement; } else if (t == Token.BLOCK && breakStatement.getFirstChild().getType() == Token.SWITCH) { jumpStatement = (Node.Jump)breakStatement.getFirstChild(); } else { throw Kit.codeBug(); } n.setJumpStatement(jumpStatement); return n; } /** * Continue (possibly labeled) */ Node createContinue(Node loop, int lineno) { if (loop.getType() != Token.LOOP) Kit.codeBug(); Node.Jump n = new Node.Jump(Token.CONTINUE, lineno); n.setJumpStatement((Node.Jump)loop); return n; } /** * Statement block * Creates the empty statement block * Must make subsequent calls to add statements to the node */ Node createBlock(int lineno) { return new Node(Token.BLOCK, lineno); } FunctionNode createFunction(String name) { return new FunctionNode(name); } Node initFunction(FunctionNode fnNode, int functionIndex, Node statements, int functionType) { fnNode.itsFunctionType = functionType; fnNode.addChildToBack(statements); int functionCount = fnNode.getFunctionCount(); if (functionCount != 0) { // Functions containing other functions require activation objects fnNode.itsNeedsActivation = true; } if (functionType == FunctionNode.FUNCTION_EXPRESSION) { String name = fnNode.getFunctionName(); if (name != null && name.length() != 0) { // 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. 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; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -