Source Code Cross Referenced for CompilerVisitor.java in  » Scripting » oscript-2.10.4 » oscript » compiler » 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 » Scripting » oscript 2.10.4 » oscript.compiler 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /*=============================================================================
0002:         *     Copyright Texas Instruments 2000-2003.  All Rights Reserved.
0003:         *   
0004:         * This program is free software; you can redistribute it and/or
0005:         * modify it under the terms of the GNU Lesser General Public
0006:         * License as published by the Free Software Foundation; either
0007:         * version 2 of the License, or (at your option) any later version.
0008:         * 
0009:         * This program is distributed in the hope that it will be useful,
0010:         * but WITHOUT ANY WARRANTY; without even the implied warranty of
0011:         * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
0012:         * Lesser General Public License for more details.
0013:         * 
0014:         * You should have received a copy of the GNU Lesser General Public
0015:         * License along with this library; if not, write to the Free Software
0016:         * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
0017:         * 
0018:         * $ProjectHeader: OSCRIPT 0.155 Fri, 20 Dec 2002 18:34:22 -0800 rclark $
0019:         */
0020:
0021:        package oscript.compiler;
0022:
0023:        import oscript.syntaxtree.*;
0024:        import oscript.data.*;
0025:        import oscript.exceptions.*;
0026:        import oscript.parser.OscriptParser;
0027:        import oscript.translator.*;
0028:
0029:        // The Bytecode Engineerign Library
0030:        import org.apache.bcel.generic.*;
0031:        import org.apache.bcel.Constants;
0032:
0033:        import java.util.Vector;
0034:        import java.util.LinkedList;
0035:        import java.util.Iterator;
0036:
0037:        /**
0038:         * The CompilerVisitor is the compiler, which compiles functions to an 
0039:         * instance of <code>CompiledNodeEvaluator</code>.
0040:         * <p>
0041:         * Some assumptions are made with respect to tracking the info needed to
0042:         * generate useful stack traces, for example that the entire function is
0043:         * defined within the same file.
0044:         * 
0045:         * @author Rob Clark (rob@ti.com)
0046:         * <!--$Format: " * @version $Revision$"$-->
0047:         * @version 1.84
0048:         */
0049:        public class CompilerVisitor implements  oscript.visitor.Visitor,
0050:                oscript.parser.OscriptParserConstants {
0051:            /**
0052:             * The instruction list which becomes the code of the <code>evalNode</code>
0053:             * method which is generated.
0054:             */
0055:            CompilerInstructionList il;
0056:
0057:            /**
0058:             * The current method being generated.
0059:             */
0060:            MethodGen mg;
0061:
0062:            /**
0063:             */
0064:            CompilerContext ctx;
0065:
0066:            /**
0067:             * Some nodes, when visited, leave a return node on the top of the stack,
0068:             * and some remove the return value from the stack.  Nodes that don't
0069:             * put or remove the return value from the top of the stack leave this
0070:             * flag unchanged.
0071:             */
0072:            private boolean retValOnStack;
0073:
0074:            /**
0075:             * Set <code>retValOnStack</code> with this function... it does some
0076:             * error checking.
0077:             */
0078:            private void setRetValOnStack(boolean retValOnStack) {
0079:                if (this .retValOnStack == retValOnStack)
0080:                    throw new ProgrammingErrorException(
0081:                            "retValOnStack is already " + retValOnStack);
0082:                else
0083:                    this .retValOnStack = retValOnStack;
0084:            }
0085:
0086:            /**
0087:             * For sanity checking, sort of like an ASSERT() for <code>retValOnStack</code>.
0088:             */
0089:            private void checkRetValOnStack(boolean retValOnStack) {
0090:                if (this .retValOnStack != retValOnStack)
0091:                    throw new ProgrammingErrorException("retValOnStack is not "
0092:                            + retValOnStack);
0093:            }
0094:
0095:            /*=======================================================================*/
0096:            /**
0097:             * The loop stack is used to track nested levels of loops, and cleanup
0098:             * such as JSR to finally or releasing monitors, that needs to happen
0099:             * when program execution jumps out of a loop, such as in the case of
0100:             * "return", "continue", or "break"
0101:             */
0102:            private LoopStackNode loopStack;
0103:
0104:            /*=======================================================================*/
0105:            /**
0106:             * List of runnables to invoke after the first pass of the compiler over
0107:             * the syntax-tree
0108:             */
0109:            private LinkedList deferredRunnableList = new LinkedList();
0110:
0111:            /*=======================================================================*/
0112:            /**
0113:             * Create a new compiler-visitor, which generates compiled code
0114:             */
0115:            CompilerVisitor(CompilerContext ctx, String name, Node node) {
0116:                this (ctx, name, node, null);
0117:            }
0118:
0119:            private CompilerVisitor(CompilerContext ctx, String name,
0120:                    Node node, int[] argIds) {
0121:                this .ctx = ctx;
0122:
0123:                il = new CompilerInstructionList();
0124:
0125:                mg = new MethodGen(Constants.ACC_PRIVATE, ctx.OBJECT_TYPE,
0126:                        ctx.EVAL_NODE_ARG_TYPES, ctx.EVAL_NODE_ARG_NAMES, "_"
0127:                                + (innerNodeIdx = ctx.getNextEvalNodeIdx(name))
0128:                                + "_" + name, ctx.className, il, ctx.cp);
0129:
0130:                scope = new CompilerScope(this , 2, argIds);
0131:
0132:                ctx.addSMITs(innerNodeIdx, scope
0133:                        .getSharedMemberIndexTableIdxs());
0134:
0135:                compileNode(node);
0136:            }
0137:
0138:            private int innerNodeIdx;
0139:
0140:            /*=======================================================================*/
0141:            /**
0142:             * The entry point to compile a node.
0143:             * 
0144:             * @param node         the node in syntaxtree to compile
0145:             */
0146:            private void compileNode(Node node) {
0147:                retValOnStack = false;
0148:
0149:                loopStack = new LoopStackNode(null);
0150:
0151:                node.accept(this );
0152:
0153:                loopStack.pop();
0154:
0155:                if (!retValOnStack)
0156:                    getInstanceConstant(Value.UNDEFINED);
0157:
0158:                /* we may end up with two ARETURN's at the end, but that should be
0159:                 * ok... we need to add a return instruction at the end just in
0160:                 * case there isn't one, or if someone calls il.setNextAsTarget(...)
0161:                 */
0162:                il.append(InstructionConstants.ARETURN);
0163:
0164:                for (Iterator itr = deferredRunnableList.iterator(); itr
0165:                        .hasNext();)
0166:                    ((Runnable) (itr.next())).run();
0167:
0168:                mg.setMaxStack();
0169:                ctx.cg.addMethod(mg.getMethod());
0170:            }
0171:
0172:            /*=======================================================================*/
0173:            CompilerScope scope;
0174:
0175:            /*=======================================================================*/
0176:            /**
0177:             */
0178:            public void visit(NodeList n) {
0179:                throw new ProgrammingErrorException("unimplemented");
0180:            }
0181:
0182:            public void visit(NodeListOptional n) {
0183:                throw new ProgrammingErrorException("unimplemented");
0184:            }
0185:
0186:            public void visit(NodeOptional n) {
0187:                throw new ProgrammingErrorException("unimplemented");
0188:            }
0189:
0190:            public void visit(NodeSequence n) {
0191:                throw new ProgrammingErrorException("unimplemented");
0192:            }
0193:
0194:            /*=======================================================================*/
0195:            private NodeToken NodeToken_lastToken;
0196:            private Vector NodeToken_lastSpecials;
0197:            private String NodeToken_lastDesc;
0198:            private int NodeToken_lastBeginLine = -1;
0199:            private InstructionHandle NodeToken_lastBranchTarget = null;
0200:
0201:            private CompilerScope NodeToken_lastScope = null; // for deciding which setLineNumber() to call
0202:
0203:            /**
0204:             * Handles storing line # info for a node-token.  This should really be
0205:             * called for every node-token to ensure that no line # info is lost.
0206:             */
0207:            void handle(NodeToken n) {
0208:                NodeToken_lastToken = n;
0209:
0210:                if (n.specialTokens != null)
0211:                    NodeToken_lastSpecials = n.specialTokens;
0212:
0213:                if (true) // XXX we should be able to enable/disable inserting this extra code at runtime
0214:                {
0215:                    // XXX I think this condition should always hold:
0216:                    if ((NodeToken_lastDesc != null)
0217:                            && !("".equals(n.desc)
0218:                                    || "".equals(NodeToken_lastDesc) || NodeToken_lastDesc
0219:                                    .equals(n.desc)))
0220:                        System.err.println("desc changed, was "
0221:                                + NodeToken_lastDesc + ", now is " + n.desc);
0222:
0223:                    // we only need to insert code to update the line # if the line # changed
0224:                    // or if there is a branch inst target between here and the last time we
0225:                    // updated the line #
0226:                    if ((NodeToken_lastBeginLine != n.beginLine)
0227:                            || (NodeToken_lastBranchTarget != il
0228:                                    .getLastBranchTarget())) {
0229:                        InstructionHandle ih;
0230:
0231:                        if (scope != NodeToken_lastScope) {
0232:                            // sf.setLineNumber( scope, n.beginLine );
0233:                            il.append(InstructionConstants.ALOAD_1); // sf
0234:                            il.append(new ALOAD(scope.getSlot()));
0235:                            ctx.pushInt(il, n.beginLine);
0236:
0237:                            ih = il.append(new INVOKEVIRTUAL(ctx.methodref(
0238:                                    "oscript.util.StackFrame", "setLineNumber",
0239:                                    "(Loscript/data/Scope;I)V")));
0240:                            NodeToken_lastScope = scope;
0241:                        } else {
0242:                            // sf.setLineNumber(n.beginLine);
0243:                            il.append(InstructionConstants.ALOAD_1); // sf
0244:                            ctx.pushInt(il, n.beginLine);
0245:
0246:                            ih = il.append(new INVOKEVIRTUAL(ctx.methodref(
0247:                                    "oscript.util.StackFrame", "setLineNumber",
0248:                                    "(I)V")));
0249:                        }
0250:
0251:                        mg.addLineNumber(ih, n.beginLine);
0252:                    }
0253:
0254:                    NodeToken_lastDesc = n.desc;
0255:                    NodeToken_lastBeginLine = n.beginLine;
0256:                    NodeToken_lastBranchTarget = il.getLastBranchTarget();
0257:                }
0258:            }
0259:
0260:            String getDebugName() {
0261:                if (NodeToken_lastDesc != null)
0262:                    return NodeToken_lastDesc + ":" + NodeToken_lastBeginLine;
0263:                return ctx.name;
0264:            }
0265:
0266:            /**
0267:             * get the "desc" of the syntax-tree being parsed... ie. the filename
0268:             */
0269:            String getDesc() {
0270:                return NodeToken_lastDesc;
0271:            }
0272:
0273:            /**
0274:             */
0275:            public void visit(NodeToken n) {
0276:                handle(n);
0277:
0278:                // XXX handle IDENTIFIER specially... it might be better to give IDENTIFIER 
0279:                // it's own production in the grammar
0280:                if (n.kind == IDENTIFIER) {
0281:                    ctx.pushSymbol(il, n.tokenImage);
0282:                    setRetValOnStack(true);
0283:                    return;
0284:                }
0285:
0286:                if (n.cachedValue == null) {
0287:                    switch (n.kind) {
0288:                    case INTEGER_LITERAL:
0289:                    case HEX_LITERAL:
0290:                    case OCTAL_LITERAL:
0291:                    case DECIMAL_LITERAL:
0292:                    case BINARY_LITERAL:
0293:                        n.cachedValue = OExactNumber
0294:                                .makeExactNumber(n.otokenImage
0295:                                        .castToExactNumber());
0296:                        break;
0297:                    case FLOATING_POINT_LITERAL:
0298:                        n.cachedValue = OInexactNumber
0299:                                .makeInexactNumber(n.otokenImage
0300:                                        .castToInexactNumber());
0301:                        break;
0302:                    case STRING_LITERAL:
0303:                        n.cachedValue = OString.makeString(OString
0304:                                .chop(n.tokenImage.substring(1, n.tokenImage
0305:                                        .length() - 1))); // should this be intern'd???
0306:                        break;
0307:                    case REGEXP_LITERAL:
0308:                        n.cachedValue = RegExp.createRegExp(n.otokenImage);
0309:                        break;
0310:                    case TRUE:
0311:                        n.cachedValue = OBoolean.TRUE;
0312:                        break;
0313:                    case FALSE:
0314:                        n.cachedValue = OBoolean.FALSE;
0315:                        break;
0316:                    case NULL:
0317:                        n.cachedValue = Value.NULL;
0318:                        break;
0319:                    case UNDEFINED:
0320:                        n.cachedValue = Value.UNDEFINED;
0321:                        break;
0322:                    case -1:
0323:                    default:
0324:                        // leave as null
0325:                    }
0326:                }
0327:
0328:                if (n.cachedValue != null) {
0329:                    getInstanceConstant(n.cachedValue);
0330:                }
0331:            }
0332:
0333:            /**
0334:             * Add a deferred runnable, which is run after the first pass over the
0335:             * syntax-tree.  This gives various parts of the compiler a way to defer
0336:             * a decision until after the first pass.
0337:             * 
0338:             * @param r  the runnable that is invoked in an unspecified order after
0339:             *    the first pass
0340:             */
0341:            void defer(Runnable r) {
0342:                deferredRunnableList.add(r);
0343:            }
0344:
0345:            /**
0346:             * push the instance constant onto the stack, setting ret-val to true.
0347:             */
0348:            void getInstanceConstant(Object obj) {
0349:                setRetValOnStack(true);
0350:                ctx.pushInstanceConstant(il, obj);
0351:            }
0352:
0353:            /*=======================================================================*/
0354:            /**
0355:             * <PRE>
0356:             * f0 -> ( &lt;UNIX_SELF_EXECUTABLE_COMMENT&gt; )?
0357:             * f1 -> Program(false)
0358:             * f2 -> &lt;EOF&gt;
0359:             * </PRE>
0360:             */
0361:            public void visit(ProgramFile n) {
0362:                n.f1.accept(this );
0363:            }
0364:
0365:            /*=======================================================================*/
0366:            /**
0367:             * <PRE>
0368:             * f0 -> ( EvaluationUnit() )*
0369:             * </PRE>
0370:             */
0371:            public void visit(Program n) {
0372:                for (int i = 0; i < n.f0.size(); i++)
0373:                    n.f0.elementAt(i).accept(this );
0374:            }
0375:
0376:            /*=======================================================================*/
0377:            /**
0378:             * <PRE>
0379:             * f0 -> ScopeBlock()
0380:             *       | VariableDeclarationBlock()
0381:             *       | FunctionDeclaration()
0382:             *       | TryStatement()
0383:             *       | ForLoopStatement()
0384:             *       | WhileLoopStatement()
0385:             *       | ConditionalStatement()
0386:             *       | SynchronizedStatement()
0387:             *       | ReturnStatement()
0388:             *       | BreakStatement()
0389:             *       | ContinueStatement()
0390:             *       | ExpressionBlock()
0391:             *       | ThrowBlock()
0392:             *       | ImportBlock()
0393:             *       | MixinBlock()
0394:             *       | EvalBlock()
0395:             * </PRE>
0396:             */
0397:            public void visit(EvaluationUnit n) {
0398:                n.f0.accept(this );
0399:
0400:                if (retValOnStack) {
0401:                    il.append(InstructionConstants.POP);
0402:                    setRetValOnStack(false);
0403:                }
0404:            }
0405:
0406:            /*=======================================================================*/
0407:            /**
0408:             * <PRE>
0409:             * f0 -> "{"
0410:             * f1 -> Program()
0411:             * f2 -> "}"
0412:             * </PRE>
0413:             */
0414:            public void visit(ScopeBlock n) {
0415:                if (n.hasVarInScope)
0416:                    scope = new CompilerScope(this , scope, n.hasFxnInScope); // push new scope
0417:                n.f1.accept(this );
0418:                if (n.hasVarInScope)
0419:                    scope = scope.pop(); // pop scope
0420:            }
0421:
0422:            /*=======================================================================*/
0423:            /**
0424:             * <PRE>
0425:             * f0 -> VariableDeclaration()
0426:             * f1 -> ";"
0427:             * </PRE>
0428:             */
0429:            public void visit(VariableDeclarationBlock n) {
0430:                n.f0.accept(this );
0431:            }
0432:
0433:            /*=======================================================================*/
0434:            /**
0435:             * <PRE>
0436:             * f0 -> Expression()
0437:             * f1 -> ";"
0438:             * </PRE>
0439:             */
0440:            public void visit(ExpressionBlock n) {
0441:                n.f0.accept(this );
0442:            }
0443:
0444:            /*=======================================================================*/
0445:            /**
0446:             * <PRE>
0447:             * f0 -> "throw"
0448:             * f1 -> Expression()
0449:             * f2 -> ";"
0450:             * </PRE>
0451:             */
0452:            public void visit(ThrowBlock n) {
0453:                handle(n.f0);
0454:
0455:                // evaluate expression:
0456:                n.f1.accept(this );
0457:                setRetValOnStack(false);
0458:
0459:                // check that the user isn't trying to throw (undefined)
0460:                il.append(new INVOKESTATIC(ctx.methodref(
0461:                        "oscript.compiler.CompiledNodeEvaluator",
0462:                        "returnHelper",
0463:                        "(Loscript/data/Value;)Loscript/data/Value;")));
0464:
0465:                // throw PackagedScriptObjectException.makeExceptionWrapper(retVal)
0466:                il
0467:                        .append(new INVOKESTATIC(
0468:                                ctx
0469:                                        .methodref(
0470:                                                "oscript.exceptions.PackagedScriptObjectException",
0471:                                                "makeExceptionWrapper2",
0472:                                                "(Loscript/data/Value;)Loscript/exceptions/PackagedScriptObjectException;")));
0473:                il.append(InstructionConstants.ATHROW);
0474:            }
0475:
0476:            /*=======================================================================*/
0477:            /**
0478:             * <PRE>
0479:             * f0 -> "import"
0480:             * f1 -> Expression()
0481:             * f2 -> ";"
0482:             * </PRE>
0483:             */
0484:            public void visit(ImportBlock n) {
0485:                handle(n.f0);
0486:
0487:                // evaluate expression:
0488:                n.f1.accept(this );
0489:
0490:                il.append(new INVOKEVIRTUAL(ctx.methodref("oscript.data.Value",
0491:                        "castToString", "()Ljava/lang/String;")));
0492:
0493:                il.append(new ALOAD(scope.getSlot()));
0494:
0495:                il
0496:                        .append(new INVOKESTATIC(
0497:                                ctx
0498:                                        .methodref(
0499:                                                "oscript.compiler.CompiledNodeEvaluator",
0500:                                                "importHelper",
0501:                                                "(Ljava/lang/String;Loscript/data/Scope;)Loscript/data/Value;")));
0502:
0503:                scope.markOpen();
0504:            }
0505:
0506:            /*=======================================================================*/
0507:            /**
0508:             * <PRE>
0509:             * f0 -> "mixin"
0510:             * f1 -> Expression()
0511:             * f2 -> ";"
0512:             * </PRE>
0513:             */
0514:            public void visit(MixinBlock n) {
0515:                handle(n.f0);
0516:
0517:                il.append(new ALOAD(scope.getSlot()));
0518:                n.f1.accept(this );
0519:                setRetValOnStack(false);
0520:                il.append(new INVOKEVIRTUAL(ctx.methodref("oscript.data.Scope",
0521:                        "mixin", "(Loscript/data/Value;)V")));
0522:
0523:                scope.markOpen(); // XXX ???  need to ensure scope object is actually created, but that doesn't make it an open scope
0524:            }
0525:
0526:            /*=======================================================================*/
0527:            /**
0528:             * <PRE>
0529:             * f0 -> "eval"
0530:             * f1 -> Expression()
0531:             * f2 -> ";"
0532:             * </PRE>
0533:             */
0534:            public void visit(EvalBlock n) {
0535:                handle(n.f0);
0536:
0537:                // evaluate expression:
0538:                n.f1.accept(this );
0539:
0540:                il.append(new INVOKEVIRTUAL(ctx.methodref("oscript.data.Value",
0541:                        "castToString", "()Ljava/lang/String;")));
0542:
0543:                il.append(new ALOAD(scope.getSlot()));
0544:
0545:                il
0546:                        .append(new INVOKESTATIC(
0547:                                ctx
0548:                                        .methodref(
0549:                                                "oscript.compiler.CompiledNodeEvaluator",
0550:                                                "evalHelper",
0551:                                                "(Ljava/lang/String;Loscript/data/Scope;)Loscript/data/Value;")));
0552:
0553:                scope.markOpen();
0554:            }
0555:
0556:            /*=======================================================================*/
0557:            /**
0558:             * <PRE>
0559:             * f0 -> Permissions()
0560:             * f1 -> "var"
0561:             * f2 -> &lt;IDENTIFIER&gt;
0562:             * f3 -> ( "=" Expression() )?
0563:             * </PRE>
0564:             */
0565:            public void visit(VariableDeclaration n) {
0566:                // need to handle for special tokens, before n.f3
0567:                int permissions = getPermissions(n.f0, Reference.ATTR_PROTECTED);
0568:
0569:                // order is important here... have to evaluate f3 before createMember
0570:                // because things like:
0571:                // 
0572:                //   var foo = foo;
0573:                // 
0574:                // should create a local which is a copy of the global with the
0575:                // same name
0576:                if (n.f3.present()) {
0577:                    ((NodeSequence) (n.f3.node)).elementAt(1).accept(this );
0578:                    setRetValOnStack(false);
0579:                }
0580:
0581:                // scope.createMember( memberName, Permissions_attr )
0582:                scope.createMember(n.f2, permissions);
0583:
0584:                if (n.f3.present()) {
0585:                    // var.opAssign(val)
0586:                    il.append(InstructionConstants.SWAP);
0587:                    il.append(new INVOKEVIRTUAL(ctx.methodref(
0588:                            "oscript.data.Value", "opAssign",
0589:                            "(Loscript/data/Value;)V")));
0590:                } else {
0591:                    il.append(InstructionConstants.POP);
0592:                }
0593:            }
0594:
0595:            /*=======================================================================*/
0596:            /**
0597:             * <PRE>
0598:             * f0 -> Permissions()
0599:             * f1 -> "function"
0600:             * f2 -> &lt;IDENTIFIER&gt;
0601:             * f3 -> "("
0602:             * f4 -> ( Arglist() )?
0603:             * f5 -> ")"
0604:             * f6 -> ( "extends" PrimaryExpressionWithTrailingFxnCallExpList() FunctionCallExpressionList() )?
0605:             * f7 -> "{"
0606:             * f8 -> Program()
0607:             * f9 -> "}"
0608:             * </PRE>
0609:             */
0610:            public void visit(FunctionDeclaration n) {
0611:                FunctionDeclarationTranslator.translate(n).accept(this );
0612:            }
0613:
0614:            /*=======================================================================*/
0615:            private boolean Arglist_varargs;
0616:
0617:            /**
0618:             * <PRE>
0619:             * f0 -> Permissions()
0620:             * f1 -> &lt;IDENTIFIER&gt;
0621:             * f2 -> ( "," Permissions() &lt;IDENTIFIER&gt; )*
0622:             * f3 -> ( "..." )?
0623:             * </PRE>
0624:             */
0625:            public void visit(Arglist n) {
0626:                throw new ProgrammingErrorException("shouldn't get here!");
0627:            }
0628:
0629:            private int[] getArglist(Arglist n) {
0630:                if (n.cachedValue == null) {
0631:                    int len = 2 * (n.f2.size() + 1);
0632:
0633:                    handle(n.f1);
0634:
0635:                    n.cachedValue = new int[len];
0636:                    n.cachedValue[0] = Symbol.getSymbol(n.f1.otokenImage)
0637:                            .getId();
0638:                    n.cachedValue[1] = getPermissions(n.f0,
0639:                            Reference.ATTR_PRIVATE);
0640:
0641:                    for (int i = 0; i < n.f2.size(); i++) {
0642:                        NodeToken nt = (NodeToken) (((NodeSequence) (n.f2
0643:                                .elementAt(i))).elementAt(2));
0644:                        handle(nt);
0645:                        n.cachedValue[2 * (i + 1)] = Symbol.getSymbol(
0646:                                nt.otokenImage).getId();
0647:                        n.cachedValue[2 * (i + 1) + 1] = getPermissions(
0648:                                (Permissions) (((NodeSequence) (n.f2
0649:                                        .elementAt(i))).elementAt(1)),
0650:                                Reference.ATTR_PRIVATE);
0651:                    }
0652:                }
0653:
0654:                Arglist_varargs = n.f3.present();
0655:
0656:                return n.cachedValue;
0657:            }
0658:
0659:            /*=======================================================================*/
0660:            /**
0661:             * <PRE>
0662:             * f0 -> "try"
0663:             * f1 -> EvaluationUnit()
0664:             * f2 -> ( "catch" "(" Expression() &lt;IDENTIFIER&gt; ")" EvaluationUnit() )*
0665:             * f3 -> ( "catch" "(" &lt;IDENTIFIER&gt; ")" EvaluationUnit() )?
0666:             * f4 -> ( "finally" EvaluationUnit() )?
0667:             * </PRE>
0668:             */
0669:            public void visit(TryStatement n) {
0670:                handle(n.f0);
0671:
0672:                scope.enterConditional();
0673:
0674:                LinkedList gotoList = new LinkedList();
0675:
0676:                final InstructionHandle[] finally_start = new InstructionHandle[1]; // array used to have ref to ref..
0677:                LoopStackNode.CleanupInstructionGenerator g = null;
0678:
0679:                if (n.f4.present()) {
0680:                    g = new LoopStackNode.CleanupInstructionGenerator() {
0681:                        public void generate(final CompilerInstructionList il) {
0682:                            final BranchInstruction JSR = new JSR(null);
0683:                            il.append(JSR);
0684:
0685:                            defer(new Runnable() {
0686:                                public void run() {
0687:                                    JSR.setTarget(finally_start[0]);
0688:                                }
0689:                            });
0690:                        }
0691:                    };
0692:                    loopStack.addCleanupInstructionGenerator(g);
0693:                }
0694:
0695:                InstructionHandle try_start = il
0696:                        .append(InstructionConstants.NOP);
0697:                n.f1.accept(this );
0698:                // jump to end/finally:
0699:                il.append(addToBranchInstructionList(gotoList, new GOTO(null)));
0700:                InstructionHandle try_end = il.append(InstructionConstants.NOP);
0701:                InstructionHandle handler_start = il
0702:                        .append(InstructionConstants.NOP);
0703:
0704:                for (int i = 0; i < n.f2.size(); i++) {
0705:                    // stack:   ..., e
0706:
0707:                    NodeSequence seq = (NodeSequence) (n.f2.elementAt(i));
0708:
0709:                    // store java exception on stack:       ..., e  ->  ..., e, e
0710:                    il.append(InstructionConstants.DUP);
0711:
0712:                    // get the script exception object:     ..., e, e  ->  ..., e, e.val
0713:                    il.append(new GETFIELD(ctx.fieldref(
0714:                            "oscript.exceptions.PackagedScriptObjectException",
0715:                            "val", "Loscript/data/Value;")));
0716:
0717:                    // check the type of the script exception:    ... e, e.val -> e, e.val
0718:                    il.append(InstructionConstants.DUP); //  ... e, e.val -> e, e.val, e.val
0719:                    seq.elementAt(2).accept(this ); //  ... e, e.val, e.val -> e, e.val, e.val, type
0720:                    setRetValOnStack(false);
0721:                    il.append(new INVOKEVIRTUAL(ctx.methodref(
0722:                            "oscript.data.Value", "bopInstanceOf",
0723:                            "(Loscript/data/Value;)Loscript/data/Value;")));
0724:                    il.append(new INVOKEVIRTUAL(ctx.methodref(
0725:                            "oscript.data.Value", "castToBoolean", "()Z")));
0726:
0727:                    BranchInstruction IFEQ = new IFEQ(null); //  ... e, e.val, bool -> e, e.val
0728:                    il.append(IFEQ);
0729:
0730:                    scope = new CompilerScope(this , scope, true); // push scope  (XXX need to know hasFxnInScope)
0731:
0732:                    // createMember & opAssign:     ..., e, e.val  ->  ..., e
0733:                    scope.createMember((NodeToken) (seq.elementAt(3)), 0);
0734:                    il.append(InstructionConstants.SWAP);
0735:                    il.append(new INVOKEVIRTUAL(ctx.methodref(
0736:                            "oscript.data.Value", "opAssign",
0737:                            "(Loscript/data/Value;)V")));
0738:
0739:                    // don't need stored java exception on stack:    ..., e  ->  ...
0740:                    il.append(InstructionConstants.POP);
0741:
0742:                    seq.elementAt(5).accept(this );
0743:
0744:                    scope = scope.pop(); // pop scope
0745:
0746:                    // jump to end/finally:
0747:                    il.append(addToBranchInstructionList(gotoList, new GOTO(
0748:                            null)));
0749:
0750:                    il.setNextAsTarget(IFEQ);
0751:
0752:                    // don't need script exception on stack:    ..., e, e.val  ->  ..., e
0753:                    il.append(InstructionConstants.POP);
0754:                }
0755:
0756:                if (n.f3.present()) {
0757:                    // stack:   ..., e
0758:
0759:                    NodeSequence seq = (NodeSequence) (n.f3.node);
0760:
0761:                    // get the script exception object:     ..., e  ->  ..., e.val
0762:                    il.append(new GETFIELD(ctx.fieldref(
0763:                            "oscript.exceptions.PackagedScriptObjectException",
0764:                            "val", "Loscript/data/Value;")));
0765:
0766:                    scope = new CompilerScope(this , scope, false); // push scope
0767:
0768:                    // createMember & opAssign:     ..., e.val  ->  ...
0769:                    scope.createMember((NodeToken) (seq.elementAt(2)), 0);
0770:                    il.append(InstructionConstants.SWAP);
0771:                    il.append(new INVOKEVIRTUAL(ctx.methodref(
0772:                            "oscript.data.Value", "opAssign",
0773:                            "(Loscript/data/Value;)V")));
0774:
0775:                    seq.elementAt(4).accept(this );
0776:
0777:                    scope = scope.pop(); // pop scope
0778:
0779:                    // jump to end/finally:
0780:                    il.append(addToBranchInstructionList(gotoList, new GOTO(
0781:                            null))); // XXX ??? do I need this?
0782:                } else {
0783:                    // don't need stored java exception on stack:    ..., e  ->  ...
0784:                    il.append(InstructionConstants.ATHROW);
0785:                }
0786:
0787:                if ((n.f2.size() > 0) || n.f3.present())
0788:                    mg.addExceptionHandler(try_start, try_end, handler_start,
0789:                            ctx.EXCEPTION_TYPE);
0790:
0791:                for (Iterator itr = gotoList.iterator(); itr.hasNext();)
0792:                    il.setNextAsTarget((BranchInstruction) (itr.next()));
0793:
0794:                if (n.f4.present()) {
0795:                    BranchInstruction REG_JSR = new JSR(null);
0796:                    BranchInstruction GOTO_END = new GOTO(null);
0797:
0798:                    InstructionHandle any_exception_end = il.append(REG_JSR); // target of "try" and "catch" gotos
0799:                    il.append(GOTO_END); // normal execution skips exception handling glue
0800:                    InstructionHandle any_handler_start = il
0801:                            .append(InstructionConstants.NOP); // begin handler for <any>
0802:
0803:                    // we need to store the exception value:
0804:                    int exceptionSlot = mg.addLocalVariable(
0805:                            ctx.makeUniqueIdentifierName("e"),
0806:                            ctx.ANY_EXCEPTION_TYPE, null, // XXX start
0807:                            null // XXX end
0808:                            ).getIndex();
0809:
0810:                    BranchInstruction ANY_EXCEPTION_JSR = new JSR(null);
0811:
0812:                    il.append(new ASTORE(exceptionSlot));
0813:                    il.append(ANY_EXCEPTION_JSR);
0814:                    il.append(new ALOAD(exceptionSlot));
0815:                    il.append(InstructionConstants.ATHROW);
0816:
0817:                    il.setNextAsTarget(REG_JSR);
0818:                    il.setNextAsTarget(ANY_EXCEPTION_JSR);
0819:
0820:                    int retAddrSlot = mg.addLocalVariable(
0821:                            ctx.makeUniqueIdentifierName("retaddr"),
0822:                            org.apache.bcel.generic.Type.OBJECT, null, // XXX start
0823:                            null // XXX end
0824:                            ).getIndex();
0825:
0826:                    loopStack.removeCleanupInstructionGenerator(g);
0827:                    finally_start[0] = il.append(new ASTORE(retAddrSlot));
0828:
0829:                    ((NodeSequence) (n.f4.node)).elementAt(1).accept(this );
0830:
0831:                    il.append(new RET(retAddrSlot));
0832:
0833:                    mg.addExceptionHandler(try_start, any_exception_end,
0834:                            any_handler_start, ctx.ANY_EXCEPTION_TYPE);
0835:
0836:                    il.setNextAsTarget(GOTO_END);
0837:                }
0838:
0839:                scope.leaveConditional();
0840:            }
0841:
0842:            // XXX move this:
0843:            private static final BranchInstruction addToBranchInstructionList(
0844:                    LinkedList list, BranchInstruction bi) {
0845:                list.addFirst(bi);
0846:                return bi;
0847:            }
0848:
0849:            /*=======================================================================*/
0850:            /**
0851:             * <PRE>
0852:             * f0 -> "for"
0853:             * f1 -> "("
0854:             * f2 -> ( PreLoopStatement() )?
0855:             * f3 -> ";"
0856:             * f4 -> ( Expression() )?
0857:             * f5 -> ";"
0858:             * f6 -> ( Expression() )?
0859:             * f7 -> ")"
0860:             * f8 -> EvaluationUnit()
0861:             * </PRE>
0862:             */
0863:            public void visit(ForLoopStatement n) {
0864:                ForLoopStatementTranslator.translate(n).accept(this );
0865:            }
0866:
0867:            /*=======================================================================*/
0868:            /**
0869:             * <PRE>
0870:             * f0 -> "for"
0871:             * f1 -> "("
0872:             * f2 -> PreLoopStatement()
0873:             * f3 -> ":"
0874:             * f4 -> Expression()
0875:             * f5 -> ")"
0876:             * f6 -> EvaluationUnit()
0877:             * </PRE>
0878:             */
0879:            public void visit(CollectionForLoopStatement n) {
0880:                CollectionForLoopStatementTranslator.translate(n).accept(this );
0881:            }
0882:
0883:            /*=======================================================================*/
0884:            /**
0885:             * <PRE>
0886:             * f0 -> VariableDeclaration()
0887:             *       | Expression()
0888:             * </PRE>
0889:             */
0890:            public void visit(PreLoopStatement n) {
0891:                n.f0.accept(this );
0892:            }
0893:
0894:            /*=======================================================================*/
0895:            /**
0896:             * <PRE>
0897:             * f0 -> "while"
0898:             * f1 -> "("
0899:             * f2 -> Expression()
0900:             * f3 -> ")"
0901:             * f4 -> EvaluationUnit()
0902:             * </PRE>
0903:             */
0904:            public void visit(WhileLoopStatement n) {
0905:                handle(n.f0);
0906:
0907:                BranchInstruction IFEQ = new IFEQ(null);
0908:                BranchInstruction GOTO = new GOTO(null);
0909:
0910:                il.setNextAsTarget(GOTO);
0911:                n.f2.accept(this );
0912:                setRetValOnStack(false);
0913:
0914:                il.append(new INVOKEVIRTUAL(ctx.methodref("oscript.data.Value",
0915:                        "castToBoolean", "()Z")));
0916:
0917:                il.append(IFEQ);
0918:
0919:                // push a new LoopStackNode:
0920:                loopStack = new LoopStackNode(loopStack);
0921:
0922:                scope.enterConditional();
0923:                n.f4.accept(this );
0924:                scope.leaveConditional();
0925:
0926:                il.append(GOTO);
0927:
0928:                il.setNextAsTarget(IFEQ);
0929:
0930:                for (Iterator itr = loopStack.getContinueInstructions()
0931:                        .iterator(); itr.hasNext();)
0932:                    ((BranchInstruction) (itr.next())).setTarget(GOTO
0933:                            .getTarget());
0934:
0935:                for (Iterator itr = loopStack.getBreakInstructions().iterator(); itr
0936:                        .hasNext();)
0937:                    il.setNextAsTarget((BranchInstruction) (itr.next()));
0938:
0939:                // pop LoopStackNode:
0940:                loopStack = loopStack.pop();
0941:            }
0942:
0943:            /*=======================================================================*/
0944:            /**
0945:             * <PRE>
0946:             * f0 -> "if"
0947:             * f1 -> "("
0948:             * f2 -> Expression()
0949:             * f3 -> ")"
0950:             * f4 -> EvaluationUnit()
0951:             * f5 -> ( "else" EvaluationUnit() )?
0952:             * </PRE>
0953:             */
0954:            public void visit(ConditionalStatement n) {
0955:                handle(n.f0);
0956:
0957:                n.f2.accept(this );
0958:                setRetValOnStack(false);
0959:
0960:                il.append(new INVOKEVIRTUAL(ctx.methodref("oscript.data.Value",
0961:                        "castToBoolean", "()Z")));
0962:
0963:                BranchInstruction IFEQ = new IFEQ(null);
0964:                il.append(IFEQ);
0965:
0966:                scope.enterConditional();
0967:                n.f4.accept(this );
0968:
0969:                if (n.f5.present()) {
0970:                    BranchInstruction GOTO = new GOTO(null);
0971:                    il.append(GOTO);
0972:
0973:                    il.setNextAsTarget(IFEQ);
0974:                    ((NodeSequence) (n.f5.node)).elementAt(1).accept(this );
0975:
0976:                    il.setNextAsTarget(GOTO);
0977:                } else {
0978:                    il.setNextAsTarget(IFEQ);
0979:                }
0980:
0981:                scope.leaveConditional();
0982:            }
0983:
0984:            /*=======================================================================*/
0985:            /**
0986:             * <PRE>
0987:             * f0 -> "synchronized"
0988:             * f1 -> "("
0989:             * f2 -> Expression()
0990:             * f3 -> ")"
0991:             * f4 -> EvaluationUnit()
0992:             * </PRE>
0993:             */
0994:            public void visit(SynchronizedStatement n) {
0995:                n.f2.accept(this );
0996:                setRetValOnStack(false);
0997:
0998:                il.append(new INVOKEVIRTUAL(ctx.methodref("oscript.data.Value",
0999:                        "getMonitor", "()Ljava/lang/Object;")));
1000:
1001:                // we need to store the monitor value:
1002:                LocalVariableGen monLg = mg.addLocalVariable(ctx
1003:                        .makeUniqueIdentifierName("monitor"), ctx.VALUE_TYPE,
1004:                        null, // XXX
1005:                        null); // XXX
1006:                final int monSlot = monLg.getIndex();
1007:
1008:                LoopStackNode.CleanupInstructionGenerator g = new LoopStackNode.CleanupInstructionGenerator() {
1009:                    public void generate(CompilerInstructionList il) {
1010:                        il.append(new ALOAD(monSlot));
1011:                        il.append(InstructionConstants.MONITOREXIT);
1012:                    }
1013:                };
1014:
1015:                loopStack.addCleanupInstructionGenerator(g);
1016:
1017:                il.append(InstructionConstants.DUP);
1018:                il.append(new ASTORE(monSlot));
1019:                InstructionHandle try_start = il
1020:                        .append(InstructionConstants.MONITORENTER);
1021:
1022:                n.f4.accept(this );
1023:
1024:                loopStack.removeCleanupInstructionGenerator(g);
1025:
1026:                il.append(new ALOAD(monSlot));
1027:                InstructionHandle try_end = il
1028:                        .append(InstructionConstants.MONITOREXIT);
1029:                BranchInstruction GOTO = new GOTO(null);
1030:                il.append(GOTO);
1031:
1032:                InstructionHandle handler_start = il.append(new ALOAD(monSlot));
1033:                il.append(InstructionConstants.MONITOREXIT);
1034:                il.append(InstructionConstants.ATHROW);
1035:
1036:                il.setNextAsTarget(GOTO);
1037:
1038:                mg.addExceptionHandler(try_start, try_end, handler_start,
1039:                        ctx.ANY_EXCEPTION_TYPE);
1040:            }
1041:
1042:            /*=======================================================================*/
1043:            /**
1044:             * <PRE>
1045:             * f0 -> "return"
1046:             * f1 -> ( Expression() )?
1047:             * </PRE>
1048:             */
1049:            public void visit(ReturnStatement n) {
1050:                handle(n.f0);
1051:
1052:                if (n.f1.present()) {
1053:                    n.f1.node.accept(this );
1054:                    checkRetValOnStack(true);
1055:
1056:                    il.append(new INVOKESTATIC(ctx.methodref(
1057:                            "oscript.compiler.CompiledNodeEvaluator",
1058:                            "returnHelper",
1059:                            "(Loscript/data/Value;)Loscript/data/Value;")));
1060:                } else {
1061:                    getInstanceConstant(Value.UNDEFINED);
1062:                    setRetValOnStack(false);
1063:                }
1064:
1065:                int retValSlot = mg.addLocalVariable(
1066:                        ctx.makeUniqueIdentifierName("retVal"), ctx.VALUE_TYPE,
1067:                        null, // XXX start
1068:                        null // XXX end
1069:                        ).getIndex();
1070:
1071:                il.append(new ASTORE(retValSlot));
1072:                loopStack.insertCleanupInstructions(il, true);
1073:                il.append(new ALOAD(retValSlot));
1074:
1075:                il.append(InstructionConstants.ARETURN);
1076:            }
1077:
1078:            /*=======================================================================*/
1079:            /**
1080:             * <PRE>
1081:             * f0 -> "break"
1082:             * f1 -> ";"
1083:             * </PRE>
1084:             */
1085:            public void visit(BreakStatement n) {
1086:                handle(n.f0);
1087:
1088:                loopStack.insertCleanupInstructions(il, false);
1089:
1090:                BranchInstruction GOTO = new GOTO(null);
1091:                il.append(GOTO);
1092:
1093:                loopStack.addBreakBranchInstruction(GOTO);
1094:            }
1095:
1096:            /*=======================================================================*/
1097:            /**
1098:             * <PRE>
1099:             * f0 -> "continue"
1100:             * f1 -> ";"
1101:             * </PRE>
1102:             */
1103:            public void visit(ContinueStatement n) {
1104:                handle(n.f0);
1105:
1106:                loopStack.insertCleanupInstructions(il, false);
1107:
1108:                BranchInstruction GOTO = new GOTO(null);
1109:                il.append(GOTO);
1110:
1111:                loopStack.addContinueBranchInstruction(GOTO);
1112:            }
1113:
1114:            /*=======================================================================*/
1115:            /**
1116:             * Note, <i>Expression</i> always returns a value on the stack, even
1117:             * if that value is <code>Value.NULL</code>.
1118:             * 
1119:             * <PRE>
1120:             * f0 -> AssignmentExpression()
1121:             * f1 -> ( "," AssignmentExpression() )*
1122:             * </PRE>
1123:             */
1124:            public void visit(Expression n) {
1125:                n.f0.accept(this );
1126:
1127:                for (int i = 0; i < n.f1.size(); i++) {
1128:                    // get rid of previous value on stack:
1129:                    il.append(InstructionConstants.POP);
1130:                    setRetValOnStack(false);
1131:
1132:                    ((NodeSequence) (n.f1.elementAt(i))).elementAt(1).accept(
1133:                            this );
1134:                }
1135:
1136:                checkRetValOnStack(true);
1137:            }
1138:
1139:            /*=======================================================================*/
1140:            /**
1141:             * <PRE>
1142:             * f0 -> "("
1143:             * f1 -> ( FunctionCallExpressionListBody() )?
1144:             * f2 -> ")"
1145:             * </PRE>
1146:             */
1147:            public void visit(FunctionCallExpressionList n) {
1148:                n.f0.accept(this ); // to record last NodeToken
1149:
1150:                if (n.f1.present()) {
1151:                    FunctionCallExpressionList_sfIsNull = false;
1152:                    n.f1.node.accept(this );
1153:                } else {
1154:                    FunctionCallExpressionList_sfIsNull = true;
1155:                    allocateMemberTable_allocateFromStack = false;
1156:                    il.append(InstructionConstants.ACONST_NULL);
1157:                }
1158:
1159:                setRetValOnStack(true);
1160:            }
1161:
1162:            /**
1163:             * If there were no args, the FunctionCallExpressionList visitor will
1164:             * push <code>null</code> onto the stack
1165:             */
1166:            private boolean FunctionCallExpressionList_sfIsNull = false;
1167:
1168:            /**
1169:             * Set to true before accept()ing the the {@link FunctionCallExpressionList}
1170:             * (or calling {@link #allocateMemberTable}, to indicate that the member-
1171:             * table should be allocated from the stack (rather than allocating an
1172:             * <code>OArray</code>).  This is reset back to <code>false</code> once
1173:             * the <code>FunctionCallExpressionList</code> is visited.
1174:             * <p>
1175:             * If set to true, the code that the member-table is created for should
1176:             * take care to call {@link MemberTable#free()}
1177:             */
1178:            private boolean allocateMemberTable_allocateFromStack = false;
1179:
1180:            private void allocateMemberTable(int sz) {
1181:                if (allocateMemberTable_allocateFromStack) {
1182:                    il.append(InstructionConstants.ALOAD_1); // sf
1183:                    ctx.pushInt(il, sz);
1184:                    il.append(new INVOKEVIRTUAL(ctx.methodref(
1185:                            "oscript.util.StackFrame", "allocateMemberTable",
1186:                            "(S)Loscript/util/MemberTable;")));
1187:                    allocateMemberTable_allocateFromStack = false;
1188:                } else {
1189:                    il.append(new NEW(ctx.cp.addClass("oscript.data.OArray")));
1190:                    il.append(InstructionConstants.DUP);
1191:                    ctx.pushInt(il, sz);
1192:                    il.append(new INVOKESPECIAL(ctx.methodref(
1193:                            "oscript.data.OArray", "<init>", "(I)V")));
1194:                }
1195:            }
1196:
1197:            /*=======================================================================*/
1198:            /**
1199:             * <PRE>
1200:             * f0 -> AssignmentExpression()
1201:             * f1 -> ( "," AssignmentExpression() )*
1202:             * </PRE>
1203:             */
1204:            public void visit(FunctionCallExpressionListBody n) {
1205:                allocateMemberTable(1 + n.f1.size());
1206:
1207:                int cnt = 0;
1208:
1209:                il.append(InstructionConstants.DUP);
1210:                n.f0.accept(this );
1211:                setRetValOnStack(false);
1212:                cnt++;
1213:
1214:                for (int i = 0; i < n.f1.size(); i++) {
1215:                    if (cnt == 4) {
1216:                        il.append(new INVOKEINTERFACE(ctx.ifmethodref(
1217:                                "oscript.util.MemberTable",
1218:                                PUSH_METHOD_NAMES[cnt],
1219:                                PUSH_METHOD_SIGNATURES[cnt]), cnt + 1));
1220:                        il.append(InstructionConstants.DUP);
1221:                        cnt = 0;
1222:                    }
1223:
1224:                    NodeSequence seq = (NodeSequence) (n.f1.elementAt(i));
1225:                    seq.elementAt(1).accept(this );
1226:                    setRetValOnStack(false);
1227:                    cnt++;
1228:                }
1229:
1230:                if (cnt > 0) {
1231:                    il.append(new INVOKEINTERFACE(ctx.ifmethodref(
1232:                            "oscript.util.MemberTable", PUSH_METHOD_NAMES[cnt],
1233:                            PUSH_METHOD_SIGNATURES[cnt]), cnt + 1));
1234:                } else {
1235:                    // get rid of extra member-table reference on top of the stack
1236:                    il.append(InstructionConstants.POP);
1237:                }
1238:            }
1239:
1240:            private static final String[] PUSH_METHOD_NAMES = new String[] {
1241:                    null, "push1", "push2", "push3", "push4" };
1242:
1243:            private static final String[] PUSH_METHOD_SIGNATURES = new String[] {
1244:                    null,
1245:                    "(Loscript/data/Value;)V",
1246:                    "(Loscript/data/Value;Loscript/data/Value;)V",
1247:                    "(Loscript/data/Value;Loscript/data/Value;Loscript/data/Value;)V",
1248:                    "(Loscript/data/Value;Loscript/data/Value;Loscript/data/Value;Loscript/data/Value;)V" };
1249:
1250:            /*=======================================================================*/
1251:            /**
1252:             * <PRE>
1253:             * f0 -> ConditionalExpression()
1254:             * f1 -> ( ( "=" | "+=" | "-=" | "*=" | "/=" | "%=" | "&gt;&gt;=" | "&lt;&lt;=" | "&gt;&gt;&gt;=" | "&=" | "^=" | "|=" ) ConditionalExpression() )*
1255:             * </PRE>
1256:             */
1257:            public void visit(AssignmentExpression n) {
1258:                // the tricky part here is that things need to be evaluated backwards:
1259:                int lastOp = -1;
1260:
1261:                for (int i = n.f1.size() - 1; i >= -1; i--) {
1262:                    int op = lastOp;
1263:
1264:                    // evaluate <i>CondidtionalExpression</i>, should return a val on stack:
1265:                    if (i >= 0) {
1266:                        NodeSequence seq = (NodeSequence) (n.f1.elementAt(i));
1267:                        seq.elementAt(1).accept(this );
1268:                        lastOp = ((NodeToken) (((NodeChoice) (seq.elementAt(0))).choice)).kind;
1269:                    } else {
1270:                        n.f0.accept(this );
1271:                    }
1272:
1273:                    // keep the val on the stack, don't return it
1274:                    setRetValOnStack(false);
1275:
1276:                    if (op != -1) {
1277:                        // stack: ..., lastVal, val 
1278:
1279:                        String methodName = null;
1280:
1281:                        switch (op) {
1282:                        case ASSIGN:
1283:                            // no-op
1284:                            break;
1285:                        case PLUSASSIGN:
1286:                            methodName = "bopPlus";
1287:                            break;
1288:                        case MINUSASSIGN:
1289:                            methodName = "bopMinus";
1290:                            break;
1291:                        case STARASSIGN:
1292:                            methodName = "bopMultiply";
1293:                            break;
1294:                        case SLASHASSIGN:
1295:                            methodName = "bopDivide";
1296:                            break;
1297:                        case ANDASSIGN:
1298:                            methodName = "bopBitwiseAnd";
1299:                            break;
1300:                        case ORASSIGN:
1301:                            methodName = "bopBitwiseOr";
1302:                            break;
1303:                        case XORASSIGN:
1304:                            methodName = "bopBitwiseXor";
1305:                            break;
1306:                        case REMASSIGN:
1307:                            methodName = "bopRemainder";
1308:                            break;
1309:                        case LSHIFTASSIGN:
1310:                            methodName = "bopLeftShift";
1311:                            break;
1312:                        case RSIGNEDSHIFTASSIGN:
1313:                            methodName = "bopSignedRightShift";
1314:                            break;
1315:                        case RUNSIGNEDSHIFTASSIGN:
1316:                            methodName = "bopUnsignedRightShift";
1317:                            break;
1318:                        default:
1319:                            throw new ProgrammingErrorException(
1320:                                    "unknown operator: " + op);
1321:                        }
1322:
1323:                        if (methodName != null) {
1324:                            // stack: ..., lastVal, val => ..., val, val, lastVal
1325:                            il.append(InstructionConstants.DUP_X1);
1326:                            il.append(InstructionConstants.SWAP);
1327:
1328:                            // stack: ..., val, val, lastVal => ..., val, lastVal
1329:                            il
1330:                                    .append(new INVOKEVIRTUAL(
1331:                                            ctx
1332:                                                    .methodref(
1333:                                                            "oscript.data.Value",
1334:                                                            methodName,
1335:                                                            "(Loscript/data/Value;)Loscript/data/Value;")));
1336:                        } else {
1337:                            // stack: ..., lastVal, val => ..., val, lastVal
1338:                            il.append(InstructionConstants.SWAP);
1339:                        }
1340:
1341:                        // stack: ..., val, lastVal => ..., lastVal, val, lastVal:
1342:                        il.append(InstructionConstants.DUP_X1);
1343:
1344:                        // stack: ..., lastVal, val, lastVal => ..., lastVal
1345:                        il.append(new INVOKEVIRTUAL(ctx.methodref(
1346:                                "oscript.data.Value", "opAssign",
1347:                                "(Loscript/data/Value;)V")));
1348:                    }
1349:                }
1350:
1351:                setRetValOnStack(true);
1352:            }
1353:
1354:            /*=======================================================================*/
1355:            /**
1356:             * <PRE>
1357:             * f0 -> LogicalOrExpression()
1358:             * f1 -> ( "?" LogicalOrExpression() ":" LogicalOrExpression() )?
1359:             * </PRE>
1360:             */
1361:            public void visit(ConditionalExpression n) {
1362:                n.f0.accept(this );
1363:
1364:                if (n.f1.present()) {
1365:                    setRetValOnStack(false);
1366:
1367:                    il.append(new INVOKEVIRTUAL(ctx.methodref(
1368:                            "oscript.data.Value", "castToBoolean", "()Z")));
1369:
1370:                    scope.enterConditional();
1371:
1372:                    BranchInstruction IFEQ = new IFEQ(null);
1373:                    il.append(IFEQ);
1374:
1375:                    ((NodeSequence) (n.f1.node)).elementAt(1).accept(this );
1376:                    setRetValOnStack(false);
1377:
1378:                    BranchInstruction GOTO = new GOTO(null);
1379:                    il.append(GOTO);
1380:
1381:                    il.setNextAsTarget(IFEQ);
1382:
1383:                    ((NodeSequence) (n.f1.node)).elementAt(3).accept(this );
1384:
1385:                    il.setNextAsTarget(GOTO);
1386:
1387:                    scope.leaveConditional();
1388:                }
1389:            }
1390:
1391:            /*=======================================================================*/
1392:            /**
1393:             * <PRE>
1394:             * f0 -> LogicalAndExpression()
1395:             * f1 -> ( "||" LogicalAndExpression() )*
1396:             * </PRE>
1397:             */
1398:            public void visit(LogicalOrExpression n) {
1399:                n.f0.accept(this );
1400:
1401:                if (n.f1.present()) {
1402:                    LinkedList branchInstructionList = new LinkedList();
1403:
1404:                    scope.enterConditional();
1405:
1406:                    for (int i = 0; i < n.f1.size(); i++) {
1407:                        setRetValOnStack(false);
1408:
1409:                        il.append(InstructionConstants.DUP);
1410:                        il.append(new INVOKEVIRTUAL(ctx.methodref(
1411:                                "oscript.data.Value", "castToBoolean", "()Z")));
1412:
1413:                        BranchInstruction IFNE = new IFNE(null);
1414:                        branchInstructionList.add(IFNE);
1415:                        il.append(IFNE);
1416:
1417:                        il.append(InstructionConstants.POP);
1418:
1419:                        ((NodeSequence) (n.f1.elementAt(i))).elementAt(1)
1420:                                .accept(this );
1421:                    }
1422:
1423:                    for (Iterator itr = branchInstructionList.iterator(); itr
1424:                            .hasNext();) {
1425:                        il.setNextAsTarget((BranchInstruction) (itr.next()));
1426:                    }
1427:
1428:                    scope.leaveConditional();
1429:                }
1430:            }
1431:
1432:            /*=======================================================================*/
1433:            /**
1434:             * <PRE>
1435:             * f0 -> BitwiseOrExpression()
1436:             * f1 -> ( "&&" BitwiseOrExpression() )*
1437:             * </PRE>
1438:             */
1439:            public void visit(LogicalAndExpression n) {
1440:                n.f0.accept(this );
1441:
1442:                if (n.f1.present()) {
1443:                    LinkedList branchInstructionList = new LinkedList();
1444:
1445:                    scope.enterConditional();
1446:
1447:                    for (int i = 0; i < n.f1.size(); i++) {
1448:                        setRetValOnStack(false);
1449:
1450:                        il.append(InstructionConstants.DUP);
1451:                        il.append(new INVOKEVIRTUAL(ctx.methodref(
1452:                                "oscript.data.Value", "castToBoolean", "()Z")));
1453:
1454:                        BranchInstruction IFEQ = new IFEQ(null);
1455:                        branchInstructionList.add(IFEQ);
1456:                        il.append(IFEQ);
1457:
1458:                        il.append(InstructionConstants.POP);
1459:
1460:                        ((NodeSequence) (n.f1.elementAt(i))).elementAt(1)
1461:                                .accept(this );
1462:                    }
1463:
1464:                    for (Iterator itr = branchInstructionList.iterator(); itr
1465:                            .hasNext();) {
1466:                        il.setNextAsTarget((BranchInstruction) (itr.next()));
1467:                    }
1468:
1469:                    scope.leaveConditional();
1470:                }
1471:            }
1472:
1473:            /*=======================================================================*/
1474:            /**
1475:             * <PRE>
1476:             * f0 -> BitwiseXorExpression()
1477:             * f1 -> ( "|" BitwiseXorExpression() )*
1478:             * </PRE>
1479:             */
1480:            public void visit(BitwiseOrExpression n) {
1481:                n.f0.accept(this );
1482:
1483:                for (int i = 0; i < n.f1.size(); i++) {
1484:                    setRetValOnStack(false);
1485:
1486:                    ((NodeSequence) (n.f1.elementAt(i))).elementAt(1).accept(
1487:                            this );
1488:                    checkRetValOnStack(true);
1489:
1490:                    il.append(new INVOKEVIRTUAL(ctx.methodref(
1491:                            "oscript.data.Value", "bopBitwiseOr",
1492:                            "(Loscript/data/Value;)Loscript/data/Value;")));
1493:                }
1494:            }
1495:
1496:            /*=======================================================================*/
1497:            /**
1498:             * <PRE>
1499:             * f0 -> BitwiseAndExpression()
1500:             * f1 -> ( "^" BitwiseAndExpression() )*
1501:             * </PRE>
1502:             */
1503:            public void visit(BitwiseXorExpression n) {
1504:                n.f0.accept(this );
1505:
1506:                for (int i = 0; i < n.f1.size(); i++) {
1507:                    setRetValOnStack(false);
1508:
1509:                    ((NodeSequence) (n.f1.elementAt(i))).elementAt(1).accept(
1510:                            this );
1511:                    checkRetValOnStack(true);
1512:
1513:                    il.append(new INVOKEVIRTUAL(ctx.methodref(
1514:                            "oscript.data.Value", "bopBitwiseXor",
1515:                            "(Loscript/data/Value;)Loscript/data/Value;")));
1516:                }
1517:            }
1518:
1519:            /*=======================================================================*/
1520:            /**
1521:             * <PRE>
1522:             * f0 -> EqualityExpression()
1523:             * f1 -> ( "&" EqualityExpression() )*
1524:             * </PRE>
1525:             */
1526:            public void visit(BitwiseAndExpression n) {
1527:                n.f0.accept(this );
1528:
1529:                for (int i = 0; i < n.f1.size(); i++) {
1530:                    setRetValOnStack(false);
1531:
1532:                    ((NodeSequence) (n.f1.elementAt(i))).elementAt(1).accept(
1533:                            this );
1534:                    checkRetValOnStack(true);
1535:
1536:                    il.append(new INVOKEVIRTUAL(ctx.methodref(
1537:                            "oscript.data.Value", "bopBitwiseAnd",
1538:                            "(Loscript/data/Value;)Loscript/data/Value;")));
1539:                }
1540:            }
1541:
1542:            /*=======================================================================*/
1543:            /**
1544:             * <PRE>
1545:             * f0 -> RelationalExpression()
1546:             * f1 -> ( ( "==" | "!=" ) RelationalExpression() )*
1547:             * </PRE>
1548:             */
1549:            public void visit(EqualityExpression n) {
1550:                n.f0.accept(this );
1551:
1552:                for (int i = 0; i < n.f1.size(); i++) {
1553:                    setRetValOnStack(false);
1554:
1555:                    NodeSequence seq = (NodeSequence) (n.f1.elementAt(i));
1556:                    NodeToken op = (NodeToken) (((NodeChoice) (seq.elementAt(0))).choice);
1557:
1558:                    seq.elementAt(1).accept(this );
1559:                    checkRetValOnStack(true);
1560:
1561:                    String methodName = null;
1562:                    switch (op.kind) {
1563:                    case EQ:
1564:                        methodName = "bopEquals";
1565:                        break;
1566:                    case NE:
1567:                        methodName = "bopNotEquals";
1568:                        break;
1569:                    default:
1570:                        throw new ProgrammingErrorException("bad binary op: "
1571:                                + OscriptParser.getTokenString(op.kind));
1572:                    }
1573:
1574:                    il.append(new INVOKEVIRTUAL(ctx.methodref(
1575:                            "oscript.data.Value", methodName,
1576:                            "(Loscript/data/Value;)Loscript/data/Value;")));
1577:                }
1578:            }
1579:
1580:            /*=======================================================================*/
1581:            /**
1582:             * <PRE>
1583:             * f0 -> ShiftExpression()
1584:             * f1 -> ( ( "&lt;" | "&gt;" | "&gt;=" | "&lt;=" | "instanceof" ) ShiftExpression() )*
1585:             * </PRE>
1586:             */
1587:            public void visit(RelationalExpression n) {
1588:                n.f0.accept(this );
1589:
1590:                for (int i = 0; i < n.f1.size(); i++) {
1591:                    setRetValOnStack(false);
1592:
1593:                    NodeSequence seq = (NodeSequence) (n.f1.elementAt(i));
1594:                    NodeToken op = (NodeToken) (((NodeChoice) (seq.elementAt(0))).choice);
1595:
1596:                    seq.elementAt(1).accept(this );
1597:                    checkRetValOnStack(true);
1598:
1599:                    String methodName = null;
1600:                    switch (op.kind) {
1601:                    case LT:
1602:                        methodName = "bopLessThan";
1603:                        break;
1604:                    case GT:
1605:                        methodName = "bopGreaterThan";
1606:                        break;
1607:                    case LE:
1608:                        methodName = "bopLessThanOrEquals";
1609:                        break;
1610:                    case GE:
1611:                        methodName = "bopGreaterThanOrEquals";
1612:                        break;
1613:                    case INSTANCEOF:
1614:                        methodName = "bopInstanceOf";
1615:                        break;
1616:                    default:
1617:                        throw new ProgrammingErrorException("bad binary op: "
1618:                                + OscriptParser.getTokenString(op.kind));
1619:                    }
1620:
1621:                    il.append(new INVOKEVIRTUAL(ctx.methodref(
1622:                            "oscript.data.Value", methodName,
1623:                            "(Loscript/data/Value;)Loscript/data/Value;")));
1624:                }
1625:            }
1626:
1627:            /*=======================================================================*/
1628:            /**
1629:             * <PRE>
1630:             * f0 -> AdditiveExpression()
1631:             * f1 -> ( ( "&lt;&lt;" | "&gt;&gt;" | "&gt;&gt;&gt;" ) AdditiveExpression() )*
1632:             * </PRE>
1633:             */
1634:            public void visit(ShiftExpression n) {
1635:                n.f0.accept(this );
1636:
1637:                for (int i = 0; i < n.f1.size(); i++) {
1638:                    setRetValOnStack(false);
1639:
1640:                    NodeSequence seq = (NodeSequence) (n.f1.elementAt(i));
1641:                    NodeToken op = (NodeToken) (((NodeChoice) (seq.elementAt(0))).choice);
1642:
1643:                    seq.elementAt(1).accept(this );
1644:                    checkRetValOnStack(true);
1645:
1646:                    String methodName = null;
1647:                    switch (op.kind) {
1648:                    case LSHIFT:
1649:                        methodName = "bopLeftShift";
1650:                        break;
1651:                    case RSIGNEDSHIFT:
1652:                        methodName = "bopSignedRightShift";
1653:                        break;
1654:                    case RUNSIGNEDSHIFT:
1655:                        methodName = "bopUnsignedRightShift";
1656:                        break;
1657:                    default:
1658:                        throw new ProgrammingErrorException("bad binary op: "
1659:                                + OscriptParser.getTokenString(op.kind));
1660:                    }
1661:
1662:                    il.append(new INVOKEVIRTUAL(ctx.methodref(
1663:                            "oscript.data.Value", methodName,
1664:                            "(Loscript/data/Value;)Loscript/data/Value;")));
1665:                }
1666:            }
1667:
1668:            /*=======================================================================*/
1669:            /**
1670:             * <PRE>
1671:             * f0 -> MultiplicativeExpression()
1672:             * f1 -> ( ( "+" | "-" ) MultiplicativeExpression() )*
1673:             * </PRE>
1674:             */
1675:            public void visit(AdditiveExpression n) {
1676:                n.f0.accept(this );
1677:
1678:                for (int i = 0; i < n.f1.size(); i++) {
1679:                    setRetValOnStack(false);
1680:
1681:                    NodeSequence seq = (NodeSequence) (n.f1.elementAt(i));
1682:                    NodeToken op = (NodeToken) (((NodeChoice) (seq.elementAt(0))).choice);
1683:
1684:                    seq.elementAt(1).accept(this );
1685:                    checkRetValOnStack(true);
1686:
1687:                    String methodName = null;
1688:                    switch (op.kind) {
1689:                    case PLUS:
1690:                        methodName = "bopPlus";
1691:                        break;
1692:                    case MINUS:
1693:                        methodName = "bopMinus";
1694:                        break;
1695:                    default:
1696:                        throw new ProgrammingErrorException("bad binary op: "
1697:                                + OscriptParser.getTokenString(op.kind));
1698:                    }
1699:
1700:                    il.append(new INVOKEVIRTUAL(ctx.methodref(
1701:                            "oscript.data.Value", methodName,
1702:                            "(Loscript/data/Value;)Loscript/data/Value;")));
1703:                }
1704:            }
1705:
1706:            /*=======================================================================*/
1707:            /**
1708:             * <PRE>
1709:             * f0 -> UnaryExpression()
1710:             * f1 -> ( ( "*" | "/" | "%" ) UnaryExpression() )*
1711:             * </PRE>
1712:             */
1713:            public void visit(MultiplicativeExpression n) {
1714:                n.f0.accept(this );
1715:
1716:                for (int i = 0; i < n.f1.size(); i++) {
1717:                    setRetValOnStack(false);
1718:
1719:                    NodeSequence seq = (NodeSequence) (n.f1.elementAt(i));
1720:                    NodeToken op = (NodeToken) (((NodeChoice) (seq.elementAt(0))).choice);
1721:
1722:                    seq.elementAt(1).accept(this );
1723:                    checkRetValOnStack(true);
1724:
1725:                    String methodName = null;
1726:                    switch (op.kind) {
1727:                    case STAR:
1728:                        methodName = "bopMultiply";
1729:                        break;
1730:                    case SLASH:
1731:                        methodName = "bopDivide";
1732:                        break;
1733:                    case REM:
1734:                        methodName = "bopRemainder";
1735:                        break;
1736:                    default:
1737:                        throw new ProgrammingErrorException("bad binary op: "
1738:                                + OscriptParser.getTokenString(op.kind));
1739:                    }
1740:
1741:                    il.append(new INVOKEVIRTUAL(ctx.methodref(
1742:                            "oscript.data.Value", methodName,
1743:                            "(Loscript/data/Value;)Loscript/data/Value;")));
1744:                }
1745:            }
1746:
1747:            /*=======================================================================*/
1748:            /**
1749:             * <PRE>
1750:             * f0 -> ( ( "++" | "--" | "+" | "-" | "~" | "!" ) )?
1751:             * f1 -> PostfixExpression()
1752:             * </PRE>
1753:             */
1754:            public void visit(UnaryExpression n) {
1755:                n.f1.accept(this );
1756:
1757:                if (n.f0.present()) {
1758:                    checkRetValOnStack(true);
1759:                    NodeToken op = (NodeToken) (((NodeChoice) (n.f0.node)).choice);
1760:
1761:                    String methodName = null;
1762:                    boolean doOpAssign = false;
1763:
1764:                    switch (op.kind) {
1765:                    case INCR:
1766:                        doOpAssign = true;
1767:                        methodName = "uopIncrement";
1768:                        break;
1769:                    case DECR:
1770:                        doOpAssign = true;
1771:                        methodName = "uopDecrement";
1772:                        break;
1773:                    case PLUS:
1774:                        methodName = "uopPlus";
1775:                        break;
1776:                    case MINUS:
1777:                        methodName = "uopMinus";
1778:                        break;
1779:                    case TILDE:
1780:                        methodName = "uopBitwiseNot";
1781:                        break;
1782:                    case BANG:
1783:                        methodName = "uopLogicalNot";
1784:                        break;
1785:                    default:
1786:                        throw new ProgrammingErrorException("bad unary op: "
1787:                                + OscriptParser.getTokenString(op.kind));
1788:                    }
1789:
1790:                    if (doOpAssign) {
1791:                        il.append(InstructionConstants.DUP);
1792:                    }
1793:
1794:                    il.append(new INVOKEVIRTUAL(ctx.methodref(
1795:                            "oscript.data.Value", methodName,
1796:                            "()Loscript/data/Value;")));
1797:
1798:                    if (doOpAssign) {
1799:                        il.append(InstructionConstants.DUP_X1);
1800:                        il.append(new INVOKEVIRTUAL(ctx.methodref(
1801:                                "oscript.data.Value", "opAssign",
1802:                                "(Loscript/data/Value;)V")));
1803:                    }
1804:                }
1805:            }
1806:
1807:            /*=======================================================================*/
1808:            /**
1809:             * <PRE>
1810:             * f0 -> TypeExpression()
1811:             * f1 -> ( "++" | "--" )?
1812:             * </PRE>
1813:             */
1814:            public void visit(PostfixExpression n) {
1815:                n.f0.accept(this );
1816:
1817:                if (n.f1.present()) {
1818:                    checkRetValOnStack(true);
1819:                    NodeToken op = (NodeToken) (((NodeChoice) (n.f1.node)).choice);
1820:
1821:                    String methodName = null;
1822:
1823:                    switch (op.kind) {
1824:                    case INCR:
1825:                        methodName = "uopIncrement";
1826:                        break;
1827:                    case DECR:
1828:                        methodName = "uopDecrement";
1829:                        break;
1830:                    default:
1831:                        throw new ProgrammingErrorException("bad unary op: "
1832:                                + OscriptParser.getTokenString(op.kind));
1833:                    }
1834:
1835:                    // the result value is the original value... since you can't assign to it,
1836:                    // unhand() works fine to get the original value:
1837:                    il.append(InstructionConstants.DUP);
1838:                    il.append(new INVOKEVIRTUAL(ctx.methodref(
1839:                            "oscript.data.Value", "unhand",
1840:                            "()Loscript/data/Value;")));
1841:                    il.append(InstructionConstants.SWAP);
1842:
1843:                    // now invoke the operation and assign it to the reference:
1844:                    il.append(InstructionConstants.DUP);
1845:                    il.append(new INVOKEVIRTUAL(ctx.methodref(
1846:                            "oscript.data.Value", methodName,
1847:                            "()Loscript/data/Value;")));
1848:                    il.append(new INVOKEVIRTUAL(ctx.methodref(
1849:                            "oscript.data.Value", "opAssign",
1850:                            "(Loscript/data/Value;)V")));
1851:                }
1852:            }
1853:
1854:            /*=======================================================================*/
1855:            /**
1856:             * <PRE>
1857:             * f0 -> AllocationExpression()
1858:             *       | CastExpression()
1859:             *       | PrimaryExpression()
1860:             * </PRE>
1861:             */
1862:            public void visit(TypeExpression n) {
1863:                n.f0.accept(this );
1864:            }
1865:
1866:            /*=======================================================================*/
1867:            /**
1868:             * <PRE>
1869:             * f0 -> "new"
1870:             * f1 -> PrimaryExpressionWithTrailingFxnCallExpList()
1871:             * f2 -> FunctionCallExpressionList()
1872:             * </PRE>
1873:             */
1874:            public void visit(AllocationExpression n) {
1875:                handle(n.f0);
1876:
1877:                n.f1.accept(this );
1878:                setRetValOnStack(false);
1879:
1880:                il.append(InstructionConstants.ALOAD_1); // sf
1881:
1882:                n.f2.accept(this );
1883:                checkRetValOnStack(true);
1884:
1885:                il
1886:                        .append(new INVOKEVIRTUAL(
1887:                                ctx
1888:                                        .methodref("oscript.data.Value",
1889:                                                "callAsConstructor",
1890:                                                "(Loscript/util/StackFrame;Loscript/util/MemberTable;)Loscript/data/Value;")));
1891:            }
1892:
1893:            /*=======================================================================*/
1894:            /**
1895:             * <PRE>
1896:             * f0 -> "("
1897:             * f1 -> PrimaryExpressionNotFunction()
1898:             * f2 -> ")"
1899:             * f3 -> PrimaryExpression()
1900:             * </PRE>
1901:             */
1902:            public void visit(CastExpression n) {
1903:                handle(n.f0);
1904:
1905:                n.f1.accept(this );
1906:                setRetValOnStack(false);
1907:
1908:                n.f3.accept(this );
1909:                checkRetValOnStack(true);
1910:
1911:                il.append(new INVOKEVIRTUAL(ctx
1912:                        .methodref("oscript.data.Value", "bopCast",
1913:                                "(Loscript/data/Value;)Loscript/data/Value;")));
1914:            }
1915:
1916:            /*=======================================================================*/
1917:            /**
1918:             * <PRE>
1919:             * f0 -> PrimaryPrefix()
1920:             * f1 -> ( PrimaryPostfix() )*
1921:             * </PRE>
1922:             */
1923:            public void visit(PrimaryExpression n) {
1924:                n.f0.accept(this );
1925:
1926:                for (int i = 0; i < n.f1.size(); i++) {
1927:                    checkRetValOnStack(true);
1928:                    n.f1.elementAt(i).accept(this );
1929:                }
1930:
1931:                checkRetValOnStack(true);
1932:            }
1933:
1934:            /*=======================================================================*/
1935:            /**
1936:             * <PRE>
1937:             * f0 -> PrimaryPrefix()
1938:             * f1 -> ( PrimaryPostfix() )*
1939:             * </PRE>
1940:             */
1941:            public void visit(PrimaryExpressionNotFunction n) {
1942:                n.f0.accept(this );
1943:
1944:                for (int i = 0; i < n.f1.size(); i++) {
1945:                    checkRetValOnStack(true);
1946:                    n.f1.elementAt(i).accept(this );
1947:                }
1948:
1949:                checkRetValOnStack(true);
1950:            }
1951:
1952:            /*=======================================================================*/
1953:            /**
1954:             * <PRE>
1955:             * f0 -> PrimaryPrefix()
1956:             * f1 -> ( PrimaryPostfixWithTrailingFxnCallExpList() )*
1957:             * </PRE>
1958:             */
1959:            public void visit(PrimaryExpressionWithTrailingFxnCallExpList n) {
1960:                n.f0.accept(this );
1961:
1962:                for (int i = 0; i < n.f1.size(); i++) {
1963:                    checkRetValOnStack(true);
1964:                    n.f1.elementAt(i).accept(this );
1965:                }
1966:
1967:                checkRetValOnStack(true);
1968:            }
1969:
1970:            /*=======================================================================*/
1971:            /**
1972:             * <PRE>
1973:             * f0 -> PrimaryPrefixNotFunction()
1974:             *       | FunctionPrimaryPrefix()
1975:             *       | ShorthandFunctionPrimaryPrefix()
1976:             * </PRE>
1977:             */
1978:            public void visit(PrimaryPrefix n) {
1979:                n.f0.accept(this );
1980:            }
1981:
1982:            /*=======================================================================*/
1983:            /**
1984:             * <PRE>
1985:             * f0 -> ThisPrimaryPrefix()
1986:             *       | SuperPrimaryPrefix()
1987:             *       | CalleePrimaryPrefix()
1988:             *       | IdentifierPrimaryPrefix()
1989:             *       | ParenPrimaryPrefix()
1990:             *       | ArrayDeclarationPrimaryPrefix()
1991:             *       | Literal()
1992:             * </PRE>
1993:             */
1994:            public void visit(PrimaryPrefixNotFunction n) {
1995:                n.f0.accept(this );
1996:            }
1997:
1998:            /*=======================================================================*/
1999:            /**
2000:             * <PRE>
2001:             * f0 -> "this"
2002:             * </PRE>
2003:             */
2004:            public void visit(ThisPrimaryPrefix n) {
2005:                handle(n.f0);
2006:
2007:                if (this Slot == -1) {
2008:                    LocalVariableGen lg = mg.addLocalVariable(ctx
2009:                            .makeUniqueIdentifierName("this"), ctx.VALUE_TYPE,
2010:                            null, null);
2011:                    this Slot = lg.getIndex();
2012:
2013:                    // insert at head in reverse order
2014:                    il.insert(new ASTORE(this Slot));
2015:                    il.insert(new INVOKEVIRTUAL(ctx.methodref(
2016:                            "oscript.data.Scope", "getThis",
2017:                            "()Loscript/data/Value;")));
2018:                    il.insert(InstructionConstants.ALOAD_2); // scope
2019:                }
2020:
2021:                il.append(new ALOAD(this Slot));
2022:                setRetValOnStack(true);
2023:            }
2024:
2025:            private int this Slot = -1;
2026:
2027:            /*=======================================================================*/
2028:            /**
2029:             * <PRE>
2030:             * f0 -> "super"
2031:             * </PRE>
2032:             */
2033:            public void visit(SuperPrimaryPrefix n) {
2034:                handle(n.f0);
2035:
2036:                if (super Slot == -1) {
2037:                    LocalVariableGen lg = mg.addLocalVariable(ctx
2038:                            .makeUniqueIdentifierName("super"), ctx.VALUE_TYPE,
2039:                            null, null);
2040:                    super Slot = lg.getIndex();
2041:
2042:                    // insert at head in reverse order
2043:                    il.insert(new ASTORE(super Slot));
2044:                    il.insert(new INVOKEVIRTUAL(ctx.methodref(
2045:                            "oscript.data.Scope", "getSuper",
2046:                            "()Loscript/data/Value;")));
2047:                    il.insert(InstructionConstants.ALOAD_2); // scope
2048:                }
2049:
2050:                il.append(new ALOAD(super Slot));
2051:                setRetValOnStack(true);
2052:            }
2053:
2054:            private int super Slot = -1;
2055:
2056:            /*=======================================================================*/
2057:            /**
2058:             * <PRE>
2059:             * f0 -> "callee"
2060:             * </PRE>
2061:             */
2062:            public void visit(CalleePrimaryPrefix n) {
2063:                handle(n.f0);
2064:
2065:                if (calleeSlot == -1) {
2066:                    LocalVariableGen lg = mg.addLocalVariable(ctx
2067:                            .makeUniqueIdentifierName("callee"),
2068:                            ctx.VALUE_TYPE, null, null);
2069:                    calleeSlot = lg.getIndex();
2070:
2071:                    // insert at head in reverse order
2072:                    il.insert(new ASTORE(calleeSlot));
2073:                    il.insert(new INVOKEVIRTUAL(ctx.methodref(
2074:                            "oscript.data.Scope", "getCallee",
2075:                            "()Loscript/data/Value;")));
2076:                    il.insert(InstructionConstants.ALOAD_2); // scope
2077:                }
2078:
2079:                il.append(new ALOAD(calleeSlot));
2080:                setRetValOnStack(true);
2081:            }
2082:
2083:            private int calleeSlot = -1;
2084:
2085:            /*=======================================================================*/
2086:            /**
2087:             * <PRE>
2088:             * f0 -> &lt;IDENTIFIER&gt;
2089:             * </PRE>
2090:             */
2091:            public void visit(IdentifierPrimaryPrefix n) {
2092:                scope.lookupInScope(this , n.f0);
2093:                setRetValOnStack(true);
2094:            }
2095:
2096:            /*=======================================================================*/
2097:            /**
2098:             * <PRE>
2099:             * f0 -> "("
2100:             * f1 -> Expression()
2101:             * f2 -> ")"
2102:             * </PRE>
2103:             */
2104:            public void visit(ParenPrimaryPrefix n) {
2105:                n.f1.accept(this );
2106:            }
2107:
2108:            /*=======================================================================*/
2109:            /**
2110:             * <PRE>
2111:             * f0 -> "function"
2112:             * f1 -> "("
2113:             * f2 -> ( Arglist() )?
2114:             * f3 -> ")"
2115:             * f4 -> ( "extends" PrimaryExpressionWithTrailingFxnCallExpList() FunctionCallExpressionList() )?
2116:             * f5 -> "{"
2117:             * f6 -> Program()
2118:             * f7 -> "}"
2119:             * </PRE>
2120:             */
2121:            public void visit(FunctionPrimaryPrefix n) {
2122:                handle(n.f0);
2123:                // new Function( scope, superFxn, n.fd )
2124:                il.append(new NEW(ctx.cp.addClass("oscript.data.Function")));
2125:                il.append(InstructionConstants.DUP);
2126:                il.append(new ALOAD(scope.getSlot())); // scope
2127:
2128:                if (n.f4.present()) {
2129:                    // superFxn
2130:                    ((NodeSequence) (n.f4.node)).elementAt(1).accept(this );
2131:                    setRetValOnStack(false);
2132:                    il.append(new INVOKEVIRTUAL(ctx.methodref(
2133:                            "oscript.data.Value", "unhand",
2134:                            "()Loscript/data/Value;")));
2135:                } else {
2136:                    il.append(InstructionConstants.ACONST_NULL); // superFxn
2137:                }
2138:
2139:                // fd
2140:                {
2141:                    Value oname = Symbol.getSymbol(n.id);
2142:                    String name = oname.castToString();
2143:
2144:                    int[] argIds;
2145:                    boolean varargs;
2146:
2147:                    // get arglist:
2148:                    if (n.f2.present()) {
2149:                        argIds = getArglist((Arglist) (n.f2.node));
2150:                        varargs = Arglist_varargs;
2151:                    } else {
2152:                        argIds = ctx.EMPTY_ARG_IDS;
2153:                        varargs = false;
2154:                    }
2155:
2156:                    // get extends evaluator:
2157:                    int extendsIdx = -1;
2158:                    if (n.f4.present()) {
2159:                        FunctionCallExpressionList fcel = (FunctionCallExpressionList) (((NodeSequence) (n.f4.node))
2160:                                .elementAt(2));
2161:
2162:                        extendsIdx = (new CompilerVisitor(ctx, name
2163:                                + "$extends", fcel)).innerNodeIdx;
2164:                    }
2165:
2166:                    int fxnIdx = (new CompilerVisitor(ctx, name, n.f6, argIds)).innerNodeIdx;
2167:                    int staticIdx = -1;
2168:                    if (n.f6.staticNodes != null)
2169:                        staticIdx = (new CompilerVisitor(ctx, name + "$static",
2170:                                n.f6.staticNodes)).innerNodeIdx;
2171:
2172:                    // just in case, to get the specials...
2173:                    handle(n.f0);
2174:
2175:                    // the syntaxtree won't change, so we only need to parse the comment once:
2176:                    synchronized (n) {
2177:                        if (!n.commentParsed) {
2178:                            n.commentParsed = true;
2179:                            if (NodeToken_lastSpecials != null)
2180:                                n.comment = Function.extractJavadocComment(
2181:                                        NodeToken_lastSpecials, oname, argIds);
2182:                        }
2183:                    }
2184:
2185:                    ctx.pushFunctionData(il, Symbol.getSymbol(name).getId(),
2186:                            argIds, varargs, extendsIdx, fxnIdx, staticIdx,
2187:                            n.hasVarInScope, n.hasFxnInScope, n.comment);
2188:                }
2189:
2190:                il.append(new INVOKESPECIAL(ctx.methodref(
2191:                        "oscript.data.Function", "<init>",
2192:                        "(Loscript/data/Scope;" + "Loscript/data/Value;"
2193:                                + "Loscript/data/Function$FunctionData;)V")));
2194:
2195:                setRetValOnStack(true);
2196:            }
2197:
2198:            /*=======================================================================*/
2199:            /**
2200:             * <PRE>
2201:             * f0 -> "'{"
2202:             * f1 -> Program(true)
2203:             * f2 -> "}"
2204:             * </PRE>
2205:             */
2206:            public void visit(ShorthandFunctionPrimaryPrefix n) {
2207:                ShorthandFunctionPrimaryPrefixTranslator.translate(n).accept(
2208:                        this );
2209:            }
2210:
2211:            /*=======================================================================*/
2212:            /**
2213:             * <PRE>
2214:             * f0 -> "["
2215:             * f1 ->   (FunctionCallExpressionListBody())?
2216:             * f2 -> "]"
2217:             * </PRE>
2218:             */
2219:            public void visit(ArrayDeclarationPrimaryPrefix n) {
2220:                if (n.f1.present())
2221:                    n.f1.node.accept(this );
2222:                else
2223:                    allocateMemberTable(0);
2224:
2225:                setRetValOnStack(true);
2226:            }
2227:
2228:            /*=======================================================================*/
2229:            /**
2230:             * <PRE>
2231:             * f0 -> FunctionCallPrimaryPostfix()
2232:             *       | ArraySubscriptPrimaryPostfix()
2233:             *       | ThisScopeQualifierPrimaryPostfix()
2234:             *       | PropertyIdentifierPrimaryPostfix()
2235:             * </PRE>
2236:             */
2237:            public void visit(PrimaryPostfix n) {
2238:                n.f0.accept(this );
2239:            }
2240:
2241:            /*=======================================================================*/
2242:            /**
2243:             * <PRE>
2244:             * f0 -> ArraySubscriptPrimaryPostfix()
2245:             *       | ThisScopeQualifierPrimaryPostfix()
2246:             *       | PropertyIdentifierPrimaryPostfix()
2247:             * </PRE>
2248:             */
2249:            public void visit(PrimaryPostfixWithTrailingFxnCallExpList n) {
2250:                n.f0.accept(this );
2251:            }
2252:
2253:            /*=======================================================================*/
2254:            /**
2255:             * <PRE>
2256:             * f0 -> FunctionCallExpressionList()
2257:             * </PRE>
2258:             */
2259:            public void visit(FunctionCallPrimaryPostfix n) {
2260:                setRetValOnStack(false);
2261:
2262:                il.append(InstructionConstants.ALOAD_1); // sf
2263:
2264:                allocateMemberTable_allocateFromStack = true;
2265:                n.f0.accept(this );
2266:                boolean sfIsNull = FunctionCallExpressionList_sfIsNull;
2267:                checkRetValOnStack(true);
2268:
2269:                // save mt:   ..., val, sf, mt => ..., [mt,] val, sf, mt
2270:                if (!sfIsNull)
2271:                    il.append(InstructionConstants.DUP_X2);
2272:
2273:                // call: ..., [mt,] val, sf, mt => ..., mt, rval
2274:                il
2275:                        .append(new INVOKEVIRTUAL(
2276:                                ctx
2277:                                        .methodref("oscript.data.Value",
2278:                                                "callAsFunction",
2279:                                                "(Loscript/util/StackFrame;Loscript/util/MemberTable;)Loscript/data/Value;")));
2280:
2281:                if (!sfIsNull) {
2282:                    // swap: ..., mt, rval => ..., rval, mt
2283:                    il.append(InstructionConstants.SWAP);
2284:
2285:                    // mt.free(): ..., rval, mt => ..., rval
2286:                    il.append(new INVOKEINTERFACE(ctx.ifmethodref(
2287:                            "oscript.util.MemberTable", "free", "()V"), 1));
2288:                }
2289:            }
2290:
2291:            /*=======================================================================*/
2292:            /**
2293:             * <PRE>
2294:             * <PRE>
2295:             * f0 -> "["
2296:             * f1 -> Expression()
2297:             * f2 -> ( ".." Expression() )?
2298:             * f3 -> "]"
2299:             * </PRE>
2300:             */
2301:            public void visit(ArraySubscriptPrimaryPostfix n) {
2302:                setRetValOnStack(false);
2303:
2304:                n.f1.accept(this );
2305:
2306:                if (n.f2.present()) {
2307:                    setRetValOnStack(false);
2308:                    ((NodeSequence) (n.f2.node)).elementAt(1).accept(this );
2309:
2310:                    checkRetValOnStack(true);
2311:                    il
2312:                            .append(new INVOKEVIRTUAL(
2313:                                    ctx
2314:                                            .methodref("oscript.data.Value",
2315:                                                    "elementsAt",
2316:                                                    "(Loscript/data/Value;Loscript/data/Value;)Loscript/data/Value;")));
2317:                } else {
2318:                    checkRetValOnStack(true);
2319:                    il.append(new INVOKEVIRTUAL(ctx.methodref(
2320:                            "oscript.data.Value", "elementAt",
2321:                            "(Loscript/data/Value;)Loscript/data/Value;")));
2322:                }
2323:            }
2324:
2325:            /*=======================================================================*/
2326:            /**
2327:             * <PRE>
2328:             * f0 -> "."
2329:             * f1 -> &lt;IDENTIFIER&gt;
2330:             * </PRE>
2331:             */
2332:            public void visit(PropertyIdentifierPrimaryPostfix n) {
2333:                setRetValOnStack(false);
2334:
2335:                n.f1.accept(this );
2336:                checkRetValOnStack(true);
2337:
2338:                il.append(new INVOKEVIRTUAL(ctx.methodref("oscript.data.Value",
2339:                        "getMember", "(I)Loscript/data/Value;")));
2340:            }
2341:
2342:            /*=======================================================================*/
2343:            /**
2344:             * <PRE>
2345:             * f0 -> "."
2346:             * f1 -> "this"
2347:             * </PRE>
2348:             */
2349:            public void visit(ThisScopeQualifierPrimaryPostfix n) {
2350:                checkRetValOnStack(true);
2351:
2352:                il.append(InstructionConstants.ALOAD_2); // scope
2353:                il.append(InstructionConstants.SWAP);
2354:                il.append(new INVOKEVIRTUAL(ctx
2355:                        .methodref("oscript.data.Scope", "getThis",
2356:                                "(Loscript/data/Value;)Loscript/data/Value;")));
2357:            }
2358:
2359:            /*=======================================================================*/
2360:            /**
2361:             * <PRE>
2362:             * f0 -> &lt;INTEGER_LITERAL&gt;
2363:             *       | &lt;FLOATING_POINT_LITERAL&gt;
2364:             *       | &lt;STRING_LITERAL&gt;
2365:             *       | &lt;REGEXP_LITERAL&gt;
2366:             *       | "true"
2367:             *       | "false"
2368:             *       | "null"
2369:             *       | "undefined"
2370:             * </PRE>
2371:             */
2372:            public void visit(Literal n) {
2373:                n.f0.accept(this );
2374:            }
2375:
2376:            /*=======================================================================*/
2377:            /**
2378:             * <PRE>
2379:             * f0 -> ( "static" | "const" | "private" | "protected" | "public" )*
2380:             * </PRE>
2381:             */
2382:            public void visit(Permissions n) {
2383:                throw new ProgrammingErrorException("shouldn't get here!");
2384:            }
2385:
2386:            /**
2387:             * Get the permissions mask...
2388:             * 
2389:             * @param n            the permissions syntaxtree node
2390:             * @param attr         the default permissions value
2391:             * @return the permissions mask
2392:             */
2393:            private int getPermissions(Permissions n, int attr) {
2394:                for (int i = 0; i < n.f0.size(); i++) {
2395:                    n.f0.elementAt(i).accept(this );
2396:
2397:                    switch (NodeToken_lastToken.kind) {
2398:                    case PRIVATE:
2399:                        attr = (attr & 0xf0) | Reference.ATTR_PRIVATE;
2400:                        break;
2401:                    case PROTECTED:
2402:                        attr = (attr & 0xf0) | Reference.ATTR_PROTECTED;
2403:                        break;
2404:                    case PUBLIC:
2405:                        attr = (attr & 0xf0) | Reference.ATTR_PUBLIC;
2406:                        break;
2407:                    case STATIC:
2408:                        attr |= Reference.ATTR_STATIC;
2409:                        break;
2410:                    case CONST:
2411:                        attr |= Reference.ATTR_CONST;
2412:                        break;
2413:                    default:
2414:                        throw new ProgrammingErrorException(
2415:                                "bad kind: "
2416:                                        + OscriptParser
2417:                                                .getTokenString(NodeToken_lastToken.kind));
2418:                    }
2419:                }
2420:
2421:                return attr;
2422:            }
2423:
2424:            public String toString() {
2425:                return mg.getName();
2426:            }
2427:        }
2428:
2429:        /*
2430:         *   Local Variables:
2431:         *   tab-width: 2
2432:         *   indent-tabs-mode: nil
2433:         *   mode: java
2434:         *   c-indentation-style: java
2435:         *   c-basic-offset: 2
2436:         *   eval: (c-set-offset 'substatement-open '0)
2437:         *   eval: (c-set-offset 'case-label '+)
2438:         *   eval: (c-set-offset 'inclass '+)
2439:         *   eval: (c-set-offset 'inline-open '0)
2440:         *   End:
2441:         */
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.