Source Code Cross Referenced for IRFactory.java in  » IDE-Netbeans » library » org » mozilla » javascript » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » IDE Netbeans » library » org.mozilla.javascript 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
0002:         *
0003:         * ***** BEGIN LICENSE BLOCK *****
0004:         * Version: MPL 1.1/GPL 2.0
0005:         *
0006:         * The contents of this file are subject to the Mozilla Public License Version
0007:         * 1.1 (the "License"); you may not use this file except in compliance with
0008:         * the License. You may obtain a copy of the License at
0009:         * http://www.mozilla.org/MPL/
0010:         *
0011:         * Software distributed under the License is distributed on an "AS IS" basis,
0012:         * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
0013:         * for the specific language governing rights and limitations under the
0014:         * License.
0015:         *
0016:         * The Original Code is Rhino code, released
0017:         * May 6, 1999.
0018:         *
0019:         * The Initial Developer of the Original Code is
0020:         * Netscape Communications Corporation.
0021:         * Portions created by the Initial Developer are Copyright (C) 1997-1999
0022:         * the Initial Developer. All Rights Reserved.
0023:         *
0024:         * Contributor(s):
0025:         *   Norris Boyd
0026:         *   Igor Bukanov
0027:         *   Ethan Hugg
0028:         *   Bob Jervis
0029:         *   Terry Lucas
0030:         *   Milen Nankov
0031:         *
0032:         * Alternatively, the contents of this file may be used under the terms of
0033:         * the GNU General Public License Version 2 or later (the "GPL"), in which
0034:         * case the provisions of the GPL are applicable instead of those above. If
0035:         * you wish to allow use of your version of this file only under the terms of
0036:         * the GPL and not to allow others to use your version of this file under the
0037:         * MPL, indicate your decision by deleting the provisions above and replacing
0038:         * them with the notice and other provisions required by the GPL. If you do
0039:         * not delete the provisions above, a recipient may use your version of this
0040:         * file under either the MPL or the GPL.
0041:         *
0042:         * ***** END LICENSE BLOCK ***** */
0043:
0044:        package org.mozilla.javascript;
0045:
0046:        /**
0047:         * This class allows the creation of nodes, and follows the Factory pattern.
0048:         *
0049:         * @see Node
0050:         * @author Mike McCabe
0051:         * @author Norris Boyd
0052:         */
0053:        final class IRFactory {
0054:            IRFactory(Parser parser) {
0055:                this .parser = parser;
0056:            }
0057:
0058:            ScriptOrFnNode createScript() {
0059:                return new ScriptOrFnNode(Token.SCRIPT);
0060:            }
0061:
0062:            /**
0063:             * Script (for associating file/url names with toplevel scripts.)
0064:             */
0065:            void initScript(ScriptOrFnNode scriptNode, Node body) {
0066:                Node children = body.getFirstChild();
0067:                if (children != null) {
0068:                    scriptNode.addChildrenToBack(children);
0069:                }
0070:            }
0071:
0072:            /**
0073:             * Leaf
0074:             */
0075:            Node createLeaf(int nodeType) {
0076:                return new Node(nodeType);
0077:            }
0078:
0079:            Node createLeaf(int nodeType, int nodeOp) {
0080:                return new Node(nodeType, nodeOp);
0081:            }
0082:
0083:            /**
0084:             * Statement leaf nodes.
0085:             */
0086:
0087:            Node createSwitch(Node expr, int lineno) {
0088:                //
0089:                // The switch will be rewritten from:
0090:                //
0091:                // switch (expr) {
0092:                //   case test1: statements1;
0093:                //   ...
0094:                //   default: statementsDefault;
0095:                //   ...
0096:                //   case testN: statementsN;
0097:                // }
0098:                //
0099:                // to:
0100:                //
0101:                // {
0102:                //     switch (expr) {
0103:                //       case test1: goto label1;
0104:                //       ...
0105:                //       case testN: goto labelN;
0106:                //     }
0107:                //     goto labelDefault;
0108:                //   label1:
0109:                //     statements1;
0110:                //   ...
0111:                //   labelDefault:
0112:                //     statementsDefault;
0113:                //   ...
0114:                //   labelN:
0115:                //     statementsN;
0116:                //   breakLabel:
0117:                // }
0118:                //
0119:                // where inside switch each "break;" without label will be replaced
0120:                // by "goto breakLabel".
0121:                //
0122:                // If the original switch does not have the default label, then
0123:                // the transformed code would contain after the switch instead of
0124:                //     goto labelDefault;
0125:                // the following goto:
0126:                //     goto breakLabel;
0127:                //
0128:
0129:                Node.Jump switchNode = new Node.Jump(Token.SWITCH, expr, lineno);
0130:                Node block = new Node(Token.BLOCK, switchNode);
0131:                return block;
0132:            }
0133:
0134:            /**
0135:             * If caseExpression argument is null it indicate default label.
0136:             */
0137:            void addSwitchCase(Node switchBlock, Node caseExpression,
0138:                    Node statements) {
0139:                if (switchBlock.getType() != Token.BLOCK)
0140:                    throw Kit.codeBug();
0141:                Node.Jump switchNode = (Node.Jump) switchBlock.getFirstChild();
0142:                if (switchNode.getType() != Token.SWITCH)
0143:                    throw Kit.codeBug();
0144:
0145:                Node gotoTarget = Node.newTarget();
0146:                if (caseExpression != null) {
0147:                    Node.Jump caseNode = new Node.Jump(Token.CASE,
0148:                            caseExpression);
0149:                    caseNode.target = gotoTarget;
0150:                    switchNode.addChildToBack(caseNode);
0151:                } else {
0152:                    switchNode.setDefault(gotoTarget);
0153:                }
0154:                switchBlock.addChildToBack(gotoTarget);
0155:                switchBlock.addChildToBack(statements);
0156:            }
0157:
0158:            void closeSwitch(Node switchBlock) {
0159:                if (switchBlock.getType() != Token.BLOCK)
0160:                    throw Kit.codeBug();
0161:                Node.Jump switchNode = (Node.Jump) switchBlock.getFirstChild();
0162:                if (switchNode.getType() != Token.SWITCH)
0163:                    throw Kit.codeBug();
0164:
0165:                Node switchBreakTarget = Node.newTarget();
0166:                // switchNode.target is only used by NodeTransformer
0167:                // to detect switch end
0168:                switchNode.target = switchBreakTarget;
0169:
0170:                Node defaultTarget = switchNode.getDefault();
0171:                if (defaultTarget == null) {
0172:                    defaultTarget = switchBreakTarget;
0173:                }
0174:
0175:                switchBlock.addChildAfter(makeJump(Token.GOTO, defaultTarget),
0176:                        switchNode);
0177:                switchBlock.addChildToBack(switchBreakTarget);
0178:            }
0179:
0180:            Node createVariables(int token, int lineno) {
0181:                return new Node(token, lineno);
0182:            }
0183:
0184:            Node createExprStatement(Node expr, int lineno) {
0185:                int type;
0186:                if (parser.insideFunction()) {
0187:                    type = Token.EXPR_VOID;
0188:                } else {
0189:                    type = Token.EXPR_RESULT;
0190:                }
0191:                return new Node(type, expr, lineno);
0192:            }
0193:
0194:            Node createExprStatementNoReturn(Node expr, int lineno) {
0195:                return new Node(Token.EXPR_VOID, expr, lineno);
0196:            }
0197:
0198:            Node createDefaultNamespace(Node expr, int lineno) {
0199:                // default xml namespace requires activation
0200:                setRequiresActivation();
0201:                Node n = createUnary(Token.DEFAULTNAMESPACE, expr);
0202:                Node result = createExprStatement(n, lineno);
0203:                return result;
0204:            }
0205:
0206:            /**
0207:             * Name
0208:             */
0209:            Node createName(String name) {
0210:                checkActivationName(name, Token.NAME);
0211:                return Node.newString(Token.NAME, name);
0212:            }
0213:
0214:            /**
0215:             * String (for literals)
0216:             */
0217:            Node createString(String string) {
0218:                return Node.newString(string);
0219:            }
0220:
0221:            /**
0222:             * Number (for literals)
0223:             */
0224:            Node createNumber(double number) {
0225:                return Node.newNumber(number);
0226:            }
0227:
0228:            /**
0229:             * Catch clause of try/catch/finally
0230:             * @param varName the name of the variable to bind to the exception
0231:             * @param catchCond the condition under which to catch the exception.
0232:             *                  May be null if no condition is given.
0233:             * @param stmts the statements in the catch clause
0234:             * @param lineno the starting line number of the catch clause
0235:             */
0236:            Node createCatch(String varName, Node catchCond, Node stmts,
0237:                    int lineno) {
0238:                if (catchCond == null) {
0239:                    catchCond = new Node(Token.EMPTY);
0240:                }
0241:                return new Node(Token.CATCH, createName(varName), catchCond,
0242:                        stmts, lineno);
0243:            }
0244:
0245:            /**
0246:             * Throw
0247:             */
0248:            Node createThrow(Node expr, int lineno) {
0249:                return new Node(Token.THROW, expr, lineno);
0250:            }
0251:
0252:            /**
0253:             * Return
0254:             */
0255:            Node createReturn(Node expr, int lineno) {
0256:                return expr == null ? new Node(Token.RETURN, lineno)
0257:                        : new Node(Token.RETURN, expr, lineno);
0258:            }
0259:
0260:            /**
0261:             * Label
0262:             */
0263:            Node createLabel(int lineno) {
0264:                return new Node.Jump(Token.LABEL, lineno);
0265:            }
0266:
0267:            Node getLabelLoop(Node label) {
0268:                return ((Node.Jump) label).getLoop();
0269:            }
0270:
0271:            /**
0272:             * Label
0273:             */
0274:            Node createLabeledStatement(Node labelArg, Node statement) {
0275:                Node.Jump label = (Node.Jump) labelArg;
0276:
0277:                // Make a target and put it _after_ the statement
0278:                // node.  And in the LABEL node, so breaks get the
0279:                // right target.
0280:
0281:                Node breakTarget = Node.newTarget();
0282:                Node block = new Node(Token.BLOCK, label, statement,
0283:                        breakTarget);
0284:                label.target = breakTarget;
0285:
0286:                return block;
0287:            }
0288:
0289:            /**
0290:             * Break (possibly labeled)
0291:             */
0292:            Node createBreak(Node breakStatement, int lineno) {
0293:                Node.Jump n = new Node.Jump(Token.BREAK, lineno);
0294:                Node.Jump jumpStatement;
0295:                int t = breakStatement.getType();
0296:                if (t == Token.LOOP || t == Token.LABEL) {
0297:                    jumpStatement = (Node.Jump) breakStatement;
0298:                } else if (t == Token.BLOCK
0299:                        && breakStatement.getFirstChild().getType() == Token.SWITCH) {
0300:                    jumpStatement = (Node.Jump) breakStatement.getFirstChild();
0301:                } else {
0302:                    throw Kit.codeBug();
0303:                }
0304:                n.setJumpStatement(jumpStatement);
0305:                return n;
0306:            }
0307:
0308:            /**
0309:             * Continue (possibly labeled)
0310:             */
0311:            Node createContinue(Node loop, int lineno) {
0312:                if (loop.getType() != Token.LOOP)
0313:                    Kit.codeBug();
0314:                Node.Jump n = new Node.Jump(Token.CONTINUE, lineno);
0315:                n.setJumpStatement((Node.Jump) loop);
0316:                return n;
0317:            }
0318:
0319:            /**
0320:             * Statement block
0321:             * Creates the empty statement block
0322:             * Must make subsequent calls to add statements to the node
0323:             */
0324:            Node createBlock(int lineno) {
0325:                return new Node(Token.BLOCK, lineno);
0326:            }
0327:
0328:            FunctionNode createFunction(String name) {
0329:                return new FunctionNode(name);
0330:            }
0331:
0332:            Node initFunction(FunctionNode fnNode, int functionIndex,
0333:                    Node statements, int functionType) {
0334:                fnNode.itsFunctionType = functionType;
0335:                fnNode.addChildToBack(statements);
0336:
0337:                int functionCount = fnNode.getFunctionCount();
0338:                if (functionCount != 0) {
0339:                    // Functions containing other functions require activation objects
0340:                    fnNode.itsNeedsActivation = true;
0341:                    for (int i = 0; i != functionCount; ++i) {
0342:                        FunctionNode fn = fnNode.getFunctionNode(i);
0343:                        // nested function expression statements overrides var
0344:                        if (fn.getFunctionType() == FunctionNode.FUNCTION_EXPRESSION_STATEMENT) {
0345:                            String name = fn.getFunctionName();
0346:                            if (name != null && name.length() != 0) {
0347:                                fnNode.removeParamOrVar(name);
0348:                            }
0349:                        }
0350:                    }
0351:                }
0352:
0353:                if (functionType == FunctionNode.FUNCTION_EXPRESSION) {
0354:                    String name = fnNode.getFunctionName();
0355:                    if (name != null && name.length() != 0
0356:                            && !fnNode.hasParamOrVar(name)) {
0357:                        // A function expression needs to have its name as a
0358:                        // variable (if it isn't already allocated as a variable).
0359:                        // See ECMA Ch. 13.  We add code to the beginning of the
0360:                        // function to initialize a local variable of the
0361:                        // function's name to the function value.
0362:                        if (fnNode.addVar(name) == ScriptOrFnNode.DUPLICATE_CONST)
0363:                            parser.addError("msg.const.redecl", name, null);
0364:                        Node setFn = new Node(Token.EXPR_VOID, new Node(
0365:                                Token.SETNAME, Node.newString(Token.BINDNAME,
0366:                                        name), new Node(Token.THISFN)));
0367:                        statements.addChildrenToFront(setFn);
0368:                    }
0369:                }
0370:
0371:                // Add return to end if needed.
0372:                Node lastStmt = statements.getLastChild();
0373:                if (lastStmt == null || lastStmt.getType() != Token.RETURN) {
0374:                    statements.addChildToBack(new Node(Token.RETURN));
0375:                }
0376:
0377:                // <netbeans>
0378:                //        Node result = Node.newString(Token.FUNCTION,
0379:                //                                     fnNode.getFunctionName());
0380:                //        result.putIntProp(Node.FUNCTION_PROP, functionIndex);
0381:                //        // Track functions directly in the AST
0382:                //        result.addChildToBack(fnNode);
0383:                Node result = fnNode;
0384:                // </netbeans>
0385:                return result;
0386:            }
0387:
0388:            /**
0389:             * Add a child to the back of the given node.  This function
0390:             * breaks the Factory abstraction, but it removes a requirement
0391:             * from implementors of Node.
0392:             */
0393:            void addChildToBack(Node parent, Node child) {
0394:                parent.addChildToBack(child);
0395:            }
0396:
0397:            /**
0398:             * Create loop node. The parser will later call
0399:             * createWhile|createDoWhile|createFor|createForIn
0400:             * to finish loop generation.
0401:             */
0402:            Node createLoopNode(Node loopLabel, int lineno) {
0403:                Node.Jump result = new Node.Jump(Token.LOOP, lineno);
0404:                if (loopLabel != null) {
0405:                    ((Node.Jump) loopLabel).setLoop(result);
0406:                }
0407:                return result;
0408:            }
0409:
0410:            /**
0411:             * While
0412:             */
0413:            Node createWhile(Node loop, Node cond, Node body) {
0414:                return createLoop((Node.Jump) loop, LOOP_WHILE, body, cond,
0415:                        null, null);
0416:            }
0417:
0418:            /**
0419:             * DoWhile
0420:             */
0421:            Node createDoWhile(Node loop, Node body, Node cond) {
0422:                return createLoop((Node.Jump) loop, LOOP_DO_WHILE, body, cond,
0423:                        null, null);
0424:            }
0425:
0426:            /**
0427:             * For
0428:             */
0429:            Node createFor(Node loop, Node init, Node test, Node incr, Node body) {
0430:                return createLoop((Node.Jump) loop, LOOP_FOR, body, test, init,
0431:                        incr);
0432:            }
0433:
0434:            private Node createLoop(Node.Jump loop, int loopType, Node body,
0435:                    Node cond, Node init, Node incr) {
0436:                Node bodyTarget = Node.newTarget();
0437:                Node condTarget = Node.newTarget();
0438:                // <netbeans>
0439:                int sourceOffset = parser.getStartOffset();
0440:                bodyTarget.setSourceBounds(body.getSourceStart(), body
0441:                        .getSourceStart());
0442:                condTarget.setSourceBounds(cond.getSourceStart(), cond
0443:                        .getSourceStart());
0444:                // </netbeans>        
0445:                if (loopType == LOOP_FOR && cond.getType() == Token.EMPTY) {
0446:                    cond = new Node(Token.TRUE);
0447:                }
0448:                Node.Jump IFEQ = new Node.Jump(Token.IFEQ, cond);
0449:                IFEQ.target = bodyTarget;
0450:                Node breakTarget = Node.newTarget();
0451:                // <netbeans>
0452:                breakTarget.setSourceBounds(sourceOffset, sourceOffset);
0453:                // </netbeans>        
0454:
0455:                loop.addChildToBack(bodyTarget);
0456:                loop.addChildrenToBack(body);
0457:                if (loopType == LOOP_WHILE || loopType == LOOP_FOR) {
0458:                    // propagate lineno to condition
0459:                    loop.addChildrenToBack(new Node(Token.EMPTY, loop
0460:                            .getLineno()));
0461:                }
0462:                loop.addChildToBack(condTarget);
0463:                loop.addChildToBack(IFEQ);
0464:                loop.addChildToBack(breakTarget);
0465:
0466:                loop.target = breakTarget;
0467:                Node continueTarget = condTarget;
0468:
0469:                if (loopType == LOOP_WHILE || loopType == LOOP_FOR) {
0470:                    // Just add a GOTO to the condition in the do..while
0471:                    loop.addChildToFront(makeJump(Token.GOTO, condTarget));
0472:
0473:                    if (loopType == LOOP_FOR) {
0474:                        if (init.getType() != Token.EMPTY) {
0475:                            if (init.getType() != Token.VAR) {
0476:                                init = new Node(Token.EXPR_VOID, init);
0477:                            }
0478:                            loop.addChildToFront(init);
0479:                        }
0480:                        Node incrTarget = Node.newTarget();
0481:                        // <netbeans>
0482:                        incrTarget.setSourceBounds(sourceOffset, sourceOffset);
0483:                        // </netbeans>        
0484:                        loop.addChildAfter(incrTarget, body);
0485:                        if (incr.getType() != Token.EMPTY) {
0486:                            incr = new Node(Token.EXPR_VOID, incr);
0487:                            loop.addChildAfter(incr, incrTarget);
0488:                        }
0489:                        continueTarget = incrTarget;
0490:                    }
0491:                }
0492:
0493:                loop.setContinue(continueTarget);
0494:
0495:                return loop;
0496:            }
0497:
0498:            /**
0499:             * For .. In
0500:             *
0501:             */
0502:            Node createForIn(Node loop, Node lhs, Node obj, Node body,
0503:                    boolean isForEach) {
0504:                // <netbeans>
0505:                int startOffset = loop.getSourceStart();
0506:                // </netbeans>
0507:                int type = lhs.getType();
0508:
0509:                Node lvalue;
0510:                if (type == Token.VAR) {
0511:                    /*
0512:                     * check that there was only one variable given.
0513:                     * we can't do this in the parser, because then the
0514:                     * parser would have to know something about the
0515:                     * 'init' node of the for-in loop.
0516:                     */
0517:                    Node lastChild = lhs.getLastChild();
0518:                    if (lhs.getFirstChild() != lastChild) {
0519:                        parser.reportError("msg.mult.index");
0520:                    }
0521:                    lvalue = Node.newString(Token.NAME, lastChild.getString());
0522:                    // <netbeans>
0523:                    //parser.setSourceOffsets(lvalue, parser.getStartOffset());
0524:                    lvalue.setSourceBounds(lastChild.getSourceStart(),
0525:                            lastChild.getSourceEnd());
0526:                    // </netbeans>
0527:                } else {
0528:                    lvalue = makeReference(lhs);
0529:                    if (lvalue == null) {
0530:                        parser.reportError("msg.bad.for.in.lhs");
0531:                        return obj;
0532:                    }
0533:                }
0534:
0535:                Node localBlock = new Node(Token.LOCAL_BLOCK);
0536:
0537:                int initType = (isForEach) ? Token.ENUM_INIT_VALUES
0538:                        : Token.ENUM_INIT_KEYS;
0539:                Node init = new Node(initType, obj);
0540:                init.putProp(Node.LOCAL_BLOCK_PROP, localBlock);
0541:                Node cond = new Node(Token.ENUM_NEXT);
0542:                cond.putProp(Node.LOCAL_BLOCK_PROP, localBlock);
0543:                Node id = new Node(Token.ENUM_ID);
0544:                id.putProp(Node.LOCAL_BLOCK_PROP, localBlock);
0545:
0546:                Node newBody = new Node(Token.BLOCK);
0547:                Node assign = simpleAssignment(lvalue, id);
0548:                // <netbeans>
0549:                assign.setSourceBounds(lvalue.getSourceStart(), lvalue
0550:                        .getSourceEnd());
0551:                // </netbeans>
0552:                newBody.addChildToBack(new Node(Token.EXPR_VOID, assign));
0553:                newBody.addChildToBack(body);
0554:                // <netbeans>
0555:                newBody.setSourceBounds(body.getSourceStart(), body
0556:                        .getSourceEnd());
0557:                // </netbeans>
0558:
0559:                loop = createWhile(loop, cond, newBody);
0560:                loop.addChildToFront(init);
0561:                if (type == Token.VAR)
0562:                    loop.addChildToFront(lhs);
0563:                localBlock.addChildToBack(loop);
0564:                // <netbeans>
0565:                localBlock.setSourceBounds(startOffset, parser.getEndOffset());
0566:                // </netbeans>
0567:
0568:                return localBlock;
0569:            }
0570:
0571:            /**
0572:             * Try/Catch/Finally
0573:             *
0574:             * The IRFactory tries to express as much as possible in the tree;
0575:             * the responsibilities remaining for Codegen are to add the Java
0576:             * handlers: (Either (but not both) of TARGET and FINALLY might not
0577:             * be defined)
0578:
0579:             * - a catch handler for javascript exceptions that unwraps the
0580:             * exception onto the stack and GOTOes to the catch target
0581:
0582:             * - a finally handler
0583:
0584:             * ... and a goto to GOTO around these handlers.
0585:             */
0586:            Node createTryCatchFinally(Node tryBlock, Node catchBlocks,
0587:                    Node finallyBlock, int lineno) {
0588:                // <netbeans>
0589:                int startOffset = tryBlock.getSourceStart();
0590:                // </netbeans>
0591:                boolean hasFinally = (finallyBlock != null)
0592:                        && (finallyBlock.getType() != Token.BLOCK || finallyBlock
0593:                                .hasChildren());
0594:
0595:                // short circuit
0596:                if (tryBlock.getType() == Token.BLOCK
0597:                        && !tryBlock.hasChildren() && !hasFinally) {
0598:                    return tryBlock;
0599:                }
0600:
0601:                boolean hasCatch = catchBlocks.hasChildren();
0602:
0603:                // short circuit
0604:                if (!hasFinally && !hasCatch) {
0605:                    // bc finally might be an empty block...
0606:                    return tryBlock;
0607:                }
0608:
0609:                Node handlerBlock = new Node(Token.LOCAL_BLOCK);
0610:                Node.Jump pn = new Node.Jump(Token.TRY, tryBlock, lineno);
0611:                pn.putProp(Node.LOCAL_BLOCK_PROP, handlerBlock);
0612:
0613:                if (hasCatch) {
0614:                    // jump around catch code
0615:                    Node endCatch = Node.newTarget();
0616:                    pn.addChildToBack(makeJump(Token.GOTO, endCatch));
0617:
0618:                    // make a TARGET for the catch that the tcf node knows about
0619:                    Node catchTarget = Node.newTarget();
0620:                    pn.target = catchTarget;
0621:                    // mark it
0622:                    pn.addChildToBack(catchTarget);
0623:
0624:                    //
0625:                    //  Given
0626:                    //
0627:                    //   try {
0628:                    //       tryBlock;
0629:                    //   } catch (e if condition1) {
0630:                    //       something1;
0631:                    //   ...
0632:                    //
0633:                    //   } catch (e if conditionN) {
0634:                    //       somethingN;
0635:                    //   } catch (e) {
0636:                    //       somethingDefault;
0637:                    //   }
0638:                    //
0639:                    //  rewrite as
0640:                    //
0641:                    //   try {
0642:                    //       tryBlock;
0643:                    //       goto after_catch:
0644:                    //   } catch (x) {
0645:                    //       with (newCatchScope(e, x)) {
0646:                    //           if (condition1) {
0647:                    //               something1;
0648:                    //               goto after_catch;
0649:                    //           }
0650:                    //       }
0651:                    //   ...
0652:                    //       with (newCatchScope(e, x)) {
0653:                    //           if (conditionN) {
0654:                    //               somethingN;
0655:                    //               goto after_catch;
0656:                    //           }
0657:                    //       }
0658:                    //       with (newCatchScope(e, x)) {
0659:                    //           somethingDefault;
0660:                    //           goto after_catch;
0661:                    //       }
0662:                    //   }
0663:                    // after_catch:
0664:                    //
0665:                    // If there is no default catch, then the last with block
0666:                    // arround  "somethingDefault;" is replaced by "rethrow;"
0667:
0668:                    // It is assumed that catch handler generation will store
0669:                    // exeception object in handlerBlock register
0670:
0671:                    // Block with local for exception scope objects
0672:                    Node catchScopeBlock = new Node(Token.LOCAL_BLOCK);
0673:
0674:                    // expects catchblocks children to be (cond block) pairs.
0675:                    Node cb = catchBlocks.getFirstChild();
0676:                    boolean hasDefault = false;
0677:                    int scopeIndex = 0;
0678:                    while (cb != null) {
0679:                        int catchLineNo = cb.getLineno();
0680:
0681:                        Node name = cb.getFirstChild();
0682:                        Node cond = name.getNext();
0683:                        Node catchStatement = cond.getNext();
0684:                        cb.removeChild(name);
0685:                        cb.removeChild(cond);
0686:                        cb.removeChild(catchStatement);
0687:
0688:                        // Add goto to the catch statement to jump out of catch
0689:                        // but prefix it with LEAVEWITH since try..catch produces
0690:                        // "with"code in order to limit the scope of the exception
0691:                        // object.
0692:                        catchStatement
0693:                                .addChildToBack(new Node(Token.LEAVEWITH));
0694:                        catchStatement.addChildToBack(makeJump(Token.GOTO,
0695:                                endCatch));
0696:
0697:                        // Create condition "if" when present
0698:                        Node condStmt;
0699:                        if (cond.getType() == Token.EMPTY) {
0700:                            condStmt = catchStatement;
0701:                            hasDefault = true;
0702:                        } else {
0703:                            condStmt = createIf(cond, catchStatement, null,
0704:                                    catchLineNo);
0705:                        }
0706:
0707:                        // Generate code to create the scope object and store
0708:                        // it in catchScopeBlock register
0709:                        Node catchScope = new Node(Token.CATCH_SCOPE, name,
0710:                                createUseLocal(handlerBlock));
0711:                        // TODO - add positions here to catchScope!
0712:
0713:                        catchScope.putProp(Node.LOCAL_BLOCK_PROP,
0714:                                catchScopeBlock);
0715:                        catchScope
0716:                                .putIntProp(Node.CATCH_SCOPE_PROP, scopeIndex);
0717:                        catchScopeBlock.addChildToBack(catchScope);
0718:
0719:                        // Add with statement based on catch scope object
0720:                        catchScopeBlock.addChildToBack(createWith(
0721:                                createUseLocal(catchScopeBlock), condStmt,
0722:                                catchLineNo));
0723:
0724:                        // move to next cb
0725:                        cb = cb.getNext();
0726:                        ++scopeIndex;
0727:                    }
0728:                    pn.addChildToBack(catchScopeBlock);
0729:                    if (!hasDefault) {
0730:                        // Generate code to rethrow if no catch clause was executed
0731:                        Node rethrow = new Node(Token.RETHROW);
0732:                        rethrow.putProp(Node.LOCAL_BLOCK_PROP, handlerBlock);
0733:                        pn.addChildToBack(rethrow);
0734:                    }
0735:
0736:                    pn.addChildToBack(endCatch);
0737:                }
0738:
0739:                if (hasFinally) {
0740:                    Node finallyTarget = Node.newTarget();
0741:                    pn.setFinally(finallyTarget);
0742:
0743:                    // add jsr finally to the try block
0744:                    pn.addChildToBack(makeJump(Token.JSR, finallyTarget));
0745:
0746:                    // jump around finally code
0747:                    Node finallyEnd = Node.newTarget();
0748:                    pn.addChildToBack(makeJump(Token.GOTO, finallyEnd));
0749:
0750:                    pn.addChildToBack(finallyTarget);
0751:                    Node fBlock = new Node(Token.FINALLY, finallyBlock);
0752:                    fBlock.putProp(Node.LOCAL_BLOCK_PROP, handlerBlock);
0753:                    pn.addChildToBack(fBlock);
0754:
0755:                    pn.addChildToBack(finallyEnd);
0756:                }
0757:                handlerBlock.addChildToBack(pn);
0758:                // <netbeans>
0759:                handlerBlock
0760:                        .setSourceBounds(startOffset, parser.getEndOffset());
0761:                // </netbeans>
0762:                return handlerBlock;
0763:            }
0764:
0765:            /**
0766:             * Throw, Return, Label, Break and Continue are defined in ASTFactory.
0767:             */
0768:
0769:            /**
0770:             * With
0771:             */
0772:            Node createWith(Node obj, Node body, int lineno) {
0773:                setRequiresActivation();
0774:                Node result = new Node(Token.BLOCK, lineno);
0775:                result.addChildToBack(new Node(Token.ENTERWITH, obj));
0776:                Node bodyNode = new Node(Token.WITH, body, lineno);
0777:                result.addChildrenToBack(bodyNode);
0778:                result.addChildToBack(new Node(Token.LEAVEWITH));
0779:                return result;
0780:            }
0781:
0782:            /**
0783:             * DOTQUERY
0784:             */
0785:            public Node createDotQuery(Node obj, Node body, int lineno) {
0786:                setRequiresActivation();
0787:                Node result = new Node(Token.DOTQUERY, obj, body, lineno);
0788:                return result;
0789:            }
0790:
0791:            Node createArrayLiteral(ObjArray elems, int skipCount) {
0792:                int length = elems.size();
0793:                int[] skipIndexes = null;
0794:                if (skipCount != 0) {
0795:                    skipIndexes = new int[skipCount];
0796:                }
0797:                Node array = new Node(Token.ARRAYLIT);
0798:                for (int i = 0, j = 0; i != length; ++i) {
0799:                    Node elem = (Node) elems.get(i);
0800:                    if (elem != null) {
0801:                        array.addChildToBack(elem);
0802:                    } else {
0803:                        skipIndexes[j] = i;
0804:                        ++j;
0805:                    }
0806:                }
0807:                if (skipCount != 0) {
0808:                    array.putProp(Node.SKIP_INDEXES_PROP, skipIndexes);
0809:                }
0810:                return array;
0811:            }
0812:
0813:            /**
0814:             * Object Literals
0815:             * <BR> createObjectLiteral rewrites its argument as object
0816:             * creation plus object property entries, so later compiler
0817:             * stages don't need to know about object literals.
0818:             */
0819:            Node createObjectLiteral(ObjArray elems) {
0820:                int size = elems.size() / 2;
0821:                Node object = new Node(Token.OBJECTLIT);
0822:                Object[] properties;
0823:                if (size == 0) {
0824:                    properties = ScriptRuntime.emptyArgs;
0825:                } else {
0826:                    properties = new Object[size];
0827:                    for (int i = 0; i != size; ++i) {
0828:                        properties[i] = elems.get(2 * i);
0829:                        Node value = (Node) elems.get(2 * i + 1);
0830:                        object.addChildToBack(value);
0831:                    }
0832:                }
0833:                object.putProp(Node.OBJECT_IDS_PROP, properties);
0834:                return object;
0835:            }
0836:
0837:            /**
0838:             * Regular expressions
0839:             */
0840:            Node createRegExp(int regexpIndex) {
0841:                Node n = new Node(Token.REGEXP);
0842:                n.putIntProp(Node.REGEXP_PROP, regexpIndex);
0843:                return n;
0844:            }
0845:
0846:            /**
0847:             * If statement
0848:             */
0849:            Node createIf(Node cond, Node ifTrue, Node ifFalse, int lineno) {
0850:                int condStatus = isAlwaysDefinedBoolean(cond);
0851:                if (condStatus == ALWAYS_TRUE_BOOLEAN) {
0852:                    return ifTrue;
0853:                } else if (condStatus == ALWAYS_FALSE_BOOLEAN) {
0854:                    if (ifFalse != null) {
0855:                        return ifFalse;
0856:                    }
0857:                    // Replace if (false) xxx by empty block
0858:                    return new Node(Token.BLOCK, lineno);
0859:                }
0860:
0861:                Node result = new Node(Token.BLOCK, lineno);
0862:                Node ifNotTarget = Node.newTarget();
0863:                Node.Jump IFNE = new Node.Jump(Token.IFNE, cond);
0864:                IFNE.target = ifNotTarget;
0865:
0866:                result.addChildToBack(IFNE);
0867:                result.addChildrenToBack(ifTrue);
0868:
0869:                if (ifFalse != null) {
0870:                    Node endTarget = Node.newTarget();
0871:                    result.addChildToBack(makeJump(Token.GOTO, endTarget));
0872:                    result.addChildToBack(ifNotTarget);
0873:                    result.addChildrenToBack(ifFalse);
0874:                    result.addChildToBack(endTarget);
0875:                } else {
0876:                    result.addChildToBack(ifNotTarget);
0877:                }
0878:
0879:                return result;
0880:            }
0881:
0882:            Node createCondExpr(Node cond, Node ifTrue, Node ifFalse) {
0883:                int condStatus = isAlwaysDefinedBoolean(cond);
0884:                if (condStatus == ALWAYS_TRUE_BOOLEAN) {
0885:                    return ifTrue;
0886:                } else if (condStatus == ALWAYS_FALSE_BOOLEAN) {
0887:                    return ifFalse;
0888:                }
0889:                return new Node(Token.HOOK, cond, ifTrue, ifFalse);
0890:            }
0891:
0892:            /**
0893:             * Unary
0894:             */
0895:            Node createUnary(int nodeType, Node child) {
0896:                int childType = child.getType();
0897:                switch (nodeType) {
0898:                case Token.DELPROP: {
0899:                    Node n;
0900:                    if (childType == Token.NAME) {
0901:                        // Transform Delete(Name "a")
0902:                        //  to Delete(Bind("a"), String("a"))
0903:                        child.setType(Token.BINDNAME);
0904:                        Node left = child;
0905:                        Node right = Node.newString(child.getString());
0906:                        n = new Node(nodeType, left, right);
0907:                    } else if (childType == Token.GETPROP
0908:                            || childType == Token.GETELEM) {
0909:                        Node left = child.getFirstChild();
0910:                        Node right = child.getLastChild();
0911:                        child.removeChild(left);
0912:                        child.removeChild(right);
0913:                        n = new Node(nodeType, left, right);
0914:                    } else if (childType == Token.GET_REF) {
0915:                        Node ref = child.getFirstChild();
0916:                        child.removeChild(ref);
0917:                        n = new Node(Token.DEL_REF, ref);
0918:                    } else {
0919:                        n = new Node(Token.TRUE);
0920:                    }
0921:                    return n;
0922:                }
0923:                case Token.TYPEOF:
0924:                    if (childType == Token.NAME) {
0925:                        child.setType(Token.TYPEOFNAME);
0926:                        return child;
0927:                    }
0928:                    break;
0929:                case Token.BITNOT:
0930:                    if (childType == Token.NUMBER) {
0931:                        int value = ScriptRuntime.toInt32(child.getDouble());
0932:                        child.setDouble(~value);
0933:                        return child;
0934:                    }
0935:                    break;
0936:                case Token.NEG:
0937:                    if (childType == Token.NUMBER) {
0938:                        child.setDouble(-child.getDouble());
0939:                        return child;
0940:                    }
0941:                    break;
0942:                case Token.NOT: {
0943:                    int status = isAlwaysDefinedBoolean(child);
0944:                    if (status != 0) {
0945:                        int type;
0946:                        if (status == ALWAYS_TRUE_BOOLEAN) {
0947:                            type = Token.FALSE;
0948:                        } else {
0949:                            type = Token.TRUE;
0950:                        }
0951:                        if (childType == Token.TRUE || childType == Token.FALSE) {
0952:                            child.setType(type);
0953:                            return child;
0954:                        }
0955:                        return new Node(type);
0956:                    }
0957:                    break;
0958:                }
0959:                }
0960:                return new Node(nodeType, child);
0961:            }
0962:
0963:            Node createCallOrNew(int nodeType, Node child) {
0964:                int type = Node.NON_SPECIALCALL;
0965:                if (child.getType() == Token.NAME) {
0966:                    String name = child.getString();
0967:                    if (name.equals("eval")) {
0968:                        type = Node.SPECIALCALL_EVAL;
0969:                    } else if (name.equals("With")) {
0970:                        type = Node.SPECIALCALL_WITH;
0971:                    }
0972:                } else if (child.getType() == Token.GETPROP) {
0973:                    String name = child.getLastChild().getString();
0974:                    if (name.equals("eval")) {
0975:                        type = Node.SPECIALCALL_EVAL;
0976:                    }
0977:                }
0978:                Node node = new Node(nodeType, child);
0979:                if (type != Node.NON_SPECIALCALL) {
0980:                    // Calls to these functions require activation objects.
0981:                    setRequiresActivation();
0982:                    node.putIntProp(Node.SPECIALCALL_PROP, type);
0983:                }
0984:                return node;
0985:            }
0986:
0987:            Node createIncDec(int nodeType, boolean post, Node child) {
0988:                child = makeReference(child);
0989:                if (child == null) {
0990:                    String msg;
0991:                    if (nodeType == Token.DEC) {
0992:                        msg = "msg.bad.decr";
0993:                    } else {
0994:                        msg = "msg.bad.incr";
0995:                    }
0996:                    parser.reportError(msg);
0997:                    return null;
0998:                }
0999:
1000:                int childType = child.getType();
1001:
1002:                switch (childType) {
1003:                case Token.NAME:
1004:                case Token.GETPROP:
1005:                case Token.GETELEM:
1006:                case Token.GET_REF: {
1007:                    Node n = new Node(nodeType, child);
1008:                    int incrDecrMask = 0;
1009:                    if (nodeType == Token.DEC) {
1010:                        incrDecrMask |= Node.DECR_FLAG;
1011:                    }
1012:                    if (post) {
1013:                        incrDecrMask |= Node.POST_FLAG;
1014:                    }
1015:                    n.putIntProp(Node.INCRDECR_PROP, incrDecrMask);
1016:                    return n;
1017:                }
1018:                }
1019:                throw Kit.codeBug();
1020:            }
1021:
1022:            Node createPropertyGet(Node target, String namespace, String name,
1023:                    int memberTypeFlags) {
1024:                if (namespace == null && memberTypeFlags == 0) {
1025:                    if (target == null) {
1026:                        return createName(name);
1027:                    }
1028:                    checkActivationName(name, Token.GETPROP);
1029:                    if (ScriptRuntime.isSpecialProperty(name)) {
1030:                        Node ref = new Node(Token.REF_SPECIAL, target);
1031:                        ref.putProp(Node.NAME_PROP, name);
1032:                        return new Node(Token.GET_REF, ref);
1033:                    }
1034:                    return new Node(Token.GETPROP, target, createString(name));
1035:                }
1036:                Node elem = createString(name);
1037:                memberTypeFlags |= Node.PROPERTY_FLAG;
1038:                return createMemberRefGet(target, namespace, elem,
1039:                        memberTypeFlags);
1040:            }
1041:
1042:            Node createElementGet(Node target, String namespace, Node elem,
1043:                    int memberTypeFlags) {
1044:                // OPT: could optimize to createPropertyGet
1045:                // iff elem is string that can not be number
1046:                if (namespace == null && memberTypeFlags == 0) {
1047:                    // stand-alone [aaa] as primary expression is array literal
1048:                    // declaration and should not come here!
1049:                    if (target == null)
1050:                        throw Kit.codeBug();
1051:                    return new Node(Token.GETELEM, target, elem);
1052:                }
1053:                return createMemberRefGet(target, namespace, elem,
1054:                        memberTypeFlags);
1055:            }
1056:
1057:            private Node createMemberRefGet(Node target, String namespace,
1058:                    Node elem, int memberTypeFlags) {
1059:                Node nsNode = null;
1060:                if (namespace != null) {
1061:                    // See 11.1.2 in ECMA 357
1062:                    if (namespace.equals("*")) {
1063:                        nsNode = new Node(Token.NULL);
1064:                    } else {
1065:                        nsNode = createName(namespace);
1066:                    }
1067:                }
1068:                Node ref;
1069:                if (target == null) {
1070:                    if (namespace == null) {
1071:                        ref = new Node(Token.REF_NAME, elem);
1072:                    } else {
1073:                        ref = new Node(Token.REF_NS_NAME, nsNode, elem);
1074:                    }
1075:                } else {
1076:                    if (namespace == null) {
1077:                        ref = new Node(Token.REF_MEMBER, target, elem);
1078:                    } else {
1079:                        ref = new Node(Token.REF_NS_MEMBER, target, nsNode,
1080:                                elem);
1081:                    }
1082:                }
1083:                if (memberTypeFlags != 0) {
1084:                    ref.putIntProp(Node.MEMBER_TYPE_PROP, memberTypeFlags);
1085:                }
1086:                return new Node(Token.GET_REF, ref);
1087:            }
1088:
1089:            /**
1090:             * Binary
1091:             */
1092:            Node createBinary(int nodeType, Node left, Node right) {
1093:                switch (nodeType) {
1094:
1095:                case Token.ADD:
1096:                    // numerical addition and string concatenation
1097:                    if (left.type == Token.STRING) {
1098:                        String s2;
1099:                        if (right.type == Token.STRING) {
1100:                            s2 = right.getString();
1101:                        } else if (right.type == Token.NUMBER) {
1102:                            s2 = ScriptRuntime.numberToString(
1103:                                    right.getDouble(), 10);
1104:                        } else {
1105:                            break;
1106:                        }
1107:                        String s1 = left.getString();
1108:                        left.setString(s1.concat(s2));
1109:                        return left;
1110:                    } else if (left.type == Token.NUMBER) {
1111:                        if (right.type == Token.NUMBER) {
1112:                            left
1113:                                    .setDouble(left.getDouble()
1114:                                            + right.getDouble());
1115:                            return left;
1116:                        } else if (right.type == Token.STRING) {
1117:                            String s1, s2;
1118:                            s1 = ScriptRuntime.numberToString(left.getDouble(),
1119:                                    10);
1120:                            s2 = right.getString();
1121:                            right.setString(s1.concat(s2));
1122:                            return right;
1123:                        }
1124:                    }
1125:                    // can't do anything if we don't know  both types - since
1126:                    // 0 + object is supposed to call toString on the object and do
1127:                    // string concantenation rather than addition
1128:                    break;
1129:
1130:                case Token.SUB:
1131:                    // numerical subtraction
1132:                    if (left.type == Token.NUMBER) {
1133:                        double ld = left.getDouble();
1134:                        if (right.type == Token.NUMBER) {
1135:                            //both numbers
1136:                            left.setDouble(ld - right.getDouble());
1137:                            return left;
1138:                        } else if (ld == 0.0) {
1139:                            // first 0: 0-x -> -x
1140:                            return new Node(Token.NEG, right);
1141:                        }
1142:                    } else if (right.type == Token.NUMBER) {
1143:                        if (right.getDouble() == 0.0) {
1144:                            //second 0: x - 0 -> +x
1145:                            // can not make simply x because x - 0 must be number
1146:                            return new Node(Token.POS, left);
1147:                        }
1148:                    }
1149:                    break;
1150:
1151:                case Token.MUL:
1152:                    // numerical multiplication
1153:                    if (left.type == Token.NUMBER) {
1154:                        double ld = left.getDouble();
1155:                        if (right.type == Token.NUMBER) {
1156:                            //both numbers
1157:                            left.setDouble(ld * right.getDouble());
1158:                            return left;
1159:                        } else if (ld == 1.0) {
1160:                            // first 1: 1 *  x -> +x
1161:                            return new Node(Token.POS, right);
1162:                        }
1163:                    } else if (right.type == Token.NUMBER) {
1164:                        if (right.getDouble() == 1.0) {
1165:                            //second 1: x * 1 -> +x
1166:                            // can not make simply x because x - 0 must be number
1167:                            return new Node(Token.POS, left);
1168:                        }
1169:                    }
1170:                    // can't do x*0: Infinity * 0 gives NaN, not 0
1171:                    break;
1172:
1173:                case Token.DIV:
1174:                    // number division
1175:                    if (right.type == Token.NUMBER) {
1176:                        double rd = right.getDouble();
1177:                        if (left.type == Token.NUMBER) {
1178:                            // both constants -- just divide, trust Java to handle x/0
1179:                            left.setDouble(left.getDouble() / rd);
1180:                            return left;
1181:                        } else if (rd == 1.0) {
1182:                            // second 1: x/1 -> +x
1183:                            // not simply x to force number convertion
1184:                            return new Node(Token.POS, left);
1185:                        }
1186:                    }
1187:                    break;
1188:
1189:                case Token.AND: {
1190:                    // Since x && y gives x, not false, when Boolean(x) is false,
1191:                    // and y, not Boolean(y), when Boolean(x) is true, x && y
1192:                    // can only be simplified if x is defined. See bug 309957.
1193:
1194:                    int leftStatus = isAlwaysDefinedBoolean(left);
1195:                    if (leftStatus == ALWAYS_FALSE_BOOLEAN) {
1196:                        // if the first one is false, just return it
1197:                        return left;
1198:                    } else if (leftStatus == ALWAYS_TRUE_BOOLEAN) {
1199:                        // if first is true, set to second
1200:                        return right;
1201:                    }
1202:                    break;
1203:                }
1204:
1205:                case Token.OR: {
1206:                    // Since x || y gives x, not true, when Boolean(x) is true,
1207:                    // and y, not Boolean(y), when Boolean(x) is false, x || y
1208:                    // can only be simplified if x is defined. See bug 309957.
1209:
1210:                    int leftStatus = isAlwaysDefinedBoolean(left);
1211:                    if (leftStatus == ALWAYS_TRUE_BOOLEAN) {
1212:                        // if the first one is true, just return it
1213:                        return left;
1214:                    } else if (leftStatus == ALWAYS_FALSE_BOOLEAN) {
1215:                        // if first is false, set to second
1216:                        return right;
1217:                    }
1218:                    break;
1219:                }
1220:                }
1221:
1222:                return new Node(nodeType, left, right);
1223:            }
1224:
1225:            private Node simpleAssignment(Node left, Node right) {
1226:                int nodeType = left.getType();
1227:                switch (nodeType) {
1228:                case Token.NAME:
1229:                    left.setType(Token.BINDNAME);
1230:                    return new Node(Token.SETNAME, left, right);
1231:
1232:                case Token.GETPROP:
1233:                case Token.GETELEM: {
1234:                    Node obj = left.getFirstChild();
1235:                    Node id = left.getLastChild();
1236:                    int type;
1237:                    if (nodeType == Token.GETPROP) {
1238:                        type = Token.SETPROP;
1239:                    } else {
1240:                        type = Token.SETELEM;
1241:                    }
1242:                    return new Node(type, obj, id, right);
1243:                }
1244:                case Token.GET_REF: {
1245:                    Node ref = left.getFirstChild();
1246:                    checkMutableReference(ref);
1247:                    return new Node(Token.SET_REF, ref, right);
1248:                }
1249:                }
1250:
1251:                throw Kit.codeBug();
1252:            }
1253:
1254:            private void checkMutableReference(Node n) {
1255:                int memberTypeFlags = n.getIntProp(Node.MEMBER_TYPE_PROP, 0);
1256:                if ((memberTypeFlags & Node.DESCENDANTS_FLAG) != 0) {
1257:                    parser.reportError("msg.bad.assign.left");
1258:                }
1259:            }
1260:
1261:            Node createAssignment(int assignType, Node left, Node right) {
1262:                left = makeReference(left);
1263:                if (left == null) {
1264:                    parser.reportError("msg.bad.assign.left");
1265:                    return right;
1266:                }
1267:
1268:                int assignOp;
1269:                switch (assignType) {
1270:                case Token.ASSIGN:
1271:                    return simpleAssignment(left, right);
1272:                case Token.ASSIGN_BITOR:
1273:                    assignOp = Token.BITOR;
1274:                    break;
1275:                case Token.ASSIGN_BITXOR:
1276:                    assignOp = Token.BITXOR;
1277:                    break;
1278:                case Token.ASSIGN_BITAND:
1279:                    assignOp = Token.BITAND;
1280:                    break;
1281:                case Token.ASSIGN_LSH:
1282:                    assignOp = Token.LSH;
1283:                    break;
1284:                case Token.ASSIGN_RSH:
1285:                    assignOp = Token.RSH;
1286:                    break;
1287:                case Token.ASSIGN_URSH:
1288:                    assignOp = Token.URSH;
1289:                    break;
1290:                case Token.ASSIGN_ADD:
1291:                    assignOp = Token.ADD;
1292:                    break;
1293:                case Token.ASSIGN_SUB:
1294:                    assignOp = Token.SUB;
1295:                    break;
1296:                case Token.ASSIGN_MUL:
1297:                    assignOp = Token.MUL;
1298:                    break;
1299:                case Token.ASSIGN_DIV:
1300:                    assignOp = Token.DIV;
1301:                    break;
1302:                case Token.ASSIGN_MOD:
1303:                    assignOp = Token.MOD;
1304:                    break;
1305:                default:
1306:                    throw Kit.codeBug();
1307:                }
1308:
1309:                int nodeType = left.getType();
1310:                switch (nodeType) {
1311:                case Token.NAME: {
1312:                    String s = left.getString();
1313:
1314:                    Node opLeft = Node.newString(Token.NAME, s);
1315:                    // <netbeans>
1316:                    opLeft.setSourceBounds(left.getSourceStart(), left
1317:                            .getSourceEnd());
1318:                    // </netbeans>
1319:                    Node op = new Node(assignOp, opLeft, right);
1320:                    Node lvalueLeft = Node.newString(Token.BINDNAME, s);
1321:                    // <netbeans>
1322:                    lvalueLeft.setSourceBounds(left.getSourceStart(), left
1323:                            .getSourceEnd());
1324:                    // </netbeans>
1325:                    return new Node(Token.SETNAME, lvalueLeft, op);
1326:                }
1327:                case Token.GETPROP:
1328:                case Token.GETELEM: {
1329:                    Node obj = left.getFirstChild();
1330:                    Node id = left.getLastChild();
1331:
1332:                    int type = nodeType == Token.GETPROP ? Token.SETPROP_OP
1333:                            : Token.SETELEM_OP;
1334:
1335:                    Node opLeft = new Node(Token.USE_STACK);
1336:                    Node op = new Node(assignOp, opLeft, right);
1337:                    return new Node(type, obj, id, op);
1338:                }
1339:                case Token.GET_REF: {
1340:                    Node ref = left.getFirstChild();
1341:                    checkMutableReference(ref);
1342:                    Node opLeft = new Node(Token.USE_STACK);
1343:                    Node op = new Node(assignOp, opLeft, right);
1344:                    return new Node(Token.SET_REF_OP, ref, op);
1345:                }
1346:                }
1347:
1348:                throw Kit.codeBug();
1349:            }
1350:
1351:            Node createUseLocal(Node localBlock) {
1352:                if (Token.LOCAL_BLOCK != localBlock.getType())
1353:                    throw Kit.codeBug();
1354:                Node result = new Node(Token.LOCAL_LOAD);
1355:                // <netbeans>
1356:                result.setSourceBounds(localBlock.getSourceStart(), localBlock
1357:                        .getSourceEnd());
1358:                // </netbeans>
1359:                result.putProp(Node.LOCAL_BLOCK_PROP, localBlock);
1360:                return result;
1361:            }
1362:
1363:            private Node.Jump makeJump(int type, Node target) {
1364:                Node.Jump n = new Node.Jump(type);
1365:                // <netbeans>
1366:                int pos = parser.getStartOffset();
1367:                n.setSourceBounds(pos, pos);
1368:                // </netbeans>
1369:                n.target = target;
1370:                return n;
1371:            }
1372:
1373:            private Node makeReference(Node node) {
1374:                int type = node.getType();
1375:                switch (type) {
1376:                case Token.NAME:
1377:                case Token.GETPROP:
1378:                case Token.GETELEM:
1379:                case Token.GET_REF:
1380:                    return node;
1381:                case Token.CALL:
1382:                    node.setType(Token.REF_CALL);
1383:                    return new Node(Token.GET_REF, node);
1384:                }
1385:                // Signal caller to report error
1386:                return null;
1387:            }
1388:
1389:            // Check if Node always mean true or false in boolean context
1390:            private static int isAlwaysDefinedBoolean(Node node) {
1391:                switch (node.getType()) {
1392:                case Token.FALSE:
1393:                case Token.NULL:
1394:                    return ALWAYS_FALSE_BOOLEAN;
1395:                case Token.TRUE:
1396:                    return ALWAYS_TRUE_BOOLEAN;
1397:                case Token.NUMBER: {
1398:                    double num = node.getDouble();
1399:                    if (num == num && num != 0.0) {
1400:                        return ALWAYS_TRUE_BOOLEAN;
1401:                    } else {
1402:                        return ALWAYS_FALSE_BOOLEAN;
1403:                    }
1404:                }
1405:                }
1406:                return 0;
1407:            }
1408:
1409:            // Commented-out: no longer used    
1410:            //     private static boolean hasSideEffects(Node exprTree)
1411:            //     {
1412:            //         switch (exprTree.getType()) {
1413:            //           case Token.INC:
1414:            //           case Token.DEC:
1415:            //           case Token.SETPROP:
1416:            //           case Token.SETELEM:
1417:            //           case Token.SETNAME:
1418:            //           case Token.CALL:
1419:            //           case Token.NEW:
1420:            //             return true;
1421:            //           default:
1422:            //             Node child = exprTree.getFirstChild();
1423:            //             while (child != null) {
1424:            //                 if (hasSideEffects(child))
1425:            //                     return true;
1426:            //                 child = child.getNext();
1427:            //             }
1428:            //             break;
1429:            //         }
1430:            //         return false;
1431:            //     }
1432:
1433:            private void checkActivationName(String name, int token) {
1434:                if (parser.insideFunction()) {
1435:                    boolean activation = false;
1436:                    if ("arguments".equals(name)
1437:                            || (parser.compilerEnv.activationNames != null && parser.compilerEnv.activationNames
1438:                                    .containsKey(name))) {
1439:                        activation = true;
1440:                    } else if ("length".equals(name)) {
1441:                        if (token == Token.GETPROP
1442:                                && parser.compilerEnv.getLanguageVersion() == Context.VERSION_1_2) {
1443:                            // Use of "length" in 1.2 requires an activation object.
1444:                            activation = true;
1445:                        }
1446:                    }
1447:                    if (activation) {
1448:                        setRequiresActivation();
1449:                    }
1450:                }
1451:            }
1452:
1453:            private void setRequiresActivation() {
1454:                if (parser.insideFunction()) {
1455:                    ((FunctionNode) parser.currentScriptOrFn).itsNeedsActivation = true;
1456:                }
1457:            }
1458:
1459:            private Parser parser;
1460:
1461:            private static final int LOOP_DO_WHILE = 0;
1462:            private static final int LOOP_WHILE = 1;
1463:            private static final int LOOP_FOR = 2;
1464:
1465:            private static final int ALWAYS_TRUE_BOOLEAN = 1;
1466:            private static final int ALWAYS_FALSE_BOOLEAN = -1;
1467:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.