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


0001:        /*
0002:         * Compiler.java
0003:         *
0004:         * Copyright (c) 1997-2007 Sun Microsystems, Inc. All Rights Reserved.
0005:         *
0006:         * See the file "LICENSE.txt" for information on usage and redistribution
0007:         * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
0008:         */
0009:        package pnuts.compiler;
0010:
0011:        import java.io.ByteArrayOutputStream;
0012:        import java.io.File;
0013:        import java.io.IOException;
0014:        import java.io.Reader;
0015:        import java.lang.reflect.Constructor;
0016:        import java.lang.reflect.Method;
0017:        import java.lang.reflect.Modifier;
0018:        import java.math.BigDecimal;
0019:        import java.math.BigInteger;
0020:        import java.net.URL;
0021:        import java.security.AccessController;
0022:        import java.security.PrivilegedAction;
0023:        import java.util.ArrayList;
0024:        import java.util.Collection;
0025:        import java.util.Enumeration;
0026:        import java.util.HashMap;
0027:        import java.util.HashSet;
0028:        import java.util.Iterator;
0029:        import java.util.List;
0030:        import java.util.Map;
0031:        import java.util.Set;
0032:        import org.pnuts.lang.ConstraintsTransformer;
0033:        import org.pnuts.lang.GeneratorHelper;
0034:        import org.pnuts.lang.NodeUtil;
0035:        import org.pnuts.lang.Signature;
0036:        import org.pnuts.lang.DefaultParseEnv;
0037:
0038:        import pnuts.lang.PnutsParser;
0039:        import pnuts.lang.Context;
0040:        import pnuts.lang.Function;
0041:        import pnuts.lang.Generator;
0042:        import pnuts.lang.ParseException;
0043:        import pnuts.lang.Pnuts;
0044:        import pnuts.lang.PnutsException;
0045:        import pnuts.lang.PnutsFunction;
0046:        import pnuts.lang.PnutsInterpreter;
0047:        import pnuts.lang.Runtime;
0048:        import pnuts.lang.SimpleNode;
0049:        import pnuts.lang.Visitor;
0050:        import pnuts.lang.PnutsParserTreeConstants;
0051:        import pnuts.lang.ParseEnvironment;
0052:
0053:        /**
0054:         * Pnuts to JVM bytecode compiler
0055:         */
0056:        public class Compiler extends Runtime implements  Visitor {
0057:
0058:            private final static boolean DEBUG = false;
0059:
0060:            private final static boolean PROFILE = false;
0061:
0062:            final static String SUPER = "super".intern();
0063:
0064:            final static String THIS = "this".intern();
0065:
0066:            final static String YIELD = "yield".intern();
0067:
0068:            final static String STAR = "*".intern();
0069:
0070:            final static String METHOD_FACTORY_FUNCTION = "$methodFactoryFunction";
0071:
0072:            private static PnutsInterpreter interpreter = new PnutsInterpreter(); // fallback
0073:
0074:            private static Preprocessor preproc = new Preprocessor();
0075:
0076:            private static boolean optimize = getBoolean("pnuts.compiler.optimize");
0077:
0078:            static boolean hasBootClassLoader = false;
0079:            static {
0080:                try {
0081:                    Class cls = ClassLoader.class;
0082:                    cls.getDeclaredConstructor(new Class[] { cls });
0083:                    hasBootClassLoader = true;
0084:                } catch (Exception e) {
0085:                    /* skip */
0086:                }
0087:            }
0088:
0089:            static boolean hasJava2Security = false;
0090:            static {
0091:                try {
0092:                    Class.class
0093:                            .getMethod("getProtectionDomain", new Class[] {});
0094:                    hasJava2Security = true;
0095:                } catch (Exception e) {
0096:                    /* skip */
0097:                }
0098:            }
0099:
0100:            static boolean hasValueOfPrimitive = false;
0101:            static {
0102:                try {
0103:                    Integer.class.getMethod("valueOf",
0104:                            new Class[] { int.class });
0105:                    hasValueOfPrimitive = true;
0106:                } catch (Exception e) {
0107:                    /* skip */
0108:                }
0109:            }
0110:
0111:            static CodeLoaderFactory codeLoaderFactory;
0112:
0113:            static CodeLoaderFactory privilegedCodeLoaderFactory;
0114:            static {
0115:                codeLoaderFactory = new CodeLoaderFactory();
0116:                if (hasJava2Security) {
0117:                    privilegedCodeLoaderFactory = new PrivilegedCodeLoaderFactory();
0118:                }
0119:            }
0120:
0121:            private static boolean proxyConf = getBoolean("pnuts.compiler.useDynamicProxy");
0122:
0123:            private long s; // for profiling
0124:
0125:            boolean _includeLineNo = !optimize;
0126:
0127:            boolean _includeColumnNo = false;
0128:
0129:            boolean _constantFolding = false;
0130:
0131:            boolean traceMode = getBoolean("pnuts.compiler.traceMode");
0132:
0133:            boolean includeMainMethod = false;
0134:
0135:            private long classCount = 0L;
0136:
0137:            boolean automatic;
0138:
0139:            String className;
0140:
0141:            String runtimeClassName;
0142:
0143:            boolean useDynamicProxy = proxyConf;
0144:
0145:            String sourceFile;
0146:
0147:            public Compiler() {
0148:                this (null);
0149:            }
0150:
0151:            public Compiler(String className) {
0152:                this (className, true);
0153:            }
0154:
0155:            public Compiler(String className, boolean automatic) {
0156:                this (className, automatic, proxyConf);
0157:            }
0158:
0159:            public Compiler(String className, boolean automatic,
0160:                    boolean useDynamicProxy) {
0161:                if (className == null) {
0162:                    this .className = "_pnuts_";
0163:                } else {
0164:                    this .className = className;
0165:                }
0166:                this .automatic = automatic;
0167:                useDynamicProxy(useDynamicProxy);
0168:            }
0169:
0170:            public void includeLineNo(boolean flag) {
0171:                this ._includeLineNo = flag;
0172:            }
0173:
0174:            public void includeColumnNo(boolean flag) {
0175:                this ._includeColumnNo = flag;
0176:            }
0177:
0178:            public void setConstantFolding(boolean flag) {
0179:                this ._constantFolding = flag;
0180:            }
0181:
0182:            public void includeMainMethod(boolean flag) {
0183:                this .includeMainMethod = flag;
0184:            }
0185:
0186:            public void setTraceMode(boolean mode) {
0187:                this .traceMode = mode;
0188:            }
0189:
0190:            public void useDynamicProxy(boolean flag) {
0191:                this .useDynamicProxy = flag;
0192:                if (flag) {
0193:                    runtimeClassName = "pnuts.compiler.DynamicRuntime";
0194:                } else {
0195:                    runtimeClassName = "pnuts.lang.Runtime";
0196:                }
0197:            }
0198:
0199:            void addLineInfo(CompileContext cc, int ctx, SimpleNode node) {
0200:                if (_includeLineNo || traceMode) {
0201:                    int line = node.beginLine;
0202:                    int column = node.beginColumn;
0203:                    ClassFile cf = cc.cf;
0204:                    if ((_includeColumnNo && (cc.line != line || cc.column != column))
0205:                            || traceMode) {
0206:                        cf.loadLocal(ctx);
0207:                        cf.pushInteger(line);
0208:                        cf.add(Opcode.INVOKESTATIC, "pnuts.lang.Runtime",
0209:                                "setLine", "(Lpnuts/lang/Context;I)", "V");
0210:                        cc.line = line;
0211:                        cc.column = column;
0212:                        cf.addLineNumber(line);
0213:                    } else if (cc.line != line) {
0214:                        cf.loadLocal(ctx);
0215:                        cf.pushInteger(line);
0216:                        cf.add(Opcode.INVOKESTATIC, "pnuts.lang.Runtime",
0217:                                "setLine", "(Lpnuts/lang/Context;I)", "V");
0218:                        cc.line = line;
0219:                        cf.addLineNumber(line);
0220:                    }
0221:                }
0222:            }
0223:
0224:            protected Object execute(CompileContext cc, Context context,
0225:                    boolean catchJump) {
0226:                if (DEBUG) {
0227:                    cc.debug();
0228:                }
0229:                try {
0230:                    Runtime rt;
0231:                    if (PROFILE) {
0232:                        s = System.currentTimeMillis();
0233:                        CodeLoader loader = createCodeLoader(context
0234:                                .getClassLoader(), true);
0235:                        Class cls = cc.loadClasses(loader);
0236:                        rt = (Runtime) cls.newInstance();
0237:                        System.out.println("load: "
0238:                                + (System.currentTimeMillis() - s));
0239:                    } else {
0240:                        CodeLoader loader = createCodeLoader(context
0241:                                .getClassLoader(), true);
0242:                        Class cls = cc.loadClasses(loader);
0243:                        rt = (Runtime) cls.newInstance();
0244:                    }
0245:                    return rt.run(context);
0246:                } catch (IOException io) {
0247:                    throw new PnutsException(io, context);
0248:                } catch (InstantiationException ie) {
0249:                    throw new PnutsException(ie, context);
0250:                } catch (IllegalAccessException iae) {
0251:                    throw new PnutsException(iae, context);
0252:                }
0253:            }
0254:
0255:            void preprocess(SimpleNode node) {
0256:                node.accept(preproc, new TranslateContext());
0257:            }
0258:
0259:            public Object startSet(SimpleNode node, Context context) {
0260:                if (!_includeLineNo && context.isVerbose()) {
0261:                    _includeLineNo = true;
0262:                }
0263:
0264:                preprocess(node);
0265:
0266:                return start(node, context);
0267:            }
0268:
0269:            public Object start(SimpleNode node, Context context) {
0270:                try {
0271:                    preprocess(node);
0272:                    return _start(node, context, true);
0273:                } catch (LinkageError e) {
0274:                    if (context.isVerbose()) {
0275:                        e.printStackTrace();
0276:                    } else {
0277:                        System.out.println(e);
0278:                    }
0279:                    if (automatic) {
0280:                        return node.accept(interpreter, context);
0281:                    } else {
0282:                        throw e;
0283:                    }
0284:                }
0285:            }
0286:
0287:            Object _start(SimpleNode node, Context context, boolean catchJump) {
0288:
0289:                if (PROFILE) {
0290:                    s = System.currentTimeMillis();
0291:                }
0292:
0293:                CompileContext cc;
0294:                Object src = null;
0295:                if (automatic) {
0296:                    cc = new CompileContext(context);
0297:                    src = getScriptSource(context);
0298:
0299:                } else {
0300:                    cc = (CompileContext) context;
0301:
0302:                    src = cc.scriptSource;
0303:                }
0304:                if (src instanceof  URL) {
0305:                    String s = ((URL) src).toString();
0306:                    int idx = s.lastIndexOf('/');
0307:                    if (idx > 0) {
0308:                        this .sourceFile = s.substring(idx + 1);
0309:                    }
0310:                }
0311:                cc.constClassName = className;
0312:                cc.cf = new ClassFile(className, runtimeClassName, sourceFile,
0313:                        Constants.ACC_PUBLIC);
0314:                ClassFile cf = cc.cf;
0315:                cf.addInterface("pnuts.compiler.Compiled");
0316:
0317:                /*
0318:                 * constructor
0319:                 */
0320:                cf.openMethod("<init>", "()V", Constants.ACC_PUBLIC);
0321:                cf.add(Opcode.ALOAD_0);
0322:                cf.add(Opcode.INVOKESPECIAL, runtimeClassName, "<init>", "()",
0323:                        "V");
0324:                cf.add(Opcode.RETURN);
0325:                cf.closeMethod();
0326:
0327:                /*
0328:                 * public static void main(String[])
0329:                 */
0330:                if (includeMainMethod) {
0331:                    cf
0332:                            .openMethod(
0333:                                    "main",
0334:                                    "([Ljava/lang/String;)V",
0335:                                    (short) (Constants.ACC_PUBLIC | Constants.ACC_STATIC));
0336:                    cf.add(Opcode.NEW, className);
0337:                    cf.add(Opcode.DUP);
0338:                    cf
0339:                            .add(Opcode.INVOKESPECIAL, className, "<init>",
0340:                                    "()", "V");
0341:
0342:                    Label catchStart = cf.getLabel(true);
0343:                    cf.add(Opcode.NEW, "pnuts.lang.Context");
0344:                    cf.add(Opcode.DUP);
0345:                    cf.add(Opcode.INVOKESPECIAL, "pnuts.lang.Context",
0346:                            "<init>", "()", "V");
0347:                    cf.add(Opcode.INVOKEINTERFACE, "pnuts.lang.Executable",
0348:                            "run", "(Lpnuts/lang/Context;)",
0349:                            "Ljava/lang/Object;");
0350:                    cf.add(Opcode.POP);
0351:                    cf.add(Opcode.RETURN);
0352:
0353:                    Label catchEnd = cf.getLabel(true);
0354:                    Label catchTarget = cf.getLabel(true);
0355:                    cf.reserveStack(1);
0356:                    cf.add(Opcode.INVOKEVIRTUAL, "pnuts.lang.Jump", "getValue",
0357:                            "()", "Ljava/lang/Object;");
0358:                    cf.add(Opcode.POP);
0359:                    cf.add(Opcode.RETURN);
0360:                    cf.addExceptionHandler(catchStart, catchEnd, catchTarget,
0361:                            "pnuts.lang.Jump");
0362:
0363:                    cf.closeMethod();
0364:                }
0365:
0366:                /*
0367:                 * protected Object exec(Context context);
0368:                 */
0369:                cf.openMethod("exec",
0370:                        "(Lpnuts/lang/Context;)Ljava/lang/Object;",
0371:                        Constants.ACC_PROTECTED);
0372:
0373:                int ctx = 1;
0374:                cc.setContextIndex(ctx);
0375:
0376:                int n = node.jjtGetNumChildren();
0377:                if (n > 0) {
0378:                    int m = n - 1;
0379:                    for (int i = 0; i < m; i++) {
0380:                        accept(node, i, cc);
0381:                        cf.add(Opcode.POP);
0382:                    }
0383:                    accept(node, m, cc);
0384:                } else {
0385:                    cf.add(Opcode.ACONST_NULL);
0386:                }
0387:                cf.add(Opcode.ARETURN);
0388:                cf.closeMethod();
0389:
0390:                /*
0391:                 * static {} clause
0392:                 */
0393:                staticBlock(cf, null, cc);
0394:
0395:                if (PROFILE) {
0396:                    System.out.println(className + " classFile: "
0397:                            + (System.currentTimeMillis() - s));
0398:                }
0399:
0400:                if (automatic) {
0401:                    return execute(cc, context, catchJump);
0402:                } else {
0403:                    return null;
0404:                }
0405:            }
0406:
0407:            void staticBlock(ClassFile cf, SimpleNode closureNode,
0408:                    CompileContext cc) {
0409:                String className = cf.getClassName();
0410:
0411:                cf.openMethod("<clinit>", "()V", Constants.ACC_STATIC);
0412:                cf.addField("NO_PARAM", "[Ljava/lang/Object;",
0413:                        Constants.ACC_STATIC);
0414:                cf.add(Opcode.ICONST_0);
0415:                cf.add(Opcode.ANEWARRAY, "java.lang.Object");
0416:                cf.add(Opcode.PUTSTATIC, className, "NO_PARAM",
0417:                        "[Ljava/lang/Object;");
0418:
0419:                /**/
0420:                if (cc.hasAttachMethod) {
0421:                    cf.add(Opcode.INVOKESTATIC, "pnuts.lang.Runtime",
0422:                            "getThreadContext", "()", "Lpnuts/lang/Context;");
0423:                    int tmp = cf.getLocal();
0424:                    cf.storeLocal(tmp);
0425:                    cf.loadLocal(tmp);
0426:                    Label end = cf.getLabel();
0427:                    cf.add(Opcode.IFNULL, end);
0428:                    cf.loadLocal(tmp);
0429:                    cf.add(Opcode.INVOKESTATIC, className, "attach",
0430:                            "(Lpnuts/lang/Context;)", "V");
0431:                    end.fix();
0432:                }
0433:                /**/
0434:                cf.addField(METHOD_FACTORY_FUNCTION,
0435:                        "Lpnuts/lang/PnutsFunction;", Constants.ACC_STATIC);
0436:
0437:                if (closureNode != null) {
0438:                    closureNode.accept(this , cc);
0439:                    cf.add(Opcode.PUTSTATIC, className,
0440:                            METHOD_FACTORY_FUNCTION,
0441:                            "Lpnuts/lang/PnutsFunction;");
0442:                }
0443:
0444:                for (Iterator it = cc.constants.keySet().iterator(); it
0445:                        .hasNext();) {
0446:                    Object obj = it.next();
0447:                    String k = (String) cc.constants.get(obj);
0448:                    if (DEBUG) {
0449:                        System.out.println(k + " : " + obj);
0450:                    }
0451:
0452:                    if (obj instanceof  Integer) {
0453:                        int value = ((Integer) obj).intValue();
0454:                        cf.addField(k, "Ljava/lang/Integer;",
0455:                                Constants.ACC_STATIC);
0456:                        cf.add(Opcode.NEW, "java.lang.Integer");
0457:                        cf.add(Opcode.DUP);
0458:                        cf.pushInteger(value);
0459:                        cf.add(Opcode.INVOKESPECIAL, "java.lang.Integer",
0460:                                "<init>", "(I)", "V");
0461:                        cf.add(Opcode.PUTSTATIC, className, k,
0462:                                "Ljava/lang/Integer;");
0463:                    } else if (obj instanceof  Byte) {
0464:                        byte value = ((Byte) obj).byteValue();
0465:                        cf
0466:                                .addField(k, "Ljava/lang/Byte;",
0467:                                        Constants.ACC_STATIC);
0468:                        cf.add(Opcode.NEW, "java.lang.Byte");
0469:                        cf.add(Opcode.DUP);
0470:                        cf.pushInteger((int) value);
0471:                        cf.add(Opcode.INVOKESPECIAL, "java.lang.Byte",
0472:                                "<init>", "(B)", "V");
0473:                        cf.add(Opcode.PUTSTATIC, className, k,
0474:                                "Ljava/lang/Byte;");
0475:                    } else if (obj instanceof  Character) {
0476:                        char value = ((Character) obj).charValue();
0477:                        cf.addField(k, "Ljava/lang/Character;",
0478:                                Constants.ACC_STATIC);
0479:                        cf.add(Opcode.NEW, "java.lang.Character");
0480:                        cf.add(Opcode.DUP);
0481:                        cf.pushInteger((int) value);
0482:                        cf.add(Opcode.INVOKESPECIAL, "java.lang.Character",
0483:                                "<init>", "(C)", "V");
0484:                        cf.add(Opcode.PUTSTATIC, className, k,
0485:                                "Ljava/lang/Character;");
0486:                    } else if (obj instanceof  Long) {
0487:                        long value = ((Long) obj).longValue();
0488:                        cf
0489:                                .addField(k, "Ljava/lang/Long;",
0490:                                        Constants.ACC_STATIC);
0491:                        cf.add(Opcode.NEW, "java.lang.Long");
0492:                        cf.add(Opcode.DUP);
0493:                        cf.pushLong(value);
0494:                        cf.add(Opcode.INVOKESPECIAL, "java.lang.Long",
0495:                                "<init>", "(J)", "V");
0496:                        cf.add(Opcode.PUTSTATIC, className, k,
0497:                                "Ljava/lang/Long;");
0498:                    } else if (obj instanceof  Float) {
0499:                        float value = ((Float) obj).floatValue();
0500:                        cf.addField(k, "Ljava/lang/Float;",
0501:                                Constants.ACC_STATIC);
0502:                        cf.add(Opcode.NEW, "java.lang.Float");
0503:                        cf.add(Opcode.DUP);
0504:                        cf.pushFloat(value);
0505:                        cf.add(Opcode.INVOKESPECIAL, "java.lang.Float",
0506:                                "<init>", "(F)", "V");
0507:                        cf.add(Opcode.PUTSTATIC, className, k,
0508:                                "Ljava/lang/Float;");
0509:                    } else if (obj instanceof  Double) {
0510:                        double value = ((Double) obj).doubleValue();
0511:                        cf.addField(k, "Ljava/lang/Double;",
0512:                                Constants.ACC_STATIC);
0513:                        cf.add(Opcode.NEW, "java.lang.Double");
0514:                        cf.add(Opcode.DUP);
0515:                        cf.pushDouble(value);
0516:                        cf.add(Opcode.INVOKESPECIAL, "java.lang.Double",
0517:                                "<init>", "(D)", "V");
0518:                        cf.add(Opcode.PUTSTATIC, className, k,
0519:                                "Ljava/lang/Double;");
0520:                    } else if (obj instanceof  BigDecimal) {
0521:                        cf.addField(k, "Ljava/math/BigDecimal;",
0522:                                Constants.ACC_STATIC);
0523:                        cf.add(Opcode.NEW, "java.math.BigDecimal");
0524:                        cf.add(Opcode.DUP);
0525:                        cf.pushString(obj.toString());
0526:                        cf.add(Opcode.INVOKESPECIAL, "java.math.BigDecimal",
0527:                                "<init>", "(Ljava/lang/String;)", "V");
0528:                        cf.add(Opcode.PUTSTATIC, className, k,
0529:                                "Ljava/math/BigDecimal;");
0530:                    } else if (obj instanceof  BigInteger) {
0531:                        cf.addField(k, "Ljava/math/BigInteger;",
0532:                                Constants.ACC_STATIC);
0533:                        cf.add(Opcode.NEW, "java.math.BigInteger");
0534:                        cf.add(Opcode.DUP);
0535:                        cf.pushString(obj.toString());
0536:                        cf.add(Opcode.INVOKESPECIAL, "java.math.BigInteger",
0537:                                "<init>", "(Ljava/lang/String;)", "V");
0538:                        cf.add(Opcode.PUTSTATIC, className, k,
0539:                                "Ljava/math/BigInteger;");
0540:                    }
0541:                }
0542:
0543:                cf.add(Opcode.RETURN);
0544:                cf.closeMethod();
0545:            }
0546:
0547:            public Object expressionList(SimpleNode node, Context context) {
0548:                CompileContext cc = (CompileContext) context;
0549:                ClassFile cf = cc.cf;
0550:
0551:                int n = node.jjtGetNumChildren();
0552:                if (n > 0) {
0553:                    int m = n - 1;
0554:                    for (int i = 0; i < m; i++) {
0555:                        accept(node, i, context);
0556:                        cf.add(Opcode.POP);
0557:                    }
0558:                    accept(node, m, context);
0559:                } else {
0560:                    cf.add(Opcode.ACONST_NULL);
0561:                }
0562:                return null;
0563:            }
0564:
0565:            public Object integerNode(SimpleNode node, Context context) {
0566:                CompileContext cc = (CompileContext) context;
0567:                ClassFile cf = cc.cf;
0568:                String str = node.str;
0569:                Object p[] = (Object[]) node.info;
0570:                Number n = (Number) p[0];
0571:
0572:                String assoc = (String) cc.constants.get(n);
0573:                if (assoc == null) {
0574:                    assoc = gensym(context);
0575:                    cc.constants.put(n, assoc);
0576:                }
0577:
0578:                if (n instanceof  Integer) {
0579:                    cf.add(Opcode.GETSTATIC, cc.constClassName, assoc,
0580:                            "Ljava/lang/Integer;");
0581:                } else if (n instanceof  Long) {
0582:                    cf.add(Opcode.GETSTATIC, cc.constClassName, assoc,
0583:                            "Ljava/lang/Long;");
0584:                } else if (n instanceof  Byte) {
0585:                    cf.add(Opcode.GETSTATIC, cc.constClassName, assoc,
0586:                            "Ljava/lang/Byte;");
0587:                } else if (n instanceof  BigInteger) {
0588:                    cf.add(Opcode.GETSTATIC, cc.constClassName, assoc,
0589:                            "Ljava/math/BigInteger;");
0590:                } else if (n instanceof  BigDecimal) {
0591:                    cf.add(Opcode.GETSTATIC, cc.constClassName, assoc,
0592:                            "Ljava/math/BigDecimal;");
0593:                } else {
0594:                    throw new InternalError("compiler error");
0595:                }
0596:
0597:                if (p[1] != null) {
0598:                    addLineInfo(cc, cc.getContextIndex(), node);
0599:
0600:                    int offset = ((int[]) p[1])[0];
0601:                    cf.add(Opcode.CHECKCAST, "java.lang.Number");
0602:
0603:                    cf.pushString(str.substring(0, offset));
0604:                    cf.add(Opcode.LDC, cf.addConstant(str.substring(offset)));
0605:                    cf.loadLocal(cc.getContextIndex());
0606:                    cf
0607:                            .add(
0608:                                    Opcode.INVOKESTATIC,
0609:                                    "pnuts.lang.Runtime",
0610:                                    "quantity",
0611:                                    "(Ljava/lang/Number;Ljava/lang/String;Ljava/lang/String;Lpnuts/lang/Context;)",
0612:                                    "Ljava/lang/Object;");
0613:                }
0614:                return null;
0615:            }
0616:
0617:            public Object floatingNode(SimpleNode node, Context context) {
0618:                CompileContext cc = (CompileContext) context;
0619:                ClassFile cf = cc.cf;
0620:                String str = node.str;
0621:                Object p[] = (Object[]) node.info;
0622:                Number n = (Number) p[0];
0623:
0624:                String assoc = (String) cc.constants.get(n);
0625:                if (assoc == null) {
0626:                    assoc = gensym(context);
0627:                    cc.constants.put(n, assoc);
0628:                }
0629:                if (n instanceof  Float) {
0630:                    cf.add(Opcode.GETSTATIC, cc.constClassName, assoc,
0631:                            "Ljava/lang/Float;");
0632:                } else if (n instanceof  Double) {
0633:                    cf.add(Opcode.GETSTATIC, cc.constClassName, assoc,
0634:                            "Ljava/lang/Double;");
0635:                } else if (n instanceof  BigDecimal) {
0636:                    cf.add(Opcode.GETSTATIC, cc.constClassName, assoc,
0637:                            "Ljava/math/BigDecimal;");
0638:                } else {
0639:                    throw new InternalError("compiler error");
0640:                }
0641:                if (p[1] != null) {
0642:                    addLineInfo(cc, cc.getContextIndex(), node);
0643:
0644:                    int offset = ((int[]) p[1])[0];
0645:                    cf.add(Opcode.CHECKCAST, "java.lang.Number");
0646:
0647:                    cf
0648:                            .add(Opcode.LDC, cf.addConstant(str.substring(0,
0649:                                    offset)));
0650:                    cf.add(Opcode.LDC, cf.addConstant(str.substring(offset)));
0651:                    cf.loadLocal(cc.getContextIndex());
0652:                    cf
0653:                            .add(
0654:                                    Opcode.INVOKESTATIC,
0655:                                    "pnuts.lang.Runtime",
0656:                                    "quantity",
0657:                                    "(Ljava/lang/Number;Ljava/lang/String;Ljava/lang/String;Lpnuts/lang/Context;)",
0658:                                    "Ljava/lang/Object;");
0659:                }
0660:                return null;
0661:            }
0662:
0663:            public Object stringNode(SimpleNode node, Context context) {
0664:                CompileContext cc = (CompileContext) context;
0665:                ClassFile cf = cc.cf;
0666:                String str = node.str;
0667:                if (str != null) {
0668:                    cf.pushString(node.str);
0669:                } else {
0670:                    cf.add(Opcode.NEW, "java.lang.StringBuffer");
0671:                    cf.add(Opcode.DUP);
0672:                    cf.add(Opcode.INVOKESPECIAL, "java.lang.StringBuffer",
0673:                            "<init>", "()", "V");
0674:                    int n = node.jjtGetNumChildren();
0675:                    for (int i = 0; i < n; i++) {
0676:                        SimpleNode c = node.jjtGetChild(i);
0677:                        if (c.id == PnutsParserTreeConstants.JJTSTRINGNODE) {
0678:                            cf.pushString(c.str);
0679:                        } else {
0680:                            c.accept(this , context);
0681:                            cf.add(Opcode.INVOKESTATIC, "java.lang.String",
0682:                                    "valueOf", "(Ljava/lang/Object;)",
0683:                                    "Ljava/lang/String;");
0684:                        }
0685:                        cf.add(Opcode.INVOKEVIRTUAL, "java.lang.StringBuffer",
0686:                                "append", "(Ljava/lang/String;)",
0687:                                "Ljava/lang/StringBuffer;");
0688:                    }
0689:                    cf.add(Opcode.INVOKEVIRTUAL, "java.lang.StringBuffer",
0690:                            "toString", "()", "Ljava/lang/String;");
0691:                }
0692:                return null;
0693:            }
0694:
0695:            public Object characterNode(SimpleNode node, Context context) {
0696:                CompileContext cc = (CompileContext) context;
0697:                ClassFile cf = cc.cf;
0698:                Character ch = (Character) node.info;
0699:                String assoc = (String) cc.constants.get(ch);
0700:                if (assoc == null) {
0701:                    assoc = gensym(context);
0702:                    cc.constants.put(ch, assoc);
0703:                }
0704:                cf.add(Opcode.GETSTATIC, cc.constClassName, assoc,
0705:                        "Ljava/lang/Character;");
0706:                return null;
0707:            }
0708:
0709:            public Object classNode(SimpleNode node, Context context) {
0710:                CompileContext cc = (CompileContext) context;
0711:                ClassFile cf = cc.cf;
0712:                int ctx = cc.getContextIndex();
0713:                addLineInfo(cc, ctx, node);
0714:
0715:                SimpleNode c = node.jjtGetChild(0);
0716:                if (c.id == PnutsParserTreeConstants.JJTCLASSNAME) {
0717:                    StringBuffer sbuf = new StringBuffer();
0718:                    sbuf.append(c.jjtGetChild(0).str);
0719:                    int n = c.jjtGetNumChildren();
0720:                    for (int i = 1; i < n; i++) {
0721:                        SimpleNode ch = c.jjtGetChild(i);
0722:                        sbuf.append('.');
0723:                        sbuf.append(ch.str);
0724:                    }
0725:                    String name = sbuf.toString();
0726:                    cf.add(Opcode.LDC, cf.addConstant(name));
0727:                } else {
0728:                    c.accept(this , context);
0729:                    cf.add(Opcode.CHECKCAST, "java.lang.String");
0730:                }
0731:                cf.loadLocal(ctx);
0732:                cf.add(Opcode.INVOKESTATIC, "pnuts.lang.Pnuts", "loadClass",
0733:                        "(Ljava/lang/String;Lpnuts/lang/Context;)",
0734:                        "Ljava/lang/Class;");
0735:
0736:                return null;
0737:            }
0738:
0739:            static class MethodSignatureInfo {
0740:                String methodName;
0741:                SimpleNode returnTypeNode;
0742:                SimpleNode[] paramTypeNodes;
0743:                SimpleNode fnode;
0744:                Map/*<String,Collection<SimpleNode>>*/this References;
0745:                Map/*<String,SimpleNode>*/paramReferences;
0746:            }
0747:
0748:            static class ConstructorSignatureInfo extends MethodSignatureInfo {
0749:            }
0750:
0751:            static class FieldSignatureInfo {
0752:                String fieldName;
0753:                SimpleNode typeNode;
0754:                //SimpleNode lhs;
0755:                SimpleNode rhs;
0756:            }
0757:
0758:            /*
0759:             * Transform methodef to function
0760:             * Also, set attributes of MethodSignatureInfo
0761:             */
0762:            static SimpleNode buildMethodFunction(SimpleNode methodDef,
0763:                    MethodSignatureInfo siginfo, Set /**/super MethodNames) {
0764:                SimpleNode n1 = methodDef.jjtGetChild(0);
0765:                SimpleNode param;
0766:                SimpleNode block;
0767:                SimpleNode returnTypeNode = null;
0768:                String symbol = methodDef.str;
0769:                siginfo.methodName = symbol;
0770:
0771:                if (n1.id == PnutsParserTreeConstants.JJTCLASSNAME
0772:                        || n1.id == PnutsParserTreeConstants.JJTARRAYTYPE) {
0773:                    returnTypeNode = n1;
0774:                    param = methodDef.jjtGetChild(1);
0775:                    block = methodDef.jjtGetChild(2);
0776:                } else {
0777:                    param = methodDef.jjtGetChild(0);
0778:                    block = methodDef.jjtGetChild(1);
0779:                }
0780:
0781:                SimpleNode newParam = new SimpleNode(
0782:                        PnutsParserTreeConstants.JJTPARAMLIST);
0783:
0784:                int nargs = param.jjtGetNumChildren();
0785:                SimpleNode[] paramTypeNodes = new SimpleNode[nargs];
0786:                siginfo.paramReferences = new HashMap();
0787:                for (int k = 0; k < nargs; k++) {
0788:                    SimpleNode c = param.jjtGetChild(k);
0789:                    SimpleNode cp = param.jjtGetChild(k);
0790:                    if (c.jjtGetNumChildren() > 1) {
0791:                        cp = c.jjtGetChild(1);
0792:                        paramTypeNodes[k] = c.jjtGetChild(0);
0793:                    } else {
0794:                        cp = c.jjtGetChild(0);
0795:                    }
0796:                    siginfo.paramReferences.put(cp.str, cp);
0797:                    newParam.jjtAddChild(cp, k);
0798:                }
0799:                siginfo.paramTypeNodes = paramTypeNodes;
0800:                siginfo.returnTypeNode = returnTypeNode;
0801:                SimpleNode fnode = new SimpleNode(
0802:                        PnutsParserTreeConstants.JJTFUNCTIONSTATEMENT);
0803:                fnode.setAttribute("isMethod", Boolean.TRUE);
0804:                fnode.info = methodDef.info;
0805:                fnode.setAttribute("frameInfo", methodDef
0806:                        .getAttribute("frameInfo"));
0807:                fnode.str = symbol;
0808:                fnode.jjtAddChild(newParam, 0);
0809:                fnode.jjtAddChild(block, 1);
0810:                fnode.jjtSetParent(methodDef.jjtGetParent());
0811:                Map/*<String,Collection<SimpleNode>>*/refs = collectThisReferences(
0812:                        block, super MethodNames);
0813:                if (DEBUG) {
0814:                    System.out.println("ref = " + refs);
0815:                }
0816:                siginfo.this References = refs;
0817:                return fnode;
0818:            }
0819:
0820:            static Map/*<String,SimpleNode>*/collectThisReferences(
0821:                    SimpleNode node, Set super MethodNames) {
0822:                Map refs = new HashMap();
0823:                collectThisReferences(node, refs, super MethodNames);
0824:                return refs;
0825:            }
0826:
0827:            static void collectThisReferences(SimpleNode node,
0828:                    Map/*<String,SimpleNode>*/frefs, Set super MethodNames) {
0829:                int n = node.jjtGetNumChildren();
0830:                for (int i = 0; i < n; i++) {
0831:                    SimpleNode c = node.jjtGetChild(i);
0832:                    if (c.id == PnutsParserTreeConstants.JJTMEMBERNODE) {
0833:                        SimpleNode lhs = c.jjtGetChild(0);
0834:                        if ((lhs.id == PnutsParserTreeConstants.JJTIDNODE)
0835:                                && lhs.str == THIS) {
0836:                            Collection refset = (Collection) frefs.get(c.str);
0837:                            if (refset == null) {
0838:                                frefs.put(c.str, refset = new ArrayList());
0839:                            }
0840:                            refset.add(c);
0841:                        }
0842:                    } else if (c.id == PnutsParserTreeConstants.JJTMETHODNODE) {
0843:                        SimpleNode target = c.jjtGetChild(0);
0844:                        if (target.id == PnutsParserTreeConstants.JJTIDNODE
0845:                                && target.str == "super") {
0846:                            SimpleNode args = c.jjtGetChild(1);
0847:                            super MethodNames.add(c.str);
0848:                        }
0849:                    } else if (c.id != PnutsParserTreeConstants.JJTCLASSDEFBODY) {
0850:                        collectThisReferences(c, frefs, super MethodNames);
0851:                    }
0852:                }
0853:            }
0854:
0855:            /*
0856:             * Examine the methodDef node and returns MethodSignatureInfo
0857:             * Also, define a function in the Package object stored at pkg
0858:             */
0859:            static MethodSignatureInfo handleMethodDef(SimpleNode methodDef,
0860:                    Set/**/super MethodNames) {
0861:                MethodSignatureInfo siginfo = new MethodSignatureInfo();
0862:                SimpleNode fnode = buildMethodFunction(methodDef, siginfo,
0863:                        super MethodNames);
0864:                siginfo.fnode = fnode;
0865:                if (DEBUG) {
0866:                    System.out.println(siginfo.this References);
0867:                    System.out.println(siginfo.paramReferences);
0868:                }
0869:                return siginfo;
0870:            }
0871:
0872:            static ConstructorSignatureInfo handleConstructorDef(
0873:                    SimpleNode defNode, Set super MethodNames) {
0874:                ConstructorSignatureInfo siginfo = new ConstructorSignatureInfo();
0875:                SimpleNode param = defNode.jjtGetChild(0);
0876:                SimpleNode block = defNode.jjtGetChild(1);
0877:                SimpleNode first = null;
0878:
0879:                SimpleNode newParam = new SimpleNode(
0880:                        PnutsParserTreeConstants.JJTPARAMLIST);
0881:
0882:                int nargs = param.jjtGetNumChildren();
0883:                SimpleNode[] paramTypeNodes = new SimpleNode[nargs];
0884:                siginfo.paramReferences = new HashMap();
0885:                for (int k = 0; k < nargs; k++) {
0886:                    SimpleNode c = param.jjtGetChild(k);
0887:                    SimpleNode cp = param.jjtGetChild(k);
0888:                    if (c.jjtGetNumChildren() > 1) {
0889:                        cp = c.jjtGetChild(1);
0890:                        paramTypeNodes[k] = c.jjtGetChild(0);
0891:                    } else {
0892:                        cp = c.jjtGetChild(0);
0893:                    }
0894:                    siginfo.paramReferences.put(cp.str, cp);
0895:                    newParam.jjtAddChild(cp, k);
0896:                }
0897:                siginfo.paramTypeNodes = paramTypeNodes;
0898:
0899:                SimpleNode fnode = new SimpleNode(
0900:                        PnutsParserTreeConstants.JJTFUNCTIONSTATEMENT);
0901:                fnode.setAttribute("isMethod", Boolean.TRUE);
0902:                fnode.info = defNode.info;
0903:                fnode.setAttribute("frameInfo", defNode
0904:                        .getAttribute("frameInfo"));
0905:                siginfo.fnode = fnode;
0906:
0907:                fnode.jjtAddChild(newParam, 0);
0908:                fnode.jjtAddChild(block, 1);
0909:
0910:                Map refs = collectThisReferences(block, super MethodNames);
0911:                if (DEBUG) {
0912:                    System.out.println("ref = " + refs);
0913:                }
0914:                siginfo.this References = refs;
0915:
0916:                return siginfo;
0917:            }
0918:
0919:            static FieldSignatureInfo handleFieldDef(SimpleNode defNode) {
0920:                FieldSignatureInfo finfo = new FieldSignatureInfo();
0921:                finfo.fieldName = defNode.str;
0922:                boolean hasTypeNode = (defNode.jjtGetChild(0).id == PnutsParserTreeConstants.JJTCLASSNAME);
0923:                if (hasTypeNode) {
0924:                    finfo.typeNode = defNode.jjtGetChild(0);
0925:                }
0926:                if (defNode.jjtGetNumChildren() > 1) {
0927:                    finfo.rhs = defNode.jjtGetChild(1);
0928:                } else if (!hasTypeNode) {
0929:                    finfo.rhs = defNode.jjtGetChild(0);
0930:                }
0931:                //finfo.lhs = defNode.jjtGetChild(0);
0932:                return finfo;
0933:            }
0934:
0935:            static void handleClassDefBody(SimpleNode classDefBody,
0936:                    List/*<MethodSignatureInfo>*/methodSigs,
0937:                    List/*<ConstructorSignatureInfo>*/constructorSigs,
0938:                    List/*<FieldSignatureInfo>*/fieldSigs, Set super MethodNames) {
0939:                for (int i = 0; i < classDefBody.jjtGetNumChildren(); i++) {
0940:                    SimpleNode defNode = classDefBody.jjtGetChild(i);
0941:                    if (defNode.id == PnutsParserTreeConstants.JJTFIELDDEF) {
0942:                        fieldSigs.add(handleFieldDef(defNode));
0943:                    } else {
0944:                        SimpleNode n0 = defNode.jjtGetChild(0);
0945:                        if (n0.id != PnutsParserTreeConstants.JJTCLASSNAME
0946:                                && n0.id != PnutsParserTreeConstants.JJTARRAYNODE) {
0947:                            SimpleNode parent = classDefBody.jjtGetParent();
0948:                            if (parent.id == PnutsParserTreeConstants.JJTCLASSSCRIPT
0949:                                    || parent.id == PnutsParserTreeConstants.JJTCLASSDEF) {
0950:                                if (defNode.str.equals(getClassName(parent
0951:                                        .jjtGetChild(0)))) {
0952:                                    /* constructor */
0953:                                    constructorSigs.add(handleConstructorDef(
0954:                                            defNode, super MethodNames));
0955:                                    continue;
0956:                                }
0957:                            }
0958:                        }
0959:                        methodSigs.add(handleMethodDef(defNode,
0960:                                super MethodNames));
0961:                    }
0962:                }
0963:            }
0964:
0965:            static void buildFieldDeclaration(FieldSignatureInfo fsig,
0966:                    List assignmentNodes) {
0967:                if (fsig.rhs != null) {
0968:                    /*
0969:                     * this.fieldName = rhs
0970:                     */
0971:                    SimpleNode assign = new SimpleNode(
0972:                            PnutsParserTreeConstants.JJTASSIGNMENT);
0973:                    SimpleNode member = new SimpleNode(
0974:                            PnutsParserTreeConstants.JJTMEMBERNODE);
0975:                    SimpleNode id = new SimpleNode(
0976:                            PnutsParserTreeConstants.JJTIDNODE);
0977:                    id.str = THIS;
0978:                    member.str = fsig.fieldName;
0979:                    member.jjtAddChild(id, 0);
0980:                    assign.jjtAddChild(fsig.rhs, 1);
0981:                    assign.jjtAddChild(member, 0);
0982:                    assignmentNodes.add(assign);
0983:                }
0984:            }
0985:
0986:            /**
0987:             * Convert 'new type(){...}' to 'class name extends type {...}'
0988:             */
0989:            SimpleNode getClassDefNode(SimpleNode node, Context cc) {
0990:                SimpleNode n0 = node.jjtGetChild(0);
0991:                String super className = getClassName(n0);
0992:                Class[] interfaces = null;
0993:                Class super class = null;
0994:
0995:                ClassSpec super typeSpec = ClassSpec.create(super className, cc);
0996:                Class super type = super typeSpec.compileTimeClass;
0997:                super className = super typeSpec.className;
0998:
0999:                String className = super className.replace('.', '_')
1000:                        + "__adapter" + "$"
1001:                        + (classCount++ & 0x7fffffffffffffffL);
1002:                SimpleNode classDefBody = node.jjtGetChild(2);
1003:
1004:                List/*<MethodSignatureInfo>*/methodSigs = new ArrayList();
1005:                List/*<ConstructorSignatureInfo>*/constructorSigs = new ArrayList();
1006:                List/*<FieldSignatureInfo>*/fieldSigs = new ArrayList();
1007:                Set super MethodNames = new HashSet();
1008:                handleClassDefBody(classDefBody, methodSigs, constructorSigs,
1009:                        fieldSigs, super MethodNames);
1010:
1011:                return getClassDefNode(className, super type != null
1012:                        && super type.isInterface(), n0, classDefBody);
1013:            }
1014:
1015:            static SimpleNode getClassDefNode(String className,
1016:                    boolean isInterface, SimpleNode typeNode,
1017:                    SimpleNode classDefBody) {
1018:                SimpleNode def = new SimpleNode(
1019:                        PnutsParserTreeConstants.JJTCLASSDEF);
1020:                SimpleNode classNameNode = new SimpleNode(
1021:                        PnutsParserTreeConstants.JJTCLASSNAME);
1022:                SimpleNode _p = new SimpleNode(
1023:                        PnutsParserTreeConstants.JJTPACKAGE);
1024:                _p.str = className;
1025:                classNameNode.jjtAddChild(_p, 0);
1026:                _p.jjtSetParent(classNameNode);
1027:                SimpleNode ext = new SimpleNode(
1028:                        PnutsParserTreeConstants.JJTEXTENDS);
1029:                SimpleNode imp = new SimpleNode(
1030:                        PnutsParserTreeConstants.JJTIMPLEMENTS);
1031:                def.jjtAddChild(classNameNode, 0);
1032:                classNameNode.jjtSetParent(def);
1033:                if (isInterface) {
1034:                    imp.jjtAddChild(typeNode, 0);
1035:                    typeNode.jjtSetParent(imp);
1036:                } else {
1037:                    ext.jjtAddChild(typeNode, 0);
1038:                    typeNode.jjtSetParent(ext);
1039:                }
1040:                def.jjtAddChild(ext, 1);
1041:                ext.jjtSetParent(def);
1042:                def.jjtAddChild(imp, 2);
1043:                imp.jjtSetParent(def);
1044:                def.jjtAddChild(classDefBody, 3);
1045:                classDefBody.jjtSetParent(def);
1046:                return def;
1047:            }
1048:
1049:            public Object newNode(SimpleNode node, Context context) {
1050:                CompileContext cc = (CompileContext) context;
1051:                ClassFile cf = cc.cf;
1052:                int ctx = cc.getContextIndex();
1053:                addLineInfo(cc, ctx, node);
1054:
1055:                SimpleNode n0 = node.jjtGetChild(0);
1056:
1057:                int n = node.jjtGetNumChildren();
1058:                if (n == 3
1059:                        && node.jjtGetChild(2).id == PnutsParserTreeConstants.JJTCLASSDEFBODY) { // subclass
1060:                    String encodedNode = NodeUtil.saveNode(node);
1061:                    cf.add(Opcode.LDC, cf.addConstant(encodedNode));
1062:                    cf.loadLocal(ctx);
1063:                    cf.add(Opcode.INVOKESTATIC, "pnuts.compiler.Compiler",
1064:                            "buildSubclassInstance",
1065:                            "(Ljava/lang/String;Lpnuts/lang/Context;)",
1066:                            "Ljava/lang/Object;");
1067:
1068:                } else if (n0.id == PnutsParserTreeConstants.JJTINDEXNODE) { // instantiation
1069:                    Object[] idx = parseIndex(n0);
1070:                    Object[] dim = (Object[]) idx[1];
1071:                    SimpleNode nameNode = (SimpleNode) idx[0];
1072:
1073:                    if (node.getAttribute("hasTryStatement") != null) {
1074:                        int[] vars = new int[dim.length];
1075:                        for (int i = 0; i < dim.length; i++) {
1076:                            int var = cf.getLocal();
1077:                            ((SimpleNode) dim[i]).accept(this , context);
1078:                            cf.storeLocal(var);
1079:                            vars[i] = var;
1080:                        }
1081:                        resolveClassName(nameNode, cc, ctx);
1082:                        cf.pushInteger(dim.length);
1083:                        cf.add(Opcode.NEWARRAY, Opcode.T_INT);
1084:                        for (int i = 0; i < dim.length; i++) {
1085:                            cf.add(Opcode.DUP);
1086:                            cf.pushInteger(i);
1087:                            cf.loadLocal(vars[i]);
1088:                            cf.add(Opcode.CHECKCAST, "java.lang.Number");
1089:                            cf.add(Opcode.INVOKEVIRTUAL, "java.lang.Number",
1090:                                    "intValue", "()", "I");
1091:                            cf.add(Opcode.IASTORE);
1092:                        }
1093:                        for (int i = 0; i < dim.length; i++) {
1094:                            cf.freeLocal(vars[i]);
1095:                        }
1096:                    } else {
1097:
1098:                        resolveClassName(nameNode, cc, ctx);
1099:
1100:                        cf.pushInteger(dim.length);
1101:                        cf.add(Opcode.NEWARRAY, Opcode.T_INT);
1102:                        for (int i = 0; i < dim.length; i++) {
1103:                            cf.add(Opcode.DUP);
1104:                            cf.pushInteger(i);
1105:                            ((SimpleNode) dim[i]).accept(this , context);
1106:
1107:                            cf.add(Opcode.CHECKCAST, "java.lang.Number");
1108:                            cf.add(Opcode.INVOKEVIRTUAL, "java.lang.Number",
1109:                                    "intValue", "()", "I");
1110:                            cf.add(Opcode.IASTORE);
1111:                        }
1112:                    }
1113:                    cf.add(Opcode.INVOKESTATIC, "java.lang.reflect.Array",
1114:                            "newInstance", "(Ljava/lang/Class;[I)",
1115:                            "Ljava/lang/Object;");
1116:
1117:                } else if (n0.id == PnutsParserTreeConstants.JJTARRAYTYPE) {
1118:                    arrayType(n0, context);
1119:
1120:                } else if (n0.id == PnutsParserTreeConstants.JJTARRAYNODE) {
1121:                    cf.loadLocal(ctx);
1122:                    accept(n0, 0, context);
1123:                    cf.add(Opcode.CHECKCAST, "java.lang.Class");
1124:                    //	    accept(n0, 1, context);
1125:                    _listElements(n0.jjtGetChild(1), context);
1126:                    cf.add(Opcode.ICONST_1);
1127:                    cf
1128:                            .add(
1129:                                    Opcode.INVOKESTATIC,
1130:                                    "pnuts.lang.Runtime",
1131:                                    "cast",
1132:                                    "(Lpnuts/lang/Context;Ljava/lang/Class;Ljava/lang/Object;Z)",
1133:                                    "Ljava/lang/Object;");
1134:
1135:                } else { // instantiation
1136:
1137:                    if (node.getAttribute("hasTryStatement") != null) {
1138:                        int arg = cf.getLocal();
1139:                        //		accept(node, 1, context);
1140:                        _listElements(node.jjtGetChild(1), context);
1141:                        cf.storeLocal(arg);
1142:                        cf.loadLocal(ctx);
1143:                        SimpleNode nameNode = node.jjtGetChild(0);
1144:                        resolveClassName(nameNode, cc, ctx);
1145:                        cf.loadLocal(arg);
1146:                        cf.freeLocal(arg);
1147:                    } else {
1148:                        cf.loadLocal(ctx);
1149:                        SimpleNode nameNode = node.jjtGetChild(0);
1150:                        resolveClassName(nameNode, cc, ctx);
1151:                        //		accept(node, 1, context);
1152:                        _listElements(node.jjtGetChild(1), context);
1153:                    }
1154:                    cf.add(Opcode.CHECKCAST, "[Ljava/lang/Object;");
1155:                    cf.add(Opcode.ACONST_NULL);
1156:                    cf
1157:                            .add(
1158:                                    Opcode.INVOKESTATIC,
1159:                                    "pnuts.lang.Runtime",
1160:                                    "callConstructor",
1161:                                    "(Lpnuts/lang/Context;Ljava/lang/Class;[Ljava/lang/Object;[Ljava/lang/Class;)",
1162:                                    "Ljava/lang/Object;");
1163:                }
1164:
1165:                return null;
1166:            }
1167:
1168:            public Object classDef(SimpleNode node, Context context) {
1169:                CompileContext cc = (CompileContext) context;
1170:                ClassFile cf = cc.cf;
1171:                int ctx = cc.getContextIndex();
1172:                ClassGenerationResult r = generateClass(node, cc);
1173:                ByteArrayOutputStream bout = new ByteArrayOutputStream();
1174:                try {
1175:                    r.classFile.write(bout);
1176:                } catch (IOException ioe) {
1177:                    ioe.printStackTrace();
1178:                }
1179:                byte[] bcode = bout.toByteArray();
1180:                String encodedBytecode = NodeUtil.byteArrayToString(bcode,
1181:                        bcode.length);
1182:                if (DEBUG) {
1183:                    System.out.println(encodedBytecode.length());
1184:                }
1185:                String className = r.classFile.getClassName();
1186:                if (className != null) {
1187:                    cf.add(Opcode.LDC, cf.addConstant(className));
1188:                } else {
1189:                    cf.add(Opcode.ACONST_NULL);
1190:                }
1191:                cf.add(Opcode.LDC, cf.addConstant(encodedBytecode));
1192:                r.closureNode.accept(this , cc);
1193:                cf.loadLocal(ctx);
1194:                cf
1195:                        .add(
1196:                                Opcode.INVOKESTATIC,
1197:                                "pnuts.compiler.Compiler",
1198:                                "loadBytecode",
1199:                                "(Ljava/lang/String;Ljava/lang/String;Lpnuts/lang/PnutsFunction;Lpnuts/lang/Context;)",
1200:                                "Ljava/lang/Class;");
1201:                return null;
1202:            }
1203:
1204:            static CodeLoader getCodeLoader(Context context) {
1205:                ClassLoader cl = context.getCodeLoader();
1206:                if (cl instanceof  CodeLoader) {
1207:                    return (CodeLoader) cl;
1208:                }
1209:                ClassLoader classLoader = context.getClassLoader();
1210:                if (classLoader == null) {
1211:                    classLoader = Thread.currentThread()
1212:                            .getContextClassLoader();
1213:                }
1214:                cl = createCodeLoader(classLoader, true);
1215:                context.setCodeLoader(cl);
1216:                Thread.currentThread().setContextClassLoader(cl);
1217:                return (CodeLoader) cl;
1218:            }
1219:
1220:            /*
1221:             * classDef/buildSubclassInstance
1222:             */
1223:            public ClassGenerationResult generateClass(SimpleNode node,
1224:                    Context context) {
1225:                String className = getClassName(node.jjtGetChild(0));
1226:                SimpleNode extendsNode = node.jjtGetChild(1);
1227:                ClassSpec super classSpec;
1228:                String super className = null;
1229:                if (extendsNode.jjtGetNumChildren() == 1) {
1230:                    SimpleNode n = extendsNode.jjtGetChild(0);
1231:                    super classSpec = ClassSpec.create(getClassName(n), context);
1232:                    super className = super classSpec.className;
1233:                } else {
1234:                    super classSpec = ClassSpec.create(Object.class);
1235:                    super className = "java.lang.Object";
1236:                }
1237:
1238:                Class compileTimeClass = super classSpec.compileTimeClass;
1239:
1240:                SimpleNode implements Node = node.jjtGetChild(2);
1241:                SimpleNode classDefBody = node.jjtGetChild(3);
1242:
1243:                List interfaces = null;
1244:                int nc = implements Node.jjtGetNumChildren();
1245:                if (nc > 0) {
1246:                    interfaces = new ArrayList();
1247:                    for (int i = 0; i < nc; i++) {
1248:                        SimpleNode n = implements Node.jjtGetChild(i);
1249:                        interfaces.add(getClassName(n));
1250:                    }
1251:                }
1252:
1253:                ClassSpec[] compileTimeInterfaces = null;
1254:                if (interfaces != null) {
1255:                    compileTimeInterfaces = new ClassSpec[interfaces.size()];
1256:                    for (int i = 0, n = interfaces.size(); i < n; i++) {
1257:                        String name = (String) interfaces.get(i);
1258:                        ClassSpec s = ClassSpec.create(name, context);
1259:                        compileTimeInterfaces[i] = s;
1260:                    }
1261:                }
1262:
1263:                CompileContext cc = new CompileContext(context);
1264:                ClassFile cf = cc.cf;
1265:
1266:                if (compileTimeClass != null) {
1267:                    ClassGenerator.transformClassDefBody(classDefBody,
1268:                            compileTimeClass);
1269:                }
1270:
1271:                CompileContext cc2 = (CompileContext) cc.clone(false, true);
1272:                cc2.constClassName = className;
1273:
1274:                return generateClass(className, null, classDefBody,
1275:                        super classSpec, compileTimeInterfaces, null, this , cc2);
1276:
1277:            }
1278:
1279:            public static Class attachClosure(Class cls, PnutsFunction closure,
1280:                    Context context) {
1281:                try {
1282:                    Method method = cls.getMethod("attach", new Class[] {
1283:                            Context.class, PnutsFunction.class });
1284:                    method.invoke(null, new Object[] { context, closure });
1285:                } catch (Exception e) {
1286:                    e.printStackTrace();
1287:                }
1288:                return cls;
1289:            }
1290:
1291:            public static Class loadBytecode(String name,
1292:                    String encodedBytecode, PnutsFunction closure,
1293:                    Context context) {
1294:                CodeLoader loader = getCodeLoader(context);
1295:                byte[] bcode = NodeUtil.stringToByteArray(encodedBytecode);
1296:                System.out.println(name);
1297:                Class cls = loader.define(name, bcode, 0, bcode.length);
1298:                return attachClosure(cls, closure, context);
1299:            }
1300:
1301:            /*
1302:             * Helper method for interpreter
1303:             */
1304:            public static Object buildSubclassInstance(String encodedNode,
1305:                    Context context) {
1306:                CompilerPnutsImpl impl = (CompilerPnutsImpl) context
1307:                        .getImplementation();
1308:                return impl.compiler.buildSubclassInstance(NodeUtil
1309:                        .loadNode(encodedNode), context);
1310:            }
1311:
1312:            public Object buildSubclassInstance(SimpleNode node, Context context) {
1313:                SimpleNode def = getClassDefNode(node, context);
1314:                Class cls = defineClass(def, context);
1315:                Object[] arg = interpreter._listElements(node.jjtGetChild(1),
1316:                        context);
1317:                return Runtime.callConstructor(context, cls, arg, null);
1318:            }
1319:
1320:            public Class defineClass(String encodedNode, Context context) {
1321:                return defineClass(NodeUtil.loadNode(encodedNode), context);
1322:            }
1323:
1324:            public Class defineClass(SimpleNode node, Context context) {
1325:
1326:                String className = getClassName(node.jjtGetChild(0));
1327:                SimpleNode extendsNode = node.jjtGetChild(1);
1328:                String super class = null;
1329:                if (extendsNode.jjtGetNumChildren() == 1) {
1330:                    SimpleNode n = extendsNode.jjtGetChild(0);
1331:                    super class = getClassName(n);
1332:                } else {
1333:                    super class = "java.lang.Object";
1334:                }
1335:
1336:                SimpleNode implements Node = node.jjtGetChild(2);
1337:                SimpleNode classDefBody = node.jjtGetChild(3);
1338:
1339:                List interfaces = null;
1340:                int nc = implements Node.jjtGetNumChildren();
1341:                if (nc > 0) {
1342:                    interfaces = new ArrayList();
1343:                    for (int i = 0; i < nc; i++) {
1344:                        SimpleNode n = implements Node.jjtGetChild(i);
1345:                        interfaces.add(getClassName(n));
1346:                    }
1347:                }
1348:
1349:                ClassSpec super classSpec = ClassSpec
1350:                        .create(super class, context);
1351:                Class compileTimeClass = super classSpec.compileTimeClass;
1352:
1353:                ClassSpec[] compileTimeInterfaces = null;
1354:                if (interfaces != null) {
1355:                    compileTimeInterfaces = new ClassSpec[interfaces.size()];
1356:                    for (int i = 0, n = interfaces.size(); i < n; i++) {
1357:                        String name = (String) interfaces.get(i);
1358:                        ClassSpec s = ClassSpec.create(name, context);
1359:                        compileTimeInterfaces[i] = s;
1360:                    }
1361:                }
1362:
1363:                CompileContext cc = new CompileContext(context);
1364:                ClassFile cf = cc.cf;
1365:
1366:                ClassGenerator.transformClassDefBody(classDefBody,
1367:                        compileTimeClass);
1368:
1369:                CompileContext cc2 = (CompileContext) cc.clone(false, true);
1370:                cc2.constClassName = className;
1371:
1372:                ClassGenerationResult cg = generateClass(className, null,
1373:                        classDefBody, super classSpec, compileTimeInterfaces,
1374:                        null, this , cc2);
1375:
1376:                ClassFile cf2 = cg.classFile;
1377:                PnutsFunction closure = (PnutsFunction) cg.closureNode.accept(
1378:                        interpreter, context);
1379:
1380:                try {
1381:                    CodeLoader loader = getCodeLoader(context);
1382:
1383:                    Class cls = cc2.loadClasses(loader);
1384:                    Method m = cls.getMethod("attach", new Class[] {
1385:                            Context.class, PnutsFunction.class });
1386:                    m.invoke(null,
1387:                            new Object[] { new Context(context), closure });
1388:                    return cls;
1389:                } catch (LinkageError e) {
1390:                    ClassLoader cl = compileTimeClass.getClassLoader();
1391:                    if (cl instanceof  CodeLoader) {
1392:                        try {
1393:                            Class cls = cc2.loadClasses((CodeLoader) cl);
1394:                            Method m = cls.getMethod("attach", new Class[] {
1395:                                    Context.class, PnutsFunction.class });
1396:                            m.invoke(null, new Object[] { new Context(context),
1397:                                    closure });
1398:                            return cls;
1399:                        } catch (Exception e2) {
1400:                        }
1401:                    }
1402:                    throw new PnutsException(e, context);
1403:                } catch (Exception ex) {
1404:                    throw new PnutsException(ex, context);
1405:                }
1406:            }
1407:
1408:            public Object methodDef(SimpleNode node, Context context) {
1409:                return null;
1410:            }
1411:
1412:            public Object classDefBody(SimpleNode node, Context context) {
1413:                return null;
1414:            }
1415:
1416:            static Signature resolveSignature(MethodSignatureInfo methodSig,
1417:                    Context context) {
1418:                Class returnType;
1419:                if (methodSig.returnTypeNode != null) {
1420:                    returnType = interpreter.resolveType(
1421:                            methodSig.returnTypeNode, context);
1422:                } else {
1423:                    returnType = null;
1424:                }
1425:                SimpleNode[] parameterTypeNodes = methodSig.paramTypeNodes;
1426:                Class[] parameterTypes = null;
1427:                if (parameterTypeNodes != null) {
1428:                    parameterTypes = new Class[parameterTypeNodes.length];
1429:                    for (int i = 0; i < parameterTypes.length; i++) {
1430:                        SimpleNode typeNode = parameterTypeNodes[i];
1431:                        if (typeNode != null) {
1432:                            parameterTypes[i] = interpreter.resolveType(
1433:                                    typeNode, context);
1434:                        }
1435:                    }
1436:                }
1437:                return new Signature(methodSig.methodName, returnType,
1438:                        parameterTypes, null, methodSig.fnode);
1439:            }
1440:
1441:            static Signature resolveSignature(
1442:                    ConstructorSignatureInfo constructorSig, Context context) {
1443:                SimpleNode[] parameterTypeNodes = constructorSig.paramTypeNodes;
1444:                Class[] parameterTypes = null;
1445:                if (parameterTypeNodes != null) {
1446:                    parameterTypes = new Class[parameterTypeNodes.length];
1447:                    for (int i = 0; i < parameterTypes.length; i++) {
1448:                        SimpleNode typeNode = parameterTypeNodes[i];
1449:                        if (typeNode != null) {
1450:                            parameterTypes[i] = interpreter.resolveType(
1451:                                    typeNode, context);
1452:                        }
1453:                    }
1454:                }
1455:                return new Signature(null, null, parameterTypes, null,
1456:                        constructorSig.fnode);
1457:            }
1458:
1459:            static String[] split(String s, char delim) {
1460:                ArrayList list = new ArrayList();
1461:                int offset = 0;
1462:                int idx = 0;
1463:                while (idx >= 0) {
1464:                    idx = s.indexOf(delim, offset);
1465:                    if (idx > 0) {
1466:                        list.add(s.substring(offset, idx));
1467:                        offset = idx + 1;
1468:                    }
1469:                }
1470:                list.add(s.substring(offset));
1471:                return (String[]) list.toArray(new String[list.size()]);
1472:            }
1473:
1474:            public static class ClassGenerationResult {
1475:                public ClassFile classFile;
1476:                public SimpleNode closureNode;
1477:            }
1478:
1479:            static ClassGenerationResult generateClass(String className,
1480:                    String scriptFile, SimpleNode classDefBody,
1481:                    ClassSpec super classSpec, ClassSpec[] interfaces,
1482:                    List importNodes, Compiler compiler, CompileContext cc) {
1483:                List/*<MethodSignatureInfo>*/methodSigs = new ArrayList();
1484:                List/*<ConstructorSignatureInfo>*/constructorSigs = new ArrayList();
1485:                List/*<FieldSignatureInfo>*/fieldSigs = new ArrayList();
1486:                Set super MethodNames = new HashSet();
1487:                handleClassDefBody(classDefBody, methodSigs, constructorSigs,
1488:                        fieldSigs, super MethodNames);
1489:                return generateClass(className, scriptFile, methodSigs,
1490:                        constructorSigs, fieldSigs, super MethodNames,
1491:                        super classSpec, interfaces, importNodes, compiler, cc);
1492:            }
1493:
1494:            static void updateMethodSignatureInfo(MethodSignatureInfo sig,
1495:                    String fieldName) {
1496:                SimpleNode fnode = sig.fnode;
1497:                Map this References = sig.this References;
1498:                Collection refs = (Collection) this References.get(fieldName);
1499:                if (refs != null) {
1500:                    Map params = sig.paramReferences;
1501:                    SimpleNode paramNode = (SimpleNode) params.get(fieldName);
1502:                    if (paramNode != null) {
1503:                        paramNode.str = (" " + paramNode.str).intern();
1504:                        renameIDs(fnode, fieldName);
1505:                    }
1506:                    for (Iterator it = refs.iterator(); it.hasNext();) {
1507:                        SimpleNode node = (SimpleNode) it.next();
1508:                        node.id = PnutsParserTreeConstants.JJTIDNODE;
1509:                        node.clearChildren();
1510:                    }
1511:                }
1512:            }
1513:
1514:            static void renameIDs(SimpleNode node, String name) {
1515:                int id = node.id;
1516:                if (id == PnutsParserTreeConstants.JJTIDNODE) {
1517:                    if (node.str == name) {
1518:                        SimpleNode parent = node.jjtGetParent();
1519:                        if (parent == null
1520:                                || parent.id != PnutsParserTreeConstants.JJTMEMBERNODE) {
1521:                            node.str = (" " + name).intern();
1522:                        }
1523:                    }
1524:                } else if (id != PnutsParserTreeConstants.JJTCLASSDEF) {
1525:                    int n = node.jjtGetNumChildren();
1526:                    for (int i = 0; i < n; i++) {
1527:                        renameIDs(node.jjtGetChild(i), name);
1528:                    }
1529:                }
1530:            }
1531:
1532:            static void updateMethodSignatureInfo(
1533:                    List/*<MethodSignatureInfo>*/sigs, String fieldName) {
1534:                for (int i = 0, n = sigs.size(); i < n; i++) {
1535:                    updateMethodSignatureInfo(
1536:                            (MethodSignatureInfo) sigs.get(i), fieldName);
1537:                }
1538:            }
1539:
1540:            static SimpleNode buildClosureNode(List/*<SimpleNode>*/nodes,
1541:                    List/*<FieldSignatureInfo>*/fieldSigs, Map typeMap) {
1542:                SimpleNode block = new SimpleNode(
1543:                        PnutsParserTreeConstants.JJTBLOCK);
1544:
1545:                SimpleNode listElements = new SimpleNode(
1546:                        PnutsParserTreeConstants.JJTLISTELEMENTS);
1547:                block.jjtAddChild(listElements, fieldSigs.size() + 1);
1548:                listElements.jjtSetParent(block);
1549:                for (int i = nodes.size() - 1; i >= 0; i--) {
1550:                    SimpleNode n = (SimpleNode) nodes.get(i);
1551:                    listElements.jjtAddChild(n, i);
1552:                    n.jjtSetParent(listElements);
1553:                }
1554:                for (int i = 0, n = fieldSigs.size(); i < n; i++) {
1555:                    FieldSignatureInfo finfo = (FieldSignatureInfo) fieldSigs
1556:                            .get(i);
1557:                    String fieldName = finfo.fieldName;
1558:                    SimpleNode rhs = finfo.rhs;
1559:                    SimpleNode var = new SimpleNode(
1560:                            PnutsParserTreeConstants.JJTIDNODE);
1561:                    var.str = fieldName;
1562:                    SimpleNode assignment = new SimpleNode(
1563:                            PnutsParserTreeConstants.JJTASSIGNMENT);
1564:                    if (rhs == null) {
1565:                        Class type = (Class) typeMap.get(fieldName);
1566:                        if (type.isPrimitive()) {
1567:                            if (type == boolean.class) {
1568:                                rhs = new SimpleNode(
1569:                                        PnutsParserTreeConstants.JJTFALSENODE);
1570:                            } else {
1571:                                rhs = new SimpleNode(
1572:                                        PnutsParserTreeConstants.JJTINTEGERNODE);
1573:                                rhs.info = new Object[] { new Integer(0), null };
1574:                            }
1575:                        } else {
1576:                            rhs = new SimpleNode(
1577:                                    PnutsParserTreeConstants.JJTNULLNODE);
1578:                        }
1579:                    }
1580:                    assignment.jjtAddChild(rhs, 1);
1581:                    rhs.jjtSetParent(assignment);
1582:                    assignment.jjtAddChild(var, 0);
1583:                    block.jjtAddChild(assignment, i + 1);
1584:                }
1585:                SimpleNode super Assignment = new SimpleNode(
1586:                        PnutsParserTreeConstants.JJTASSIGNMENT);
1587:                SimpleNode super ID = new SimpleNode(
1588:                        PnutsParserTreeConstants.JJTIDNODE);
1589:                super ID.str = SUPER;
1590:                block.jjtAddChild(super Assignment, 0);
1591:                super Assignment.jjtSetParent(super Assignment);
1592:
1593:                SimpleNode closure = new SimpleNode(
1594:                        PnutsParserTreeConstants.JJTFUNCTIONSTATEMENT);
1595:                SimpleNode paramList = new SimpleNode(
1596:                        PnutsParserTreeConstants.JJTPARAMLIST);
1597:
1598:                SimpleNode this Param = new SimpleNode(
1599:                        PnutsParserTreeConstants.JJTPARAM);
1600:                this Param.str = THIS;
1601:                SimpleNode super Creation = new SimpleNode(
1602:                        PnutsParserTreeConstants.JJTNEW);
1603:                super Assignment.jjtAddChild(super Creation, 1);
1604:                super Assignment.jjtAddChild(super ID, 0);
1605:                SimpleNode typeNode = new SimpleNode(
1606:                        PnutsParserTreeConstants.JJTCLASSNAME);
1607:                SimpleNode pkg0 = new SimpleNode(
1608:                        PnutsParserTreeConstants.JJTPACKAGE);
1609:                pkg0.str = "pnuts";
1610:                SimpleNode pkg1 = new SimpleNode(
1611:                        PnutsParserTreeConstants.JJTPACKAGE);
1612:                pkg1.str = "compiler";
1613:                SimpleNode pkg2 = new SimpleNode(
1614:                        PnutsParserTreeConstants.JJTPACKAGE);
1615:                pkg2.str = "ClassGenerator$SuperCallProxy";
1616:                typeNode.jjtAddChild(pkg2, 2);
1617:                typeNode.jjtAddChild(pkg1, 1);
1618:                typeNode.jjtAddChild(pkg0, 0);
1619:                SimpleNode arg = new SimpleNode(
1620:                        PnutsParserTreeConstants.JJTLISTELEMENTS);
1621:                SimpleNode this Node = new SimpleNode(
1622:                        PnutsParserTreeConstants.JJTIDNODE);
1623:                this Node.str = THIS;
1624:                arg.jjtAddChild(this Node, 0);
1625:                super Creation.jjtAddChild(arg, 1);
1626:                super Creation.jjtAddChild(typeNode, 0);
1627:
1628:                paramList.jjtAddChild(this Param, 0);
1629:                this Param.jjtSetParent(paramList);
1630:
1631:                closure.jjtAddChild(block, 1);
1632:                closure.jjtAddChild(paramList, 0);
1633:                block.jjtSetParent(closure);
1634:                paramList.jjtSetParent(closure);
1635:
1636:                if (DEBUG) {
1637:                    System.out.println(closure.unparse());
1638:                }
1639:                return closure;
1640:
1641:            }
1642:
1643:            /*
1644:             * intermediate results:
1645:             *   methodIDs
1646:             *   signatureList
1647:             *   closure
1648:             */
1649:            static ClassGenerationResult generateClass(String className,
1650:                    String scriptFile,
1651:                    List/*<MethodSignatureInfo>*/methodSigs,
1652:                    List/*<ConstructorSignatureInfo>*/constructorSigs,
1653:                    List/*<FieldSignatureInfo>*/fieldSigs,
1654:                    Set super MethodNames, ClassSpec super classSpec,
1655:                    ClassSpec[] interfaces, List importNodes,
1656:                    Compiler compiler, CompileContext cc) {
1657:                Class super class = super classSpec.compileTimeClass;
1658:                String super className = super classSpec.className;
1659:                /*
1660:                 * instance fields
1661:                 */
1662:                Map typeMap = new HashMap();
1663:                for (int i = 0, n = fieldSigs.size(); i < n; i++) {
1664:                    FieldSignatureInfo finfo = (FieldSignatureInfo) fieldSigs
1665:                            .get(i);
1666:                    String fieldName = finfo.fieldName;
1667:
1668:                    updateMethodSignatureInfo(methodSigs, fieldName);
1669:                    updateMethodSignatureInfo(constructorSigs, fieldName);
1670:                    SimpleNode rhs = finfo.rhs;
1671:
1672:                    Class type = (finfo.typeNode != null) ? interpreter
1673:                            .resolveType(finfo.typeNode, cc) : Object.class;
1674:                    typeMap.put(fieldName, type);
1675:
1676:                }
1677:
1678:                Set/*<Signature>*/signatureSet = new HashSet();
1679:                for (int i = 0, n = methodSigs.size(); i < n; i++) {
1680:                    MethodSignatureInfo sig = (MethodSignatureInfo) methodSigs
1681:                            .get(i);
1682:                    Signature s = resolveSignature(sig, cc);
1683:                    Class[] parameterTypes;
1684:                    Class[] exceptionTypes;
1685:                    Class returnType;
1686:                    int modifiers;
1687:                    boolean resolved = s.isResolved();
1688:                    if (!resolved) {
1689:                        String methodName = s.getMethodName();
1690:                        int n_types = s.getParameterTypes().length;
1691:                        String prop = null;
1692:                        if (n_types == 0) {
1693:                            if (methodName.startsWith("get")) {
1694:                                prop = decapitalize(methodName.substring(3));
1695:                                Class t = (Class) typeMap.get(prop);
1696:                                Class t2 = s.getReturnType();
1697:                                if (t != null && (t2 == null || t2.equals(t))) {
1698:                                    returnType = t;
1699:                                    s.setReturnType(returnType);
1700:                                    s.setModifiers(Modifier.PUBLIC);
1701:                                }
1702:                            } else if (methodName.startsWith("is")) {
1703:                                prop = decapitalize(methodName.substring(2));
1704:                                Class t = (Class) typeMap.get(prop);
1705:                                Class t2 = s.getReturnType();
1706:                                if (t != null && t2 == null) {
1707:                                    returnType = t;
1708:                                    s.setReturnType(returnType);
1709:                                    s.setModifiers(Modifier.PUBLIC);
1710:                                }
1711:                            }
1712:                        } else if (n_types == 1 && methodName.startsWith("set")) {
1713:                            prop = decapitalize(methodName.substring(3));
1714:                            Class p = s.getParameterTypes()[0];
1715:                            Class t = (Class) typeMap.get(prop);
1716:                            Class t2 = s.getReturnType();
1717:                            if (t != null && p == null
1718:                                    && (t2 == null || t2.equals(void.class))) {
1719:                                parameterTypes = new Class[] { t };
1720:                                returnType = void.class;
1721:                                s.setReturnType(returnType);
1722:                                s.setParameterTypes(parameterTypes);
1723:                                s.setModifiers(Modifier.PUBLIC);
1724:                            }
1725:                        }
1726:                    }
1727:
1728:                    List/*<Method>*/methods = new ArrayList();
1729:                    Class[] interfaceTypes = null;
1730:                    if (interfaces != null) {
1731:                        interfaceTypes = new Class[interfaces.length];
1732:                        for (int j = 0; j < interfaces.length; j++) {
1733:                            interfaceTypes[j] = interfaces[j].compileTimeClass;
1734:                        }
1735:                    }
1736:                    if (super class != null
1737:                            && s.resolve(super class, interfaceTypes, methods)) {
1738:                        for (int j = 0, n2 = methods.size(); j < n2; j++) {
1739:                            Method first = (Method) methods.get(j);
1740:                            parameterTypes = first.getParameterTypes();
1741:                            returnType = first.getReturnType();
1742:                            exceptionTypes = first.getExceptionTypes();
1743:                            modifiers = Constants.ACC_PUBLIC;
1744:
1745:                            Signature s2 = (Signature) s.clone();
1746:                            s2.setParameterTypes(parameterTypes);
1747:                            s2.setReturnType(returnType);
1748:                            s2.setExceptionTypes(exceptionTypes);
1749:                            s2.setModifiers(Constants.ACC_PUBLIC);
1750:
1751:                            signatureSet.add(s2);
1752:                        }
1753:
1754:                    } else {
1755:                        parameterTypes = s.getParameterTypes();
1756:                        returnType = s.getReturnType();
1757:                        if (returnType == null) {
1758:                            returnType = Object.class;
1759:                        }
1760:                        exceptionTypes = new Class[0];
1761:                        for (int j = 0; j < parameterTypes.length; j++) {
1762:                            if (parameterTypes[j] == null) {
1763:                                parameterTypes[j] = Object.class;
1764:                            }
1765:                        }
1766:                        modifiers = Constants.ACC_PUBLIC;
1767:
1768:                        Signature s2 = (Signature) s.clone();
1769:                        s2.setParameterTypes(parameterTypes);
1770:                        s2.setReturnType(returnType);
1771:                        s2.setExceptionTypes(exceptionTypes);
1772:                        s2.setModifiers(Constants.ACC_PUBLIC);
1773:
1774:                        signatureSet.add(s2);
1775:                    }
1776:                }
1777:
1778:                List/*<String>*/methodIDs = new ArrayList();
1779:                List/*<Signature>*/signatureList = new ArrayList();
1780:                List/*<Signature>*/constructorSignatureList = new ArrayList();
1781:                List/*<SimpleNode>*/nodes = new ArrayList();
1782:
1783:                for (int i = 0, n = constructorSigs.size(); i < n; i++) {
1784:                    ConstructorSignatureInfo constructorSig = (ConstructorSignatureInfo) constructorSigs
1785:                            .get(i);
1786:                    Signature sig = resolveSignature(constructorSig, cc);
1787:                    constructorSignatureList.add(sig);
1788:                    List constructors = new ArrayList();
1789:                    Class[] parameterTypes;
1790:                    Class[] exceptionTypes;
1791:                    if (super class != null
1792:                            && sig.resolveAsConstructor(super class,
1793:                                    constructors)) {
1794:                        for (int j = 0, n2 = constructors.size(); j < n2; j++) {
1795:                            Constructor cons = (Constructor) constructors
1796:                                    .get(j);
1797:                            parameterTypes = cons.getParameterTypes();
1798:                            exceptionTypes = cons.getExceptionTypes();
1799:                            String constructorSignature = ClassFile
1800:                                    .signature(parameterTypes);
1801:
1802:                            Signature s2 = (Signature) sig.clone();
1803:                            s2.setParameterTypes(parameterTypes);
1804:                            s2.setReturnType(void.class);
1805:                            s2.setExceptionTypes(exceptionTypes);
1806:                            s2.setModifiers(Constants.ACC_PUBLIC);
1807:                            signatureSet.add(s2);
1808:                        }
1809:                    } else {
1810:                        parameterTypes = sig.getParameterTypes();
1811:                        exceptionTypes = new Class[0];
1812:                        for (int j = 0; j < parameterTypes.length; j++) {
1813:                            if (parameterTypes[j] == null) {
1814:                                parameterTypes[j] = Object.class;
1815:                            }
1816:                        }
1817:
1818:                        Signature s2 = (Signature) sig.clone();
1819:                        s2.setParameterTypes(parameterTypes);
1820:                        s2.setReturnType(void.class);
1821:                        s2.setExceptionTypes(exceptionTypes);
1822:                        s2.setModifiers(Constants.ACC_PUBLIC);
1823:
1824:                        signatureSet.add(s2);
1825:                    }
1826:                }
1827:
1828:                HashMap readableAttributes = new HashMap();
1829:                HashMap writableAttributes = new HashMap();
1830:
1831:                for (Iterator it = typeMap.entrySet().iterator(); it.hasNext();) {
1832:                    Map.Entry entry = (Map.Entry) it.next();
1833:                    String name = (String) entry.getKey();
1834:                    Class type = (Class) entry.getValue();
1835:                    Signature s = getterSignature(type, name);
1836:                    if (!signatureSet.contains(s)) {
1837:                        readableAttributes.put(name, type);
1838:                    }
1839:
1840:                    s = setterSignature(type, name);
1841:                    if (!signatureSet.contains(s)) {
1842:                        writableAttributes.put(name, type);
1843:                    }
1844:                }
1845:                if (DEBUG) {
1846:                    System.out.println("readableAttributes are "
1847:                            + readableAttributes);
1848:                    System.out.println("writableAttributes are "
1849:                            + writableAttributes);
1850:                }
1851:                for (Iterator it = signatureSet.iterator(); it.hasNext();) {
1852:                    Signature sig = (Signature) it.next();
1853:                    SimpleNode node = (SimpleNode) sig.nodeInfo;
1854:                    nodes.add(loadNode(saveNode(node)));
1855:                    String mid = sig.toJavaIdentifier();
1856:                    signatureList.add(sig);
1857:                    methodIDs.add(mid);
1858:                }
1859:                for (Iterator it = readableAttributes.entrySet().iterator(); it
1860:                        .hasNext();) {
1861:                    Map.Entry entry = (Map.Entry) it.next();
1862:                    String name = (String) entry.getKey();
1863:                    Class type = (Class) entry.getValue();
1864:                    SimpleNode getterNode = buildGetterNode(type, name);
1865:                    nodes.add(getterNode);
1866:                    Signature sig = new Signature(getterNode.str, type,
1867:                            new Class[0], new Class[0], Constants.ACC_PUBLIC);
1868:                    String mid = sig.toJavaIdentifier();
1869:                    signatureList.add(sig);
1870:                    methodIDs.add(mid);
1871:                }
1872:                for (Iterator it = writableAttributes.entrySet().iterator(); it
1873:                        .hasNext();) {
1874:                    Map.Entry entry = (Map.Entry) it.next();
1875:                    String name = (String) entry.getKey();
1876:                    Class type = (Class) entry.getValue();
1877:                    SimpleNode setterNode = buildSetterNode(type, name);
1878:                    nodes.add(setterNode);
1879:                    Signature sig = new Signature(setterNode.str, void.class,
1880:                            new Class[] { type }, new Class[0],
1881:                            Constants.ACC_PUBLIC);
1882:                    String mid = sig.toJavaIdentifier();
1883:                    signatureList.add(sig);
1884:                    methodIDs.add(mid);
1885:                }
1886:                if (DEBUG) {
1887:                    System.out.println("methodIDs = " + methodIDs);
1888:                    System.out.println("signatureList = " + signatureList);
1889:                }
1890:
1891:                SimpleNode closure = buildClosureNode(nodes, fieldSigs, typeMap);
1892:
1893:                /*
1894:                 * className, superclass, interfaces, superMethodNames,signatureList, constructorSignatureList, cc, methodIDs
1895:                 */
1896:                cc.cf = ClassGenerator.createClassFile(className,
1897:                        super classSpec, interfaces, super MethodNames);
1898:                ClassFile cf = cc.cf;
1899:
1900:                ClassGenerator.constructor(cf, super classSpec, compiler, cc,
1901:                        constructorSignatureList);
1902:
1903:                for (int i = 0, n = methodIDs.size(); i < n; i++) {
1904:                    String mid = (String) methodIDs.get(i);
1905:                    cf.addField(mid, "Lpnuts/lang/PnutsFunction;",
1906:                            Constants.ACC_PRIVATE);
1907:                    Signature sig = (Signature) signatureList.get(i);
1908:                    String methodName = sig.getMethodName();
1909:                    if (methodName != null) {
1910:                        ClassGenerator.defineMethod(cf,
1911:                                sig.getParameterTypes(), sig.getReturnType(),
1912:                                sig.getExceptionTypes(), sig.getModifiers(),
1913:                                sig.getMethodName(), sig.getMethodName()
1914:                                        + ClassFile.signature(sig
1915:                                                .getParameterTypes()), mid);
1916:                    }
1917:
1918:                }
1919:
1920:                cf.openMethod("__initialize", "()V", Constants.ACC_PRIVATE);
1921:                cf.add(Opcode.GETSTATIC, className, METHOD_FACTORY_FUNCTION,
1922:                        "Lpnuts/lang/PnutsFunction;");
1923:                cf.add(Opcode.ICONST_1);
1924:                cf.add(Opcode.ANEWARRAY, "java.lang.Object");
1925:                cf.add(Opcode.DUP);
1926:                cf.add(Opcode.ICONST_0);
1927:                cf.add(Opcode.ALOAD_0);
1928:                cf.add(Opcode.AASTORE);
1929:                cf.add(Opcode.GETSTATIC, className, "_context",
1930:                        "Lpnuts/lang/Context;");
1931:                cf.add(Opcode.INVOKEVIRTUAL, "pnuts.lang.PnutsFunction",
1932:                        "call", "([Ljava/lang/Object;Lpnuts/lang/Context;)",
1933:                        "Ljava/lang/Object;");
1934:                cf.add(Opcode.CHECKCAST, "[Ljava/lang/Object;");
1935:                int array = cf.getLocal();
1936:                cf.storeLocal(array);
1937:
1938:                for (int i = 0; i < methodIDs.size(); i++) {
1939:                    cf.add(Opcode.ALOAD_0);
1940:                    cf.loadLocal(array);
1941:                    cf.pushInteger(i);
1942:                    cf.add(Opcode.AALOAD);
1943:                    cf.add(Opcode.CHECKCAST, "pnuts.lang.PnutsFunction");
1944:                    cf.add(Opcode.PUTFIELD, className, (String) methodIDs
1945:                            .get(i), "Lpnuts/lang/PnutsFunction;");
1946:                }
1947:                cf.add(Opcode.RETURN);
1948:                cf.closeMethod();
1949:
1950:                /*
1951:                 * public static void attach(Context);
1952:                 */
1953:                cf.openMethod("attach", "(Lpnuts/lang/Context;)V",
1954:                        (short) (Constants.ACC_PUBLIC | Constants.ACC_STATIC));
1955:                cc.setContextIndex(0);
1956:                cc.hasAttachMethod = true;
1957:                cf.add(Opcode.ALOAD_0);
1958:                cf.add(Opcode.PUTSTATIC, className, "_context",
1959:                        "Lpnuts/lang/Context;");
1960:                cf.add(Opcode.RETURN);
1961:                cf.closeMethod();
1962:
1963:                /*
1964:                 * public static void attach(Context, PnutsFunction);
1965:                 */
1966:                cf.openMethod("attach",
1967:                        "(Lpnuts/lang/Context;Lpnuts/lang/PnutsFunction;)V",
1968:                        (short) (Constants.ACC_PUBLIC | Constants.ACC_STATIC));
1969:                cc.setContextIndex(0);
1970:                cc.hasAttachMethod = true;
1971:                cf.add(Opcode.ALOAD_0);
1972:                cf.add(Opcode.PUTSTATIC, className, "_context",
1973:                        "Lpnuts/lang/Context;");
1974:                cf.add(Opcode.ALOAD_1);
1975:                cf.add(Opcode.PUTSTATIC, className, METHOD_FACTORY_FUNCTION,
1976:                        "Lpnuts/lang/PnutsFunction;");
1977:                cf.add(Opcode.RETURN);
1978:                cf.closeMethod();
1979:
1980:                /*
1981:                 * static {}
1982:                 */
1983:                compiler.staticBlock(cf, (scriptFile != null) ? closure : null,
1984:                        cc);
1985:
1986:                ClassGenerationResult result = new ClassGenerationResult();
1987:                result.classFile = cf;
1988:                result.closureNode = closure;
1989:                return result;
1990:            }
1991:
1992:            static SimpleNode buildSetterNode(Class type, String name) {
1993:                SimpleNode n = new SimpleNode(
1994:                        PnutsParserTreeConstants.JJTFUNCTIONSTATEMENT);
1995:                SimpleNode p = new SimpleNode(
1996:                        PnutsParserTreeConstants.JJTPARAMLIST);
1997:                SimpleNode p0 = new SimpleNode(
1998:                        PnutsParserTreeConstants.JJTPARAM);
1999:                p0.str = ("_" + name).intern();
2000:                p.jjtAddChild(p0, 0);
2001:                SimpleNode block = new SimpleNode(
2002:                        PnutsParserTreeConstants.JJTBLOCK);
2003:                SimpleNode assign = new SimpleNode(
2004:                        PnutsParserTreeConstants.JJTASSIGNMENT);
2005:                SimpleNode lhs = new SimpleNode(
2006:                        PnutsParserTreeConstants.JJTIDNODE);
2007:                SimpleNode rhs = new SimpleNode(
2008:                        PnutsParserTreeConstants.JJTIDNODE);
2009:                lhs.str = name;
2010:                rhs.str = p0.str;
2011:                assign.jjtAddChild(rhs, 1);
2012:                assign.jjtAddChild(lhs, 0);
2013:                block.jjtAddChild(assign, 0);
2014:                n.jjtAddChild(block, 1);
2015:                n.jjtAddChild(p, 0);
2016:                n.str = ("set" + Character.toUpperCase(name.charAt(0)) + name
2017:                        .substring(1)).intern();
2018:                return n;
2019:            }
2020:
2021:            static SimpleNode buildGetterNode(Class type, String name) {
2022:                SimpleNode n = new SimpleNode(
2023:                        PnutsParserTreeConstants.JJTFUNCTIONSTATEMENT);
2024:                SimpleNode p = new SimpleNode(
2025:                        PnutsParserTreeConstants.JJTPARAMLIST);
2026:                SimpleNode block = new SimpleNode(
2027:                        PnutsParserTreeConstants.JJTBLOCK);
2028:                SimpleNode id = new SimpleNode(
2029:                        PnutsParserTreeConstants.JJTIDNODE);
2030:                id.str = name;
2031:                block.jjtAddChild(id, 0);
2032:                n.jjtAddChild(block, 1);
2033:                n.jjtAddChild(p, 0);
2034:                String prefix = (type == boolean.class) ? "is" : "get";
2035:                n.str = (prefix + Character.toUpperCase(name.charAt(0)) + name
2036:                        .substring(1)).intern();
2037:                return n;
2038:            }
2039:
2040:            static String capitalize(String name) {
2041:                if (name == null || name.length() == 0) {
2042:                    return name;
2043:                }
2044:                return name.substring(0, 1).toUpperCase() + name.substring(1);
2045:            }
2046:
2047:            static String decapitalize(String name) {
2048:                if (name == null || name.length() == 0) {
2049:                    return name;
2050:                }
2051:                if (name.length() > 1 && Character.isUpperCase(name.charAt(1))
2052:                        && Character.isUpperCase(name.charAt(0))) {
2053:                    return name;
2054:                }
2055:                char chars[] = name.toCharArray();
2056:                chars[0] = Character.toLowerCase(chars[0]);
2057:                return new String(chars);
2058:            }
2059:
2060:            static final Class[] NO_PARAM = new Class[0];
2061:
2062:            public static Signature getterSignature(Class type, String name) {
2063:                String prefix;
2064:                if (type == boolean.class) {
2065:                    prefix = "is";
2066:                } else {
2067:                    prefix = "get";
2068:                }
2069:                return new Signature(prefix + capitalize(name), type, NO_PARAM,
2070:                        NO_PARAM, Modifier.PUBLIC);
2071:            }
2072:
2073:            public static Signature setterSignature(Class type, String name) {
2074:                String prefix = "set";
2075:                return new Signature(prefix + capitalize(name), void.class,
2076:                        new Class[] { type }, NO_PARAM, Modifier.PUBLIC);
2077:            }
2078:
2079:            /*
2080:             * classScript->generateClass
2081:             */
2082:            void generateClass(SimpleNode classDefBody, String className,
2083:                    ClassSpec super classSpec, List/*<ClassSpec>*/interfaces,
2084:                    List importNodes, CompileContext cc) {
2085:                String scriptFile = null;
2086:                if (cc.scriptSource instanceof  URL) {
2087:                    String file = ((URL) cc.scriptSource).getFile();
2088:                    int idx = file.lastIndexOf('/');
2089:                    if (idx < 0) {
2090:                        scriptFile = file;
2091:                    } else {
2092:                        scriptFile = file.substring(idx + 1);
2093:                    }
2094:                } else if (cc.scriptSource instanceof  File) {
2095:                    scriptFile = ((File) cc.scriptSource).getName();
2096:                }
2097:                cc.constClassName = className;
2098:
2099:                Class super class = super classSpec.compileTimeClass;
2100:                ClassSpec[] interfaceArray;
2101:                if (interfaces != null) {
2102:                    interfaceArray = (ClassSpec[]) interfaces
2103:                            .toArray(new ClassSpec[interfaces.size()]);
2104:                } else {
2105:                    interfaceArray = new ClassSpec[0];
2106:                }
2107:
2108:                ClassGenerator.transformClassDefBody(classDefBody, super class);
2109:
2110:                generateClass(className, scriptFile, classDefBody,
2111:                        super classSpec, interfaceArray, importNodes, this , cc);
2112:            }
2113:
2114:            public Object classScript(SimpleNode node, Context context) {
2115:                int num = node.jjtGetNumChildren();
2116:                List importNodes = new ArrayList();
2117:                SimpleNode packageNode = null;
2118:                for (int i = 0; i < num; i++) {
2119:                    SimpleNode n = node.jjtGetChild(i);
2120:                    if (n.id == PnutsParserTreeConstants.JJTPACKAGESTATEMENT) {
2121:                        packageNode = n;
2122:                    } else if (n.id == PnutsParserTreeConstants.JJTIMPORT) {
2123:                        importNodes.add(n);
2124:                        n.accept(interpreter, context);
2125:                    } else if (n.id == PnutsParserTreeConstants.JJTCLASSDEF) {
2126:                        String className;
2127:                        if (packageNode != null) {
2128:                            className = packageName(packageNode) + "."
2129:                                    + getClassName(n.jjtGetChild(0));
2130:                        } else {
2131:                            className = getClassName(n.jjtGetChild(0));
2132:                        }
2133:
2134:                        SimpleNode extendsNode = n.jjtGetChild(1);
2135:                        String super class = null;
2136:                        ClassSpec super classSpec;
2137:                        if (extendsNode.jjtGetNumChildren() == 1) {
2138:                            SimpleNode n0 = extendsNode.jjtGetChild(0);
2139:                            super classSpec = ClassSpec.create(getClassName(n0),
2140:                                    context);
2141:                            super class = super classSpec.className;
2142:                        } else {
2143:                            super class = "java.lang.Object";
2144:                            super classSpec = ClassSpec.create(super class,
2145:                                    context);
2146:                        }
2147:
2148:                        List interfaces = null;
2149:                        SimpleNode implements Node = n.jjtGetChild(2);
2150:                        int nc = implements Node.jjtGetNumChildren();
2151:                        if (nc > 0) {
2152:                            interfaces = new ArrayList();
2153:                            for (int j = 0; j < nc; j++) {
2154:                                SimpleNode nj = implements Node.jjtGetChild(j);
2155:                                String typename = getClassName(nj);
2156:                                ClassSpec spec = ClassSpec.create(typename,
2157:                                        context);
2158:                                interfaces.add(spec);
2159:                            }
2160:                        }
2161:                        SimpleNode classDefBody = n.jjtGetChild(3);
2162:                        this .className = className;
2163:                        CompileContext cc = (CompileContext) context;
2164:
2165:                        generateClass(classDefBody, className, super classSpec,
2166:                                interfaces, importNodes, cc);
2167:                        return null;
2168:                    } else {
2169:                        throw new InternalError();
2170:                    }
2171:                }
2172:                throw new InternalError();
2173:            }
2174:
2175:            static String packageName(SimpleNode node) {
2176:                StringBuffer sbuf = new StringBuffer();
2177:                sbuf.append(node.jjtGetChild(0).str);
2178:                for (int i = 1, n = node.jjtGetNumChildren(); i < n; i++) {
2179:                    sbuf.append('.');
2180:                    sbuf.append(node.jjtGetChild(i).str);
2181:                }
2182:                return sbuf.toString();
2183:            }
2184:
2185:            public Object packageNode(SimpleNode node, Context context) {
2186:                CompileContext cc = (CompileContext) context;
2187:                ClassFile cf = cc.cf;
2188:                int ctx = cc.getContextIndex();
2189:                int n = node.jjtGetNumChildren();
2190:                cf.add(Opcode.GETSTATIC, "pnuts.lang.PnutsFunction", "PACKAGE",
2191:                        "Lpnuts/lang/PnutsFunction;");
2192:                if (n == 0) {
2193:                    if ("(".equals(node.str)) {
2194:                        cf.add(Opcode.GETSTATIC, className, "NO_PARAM",
2195:                                "[Ljava/lang/Object;");
2196:                        cf.loadLocal(ctx);
2197:                        cf.add(Opcode.INVOKEVIRTUAL,
2198:                                "pnuts.lang.PnutsFunction", "call",
2199:                                "([Ljava/lang/Object;Lpnuts/lang/Context;)",
2200:                                "Ljava/lang/Object;");
2201:                    } else {
2202:                        return null;
2203:                    }
2204:                } else {
2205:                    SimpleNode c = node.jjtGetChild(0);
2206:                    cf.add(Opcode.ICONST_1);
2207:                    cf.add(Opcode.ANEWARRAY, "java.lang.Object");
2208:                    cf.add(Opcode.DUP);
2209:                    cf.add(Opcode.ICONST_0);
2210:                    if (n == 1 && c.id != PnutsParserTreeConstants.JJTPACKAGE) { // package("...")
2211:                        c.accept(this , context);
2212:                    } else {
2213:                        cf.add(Opcode.LDC, cf.addConstant(packageName(node)));
2214:                    }
2215:                    cf.add(Opcode.AASTORE);
2216:                    cf.loadLocal(ctx);
2217:                    cf.add(Opcode.INVOKEVIRTUAL, "pnuts.lang.PnutsFunction",
2218:                            "call",
2219:                            "([Ljava/lang/Object;Lpnuts/lang/Context;)",
2220:                            "Ljava/lang/Object;");
2221:                }
2222:                return null;
2223:            }
2224:
2225:            public Object importNode(SimpleNode node, Context context) {
2226:                CompileContext cc = (CompileContext) context;
2227:                ClassFile cf = cc.cf;
2228:                int ctx = cc.getContextIndex();
2229:
2230:                SimpleNode p = node.jjtGetParent();
2231:                if (p != null
2232:                        && p.id == PnutsParserTreeConstants.JJTEXPRESSIONLIST) {
2233:                    node.accept(interpreter, context);
2234:                }
2235:
2236:                String t2 = node.str;
2237:                int n = node.jjtGetNumChildren();
2238:                if (n == 0) {
2239:                    if ("*".equals(t2)) {
2240:                        cf.loadLocal(ctx);
2241:                        cf.add(Opcode.LDC, cf.addConstant("*"));
2242:                        cf
2243:                                .add(
2244:                                        Opcode.INVOKESTATIC,
2245:                                        "pnuts.lang.Runtime",
2246:                                        "addImport",
2247:                                        "(Lpnuts/lang/Context;Ljava/lang/String;)",
2248:                                        "V");
2249:                        cf.add(Opcode.ACONST_NULL);
2250:                    } else if ("(".equals(t2)) {
2251:                        cf.add(Opcode.GETSTATIC, "pnuts.lang.PnutsFunction",
2252:                                "IMPORT", "Lpnuts/lang/PnutsFunction;");
2253:                        cf.add(Opcode.GETSTATIC, className, "NO_PARAM",
2254:                                "[Ljava/lang/Object;");
2255:                        cf.loadLocal(ctx);
2256:                        cf.add(Opcode.INVOKEVIRTUAL,
2257:                                "pnuts.lang.PnutsFunction", "call",
2258:                                "([Ljava/lang/Object;Lpnuts/lang/Context;)",
2259:                                "Ljava/lang/Object;");
2260:                    } else {
2261:                        cf.add(Opcode.GETSTATIC, "pnuts.lang.PnutsFunction",
2262:                                "IMPORT", "Lpnuts/lang/PnutsFunction;");
2263:                    }
2264:                    return null;
2265:                }
2266:                if (n == 1
2267:                        && node.jjtGetChild(0).id != PnutsParserTreeConstants.JJTPACKAGE) { // import(...)
2268:                    int arg = cf.getLocal();
2269:                    accept(node, 0, context);
2270:                    cf.storeLocal(arg);
2271:                    cf.add(Opcode.GETSTATIC, "pnuts.lang.PnutsFunction",
2272:                            "IMPORT", "Lpnuts/lang/PnutsFunction;");
2273:                    cf.add(Opcode.ICONST_1);
2274:                    cf.add(Opcode.ANEWARRAY, "java.lang.Object");
2275:                    cf.add(Opcode.DUP);
2276:                    cf.add(Opcode.ICONST_0);
2277:                    cf.loadLocal(arg);
2278:                    cf.freeLocal(arg);
2279:                    cf.add(Opcode.AASTORE);
2280:                    cf.loadLocal(ctx);
2281:                    cf.add(Opcode.INVOKEVIRTUAL, "pnuts.lang.PnutsFunction",
2282:                            "call",
2283:                            "([Ljava/lang/Object;Lpnuts/lang/Context;)",
2284:                            "Ljava/lang/Object;");
2285:                    return null;
2286:                }
2287:                StringBuffer sbuf = new StringBuffer();
2288:                sbuf.append(node.jjtGetChild(0).str);
2289:                for (int i = 1; i < n; i++) {
2290:                    sbuf.append('.');
2291:                    sbuf.append(node.jjtGetChild(i).str);
2292:                }
2293:                cf.loadLocal(ctx);
2294:                if (node.info != null) { // static import
2295:                    cf.add(Opcode.LDC, cf.addConstant(sbuf.toString()));
2296:                    cf.add(t2 == null ? Opcode.ICONST_0 : Opcode.ICONST_1);
2297:                    cf.add(Opcode.INVOKESTATIC, "pnuts.lang.Runtime",
2298:                            "addStaticMembers",
2299:                            "(Lpnuts/lang/Context;Ljava/lang/String;Z)", "V");
2300:                } else {
2301:                    if (t2 != null) {
2302:                        sbuf.append(".*");
2303:                    }
2304:                    cf.add(Opcode.LDC, cf.addConstant(sbuf.toString()));
2305:                    cf.add(Opcode.INVOKESTATIC, "pnuts.lang.Runtime",
2306:                            "addImport",
2307:                            "(Lpnuts/lang/Context;Ljava/lang/String;)", "V");
2308:                }
2309:                cf.add(Opcode.ACONST_NULL);
2310:                return null;
2311:            }
2312:
2313:            void booleanCheck(int id, ClassFile cf, Context context) {
2314:                if (id != PnutsParserTreeConstants.JJTTRUENODE
2315:                        && id != PnutsParserTreeConstants.JJTFALSENODE
2316:                        && id != PnutsParserTreeConstants.JJTLENODE
2317:                        && id != PnutsParserTreeConstants.JJTLTNODE
2318:                        && id != PnutsParserTreeConstants.JJTGENODE
2319:                        && id != PnutsParserTreeConstants.JJTGTNODE
2320:                        && id != PnutsParserTreeConstants.JJTEQUALNODE
2321:                        && id != PnutsParserTreeConstants.JJTNOTEQNODE
2322:                        && id != PnutsParserTreeConstants.JJTINSTANCEOFEXPRESSION
2323:                        && id != PnutsParserTreeConstants.JJTORNODE
2324:                        && id != PnutsParserTreeConstants.JJTANDNODE
2325:                        && id != PnutsParserTreeConstants.JJTNOTNODE) {
2326:                    int index = cf.getLocal();
2327:                    cf.add(Opcode.DUP);
2328:                    cf.storeLocal(index);
2329:
2330:                    cf.add(Opcode.INSTANCEOF, "java.lang.Boolean");
2331:                    Label l_next = cf.getLabel();
2332:                    cf.add(Opcode.IFNE, l_next);
2333:                    Label l_next_2 = cf.getLabel();
2334:
2335:                    // disable boolean check
2336:                    // error(cf, "boolean.expected", new int[] { index }, (CompileContext) context);
2337:
2338:                    cf.loadLocal(index);
2339:                    cf.add(Opcode.INVOKESTATIC, "pnuts.lang.Runtime",
2340:                            "toBoolean", "(Ljava/lang/Object;)",
2341:                            "Ljava/lang/Boolean;");
2342:                    cf.add(Opcode.GOTO, l_next_2);
2343:                    l_next.fix();
2344:                    cf.loadLocal(index);
2345:                    l_next_2.fix();
2346:                    cf.freeLocal(index);
2347:                }
2348:            }
2349:
2350:            public Object logAndNode(SimpleNode node, Context context) {
2351:                CompileContext cc = (CompileContext) context;
2352:                ClassFile cf = cc.cf;
2353:                addLineInfo(cc, cc.getContextIndex(), node);
2354:
2355:                accept(node, 0, context);
2356:                booleanCheck(node.jjtGetChild(0).id, cf, context);
2357:                cf.add(Opcode.CHECKCAST, "java.lang.Boolean");
2358:                int tgt1 = cf.getLocal();
2359:                cf.add(Opcode.DUP);
2360:                cf.storeLocal(tgt1);
2361:
2362:                cf.add(Opcode.INVOKEVIRTUAL, "java.lang.Boolean",
2363:                        "booleanValue", "()", "Z");
2364:                Label l_else = cf.getLabel();
2365:                cf.add(Opcode.IFEQ, l_else);
2366:                accept(node, 1, context);
2367:                booleanCheck(node.jjtGetChild(1).id, cf, context);
2368:                Label next = cf.getLabel();
2369:                cf.add(Opcode.GOTO, next);
2370:                l_else.fix();
2371:                cf.popStack();
2372:                cf.loadLocal(tgt1);
2373:                next.fix();
2374:                cf.freeLocal(tgt1);
2375:                return null;
2376:            }
2377:
2378:            public Object logOrNode(SimpleNode node, Context context) {
2379:                CompileContext cc = (CompileContext) context;
2380:                ClassFile cf = cc.cf;
2381:                addLineInfo(cc, cc.getContextIndex(), node);
2382:
2383:                accept(node, 0, context);
2384:                booleanCheck(node.jjtGetChild(0).id, cf, context);
2385:                cf.add(Opcode.CHECKCAST, "java.lang.Boolean");
2386:                int tgt1 = cf.getLocal();
2387:                cf.add(Opcode.DUP);
2388:                cf.storeLocal(tgt1);
2389:
2390:                cf.add(Opcode.INVOKEVIRTUAL, "java.lang.Boolean",
2391:                        "booleanValue", "()", "Z");
2392:                Label l_else = cf.getLabel();
2393:                cf.add(Opcode.IFNE, l_else);
2394:                accept(node, 1, context);
2395:                booleanCheck(node.jjtGetChild(1).id, cf, context);
2396:                Label next = cf.getLabel();
2397:                cf.add(Opcode.GOTO, next);
2398:                l_else.fix();
2399:                cf.popStack();
2400:                cf.loadLocal(tgt1);
2401:                next.fix();
2402:                cf.freeLocal(tgt1);
2403:                return null;
2404:            }
2405:
2406:            public Object logNotNode(SimpleNode node, Context context) {
2407:                CompileContext cc = (CompileContext) context;
2408:                ClassFile cf = cc.cf;
2409:                addLineInfo(cc, cc.getContextIndex(), node);
2410:
2411:                accept(node, 0, context);
2412:                booleanCheck(node.jjtGetChild(0).id, cf, context);
2413:                cf.add(Opcode.CHECKCAST, "java.lang.Boolean");
2414:                cf.add(Opcode.INVOKEVIRTUAL, "java.lang.Boolean",
2415:                        "booleanValue", "()", "Z");
2416:                Label t = cf.getLabel();
2417:                Label next = cf.getLabel();
2418:                cf.add(Opcode.IFEQ, t);
2419:                cf.add(Opcode.GETSTATIC, "java.lang.Boolean", "FALSE",
2420:                        "Ljava/lang/Boolean;");
2421:                cf.add(Opcode.GOTO, next);
2422:                t.fix();
2423:                cf.popStack();
2424:                cf.add(Opcode.GETSTATIC, "java.lang.Boolean", "TRUE",
2425:                        "Ljava/lang/Boolean;");
2426:                next.fix();
2427:                return null;
2428:            }
2429:
2430:            boolean canConstantFold(SimpleNode node) {
2431:                return _constantFolding && isConstant(node.jjtGetChild(0))
2432:                        && isConstant(node.jjtGetChild(1));
2433:            }
2434:
2435:            static boolean isConstant(SimpleNode node) {
2436:                switch (node.id) {
2437:                case PnutsParserTreeConstants.JJTINTEGERNODE: {
2438:                    Object[] p = (Object[]) node.info;
2439:                    return p[1] == null;
2440:                }
2441:                case PnutsParserTreeConstants.JJTFLOATINGNODE: {
2442:                    Object[] p = (Object[]) node.info;
2443:                    return p[1] == null;
2444:                }
2445:                case PnutsParserTreeConstants.JJTSTRINGNODE:
2446:                case PnutsParserTreeConstants.JJTCHARACTERNODE:
2447:                case PnutsParserTreeConstants.JJTTRUENODE:
2448:                case PnutsParserTreeConstants.JJTFALSENODE:
2449:                case PnutsParserTreeConstants.JJTNULLNODE:
2450:                    return true;
2451:                case PnutsParserTreeConstants.JJTLENODE:
2452:                case PnutsParserTreeConstants.JJTLTNODE:
2453:                case PnutsParserTreeConstants.JJTGENODE:
2454:                case PnutsParserTreeConstants.JJTGTNODE:
2455:                case PnutsParserTreeConstants.JJTEQUALNODE:
2456:                case PnutsParserTreeConstants.JJTNOTEQNODE:
2457:                case PnutsParserTreeConstants.JJTANDNODE:
2458:                case PnutsParserTreeConstants.JJTORNODE:
2459:                case PnutsParserTreeConstants.JJTXORNODE:
2460:                case PnutsParserTreeConstants.JJTLOGORNODE:
2461:                case PnutsParserTreeConstants.JJTLOGANDNODE:
2462:                case PnutsParserTreeConstants.JJTSHIFTLEFTNODE:
2463:                case PnutsParserTreeConstants.JJTSHIFTRIGHTNODE:
2464:                case PnutsParserTreeConstants.JJTSHIFTARITHMETICNODE:
2465:                case PnutsParserTreeConstants.JJTADDNODE:
2466:                case PnutsParserTreeConstants.JJTSUBTRACTNODE:
2467:                case PnutsParserTreeConstants.JJTMULTNODE:
2468:                case PnutsParserTreeConstants.JJTDIVIDENODE:
2469:                case PnutsParserTreeConstants.JJTMODNODE:
2470:                    return isConstant(node.jjtGetChild(0))
2471:                            && isConstant(node.jjtGetChild(1));
2472:                case PnutsParserTreeConstants.JJTNEGATIVENODE:
2473:                case PnutsParserTreeConstants.JJTNOTNODE:
2474:                case PnutsParserTreeConstants.JJTLOGNOTNODE:
2475:                    return isConstant(node.jjtGetChild(0));
2476:                default:
2477:                    return false;
2478:                }
2479:            }
2480:
2481:            Object binary(String operator, SimpleNode node, Context context) {
2482:                CompileContext cc = (CompileContext) context;
2483:                ClassFile cf = cc.cf;
2484:                int ctx = cc.getContextIndex();
2485:                addLineInfo(cc, ctx, node);
2486:
2487:                SimpleNode n0 = node.jjtGetChild(0);
2488:                SimpleNode n1 = node.jjtGetChild(1);
2489:                if (node.getAttribute("hasTryStatement") != null) {
2490:                    int arg0 = cf.getLocal();
2491:                    int arg1 = cf.getLocal();
2492:                    n0.accept(this , context);
2493:                    cf.storeLocal(arg0);
2494:                    n1.accept(this , context);
2495:                    cf.storeLocal(arg1);
2496:                    cf.loadLocal(arg0);
2497:                    cf.loadLocal(arg1);
2498:                    cf.freeLocal(arg0);
2499:                    cf.freeLocal(arg1);
2500:                } else {
2501:                    n0.accept(this , context);
2502:                    n1.accept(this , context);
2503:                }
2504:                cf.loadLocal(ctx);
2505:                cf
2506:                        .add(
2507:                                Opcode.INVOKESTATIC,
2508:                                "pnuts.lang.Runtime",
2509:                                operator,
2510:                                "(Ljava/lang/Object;Ljava/lang/Object;Lpnuts/lang/Context;)",
2511:                                "Ljava/lang/Object;");
2512:                return null;
2513:            }
2514:
2515:            public Object shiftLeftNode(SimpleNode node, Context context) {
2516:                try {
2517:                    if (canConstantFold(node)) {
2518:                        addConstant(interpreter.shiftLeftNode(node, context),
2519:                                context);
2520:                        return null;
2521:                    }
2522:                } catch (Exception e) {
2523:                }
2524:                return binary("shiftLeft", node, context);
2525:            }
2526:
2527:            public Object shiftRightNode(SimpleNode node, Context context) {
2528:                try {
2529:                    if (canConstantFold(node)) {
2530:                        addConstant(interpreter.shiftRightNode(node, context),
2531:                                context);
2532:                        return null;
2533:                    }
2534:                } catch (Exception e) {
2535:                }
2536:                return binary("shiftRight", node, context);
2537:            }
2538:
2539:            public Object shiftArithmeticNode(SimpleNode node, Context context) {
2540:                try {
2541:                    if (canConstantFold(node)) {
2542:                        addConstant(interpreter.shiftArithmeticNode(node,
2543:                                context), context);
2544:                        return null;
2545:                    }
2546:                } catch (Exception e) {
2547:                }
2548:                return binary("shiftArithmetic", node, context);
2549:            }
2550:
2551:            static void addConstant(Object n, Context context) {
2552:                CompileContext cc = (CompileContext) context;
2553:                ClassFile cf = cc.cf;
2554:                if (n instanceof  String) {
2555:                    cf.add(Opcode.LDC, cf.addConstant((String) n));
2556:                    return;
2557:                }
2558:                String assoc = (String) cc.constants.get(n);
2559:                if (assoc == null) {
2560:                    assoc = gensym(cc);
2561:                    cc.constants.put(n, assoc);
2562:                }
2563:                if (n instanceof  Integer) {
2564:                    cf.add(Opcode.GETSTATIC, cc.constClassName, assoc,
2565:                            "Ljava/lang/Integer;");
2566:                } else if (n instanceof  Long) {
2567:                    cf.add(Opcode.GETSTATIC, cc.constClassName, assoc,
2568:                            "Ljava/lang/Long;");
2569:                } else if (n instanceof  Byte) {
2570:                    cf.add(Opcode.GETSTATIC, cc.constClassName, assoc,
2571:                            "Ljava/lang/Byte;");
2572:                } else if (n instanceof  BigInteger) {
2573:                    cf.add(Opcode.GETSTATIC, cc.constClassName, assoc,
2574:                            "Ljava/math/BigInteger;");
2575:                } else if (n instanceof  BigDecimal) {
2576:                    cf.add(Opcode.GETSTATIC, cc.constClassName, assoc,
2577:                            "Ljava/math/BigDecimal;");
2578:                } else if (n instanceof  Float) {
2579:                    cf.add(Opcode.GETSTATIC, cc.constClassName, assoc,
2580:                            "Ljava/lang/Float;");
2581:                } else if (n instanceof  Double) {
2582:                    cf.add(Opcode.GETSTATIC, cc.constClassName, assoc,
2583:                            "Ljava/lang/Double;");
2584:                } else {
2585:                    throw new InternalError("compiler error");
2586:                }
2587:
2588:            }
2589:
2590:            public Object addNode(SimpleNode node, Context context) {
2591:                try {
2592:                    if (canConstantFold(node)) {
2593:                        addConstant(interpreter.addNode(node, context), context);
2594:                        return null;
2595:                    }
2596:                } catch (Exception e) {
2597:                }
2598:                return binary("add", node, context);
2599:            }
2600:
2601:            public Object subtractNode(SimpleNode node, Context context) {
2602:                try {
2603:                    if (canConstantFold(node)) {
2604:                        addConstant(interpreter.subtractNode(node, context),
2605:                                context);
2606:                        return null;
2607:                    }
2608:                } catch (Exception e) {
2609:                }
2610:                return binary("subtract", node, context);
2611:            }
2612:
2613:            public Object multNode(SimpleNode node, Context context) {
2614:                try {
2615:                    if (canConstantFold(node)) {
2616:                        addConstant(interpreter.multNode(node, context),
2617:                                context);
2618:                        return null;
2619:                    }
2620:                } catch (Exception e) {
2621:                }
2622:                return binary("multiply", node, context);
2623:            }
2624:
2625:            public Object divideNode(SimpleNode node, Context context) {
2626:                try {
2627:                    if (canConstantFold(node)) {
2628:                        addConstant(interpreter.divideNode(node, context),
2629:                                context);
2630:                        return null;
2631:                    }
2632:                } catch (Exception e) {
2633:                }
2634:                return binary("divide", node, context);
2635:            }
2636:
2637:            public Object modNode(SimpleNode node, Context context) {
2638:                try {
2639:                    if (canConstantFold(node)) {
2640:                        addConstant(interpreter.modNode(node, context), context);
2641:                        return null;
2642:                    }
2643:                } catch (Exception e) {
2644:                }
2645:                return binary("mod", node, context);
2646:            }
2647:
2648:            public Object xorNode(SimpleNode node, Context context) {
2649:                try {
2650:                    if (canConstantFold(node)) {
2651:                        Object xor = interpreter.xorNode(node, context);
2652:                        if (xor instanceof  Number) {
2653:                            addConstant(xor, context);
2654:                            return null;
2655:                        } else if (xor instanceof  Boolean) {
2656:                            CompileContext cc = (CompileContext) context;
2657:                            ClassFile cf = cc.cf;
2658:                            if (((Boolean) xor).booleanValue()) {
2659:                                cf.add(Opcode.ICONST_0);
2660:                            } else {
2661:                                cf.add(Opcode.ICONST_1);
2662:                            }
2663:                        }
2664:                    }
2665:                } catch (Exception e) {
2666:                }
2667:                return binary("xor", node, context);
2668:            }
2669:
2670:            public Object orNode(SimpleNode node, Context context) {
2671:                try {
2672:                    if (canConstantFold(node)) {
2673:                        Object or = interpreter.orNode(node, context);
2674:                        if (or instanceof  Number) {
2675:                            addConstant(or, context);
2676:                            return null;
2677:                        } else if (or instanceof  Boolean) {
2678:                            CompileContext cc = (CompileContext) context;
2679:                            ClassFile cf = cc.cf;
2680:                            if (((Boolean) or).booleanValue()) {
2681:                                cf.add(Opcode.ICONST_0);
2682:                            } else {
2683:                                cf.add(Opcode.ICONST_1);
2684:                            }
2685:                        }
2686:                    }
2687:                } catch (Exception e) {
2688:                }
2689:                return binary("or", node, context);
2690:            }
2691:
2692:            public Object andNode(SimpleNode node, Context context) {
2693:                try {
2694:                    if (canConstantFold(node)) {
2695:                        Object and = interpreter.andNode(node, context);
2696:                        if (and instanceof  Number) {
2697:                            addConstant(and, context);
2698:                            return null;
2699:                        } else if (and instanceof  Boolean) {
2700:                            if (((Boolean) and).booleanValue()) {
2701:                                CompileContext cc = (CompileContext) context;
2702:                                ClassFile cf = cc.cf;
2703:                                if (((Boolean) and).booleanValue()) {
2704:                                    cf.add(Opcode.ICONST_0);
2705:                                } else {
2706:                                    cf.add(Opcode.ICONST_1);
2707:                                }
2708:                            }
2709:                        }
2710:                    }
2711:                } catch (Exception e) {
2712:                }
2713:                return binary("and", node, context);
2714:            }
2715:
2716:            Object unary(String operator, SimpleNode node, Context context) {
2717:                CompileContext cc = (CompileContext) context;
2718:                int ctx = cc.getContextIndex();
2719:                ClassFile cf = cc.cf;
2720:                accept(node, 0, context);
2721:                cf.loadLocal(ctx);
2722:                cf.add(Opcode.INVOKESTATIC, "pnuts.lang.Runtime", operator,
2723:                        "(Ljava/lang/Object;Lpnuts/lang/Context;)",
2724:                        "Ljava/lang/Object;");
2725:                return null;
2726:            }
2727:
2728:            public Object negativeNode(SimpleNode node, Context context) {
2729:                return unary("negate", node, context);
2730:            }
2731:
2732:            public Object notNode(SimpleNode node, Context context) {
2733:                return unary("not", node, context);
2734:            }
2735:
2736:            Object bool(String operator, SimpleNode node, Context context) {
2737:                CompileContext cc = (CompileContext) context;
2738:                ClassFile cf = cc.cf;
2739:                int ctx = cc.getContextIndex();
2740:                addLineInfo(cc, ctx, node);
2741:
2742:                if (node.getAttribute("hasTryStatement") != null) {
2743:                    int arg0 = cf.getLocal();
2744:                    int arg1 = cf.getLocal();
2745:                    accept(node, 0, cc);
2746:                    cf.storeLocal(arg0);
2747:                    accept(node, 1, cc);
2748:                    cf.storeLocal(arg1);
2749:                    cf.loadLocal(arg0);
2750:                    cf.loadLocal(arg1);
2751:                    cf.freeLocal(arg0);
2752:                    cf.freeLocal(arg1);
2753:                } else {
2754:                    accept(node, 0, cc);
2755:                    accept(node, 1, cc);
2756:                }
2757:                cf.loadLocal(ctx);
2758:                cf
2759:                        .add(
2760:                                Opcode.INVOKESTATIC,
2761:                                "pnuts.lang.Runtime",
2762:                                operator,
2763:                                "(Ljava/lang/Object;Ljava/lang/Object;Lpnuts/lang/Context;)",
2764:                                "Z");
2765:                if (isConditionalNode(node)) {
2766:                    node.setAttribute("inlinedBoolean", Boolean.TRUE);
2767:                } else {
2768:                    Label deny = cf.getLabel();
2769:                    cf.add(Opcode.IFEQ, deny);
2770:                    cf.add(Opcode.GETSTATIC, "java.lang.Boolean", "TRUE",
2771:                            "Ljava/lang/Boolean;");
2772:                    Label next = cf.getLabel();
2773:                    cf.add(Opcode.GOTO, next);
2774:                    deny.fix();
2775:                    cf.popStack();
2776:                    cf.add(Opcode.GETSTATIC, "java.lang.Boolean", "FALSE",
2777:                            "Ljava/lang/Boolean;");
2778:                    next.fix();
2779:                }
2780:                return null;
2781:            }
2782:
2783:            public Object ltNode(SimpleNode node, Context context) {
2784:                return bool("lt", node, context);
2785:            }
2786:
2787:            public Object leNode(SimpleNode node, Context context) {
2788:                return bool("le", node, context);
2789:            }
2790:
2791:            public Object gtNode(SimpleNode node, Context context) {
2792:                return bool("gt", node, context);
2793:            }
2794:
2795:            public Object geNode(SimpleNode node, Context context) {
2796:                return bool("ge", node, context);
2797:            }
2798:
2799:            public Object equalNode(SimpleNode node, Context context) {
2800:                return bool("eq", node, context);
2801:            }
2802:
2803:            public Object notEqNode(SimpleNode node, Context context) {
2804:                return bool("ne", node, context);
2805:            }
2806:
2807:            public Object ifStatement(SimpleNode node, Context context) {
2808:                CompileContext cc = (CompileContext) context;
2809:                ClassFile cf = cc.cf;
2810:                int ctx = cc.getContextIndex();
2811:
2812:                addLineInfo(cc, ctx, node);
2813:
2814:                SimpleNode condNode = node.jjtGetChild(0);
2815:                condNode.accept(this , context);
2816:
2817:                Label l_else = cf.getLabel();
2818:                Label next = cf.getLabel();
2819:
2820:                cc.openBranchEnv();
2821:
2822:                if (condNode.getAttribute("inlinedBoolean") != null) {
2823:                    cf.add(Opcode.IFEQ, l_else);
2824:                    accept(node, 1, context);
2825:                    cf.add(Opcode.GOTO, next);
2826:                    l_else.fix();
2827:                    cf.popStack();
2828:                } else {
2829:                    booleanCheck(node.jjtGetChild(0).id, cf, context);
2830:                    cf.add(Opcode.CHECKCAST, "java.lang.Boolean");
2831:                    cf.add(Opcode.INVOKEVIRTUAL, "java.lang.Boolean",
2832:                            "booleanValue", "()", "Z");
2833:                    cf.add(Opcode.IFEQ, l_else);
2834:                    accept(node, 1, context);
2835:                    cf.add(Opcode.GOTO, next);
2836:                    l_else.fix();
2837:                    cf.popStack();
2838:                }
2839:                int n = node.jjtGetNumChildren();
2840:                int j = 0;
2841:                /*
2842:                 * if (n < 3){ cf.add(Opcode.ACONST_NULL); cf.add(Opcode.GOTO, next); }
2843:                 */
2844:                for (int i = 2; i < n; i++) {
2845:                    SimpleNode _node = node.jjtGetChild(i);
2846:                    if (_node.id == PnutsParserTreeConstants.JJTELSEIFNODE) {
2847:                        cc.addBranch();
2848:
2849:                        SimpleNode _condNode = _node.jjtGetChild(0);
2850:                        _condNode.accept(this , context);
2851:
2852:                        Label next_else = cf.getLabel();
2853:                        if (_condNode.getAttribute("inlinedBoolean") != null) {
2854:                            cf.add(Opcode.IFEQ, next_else);
2855:                            accept(_node, 1, context);
2856:                            cf.add(Opcode.GOTO, next);
2857:                            next_else.fix();
2858:                            cf.popStack();
2859:                        } else {
2860:                            booleanCheck(_node.jjtGetChild(0).id, cf, context);
2861:                            cf.add(Opcode.CHECKCAST, "java.lang.Boolean");
2862:                            cf.add(Opcode.INVOKEVIRTUAL, "java.lang.Boolean",
2863:                                    "booleanValue", "()", "Z");
2864:                            cf.add(Opcode.IFEQ, next_else);
2865:                            accept(_node, 1, context);
2866:                            cf.add(Opcode.GOTO, next);
2867:                            next_else.fix();
2868:                            cf.popStack();
2869:                        }
2870:                    } else if (_node.id == PnutsParserTreeConstants.JJTELSENODE) {
2871:                        cc.addBranch();
2872:
2873:                        accept(_node, 0, context);
2874:                        if (i == n - 1) {
2875:                            next.fix();
2876:                            cc.closeBranchEnv();
2877:                            return null;
2878:                        } else {
2879:                            cf.add(Opcode.GOTO, next);
2880:                        }
2881:                    }
2882:                }
2883:                cf.add(Opcode.ACONST_NULL);
2884:
2885:                cc.closeBranchEnv();
2886:
2887:                next.fix();
2888:                return null;
2889:            }
2890:
2891:            static boolean isLeafFrame(SimpleNode node) {
2892:                FrameInfo info = (FrameInfo) node.getAttribute("frameInfo");
2893:                if (!info.leafCheckDone) {
2894:                    scanLeafFrames(node);
2895:                }
2896:                return info.isLeaf;
2897:            }
2898:
2899:            private static boolean isFrame(SimpleNode node) {
2900:                int id = node.id;
2901:                if (id == PnutsParserTreeConstants.JJTFUNCTIONSTATEMENT
2902:                        || id == PnutsParserTreeConstants.JJTMETHODDEF
2903:                        || id == PnutsParserTreeConstants.JJTFOREACHSTATEMENT) {
2904:                    return true;
2905:                }
2906:                if (id == PnutsParserTreeConstants.JJTFORSTATEMENT) {
2907:                    SimpleNode c = node.jjtGetChild(0);
2908:                    if (c.id == PnutsParserTreeConstants.JJTFORENUM) {
2909:                        return (c.jjtGetNumChildren() == 1);
2910:                    }
2911:                }
2912:                return false;
2913:            }
2914:
2915:            static boolean scanLeafFrames(SimpleNode node) {
2916:                boolean c = true;
2917:                int n = node.jjtGetNumChildren();
2918:                for (int i = 0; i < n; i++) {
2919:                    SimpleNode child = node.jjtGetChild(i);
2920:                    if (!scanLeafFrames(child)) {
2921:                        if (isFrame(node)) {
2922:                            FrameInfo info = (FrameInfo) node
2923:                                    .getAttribute("frameInfo");
2924:                            if (info == null) {
2925:                                node.setAttribute("frameInfo",
2926:                                        info = new FrameInfo());
2927:                            }
2928:                            info.isLeaf = false;
2929:                            info.leafCheckDone = true;
2930:                        }
2931:                        c = false;
2932:                    }
2933:                }
2934:                boolean c1 = !isFrame(node);
2935:                boolean c2 = (c && c1);
2936:                if (node.id == PnutsParserTreeConstants.JJTFUNCTIONSTATEMENT
2937:                        || node.id == PnutsParserTreeConstants.JJTMETHODDEF) {
2938:                    FrameInfo info = (FrameInfo) node.getAttribute("frameInfo");
2939:                    if (info == null) {
2940:                        node.setAttribute("frameInfo", info = new FrameInfo());
2941:                    }
2942:                    info.isLeaf = c;
2943:                    info.leafCheckDone = true;
2944:                }
2945:                return c2;
2946:            }
2947:
2948:            public Object functionStatement(SimpleNode node, Context context) {
2949:                FrameInfo info = (FrameInfo) node.getAttribute("frameInfo");
2950:                if (info == null) {
2951:                    node.setAttribute("frameInfo", info = new FrameInfo());
2952:                }
2953:                if (!info.preprocessed) {
2954:                    preprocess(node);
2955:                }
2956:
2957:                CompileContext cc = (CompileContext) context;
2958:                int ctx = cc.getContextIndex();
2959:                ClassFile cf = cc.cf;
2960:
2961:                addLineInfo(cc, ctx, node);
2962:
2963:                SimpleNode block = node.jjtGetChild(1);
2964:                SimpleNode param = node.jjtGetChild(0);
2965:                int nargs = param.jjtGetNumChildren();
2966:                boolean varargs = "[".equals(param.str);
2967:                String[] locals = new String[nargs];
2968:
2969:                SimpleNode n0 = null;
2970:                if (nargs == 1
2971:                        && (n0 = param.jjtGetChild(0)).id == PnutsParserTreeConstants.JJTINDEXNODE) {
2972:                    nargs = -1;
2973:                    locals[0] = n0.jjtGetChild(0).str;
2974:                } else {
2975:                    for (int j = 0; j < nargs; j++) {
2976:                        locals[j] = param.jjtGetChild(j).str;
2977:                    }
2978:                }
2979:
2980:                boolean isGenerator = Runtime.isGenerator(block);
2981:
2982:                String cls = className + "$"
2983:                        + (classCount++ & 0x7fffffffffffffffL);
2984:                node.setAttribute("classname", cls);
2985:
2986:                cf = new ClassFile(cls, "pnuts.lang.Function", sourceFile,
2987:                        Constants.ACC_PUBLIC);
2988:                cf.addInterface("pnuts.compiler.Compiled");
2989:                cc.classFiles.add(cf);
2990:                cf.parent = cc.cf;
2991:
2992:                /*
2993:                 * public PnutsFunction register(PnutsFunction pf, boolean);
2994:                 */
2995:                cf
2996:                        .openMethod(
2997:                                "register",
2998:                                "(Lpnuts/lang/PnutsFunction;Z)Lpnuts/lang/PnutsFunction;",
2999:                                Constants.ACC_PUBLIC);
3000:
3001:                cf.add(Opcode.ALOAD_0);
3002:                cf.add(Opcode.ALOAD_1);
3003:                cf.add(Opcode.ILOAD_2);
3004:                cf.add(Opcode.INVOKESPECIAL, "pnuts.lang.Function", "register",
3005:                        "(Lpnuts/lang/PnutsFunction;Z)",
3006:                        "Lpnuts/lang/PnutsFunction;");
3007:                cf.add(Opcode.ARETURN);
3008:                cf.closeMethod();
3009:
3010:                if (optimize) {
3011:                    /*
3012:                     * protected String unparse(Context context);
3013:                     */
3014:                    cf.openMethod("unparse",
3015:                            "(Lpnuts/lang/Context;)Ljava/lang/String;",
3016:                            Constants.ACC_PROTECTED);
3017:                    cf.pushString(Runtime.unparse(node, context));
3018:                    cf.add(Opcode.ARETURN);
3019:                    cf.closeMethod();
3020:                } else {
3021:                    /*
3022:                     * protected SimpleNode getNode();
3023:                     */
3024:                    cf.openMethod("getNode", "()Lpnuts/lang/SimpleNode;",
3025:                            Constants.ACC_PROTECTED);
3026:                    cf.pushString(Runtime.saveNode(node));
3027:                    cf.add(Opcode.INVOKESTATIC, "pnuts.lang.Runtime",
3028:                            "loadNode", "(Ljava/lang/String;)",
3029:                            "Lpnuts/lang/SimpleNode;");
3030:                    cf.add(Opcode.ARETURN);
3031:                    cf.closeMethod();
3032:                }
3033:
3034:                String fname = node.str;
3035:
3036:                /*
3037:                 * protected Object exec(Object[] args, Context conext);
3038:                 */
3039:                cc._openFrame(fname, locals, isLeafFrame(node));
3040:                cf
3041:                        .openMethod(
3042:                                "exec",
3043:                                "([Ljava/lang/Object;Lpnuts/lang/Context;)Ljava/lang/Object;",
3044:                                Constants.ACC_PROTECTED);
3045:                CompileContext cc2 = (CompileContext) cc.clone(false, true);
3046:                cc2.line = 0xffffffff;
3047:                cc2.cf = cf;
3048:                cc2.setContextIndex(2);
3049:                cc2.returnLabel = cf.getLabel();
3050:
3051:                ByteBuffer code = cf.getCodeBuffer();
3052:                ByteBuffer blockCode = new ByteBuffer();
3053:                cf.setCodeBuffer(blockCode);
3054:
3055:                if (fname != null) {
3056:                    int f = cf.getLocal();
3057:                    //cc2._declare(fname, f, -1);
3058:                    cc2._declare_frame(fname, f);
3059:                    cf.add(Opcode.ALOAD_0);
3060:                    cf.add(Opcode.GETFIELD, "pnuts.lang.Function", "function",
3061:                            "Lpnuts/lang/PnutsFunction;");
3062:                    cf.storeLocal(f);
3063:                }
3064:
3065:                int expt = cf.getLocal();
3066:                cc2._declare(EXCEPTOIN_FIELD_SYMBOL, expt, -1);
3067:
3068:                CompileContext cc3 = null;
3069:                ClassFile cf2 = null;
3070:
3071:                if (isGenerator) {
3072:
3073:                    String cls2 = className + "$"
3074:                            + (classCount++ & 0x7fffffffffffffffL);
3075:                    cf2 = new ClassFile(cls2, "pnuts.lang.PnutsFunction",
3076:                            sourceFile, Constants.ACC_PUBLIC);
3077:
3078:                    cc.classFiles.add(cf2);
3079:                    cf2.parent = cf;
3080:
3081:                    String closureSymbol = YIELD;
3082:
3083:                    SimpleNode gnode = Generator.convertYield(block,
3084:                            closureSymbol);
3085:
3086:                    cc3 = (CompileContext) cc2.clone();
3087:                    cc3.cf = cf2;
3088:
3089:                    /*
3090:                     * protected Object exec(Object[], Context)
3091:                     */
3092:                    cc3._openFrame(fname, locals, false);
3093:                    cf2
3094:                            .openMethod(
3095:                                    "exec",
3096:                                    "([Ljava/lang/Object;Lpnuts/lang/Context;)Ljava/lang/Object;",
3097:                                    Constants.ACC_PROTECTED);
3098:
3099:                    cf2.loadLocal(0);
3100:                    cf2.add(Opcode.GETFIELD, cls2, "$context$",
3101:                            "Lpnuts/lang/Context;");
3102:                    cf2.storeLocal(2);
3103:
3104:                    cc3.setContextIndex(2);
3105:                    cc3.returnLabel = cf2.getLabel();
3106:
3107:                    ByteBuffer code2 = cf2.getCodeBuffer();
3108:                    ByteBuffer blockCode2 = new ByteBuffer();
3109:                    cf2.setCodeBuffer(blockCode2);
3110:
3111:                    cc3.openScope(new String[] {});
3112:                    int args = cf2.getLocal();
3113:                    cf2.loadLocal(0);
3114:                    cf2.add(Opcode.GETFIELD, cls2, "args",
3115:                            "[Ljava/lang/Object;");
3116:                    cf2.storeLocal(args);
3117:                    for (int i = 0; i < locals.length; i++) {
3118:                        cc3._declare(locals[i], args, i);
3119:                    }
3120:                    int closure = cf2.getLocal();
3121:
3122:                    cc3._declare(closureSymbol, closure, -1);
3123:
3124:                    cf2.add(Opcode.ALOAD_1);
3125:                    cf2.add(Opcode.ICONST_0);
3126:                    cf2.add(Opcode.AALOAD);
3127:                    cf2.add(Opcode.CHECKCAST, "pnuts.lang.PnutsFunction");
3128:                    cf2.storeLocal(closure);
3129:
3130:                    gnode.accept(this , cc3);
3131:
3132:                    cc3.returnLabel.fix();
3133:
3134:                    cf2.setCodeBuffer(code2);
3135:
3136:                    LocalInfo[] infos = cc3.env.bottom.info;
3137:                    int count = cc3.env.bottom.count;
3138:
3139:                    for (int i = 0; i < infos.length; i++) {
3140:                        if (infos[i] != null) {
3141:                            int idx = infos[i].index;
3142:                            String sym = infos[i].symbol;
3143:                            int map = infos[i].map;
3144:                            if (idx < 0) {
3145:                                cf2.add(Opcode.ACONST_NULL);
3146:                                cf2.storeLocal(map);
3147:                            } else if (idx == 0) {
3148:                                cf2.add(Opcode.ICONST_1);
3149:                                cf2.add(Opcode.ANEWARRAY, "java.lang.Object");
3150:                                cf2.add(Opcode.DUP);
3151:                                cf2.add(Opcode.ICONST_0);
3152:                                cf2.add(Opcode.ACONST_NULL);
3153:
3154:                                cf2.add(Opcode.AASTORE);
3155:                                cf2.storeLocal(map);
3156:                            }
3157:                        }
3158:                    }
3159:
3160:                    cf2.shift(code2.size());
3161:
3162:                    blockCode2.prepend(code2);
3163:                    cf2.setCodeBuffer(blockCode2);
3164:
3165:                    cf2.add(Opcode.ARETURN);
3166:
3167:                    cc3.closeScope();
3168:
3169:                    cf2.closeMethod();
3170:
3171:                    ArrayList exports = (ArrayList) cc3.env.parent.exports
3172:                            .get(cc3.env);
3173:
3174:                    cc3._closeFrame();
3175:
3176:                    StringBuffer arg = new StringBuffer("([Ljava/lang/Object;");
3177:                    int n_names = 0;
3178:
3179:                    if (exports != null) {
3180:                        n_names = exports.size();
3181:                    }
3182:                    String names[] = new String[n_names];
3183:
3184:                    int j = 0;
3185:                    if (n_names > 0) {
3186:                        for (int i = 0, n = exports.size(); i < n; i++) {
3187:                            names[j++] = ((Reference) exports.get(i)).symbol;
3188:                            arg.append("[Ljava/lang/Object;");
3189:                        }
3190:                    }
3191:
3192:                    arg.append("Lpnuts/lang/Context;");
3193:                    arg.append(')');
3194:
3195:                    cf2.openMethod("<init>", arg + "V", Constants.ACC_PUBLIC);
3196:                    cf2.add(Opcode.ALOAD_0);
3197:                    cf2.add(Opcode.INVOKESPECIAL, "pnuts.lang.PnutsFunction",
3198:                            "<init>", "()", "V");
3199:
3200:                    cf2.addField("args", "[Ljava/lang/Object;",
3201:                            Constants.ACC_PRIVATE);
3202:                    cf2.add(Opcode.ALOAD_0);
3203:                    cf2.add(Opcode.ALOAD_1);
3204:                    cf2.add(Opcode.PUTFIELD, cls2, "args",
3205:                            "[Ljava/lang/Object;");
3206:
3207:                    for (int i = 0; i < n_names; i++) {
3208:                        cf2
3209:                                .addField(names[i], "[Ljava/lang/Object;",
3210:                                        (short) 0);
3211:                        cf2.add(Opcode.ALOAD_0);
3212:                        cf2.loadLocal(2 + i);
3213:                        cf2.add(Opcode.PUTFIELD, cf2.getClassName(), names[i],
3214:                                "[Ljava/lang/Object;");
3215:                    }
3216:
3217:                    cf2
3218:                            .addField("$context$", "Lpnuts/lang/Context;",
3219:                                    (short) 0);
3220:                    cf2.add(Opcode.ALOAD_0);
3221:                    cf2.loadLocal(2 + n_names);
3222:                    cf2.add(Opcode.ICONST_0);
3223:                    cf2.add(Opcode.ICONST_0);
3224:                    cf2.add(Opcode.INVOKEVIRTUAL, "pnuts.lang.Context",
3225:                            "clone", "(ZZ)", "Ljava/lang/Object;");
3226:                    cf2.add(Opcode.CHECKCAST, "pnuts.lang.Context");
3227:                    cf2.add(Opcode.PUTFIELD, cf2.getClassName(), "$context$",
3228:                            "Lpnuts/lang/Context;");
3229:
3230:                    cf2.add(Opcode.RETURN);
3231:                    cf2.closeMethod();
3232:
3233:                    //	    cc.debug(cf2);
3234:
3235:                    cf.add(Opcode.NEW, "pnuts.lang.Generator");
3236:                    cf.add(Opcode.DUP);
3237:
3238:                    cf.add(Opcode.NEW, cls2);
3239:                    cf.add(Opcode.DUP);
3240:                    cf.loadLocal(1);
3241:
3242:                    if (exports != null) {
3243:                        int size = exports.size();
3244:                        for (int i = 0; i < size; i++) {
3245:                            Reference ref = (Reference) exports.get(i);
3246:                            if (ref.index < 0) {
3247:                                cf.add(Opcode.ALOAD_0);
3248:                                cf.add(Opcode.GETFIELD, cf.getClassName(),
3249:                                        ref.symbol, "[Ljava/lang/Object;");
3250:                            } else if (ref.offset < 0) {
3251:                                cf.add(Opcode.ICONST_1);
3252:                                cf.add(Opcode.ANEWARRAY, "java.lang.Object");
3253:                                cf.add(Opcode.DUP);
3254:                                cf.add(Opcode.ICONST_0);
3255:                                cf.loadLocal(ref.index);
3256:                                cf.add(Opcode.AASTORE);
3257:                            } else {
3258:                                cf.loadLocal(ref.index);
3259:                                cf.add(Opcode.CHECKCAST, "[Ljava/lang/Object;");
3260:                            }
3261:                        }
3262:                    }
3263:
3264:                    cf.loadLocal(2);
3265:
3266:                    cf.add(Opcode.INVOKESPECIAL, cls2, "<init>",
3267:                            arg.toString(), "V");
3268:
3269:                    cf.add(Opcode.INVOKESPECIAL, "pnuts.lang.Generator",
3270:                            "<init>", "(Lpnuts/lang/PnutsFunction;)", "V");
3271:
3272:                } else {
3273:                    if (info.freeVars != null) {
3274:                        int loc = cf.getLocal();
3275:                        for (Iterator it = info.freeVars.iterator(); it
3276:                                .hasNext();) {
3277:                            String var = (String) it.next();
3278:                            if (var == fname) {
3279:                                continue;
3280:                            }
3281:                            cc2.declare(var);
3282:                            Reference ref = cc2.getReference(var);
3283:                            cf.loadLocal(cc2.getContextIndex());
3284:                            cf.add(Opcode.LDC, cf.addConstant(var));
3285:                            cf.add(Opcode.INVOKEVIRTUAL, "pnuts.lang.Context",
3286:                                    "getId", "(Ljava/lang/String;)",
3287:                                    "Ljava/lang/Object;");
3288:                            cf.storeLocal(loc);
3289:                            ref.set(cf, loc);
3290:                        }
3291:                        cf.freeLocal(loc);
3292:                    }
3293:                    block.accept(this , cc2);
3294:                }
3295:
3296:                cc2.returnLabel.fix();
3297:
3298:                cf.setCodeBuffer(code);
3299:
3300:                LocalInfo[] infos = cc.env.bottom.info;
3301:                int count = cc.env.bottom.count;
3302:
3303:                for (int i = 0; i < cc.env.bottom.count; i++) {
3304:                    int idx = infos[i].index;
3305:                    String sym = infos[i].symbol;
3306:                    int map = infos[i].map;
3307:                    if (idx < 0) {
3308:                        cf.add(Opcode.ACONST_NULL);
3309:                        cf.storeLocal(map);
3310:                    } else if (idx == 0) {
3311:                        cf.add(Opcode.ICONST_1);
3312:                        cf.add(Opcode.ANEWARRAY, "java.lang.Object");
3313:                        cf.add(Opcode.DUP);
3314:                        cf.add(Opcode.ICONST_0);
3315:                        cf.add(Opcode.ACONST_NULL);
3316:
3317:                        cf.add(Opcode.AASTORE);
3318:                        cf.storeLocal(map);
3319:                    }
3320:                }
3321:
3322:                Reference eref = cc2.getReference(EXCEPTOIN_FIELD_SYMBOL);
3323:                cf.add(Opcode.ACONST_NULL);
3324:                cf.storeLocal(eref.index);
3325:
3326:                cf.shift(code.size());
3327:
3328:                Label catchStart = cf.getLabel(true);
3329:
3330:                blockCode.prepend(code);
3331:                cf.setCodeBuffer(blockCode);
3332:
3333:                boolean finallyIsSet = cc2.env.finallySet;
3334:                Label jsrTag = cf.getLabel();
3335:                Label finallyEnd = cf.getLabel();
3336:
3337:                if (finallyIsSet) {
3338:                    int value = cf.getLocal();
3339:                    cf.storeLocal(value);
3340:                    cf.add(Opcode.JSR, jsrTag);
3341:                    cf.loadLocal(value);
3342:                    cf.freeLocal(value);
3343:                }
3344:
3345:                cf.add(Opcode.ARETURN);
3346:
3347:                Label catchEnd = cf.getLabel(true);
3348:                Label catchTarget = cf.getLabel(true);
3349:                Label finallyTarget = cf.getLabel();
3350:                cf.reserveStack(1);
3351:
3352:                int caught = cf.getLocal();
3353:                cf.storeLocal(caught);
3354:                cf.loadLocal(cc2.getContextIndex());
3355:                cf.loadLocal(caught);
3356:                cf.freeLocal(caught);
3357:
3358:                if (!isGenerator) {
3359:                    cf.loadLocal(eref.index);
3360:                    cf.add(Opcode.CHECKCAST, "pnuts.lang.Runtime$TypeMap");
3361:                    cf
3362:                            .add(
3363:                                    Opcode.INVOKESTATIC,
3364:                                    "pnuts.lang.Runtime",
3365:                                    "checkException",
3366:                                    "(Lpnuts/lang/Context;Ljava/lang/Throwable;Lpnuts/lang/Runtime$TypeMap;)",
3367:                                    "V");
3368:                }
3369:                if (finallyIsSet) {
3370:                    finallyEnd.fix();
3371:                    cf.add(Opcode.JSR, jsrTag);
3372:                }
3373:
3374:                cf.add(Opcode.ACONST_NULL);
3375:                cf.add(Opcode.ARETURN);
3376:
3377:                if (finallyIsSet) {
3378:                    int throwable = cf.getLocal();
3379:                    int returnAddr = cf.getLocal();
3380:
3381:                    finallyTarget.fix();
3382:
3383:                    cf.reserveStack(1);
3384:                    cf.storeLocal(throwable);
3385:                    cf.add(Opcode.JSR, jsrTag);
3386:                    cf.loadLocal(throwable);
3387:                    cf.freeLocal(throwable);
3388:                    cf.add(Opcode.ATHROW);
3389:
3390:                    jsrTag.fix();
3391:
3392:                    cf.reserveStack(1);
3393:                    cf.storeLocal(returnAddr);
3394:                    Reference ref = cc.getReference("!finally");
3395:                    cf.loadLocal(ref.index);
3396:                    cf.add(Opcode.CHECKCAST, "pnuts.lang.PnutsFunction");
3397:                    cf.add(Opcode.GETSTATIC, className, "NO_PARAM",
3398:                            "[Ljava/lang/Object;");
3399:
3400:                    cf.loadLocal(cc2.getContextIndex());
3401:                    cf.add(Opcode.INVOKEVIRTUAL, "pnuts.lang.PnutsFunction",
3402:                            "call",
3403:                            "([Ljava/lang/Object;Lpnuts/lang/Context;)",
3404:                            "Ljava/lang/Object;");
3405:                    cf.add(Opcode.POP);
3406:                    cf.add(Opcode.RET, returnAddr);
3407:                    cf.freeLocal(returnAddr);
3408:                }
3409:
3410:                cf.addExceptionHandler(catchStart, catchEnd, catchTarget,
3411:                        "java.lang.Throwable");
3412:
3413:                if (finallyIsSet) {
3414:                    cf.addExceptionHandler(catchStart, finallyEnd,
3415:                            finallyTarget, null);
3416:                }
3417:
3418:                StringBuffer arg = new StringBuffer(
3419:                        "(Ljava/lang/String;[Ljava/lang/String;IZLpnuts/lang/SimpleNode;Lpnuts/lang/Package;Lpnuts/lang/Context;");
3420:                int n_names = 0;
3421:                if (cc.env.imports != null) {
3422:                    n_names = cc.env.imports.size();
3423:                }
3424:
3425:                String names[] = new String[n_names];
3426:
3427:                int j = 0;
3428:                if (n_names > 0) {
3429:                    List imports = cc.env.imports;
3430:                    for (int i = 0, n = imports.size(); i < n; i++) {
3431:                        String sym = (String) imports.get(i);
3432:                        if (DEBUG) {
3433:                            System.out.println(fname + ": " + sym);
3434:                        }
3435:                        names[j++] = sym;
3436:                        arg.append("[Ljava/lang/Object;");
3437:                    }
3438:                }
3439:
3440:                if (DEBUG) {
3441:                    System.out.println(cf.getClassName() + ": " + arg);
3442:                }
3443:
3444:                cf.closeMethod();
3445:                cc._closeFrame();
3446:
3447:                arg.append(")");
3448:                /*
3449:                 * constructor
3450:                 */
3451:                cf.openMethod("<init>", arg + "V", (short) 0);
3452:                cf.add(Opcode.ALOAD_0);
3453:                cf.add(Opcode.ALOAD_1); // String name
3454:                cf.add(Opcode.ALOAD_2); // String[] locals
3455:                cf.add(Opcode.ILOAD_3); // int nargs
3456:                cf.add(Opcode.ILOAD, 4); // int nargs
3457:                cf.add(Opcode.ALOAD, 5); // SimpleNode
3458:                cf.add(Opcode.ALOAD, 6); // Package
3459:                cf.add(Opcode.ALOAD, 7); // Context
3460:                cf
3461:                        .add(
3462:                                Opcode.INVOKESPECIAL,
3463:                                "pnuts.lang.Function",
3464:                                "<init>",
3465:                                "(Ljava/lang/String;[Ljava/lang/String;IZLpnuts/lang/SimpleNode;Lpnuts/lang/Package;Lpnuts/lang/Context;)",
3466:                                "V");
3467:
3468:                for (int i = 0; i < n_names; i++) {
3469:                    cf.addField(names[i], "[Ljava/lang/Object;", (short) 0);
3470:                    cf.add(Opcode.ALOAD_0);
3471:                    cf.add(Opcode.ALOAD, 8 + i);
3472:                    cf.add(Opcode.PUTFIELD, cf.getClassName(), names[i],
3473:                            "[Ljava/lang/Object;");
3474:                }
3475:
3476:                cf.add(Opcode.RETURN);
3477:                cf.closeMethod();
3478:
3479:                cf = cc.cf;
3480:                cf.loadLocal(ctx);
3481:                cf.add(Opcode.INVOKEVIRTUAL, "pnuts.lang.Context",
3482:                        "getCurrentPackage", "()", "Lpnuts/lang/Package;");
3483:                int pkg = cf.getLocal();
3484:                cf.storeLocal(pkg);
3485:
3486:                cf.add(Opcode.NEW, cls);
3487:                cf.add(Opcode.DUP);
3488:                int fnameIndex = 0;
3489:                if (fname != null) {
3490:                    fnameIndex = cf.addConstant(fname);
3491:                    cf.add(Opcode.LDC, fnameIndex);
3492:                } else {
3493:                    cf.add(Opcode.ACONST_NULL);
3494:                }
3495:                cf.pushInteger(locals.length);
3496:                cf.add(Opcode.ANEWARRAY, "java.lang.String");
3497:                for (int i = 0; i < locals.length; i++) {
3498:                    cf.add(Opcode.DUP);
3499:                    cf.pushInteger(i);
3500:                    cf.add(Opcode.LDC, cf.addConstant(locals[i]));
3501:                    cf.add(Opcode.AASTORE);
3502:                }
3503:                cf.pushInteger(nargs);
3504:                cf.add(varargs ? Opcode.ICONST_1 : Opcode.ICONST_0);
3505:                cf.add(Opcode.ACONST_NULL);
3506:                cf.loadLocal(pkg);
3507:                cf.loadLocal(ctx);
3508:
3509:                ArrayList exports;
3510:
3511:                if (isGenerator) {
3512:                    exports = (ArrayList) cc.env.exports.get(cc3.env);
3513:                } else {
3514:                    exports = (ArrayList) cc.env.exports.get(cc2.env);
3515:                }
3516:
3517:                if (exports != null) {
3518:                    int size = exports.size();
3519:                    for (int i = 0; i < size; i++) {
3520:                        Reference ref = (Reference) exports.get(i);
3521:                        if (ref.index < 0) {
3522:                            cf.add(Opcode.ALOAD_0);
3523:                            cf.add(Opcode.GETFIELD, cf.getClassName(),
3524:                                    ref.symbol, "[Ljava/lang/Object;");
3525:                        } else if (ref.offset < 0) {
3526:                            cf.add(Opcode.ICONST_1);
3527:                            cf.add(Opcode.ANEWARRAY, "java.lang.Object");
3528:                            cf.add(Opcode.DUP);
3529:                            cf.add(Opcode.ICONST_0);
3530:                            cf.loadLocal(ref.index);
3531:                            cf.add(Opcode.AASTORE);
3532:                        } else {
3533:                            cf.loadLocal(ref.index);
3534:                            cf.add(Opcode.CHECKCAST, "[Ljava/lang/Object;");
3535:                        }
3536:                    }
3537:                }
3538:
3539:                cf
3540:                        .add(Opcode.INVOKESPECIAL, cls, "<init>", arg
3541:                                .toString(), "V");
3542:
3543:                int func = cf.getLocal();
3544:                cf.storeLocal(func);
3545:
3546:                int pfunc = cf.getLocal();
3547:                cf.add(Opcode.ACONST_NULL);
3548:                cf.storeLocal(pfunc);
3549:
3550:                Reference ref = null;
3551:                Reference ref2 = null;
3552:                if (fname != null && node.getAttribute("isMethod") == null) {
3553:                    ref = cc.env.findReference(fname); // without lexical scope
3554:                    ref2 = cc.findReference(fname); // with lexical scope
3555:                    if (ref != null && ref.frame != cc.env) {
3556:                        getRef(ref, cc);
3557:                        cf.storeLocal(pfunc);
3558:
3559:                        cf.loadLocal(pfunc);
3560:                        cf.add(Opcode.INSTANCEOF, "pnuts.lang.PnutsFunction");
3561:                        Label instance = cf.getLabel();
3562:                        cf.add(Opcode.IFNE, instance);
3563:                        cf.add(Opcode.ACONST_NULL);
3564:                        cf.storeLocal(pfunc);
3565:                        instance.fix();
3566:
3567:                        cf.loadLocal(func);
3568:                        cf.loadLocal(pfunc);
3569:                        cf.add(Opcode.CHECKCAST, "pnuts.lang.PnutsFunction");
3570:                        cf.add(Opcode.ICONST_0);
3571:                        cf.add(Opcode.INVOKEVIRTUAL, cls, "register",
3572:                                "(Lpnuts/lang/PnutsFunction;Z)",
3573:                                "Lpnuts/lang/PnutsFunction;");
3574:                        cf.storeLocal(pfunc);
3575:
3576:                    } else if (ref2 != null) { // ref == null && ref2 != null
3577:                        getRef(ref2, cc);
3578:                        cf.storeLocal(pfunc);
3579:
3580:                        cf.loadLocal(pfunc);
3581:                        cf.add(Opcode.INSTANCEOF, "pnuts.lang.PnutsFunction");
3582:                        Label instance = cf.getLabel();
3583:                        cf.add(Opcode.IFNE, instance);
3584:                        cf.add(Opcode.ACONST_NULL);
3585:                        cf.storeLocal(pfunc);
3586:                        instance.fix();
3587:
3588:                        cf.loadLocal(func);
3589:                        cf.loadLocal(pfunc);
3590:                        cf.add(Opcode.CHECKCAST, "pnuts.lang.PnutsFunction");
3591:                        cf.add(Opcode.ICONST_1);
3592:                        cf.add(Opcode.INVOKEVIRTUAL, cls, "register",
3593:                                "(Lpnuts/lang/PnutsFunction;Z)",
3594:                                "Lpnuts/lang/PnutsFunction;");
3595:                        cf.storeLocal(pfunc);
3596:
3597:                    } else if (cc.env.parent != null) {
3598:                        cf.loadLocal(func);
3599:                        cf.add(Opcode.LDC, fnameIndex);
3600:                        cf.loadLocal(pkg);
3601:                        cf
3602:                                .add(
3603:                                        Opcode.INVOKESTATIC,
3604:                                        "pnuts.lang.Runtime",
3605:                                        "defineUnboundFunction",
3606:                                        "(Lpnuts/lang/Function;Ljava/lang/String;Lpnuts/lang/Package;)",
3607:                                        "Lpnuts/lang/PnutsFunction;");
3608:                        cf.storeLocal(pfunc);
3609:
3610:                        cc.declare(fname);
3611:                        ref = cc.getReference(fname);
3612:                        ref.set(cf, pfunc);
3613:                        cf.loadLocal(pfunc);
3614:                        return null;
3615:                    } else {
3616:                        cf.loadLocal(func);
3617:                        cf.add(Opcode.LDC, fnameIndex);
3618:                        cf.loadLocal(pkg);
3619:                        cf.loadLocal(ctx);
3620:                        cf
3621:                                .add(
3622:                                        Opcode.INVOKESTATIC,
3623:                                        "pnuts.lang.Runtime",
3624:                                        "defineTopLevelFunction",
3625:                                        "(Lpnuts/lang/Function;Ljava/lang/String;Lpnuts/lang/Package;Lpnuts/lang/Context;)",
3626:                                        "Lpnuts/lang/PnutsFunction;");
3627:                        return null;
3628:                    }
3629:                } else { // fname == null
3630:                    cf.loadLocal(func);
3631:                    cf.add(Opcode.ACONST_NULL);
3632:                    cf.add(Opcode.ICONST_0);
3633:                    cf.add(Opcode.INVOKEVIRTUAL, cls, "register",
3634:                            "(Lpnuts/lang/PnutsFunction;Z)",
3635:                            "Lpnuts/lang/PnutsFunction;");
3636:                    return null;
3637:                }
3638:
3639:                if (cc.env.parent != null) {
3640:                    if (ref == null) {
3641:                        cc.declare(fname);
3642:                        ref = cc.getReference(fname);
3643:                    } else {
3644:                        cc.redefine(fname);
3645:                    }
3646:                    ref.set(cf, pfunc);
3647:                    cf.loadLocal(pfunc);
3648:                } else {
3649:                    cf.loadLocal(pkg);
3650:                    cf.add(Opcode.LDC, fnameIndex);
3651:                    cf.loadLocal(pfunc);
3652:                    cf.loadLocal(ctx);
3653:                    cf
3654:                            .add(
3655:                                    Opcode.INVOKEVIRTUAL,
3656:                                    "pnuts.lang.Package",
3657:                                    "set",
3658:                                    "(Ljava/lang/String;Ljava/lang/Object;Lpnuts/lang/Context;)",
3659:                                    "V");
3660:                    cf.loadLocal(pfunc);
3661:                }
3662:                cf.freeLocal(func);
3663:                cf.freeLocal(pfunc);
3664:                cf.freeLocal(pkg);
3665:                return null;
3666:            }
3667:
3668:            public Object applicationNode(SimpleNode node, Context context) {
3669:                CompileContext cc = (CompileContext) context;
3670:                ClassFile cf = cc.cf;
3671:                int ctx = cc.getContextIndex();
3672:
3673:                addLineInfo(cc, ctx, node);
3674:
3675:                SimpleNode n0 = node.jjtGetChild(0);
3676:                if (n0.id == PnutsParserTreeConstants.JJTIDNODE) {
3677:                    String sym = n0.str;
3678:                    Reference ref = cc.getReference(sym);
3679:                    if (ref != null) {
3680:                        Frame frame = ref.frame;
3681:                        if (frame != null) {
3682:                            SimpleNode n1 = node.jjtGetChild(1);
3683:                            int nargs = n1.jjtGetNumChildren();
3684:                            if (frame.fname == sym
3685:                                    && frame.locals.length == nargs) {
3686:                                if (DEBUG) {
3687:                                    System.out.println("recursive " + sym);
3688:                                }
3689:                                //System.out.println("ref.frame = " + frame + ", env=" + cc.env);
3690:                                cf.add(Opcode.ALOAD_0);
3691:                                _listElements(node.jjtGetChild(1), context);
3692:                                cf.loadLocal(ctx);
3693:                                cf
3694:                                        .add(
3695:                                                Opcode.INVOKEVIRTUAL,
3696:                                                "pnuts.lang.Function",
3697:                                                "exec",
3698:                                                "([Ljava/lang/Object;Lpnuts/lang/Context;)",
3699:                                                "Ljava/lang/Object;");
3700:                                return null;
3701:                            }
3702:                        }
3703:                    }
3704:                }
3705:
3706:                if (node.getAttribute("hasTryStatement") != null) {
3707:                    int tgt = cf.getLocal();
3708:                    int arg = cf.getLocal();
3709:                    accept(node, 0, context);
3710:                    cf.storeLocal(tgt);
3711:                    //	    accept(node, 1, context);
3712:                    _listElements(node.jjtGetChild(1), context);
3713:                    cf.storeLocal(arg);
3714:
3715:                    cf.loadLocal(ctx);
3716:                    cf.loadLocal(tgt);
3717:                    cf.loadLocal(arg);
3718:
3719:                    cf.freeLocal(tgt);
3720:                    cf.freeLocal(arg);
3721:                } else {
3722:                    cf.loadLocal(ctx);
3723:                    accept(node, 0, context);
3724:                    //	    accept(node, 1, context);
3725:                    _listElements(node.jjtGetChild(1), context);
3726:                }
3727:
3728:                SimpleNode argNode = node.jjtGetChild(1);
3729:                int nargs = argNode.jjtGetNumChildren();
3730:
3731:                boolean types_created = false;
3732:                for (int i = 0; i < nargs; i++) {
3733:                    SimpleNode n = argNode.jjtGetChild(i);
3734:                    if (n.id == PnutsParserTreeConstants.JJTCASTEXPRESSION) {
3735:                        if (!types_created) {
3736:                            cf.pushInteger(nargs);
3737:                            cf.add(Opcode.ANEWARRAY, "java.lang.Class");
3738:                            types_created = true;
3739:                        }
3740:                        cf.add(Opcode.DUP);
3741:                        cf.pushInteger(i);
3742:
3743:                        resolveType(n.jjtGetChild(0), cc, ctx);
3744:
3745:                        cf.add(Opcode.AASTORE);
3746:                    }
3747:                }
3748:                if (!types_created) {
3749:                    cf.add(Opcode.ACONST_NULL);
3750:                }
3751:
3752:                if (_includeLineNo) {
3753:                    cf.pushInteger(node.beginLine);
3754:                    if (_includeColumnNo) {
3755:                        cf.pushInteger(node.beginColumn);
3756:                    } else {
3757:                        cf.pushInteger(-1);
3758:                    }
3759:                    cf
3760:                            .add(
3761:                                    Opcode.INVOKESTATIC,
3762:                                    "pnuts.lang.Runtime",
3763:                                    "call",
3764:                                    "(Lpnuts/lang/Context;Ljava/lang/Object;[Ljava/lang/Object;[Ljava/lang/Class;II)",
3765:                                    "Ljava/lang/Object;");
3766:                } else {
3767:                    cf
3768:                            .add(
3769:                                    Opcode.INVOKESTATIC,
3770:                                    "pnuts.lang.Runtime",
3771:                                    "call",
3772:                                    "(Lpnuts/lang/Context;Ljava/lang/Object;[Ljava/lang/Object;[Ljava/lang/Class;)",
3773:                                    "Ljava/lang/Object;");
3774:                }
3775:
3776:                return null;
3777:            }
3778:
3779:            public Object tryStatement(SimpleNode node, Context context) {
3780:                CompileContext cc = (CompileContext) context;
3781:                ClassFile cf = cc.cf;
3782:                /*
3783:                 * if (node.jjtGetParent().id ==
3784:                 * PnutsParserTreeConstants.JJTLISTELEMENTS){ throw new
3785:                 * PnutsException("try/catch is not allowed in parameters", context); }
3786:                 * if (cf.stackTop > 0){ throw new PnutsException("try/catch is not
3787:                 * allowed in parameters", context); }
3788:                 */
3789:                int throwable = cf.getLocal();
3790:                cf.add(Opcode.ACONST_NULL);
3791:                cf.storeLocal(throwable);
3792:
3793:                int value = cf.getLocal();
3794:                cf.add(Opcode.ACONST_NULL);
3795:                cf.storeLocal(value);
3796:
3797:                Label next = cf.getLabel();
3798:                Label finalTag = cf.getLabel();
3799:                Label jsrTag = cf.getLabel();
3800:
3801:                int n = node.jjtGetNumChildren();
3802:                SimpleNode lastNode = node.jjtGetChild(n - 1);
3803:                SimpleNode finallyBlock = null;
3804:                if (lastNode.id == PnutsParserTreeConstants.JJTFINALLYBLOCK) {
3805:                    finallyBlock = lastNode;
3806:                    cc.pushFinallyBlock(jsrTag);
3807:                }
3808:                boolean hasCatchBlock = false;
3809:                if (n > 1
3810:                        && node.jjtGetChild(1).id == PnutsParserTreeConstants.JJTCATCHBLOCK) {
3811:                    hasCatchBlock = true;
3812:                }
3813:
3814:                Label catchStart = cf.getLabel(true);
3815:
3816:                accept(node, 0, context);
3817:                cf.storeLocal(value);
3818:
3819:                Label catchEnd = cf.getLabel(true);
3820:
3821:                if (finallyBlock != null) {
3822:                    cf.add(Opcode.JSR, jsrTag);
3823:                }
3824:                cf.add(Opcode.GOTO, next);
3825:
3826:                Label escape = cf.getLabel(true);
3827:                cf.reserveStack(1);
3828:
3829:                cf.storeLocal(throwable);
3830:                cf.loadLocal(throwable);
3831:                cf.add(Opcode.ATHROW);
3832:
3833:                Label catchTarget = null;
3834:                if (hasCatchBlock) {
3835:                    catchTarget = cf.getLabel(true);
3836:                    cf.reserveStack(1);
3837:                    cf.storeLocal(throwable);
3838:
3839:                    cf.loadLocal(throwable);
3840:                    cf.add(Opcode.INSTANCEOF, "pnuts.lang.PnutsException");
3841:                    Label l1 = cf.getLabel();
3842:                    cf.add(Opcode.IFEQ, l1);
3843:                    cf.loadLocal(throwable);
3844:                    cf.add(Opcode.CHECKCAST, "pnuts.lang.PnutsException");
3845:                    cf.add(Opcode.INVOKEVIRTUAL, "pnuts.lang.PnutsException",
3846:                            "getThrowable", "()", "Ljava/lang/Throwable;");
3847:                    cf.storeLocal(throwable);
3848:                    l1.fix();
3849:
3850:                    int cls = cf.getLocal();
3851:
3852:                    for (int i = 1; i < n; i++) {
3853:                        SimpleNode c = node.jjtGetChild(i);
3854:                        if (c.id == PnutsParserTreeConstants.JJTCATCHBLOCK) {
3855:                            String var = c.str;
3856:                            StringBuffer sbuf = new StringBuffer();
3857:                            SimpleNode classNode = c.jjtGetChild(0);
3858:                            sbuf.append(classNode.jjtGetChild(0).str);
3859:                            for (int j = 1; j < classNode.jjtGetNumChildren(); j++) {
3860:                                sbuf.append('.');
3861:                                sbuf.append(classNode.jjtGetChild(j).str);
3862:                            }
3863:                            cf.loadLocal(cc.getContextIndex());
3864:                            cf.add(Opcode.LDC, cf.addConstant(sbuf.toString()));
3865:                            cf.add(Opcode.INVOKEVIRTUAL, "pnuts.lang.Context",
3866:                                    "resolveClass", "(Ljava/lang/String;)",
3867:                                    "Ljava/lang/Class;");
3868:                            cf.storeLocal(cls);
3869:                            cf.loadLocal(cls);
3870:                            Label nextCatch = cf.getLabel();
3871:                            cf.add(Opcode.IFNULL, nextCatch);
3872:                            cf.loadLocal(cls);
3873:                            cf.loadLocal(throwable);
3874:                            cf.add(Opcode.INVOKEVIRTUAL, "java.lang.Class",
3875:                                    "isInstance", "(Ljava/lang/Object;)", "Z");
3876:                            cf.add(Opcode.IFEQ, nextCatch);
3877:                            cc.openScope(new String[] {});
3878:                            cc._declare(var, throwable, -1);
3879:                            accept(c, 1, context);
3880:                            cc.closeScope();
3881:                            cf.storeLocal(value);
3882:                            if (finallyBlock != null) {
3883:                                cf.add(Opcode.JSR, jsrTag);
3884:                            }
3885:                            cf.add(Opcode.GOTO, next);
3886:                            nextCatch.fix();
3887:                        }
3888:                    }
3889:                    cf.loadLocal(throwable);
3890:                    cf.add(Opcode.ATHROW);
3891:                }
3892:
3893:                if (finallyBlock != null) {
3894:                    finalTag = cf.getLabel(true);
3895:                    cf.reserveStack(1);
3896:                    cf.storeLocal(throwable);
3897:                    cf.add(Opcode.JSR, jsrTag);
3898:                    cf.loadLocal(throwable);
3899:                    cf.add(Opcode.ATHROW);
3900:
3901:                    jsrTag.fix();
3902:
3903:                    int retAddr = cf.getLocal();
3904:                    cf.reserveStack(1);
3905:                    cf.storeLocal(retAddr);
3906:
3907:                    cc.popFinallyBlock();
3908:                    accept(finallyBlock, 0, context);
3909:                    cf.add(Opcode.POP);
3910:                    cf.add(Opcode.RET, retAddr);
3911:                }
3912:
3913:                cf.addExceptionHandler(catchStart, catchEnd, escape,
3914:                        "pnuts.lang.Escape");
3915:                if (hasCatchBlock) {
3916:                    cf.addExceptionHandler(catchStart, catchEnd, catchTarget,
3917:                            "java.lang.Throwable");
3918:                }
3919:                if (finallyBlock != null) {
3920:                    cf
3921:                            .addExceptionHandler(catchStart, finalTag,
3922:                                    finalTag, null);
3923:                }
3924:
3925:                next.fix();
3926:
3927:                cf.loadLocal(value);
3928:
3929:                //	cf.freeLocal(throwable);
3930:                //	cf.freeLocal(value);
3931:
3932:                return null;
3933:            }
3934:
3935:            public Object catchBlock(SimpleNode node, Context context) {
3936:                return null;
3937:            }
3938:
3939:            public Object blockNode(SimpleNode node, Context context) {
3940:                CompileContext cc = (CompileContext) context;
3941:                ClassFile cf = cc.cf;
3942:                int n = node.jjtGetNumChildren();
3943:
3944:                if (n > 0) {
3945:                    int m = n - 1;
3946:                    for (int i = 0; i < m; i++) {
3947:                        accept(node, i, context);
3948:                        cf.add(Opcode.POP);
3949:                    }
3950:                    accept(node, m, context);
3951:                } else {
3952:                    cf.add(Opcode.ACONST_NULL);
3953:                }
3954:                return null;
3955:            }
3956:
3957:            public Object trueNode(SimpleNode node, Context context) {
3958:                CompileContext cc = (CompileContext) context;
3959:                ClassFile cf = cc.cf;
3960:                if (isConditionalNode(node)) {
3961:                    node.setAttribute("inlinedBoolean", Boolean.TRUE);
3962:                    cf.add(Opcode.ICONST_1);
3963:                } else {
3964:                    cf.add(Opcode.GETSTATIC, "java.lang.Boolean", "TRUE",
3965:                            "Ljava/lang/Boolean;");
3966:                }
3967:                return null;
3968:            }
3969:
3970:            public Object falseNode(SimpleNode node, Context context) {
3971:                CompileContext cc = (CompileContext) context;
3972:                ClassFile cf = cc.cf;
3973:                if (isConditionalNode(node)) {
3974:                    node.setAttribute("inlinedBoolean", Boolean.TRUE);
3975:                    cf.add(Opcode.ICONST_0);
3976:                } else {
3977:                    cc.cf.add(Opcode.GETSTATIC, "java.lang.Boolean", "FALSE",
3978:                            "Ljava/lang/Boolean;");
3979:                }
3980:                return null;
3981:            }
3982:
3983:            public Object nullNode(SimpleNode node, Context context) {
3984:                CompileContext cc = (CompileContext) context;
3985:                cc.cf.add(Opcode.ACONST_NULL);
3986:                return null;
3987:            }
3988:
3989:            public Object idNode(SimpleNode node, Context context) {
3990:                CompileContext cc = (CompileContext) context;
3991:                ClassFile cf = cc.cf;
3992:
3993:                String symbol = node.str;
3994:                int ctx = cc.getContextIndex();
3995:
3996:                addLineInfo(cc, ctx, node);
3997:
3998:                Reference ref = cc.getReference(symbol);
3999:
4000:                if (ref != null) {
4001:                    getRef(ref, cc);
4002:                } else {
4003:                    cf.loadLocal(ctx);
4004:                    cf.add(Opcode.LDC, cf.addConstant(symbol));
4005:                    cf.add(Opcode.INVOKEVIRTUAL, "pnuts.lang.Context", "getId",
4006:                            "(Ljava/lang/String;)", "Ljava/lang/Object;");
4007:                }
4008:                return null;
4009:            }
4010:
4011:            public Object global(SimpleNode node, Context context) {
4012:                CompileContext cc = (CompileContext) context;
4013:                ClassFile cf = cc.cf;
4014:                int ctx = cc.getContextIndex();
4015:
4016:                cf.add(Opcode.LDC, cf.addConstant(""));
4017:                cf.loadLocal(ctx);
4018:                cf.add(Opcode.INVOKESTATIC, "pnuts.lang.Package", "find",
4019:                        "(Ljava/lang/String;Lpnuts/lang/Context;)",
4020:                        "Lpnuts/lang/Package;");
4021:
4022:                int gbl = cf.getLocal();
4023:                cf.add(Opcode.DUP);
4024:                cf.storeLocal(gbl);
4025:
4026:                Label else_ = cf.getLabel();
4027:                cf.add(Opcode.IFNULL, else_);
4028:
4029:                cf.loadLocal(gbl);
4030:                int symbol = cf.addConstant(node.str);
4031:                cf.add(Opcode.LDC, symbol);
4032:                cf.loadLocal(ctx);
4033:
4034:                cf.add(Opcode.INVOKEVIRTUAL, "pnuts.lang.Package", "lookup",
4035:                        "(Ljava/lang/String;Lpnuts/lang/Context;)",
4036:                        "Lpnuts/lang/NamedValue;");
4037:
4038:                int val = cf.getLocal();
4039:                cf.add(Opcode.DUP);
4040:                cf.storeLocal(val);
4041:
4042:                cf.add(Opcode.IFNULL, else_);
4043:
4044:                cf.loadLocal(val);
4045:                cf.add(Opcode.INVOKEINTERFACE, "pnuts.lang.Value", "get", "()",
4046:                        "Ljava/lang/Object;");
4047:
4048:                Label next = cf.getLabel();
4049:                cf.add(Opcode.GOTO, next);
4050:                else_.fix();
4051:                errorSymbol(cf, "not.defined", symbol, cc);
4052:                next.fix();
4053:
4054:                cf.freeLocal(gbl);
4055:                return null;
4056:            }
4057:
4058:            public Object listElements(SimpleNode node, Context context) {
4059:                if ("{".equals(node.str)) {
4060:                    buildList(node, context);
4061:                } else {
4062:                    buildArray(node, context);
4063:                }
4064:                return null;
4065:            }
4066:
4067:            void buildList(SimpleNode node, Context context) {
4068:                int n = node.jjtGetNumChildren();
4069:                CompileContext cc = (CompileContext) context;
4070:                ClassFile cf = cc.cf;
4071:                int ctx = cc.getContextIndex();
4072:                boolean hasTryStatement = (node.getAttribute("hasTryStatement") != null);
4073:                if (hasTryStatement) {
4074:                    int[] vars = new int[n];
4075:                    for (int i = 0; i < n; i++) {
4076:                        int var = cf.getLocal();
4077:                        accept(node, i, context);
4078:                        cf.storeLocal(var);
4079:                        vars[i] = var;
4080:                    }
4081:                    cf.loadLocal(ctx);
4082:                    cf.add(Opcode.INVOKESTATIC, "pnuts.lang.Runtime",
4083:                            "createList", "(Lpnuts/lang/Context;)",
4084:                            "Ljava/util/List;");
4085:                    int ret = cf.getLocal();
4086:                    cf.storeLocal(ret);
4087:                    for (int i = 0; i < n; i++) {
4088:                        cf.loadLocal(ret);
4089:                        accept(node, i, context);
4090:                        cf.add(Opcode.INVOKEINTERFACE, "java.util.List", "add",
4091:                                "(Ljava/lang/Object;)", "Z");
4092:                        cf.add(Opcode.POP);
4093:                    }
4094:                    for (int i = 0; i < n; i++) {
4095:                        cf.freeLocal(vars[i]);
4096:                    }
4097:                    cf.loadLocal(ret);
4098:                } else {
4099:                    cf.loadLocal(ctx);
4100:                    cf.add(Opcode.INVOKESTATIC, "pnuts.lang.Runtime",
4101:                            "createList", "(Lpnuts/lang/Context;)",
4102:                            "Ljava/util/List;");
4103:                    int ret = cf.getLocal();
4104:                    cf.storeLocal(ret);
4105:                    for (int i = 0; i < n; i++) {
4106:                        cf.loadLocal(ret);
4107:                        accept(node, i, context);
4108:                        cf.add(Opcode.INVOKEINTERFACE, "java.util.List", "add",
4109:                                "(Ljava/lang/Object;)", "Z");
4110:                        cf.add(Opcode.POP);
4111:                    }
4112:                    cf.loadLocal(ret);
4113:                }
4114:            }
4115:
4116:            void buildArray(SimpleNode node, Context context) {
4117:                CompileContext cc = (CompileContext) context;
4118:                ClassFile cf = cc.cf;
4119:                int ctx = cc.getContextIndex();
4120:                _listElements(node, context);
4121:                cf.loadLocal(ctx);
4122:                cf.add(Opcode.INVOKESTATIC, "pnuts.lang.Runtime", "makeArray",
4123:                        "([Ljava/lang/Object;Lpnuts/lang/Context;)",
4124:                        "Ljava/lang/Object;");
4125:            }
4126:
4127:            public Object _listElements(SimpleNode node, Context context) {
4128:                CompileContext cc = (CompileContext) context;
4129:                ClassFile cf = cc.cf;
4130:
4131:                int n = node.jjtGetNumChildren();
4132:                if (n == 0) {
4133:                    cf.add(Opcode.GETSTATIC, cc.constClassName, "NO_PARAM",
4134:                            "[Ljava/lang/Object;");
4135:                } else {
4136:                    boolean hasTryStatement = (node
4137:                            .getAttribute("hasTryStatement") != null);
4138:                    if (hasTryStatement) {
4139:                        int[] vars = new int[n];
4140:                        for (int i = 0; i < n; i++) {
4141:                            int var = cf.getLocal();
4142:                            accept(node, i, context);
4143:                            cf.storeLocal(var);
4144:                            vars[i] = var;
4145:                        }
4146:                        cf.pushInteger(n);
4147:                        cf.add(Opcode.ANEWARRAY, "java.lang.Object");
4148:                        for (int i = 0; i < n; i++) {
4149:                            cf.add(Opcode.DUP);
4150:                            cf.pushInteger(i);
4151:                            cf.loadLocal(vars[i]);
4152:                            cf.add(Opcode.AASTORE);
4153:                        }
4154:                        for (int i = 0; i < n; i++) {
4155:                            cf.freeLocal(vars[i]);
4156:                        }
4157:                    } else {
4158:                        cf.pushInteger(n);
4159:                        cf.add(Opcode.ANEWARRAY, "java.lang.Object");
4160:                        for (int i = 0; i < n; i++) {
4161:                            cf.add(Opcode.DUP);
4162:                            cf.pushInteger(i);
4163:                            accept(node, i, context);
4164:                            cf.add(Opcode.AASTORE);
4165:                        }
4166:                    }
4167:                }
4168:                return null;
4169:            }
4170:
4171:            public Object mapNode(SimpleNode node, Context context) {
4172:                CompileContext cc = (CompileContext) context;
4173:                ClassFile cf = cc.cf;
4174:                int n = node.jjtGetNumChildren();
4175:                cf.pushInteger(n);
4176:                cf.loadLocal(cc.getContextIndex());
4177:                cf.add(Opcode.INVOKESTATIC, "pnuts.lang.Runtime", "createMap",
4178:                        "(ILpnuts/lang/Context;)", "Ljava/util/Map;");
4179:                int map = cf.getLocal();
4180:                cf.storeLocal(map);
4181:                for (int i = 0; i < n; i++) {
4182:                    SimpleNode c = node.jjtGetChild(i);
4183:                    cf.loadLocal(map);
4184:                    accept(c, 0, context);
4185:                    accept(c, 1, context);
4186:                    cf.add(Opcode.INVOKEINTERFACE, "java.util.Map", "put",
4187:                            "(Ljava/lang/Object;Ljava/lang/Object;)",
4188:                            "Ljava/lang/Object;");
4189:                    cf.add(Opcode.POP);
4190:                }
4191:                cf.loadLocal(map);
4192:                return null;
4193:            }
4194:
4195:            public Object castExpression(SimpleNode node, Context context) {
4196:                CompileContext cc = (CompileContext) context;
4197:                ClassFile cf = cc.cf;
4198:                int ctx = cc.getContextIndex();
4199:
4200:                int tgt = cf.getLocal();
4201:                accept(node, 1, context);
4202:                cf.storeLocal(tgt);
4203:
4204:                cf.loadLocal(ctx);
4205:                resolveType(node.jjtGetChild(0), cc, ctx);
4206:                cf.loadLocal(tgt);
4207:                cf.freeLocal(tgt);
4208:                cf.add(Opcode.ICONST_1);
4209:                cf
4210:                        .add(
4211:                                Opcode.INVOKESTATIC,
4212:                                "pnuts.lang.Runtime",
4213:                                "cast",
4214:                                "(Lpnuts/lang/Context;Ljava/lang/Class;Ljava/lang/Object;Z)",
4215:                                "Ljava/lang/Object;");
4216:                return null;
4217:            }
4218:
4219:            public Object memberNode(SimpleNode node, Context context) {
4220:                CompileContext cc = (CompileContext) context;
4221:                ClassFile cf = cc.cf;
4222:                int ctx = cc.getContextIndex();
4223:
4224:                accept(node, 0, context);
4225:                int tgt = cf.getLocal();
4226:                cf.storeLocal(tgt);
4227:
4228:                Label else_end = cf.getLabel();
4229:
4230:                if ("length".equals(node.str)) {
4231:                    cf.loadLocal(tgt);
4232:                    cf.add(Opcode.INVOKESTATIC, "pnuts.lang.Runtime",
4233:                            "isArray", "(Ljava/lang/Object;)", "Z");
4234:                    Label else_ = cf.getLabel();
4235:                    cf.add(Opcode.IFEQ, else_);
4236:
4237:                    if (hasValueOfPrimitive) {
4238:                        cf.loadLocal(tgt);
4239:                        cf.add(Opcode.INVOKESTATIC, "java.lang.reflect.Array",
4240:                                "getLength", "(Ljava/lang/Object;)", "I");
4241:                        cf.add(Opcode.INVOKESTATIC, "java.lang.Integer",
4242:                                "valueOf", "(I)", "Ljava/lang/Integer;");
4243:                    } else {
4244:                        cf.add(Opcode.NEW, "java.lang.Integer");
4245:                        cf.add(Opcode.DUP);
4246:                        cf.loadLocal(tgt);
4247:                        cf.add(Opcode.INVOKESTATIC, "java.lang.reflect.Array",
4248:                                "getLength", "(Ljava/lang/Object;)", "I");
4249:                        cf.add(Opcode.INVOKESPECIAL, "java.lang.Integer",
4250:                                "<init>", "(I)", "V");
4251:                    }
4252:
4253:                    cf.add(Opcode.GOTO, else_end);
4254:                    else_.fix();
4255:                    cf.popStack();
4256:                }
4257:
4258:                if (node.info != null) { /* experimental BIND feature */
4259:                    Object[] info = (Object[]) node.info;
4260:                    int targetIndex = ((int[]) info[0])[0];
4261:                    int tableIndex = ((int[]) info[0])[1];
4262:                    final SimpleNode c = (SimpleNode) info[1];
4263:                    SimpleNode c0 = c.jjtGetChild(0);
4264:
4265:                    cf.loadLocal(tableIndex);
4266:                    cf.loadLocal(targetIndex);
4267:                    cf.add(Opcode.LDC, cf.addConstant(c.str));
4268:                    cf.loadLocal(tgt);
4269:                    cf.add(Opcode.LDC, cf.addConstant(node.str));
4270:                    toFunctionNode(c0).accept(this , context);
4271:                    cf
4272:                            .add(
4273:                                    Opcode.INVOKESTATIC,
4274:                                    "pnuts.lang.Runtime",
4275:                                    "watchProperty",
4276:                                    "(Ljava/util/Map;Ljava/lang/Object;Ljava/lang/String;Ljava/lang/Object;Ljava/lang/String;Lpnuts/lang/Callable;)",
4277:                                    "V");
4278:
4279:                    if (c0 == node) {
4280:                        cf.loadLocal(tableIndex);
4281:                        cf.loadLocal(tgt);
4282:                        cf.add(Opcode.LDC, cf.addConstant(node.str));
4283:                        cf.loadLocal(targetIndex);
4284:                        cf.add(Opcode.LDC, cf.addConstant(c.str));
4285:                        cf.add(Opcode.ACONST_NULL);
4286:                        cf
4287:                                .add(
4288:                                        Opcode.INVOKESTATIC,
4289:                                        "pnuts.lang.Runtime",
4290:                                        "watchProperty",
4291:                                        "(Ljava/util/Map;Ljava/lang/Object;Ljava/lang/String;Ljava/lang/Object;Ljava/lang/String;Lpnuts/lang/Callable;)",
4292:                                        "V");
4293:                    }
4294:                    node.info = null;
4295:                }
4296:
4297:                cf.loadLocal(ctx);
4298:                cf.loadLocal(tgt);
4299:                cf.add(Opcode.LDC, cf.addConstant(node.str));
4300:                cf
4301:                        .add(
4302:                                Opcode.INVOKESTATIC,
4303:                                "pnuts.lang.Runtime",
4304:                                "getField",
4305:                                "(Lpnuts/lang/Context;Ljava/lang/Object;Ljava/lang/String;)",
4306:                                "Ljava/lang/Object;");
4307:                else_end.fix();
4308:                cf.freeLocal(tgt);
4309:                return null;
4310:            }
4311:
4312:            public Object methodNode(SimpleNode node, Context context) {
4313:                CompileContext cc = (CompileContext) context;
4314:                ClassFile cf = cc.cf;
4315:                int ctx = cc.getContextIndex();
4316:
4317:                addLineInfo(cc, ctx, node);
4318:
4319:                accept(node, 0, context);
4320:                int tgt = cf.getLocal();
4321:                cf.storeLocal(tgt);
4322:
4323:                SimpleNode argNode = node.jjtGetChild(1);
4324:                int nargs = argNode.jjtGetNumChildren();
4325:                int arg = cf.getLocal();
4326:                //	accept(node, 1, context);
4327:                _listElements(argNode, context);
4328:                cf.storeLocal(arg);
4329:
4330:                boolean types_created = false;
4331:                for (int i = 0; i < nargs; i++) {
4332:                    SimpleNode n = argNode.jjtGetChild(i);
4333:                    if (n.id == PnutsParserTreeConstants.JJTCASTEXPRESSION) {
4334:                        if (!types_created) {
4335:                            cf.pushInteger(nargs);
4336:                            cf.add(Opcode.ANEWARRAY, "java.lang.Class");
4337:                            types_created = true;
4338:                        }
4339:                        cf.add(Opcode.DUP);
4340:                        cf.pushInteger(i);
4341:                        resolveType(n.jjtGetChild(0), cc, ctx);
4342:                        cf.add(Opcode.AASTORE);
4343:                    }
4344:                }
4345:                int types = 0;
4346:                if (types_created) {
4347:                    types = cf.getLocal();
4348:                    cf.storeLocal(types);
4349:                }
4350:
4351:                cf.loadLocal(ctx);
4352:                cf.loadLocal(tgt);
4353:                cf.add(Opcode.INVOKEVIRTUAL, "java.lang.Object", "getClass",
4354:                        "()", "Ljava/lang/Class;");
4355:                cf.add(Opcode.LDC, cf.addConstant(node.str));
4356:                cf.loadLocal(arg);
4357:                cf.freeLocal(arg);
4358:
4359:                if (types_created) {
4360:                    cf.loadLocal(types);
4361:                } else {
4362:                    cf.add(Opcode.ACONST_NULL);
4363:                }
4364:                cf.loadLocal(tgt);
4365:                cf.freeLocal(tgt);
4366:
4367:                cf
4368:                        .add(
4369:                                Opcode.INVOKESTATIC,
4370:                                "pnuts.lang.Runtime",
4371:                                "callMethod",
4372:                                "(Lpnuts/lang/Context;Ljava/lang/Class;Ljava/lang/String;[Ljava/lang/Object;[Ljava/lang/Class;Ljava/lang/Object;)",
4373:                                "Ljava/lang/Object;");
4374:                return null;
4375:            }
4376:
4377:            public Object className(SimpleNode node, Context context) {
4378:                CompileContext cc = (CompileContext) context;
4379:                int ctx = cc.getContextIndex();
4380:                resolveClassName(node, cc, ctx);
4381:                return null;
4382:            }
4383:
4384:            /*
4385:             * ArrayType .. ArrayType IndexNode IdNode IntegerNode
4386:             */
4387:            public Object arrayType(SimpleNode node, Context context) {
4388:                CompileContext cc = (CompileContext) context;
4389:                ClassFile cf = cc.cf;
4390:
4391:                SimpleNode n = node;
4392:                int count = 0;
4393:                while (n != null
4394:                        && n.id == PnutsParserTreeConstants.JJTARRAYTYPE) {
4395:                    count++;
4396:                    n = n.jjtGetChild(0);
4397:                }
4398:                if (n != null && n.id == PnutsParserTreeConstants.JJTINDEXNODE) {
4399:                    Label clserr = cf.getLabel();
4400:                    Label numerr = cf.getLabel();
4401:
4402:                    Object[] idx = parseIndex(n);
4403:                    SimpleNode idx0 = (SimpleNode) idx[0];
4404:                    idx0.accept(this , context);
4405:                    cf.add(Opcode.DUP);
4406:                    cf.add(Opcode.INSTANCEOF, "java.lang.Class");
4407:
4408:                    cf.add(Opcode.IFEQ, clserr);
4409:                    cf.add(Opcode.CHECKCAST, "java.lang.Class");
4410:
4411:                    cf.pushInteger(count);
4412:                    cf.add(Opcode.INVOKESTATIC, "pnuts.lang.Runtime",
4413:                            "arrayType", "(Ljava/lang/Class;I)",
4414:                            "Ljava/lang/Class;");
4415:
4416:                    Object[] dim = (Object[]) idx[1];
4417:
4418:                    cf.pushInteger(dim.length);
4419:                    cf.add(Opcode.NEWARRAY, Opcode.T_INT);
4420:                    int dlen = dim.length;
4421:                    for (int i = 0; i < dlen; i++) {
4422:                        cf.add(Opcode.DUP);
4423:                        cf.pushInteger(i);
4424:                        ((SimpleNode) dim[i]).accept(this , context);
4425:                        /*
4426:                         * cf.add(Opcode.DUP); cf.add(Opcode.INSTANCEOF,
4427:                         * "java.lang.Number"); cf.add(Opcode.IFEQ, numerr);
4428:                         */
4429:                        cf.add(Opcode.CHECKCAST, "java.lang.Number");
4430:                        cf.add(Opcode.INVOKEVIRTUAL, "java.lang.Number",
4431:                                "intValue", "()", "I");
4432:                        cf.add(Opcode.IASTORE);
4433:                    }
4434:
4435:                    cf.add(Opcode.INVOKESTATIC, "java.lang.reflect.Array",
4436:                            "newInstance", "(Ljava/lang/Class;[I)",
4437:                            "Ljava/lang/Object;");
4438:                    Label next = cf.getLabel();
4439:                    cf.add(Opcode.GOTO, next);
4440:                    numerr.fix();
4441:                    error(cf, "number.expected", cc);
4442:                    cf.add(Opcode.GOTO, next);
4443:                    clserr.fix();
4444:                    error(cf, "classOrArray.expected", cc);
4445:                    next.fix();
4446:                    return null;
4447:                } else if (node.jjtGetParent().id != PnutsParserTreeConstants.JJTNEW) {
4448:                    n.accept(this , context);
4449:                    int type = cf.getLocal();
4450:                    cf.add(Opcode.DUP);
4451:                    cf.storeLocal(type);
4452:
4453:                    cf.add(Opcode.INSTANCEOF, "java.lang.Class");
4454:                    Label err = cf.getLabel();
4455:                    cf.add(Opcode.IFEQ, err);
4456:                    cf.loadLocal(type);
4457:                    cf.freeLocal(type);
4458:                    cf.add(Opcode.CHECKCAST, "java.lang.Class");
4459:                    cf.pushInteger(count);
4460:                    cf.add(Opcode.INVOKESTATIC, "pnuts.lang.Runtime",
4461:                            "arrayType", "(Ljava/lang/Class;I)",
4462:                            "Ljava/lang/Class;");
4463:                    Label next = cf.getLabel();
4464:                    cf.add(Opcode.GOTO, next);
4465:                    err.fix();
4466:                    error(cf, "classOrArray.expected", new int[] { type }, cc);
4467:                    next.fix();
4468:                } else {
4469:                    cf.add(Opcode.NEW, "java.lang.IllegalArgumentException");
4470:                    cf.add(Opcode.DUP);
4471:                    cf.add(Opcode.INVOKESPECIAL,
4472:                            "java.lang.IllegalArgumentException", "<init>",
4473:                            "()", "V");
4474:                    cf.add(Opcode.ATHROW);
4475:                }
4476:                return null;
4477:            }
4478:
4479:            /**
4480:             * @return [base_component_node, [idx_node_0, idx_node_1, ...]]
4481:             */
4482:            static Object[] parseIndex(SimpleNode node) {
4483:                SimpleNode c0 = node.jjtGetChild(0);
4484:                SimpleNode c1 = node.jjtGetChild(1);
4485:                if (c0.id != PnutsParserTreeConstants.JJTINDEXNODE) {
4486:                    return new Object[] { c0, new Object[] { c1 } };
4487:                } else {
4488:                    Object[] r = parseIndex(c0);
4489:                    Object[] d = (Object[]) r[1];
4490:                    Object[] a = new Object[d.length + 1];
4491:                    System.arraycopy(d, 0, a, 0, d.length);
4492:                    a[d.length] = c1;
4493:                    return new Object[] { r[0], a };
4494:                }
4495:            }
4496:
4497:            static void convertIndexNode(SimpleNode node) {
4498:                SimpleNode n0 = node.jjtGetChild(0);
4499:                SimpleNode n1 = node.jjtGetChild(1);
4500:                if (ConstraintsTransformer.isPredicate(n1)) {
4501:                    SimpleNode n = ConstraintsTransformer.buildFunc(n1);
4502:                    node.jjtAddChild(n, 1);
4503:                    n.jjtSetParent(node);
4504:                }
4505:                if (n0.id == PnutsParserTreeConstants.JJTINDEXNODE) {
4506:                    convertIndexNode(n0);
4507:                }
4508:            }
4509:
4510:            public Object indexNode(SimpleNode node, Context context) {
4511:                FrameInfo info = (FrameInfo) node.getAttribute("frameInfo");
4512:                if (info == null) {
4513:                    node.setAttribute("frameInfo", info = new FrameInfo());
4514:                }
4515:
4516:                if (!info.preprocessed) {
4517:                    info.preprocessed = true;
4518:                    convertIndexNode(node);
4519:                }
4520:
4521:                CompileContext cc = (CompileContext) context;
4522:                ClassFile cf = cc.cf;
4523:                Object[] idx = parseIndex(node);
4524:                SimpleNode c = (SimpleNode) idx[0];
4525:                c.accept(this , context);
4526:                int tgt = cf.getLocal();
4527:                cf.storeLocal(tgt);
4528:
4529:                Object[] dim = (Object[]) idx[1];
4530:
4531:                Label else_end = cf.getLabel();
4532:                int ctx = cc.getContextIndex();
4533:
4534:                if (c.id == PnutsParserTreeConstants.JJTCLASS
4535:                        || c.id == PnutsParserTreeConstants.JJTIDNODE) {
4536:                    cf.loadLocal(tgt);
4537:                    cf.add(Opcode.INSTANCEOF, "java.lang.Class");
4538:                    Label else_ = cf.getLabel();
4539:                    cf.add(Opcode.IFEQ, else_);
4540:
4541:                    if (node.getAttribute("hasTryStatement") != null) {
4542:                        int[] vars = new int[dim.length];
4543:                        for (int i = 0; i < dim.length; i++) {
4544:                            int var = cf.getLocal();
4545:                            ((SimpleNode) dim[i]).accept(this , context);
4546:                            cf.storeLocal(var);
4547:                            vars[i] = var;
4548:                        }
4549:                        cf.loadLocal(tgt);
4550:                        cf.add(Opcode.CHECKCAST, "java.lang.Class");
4551:                        cf.pushInteger(dim.length);
4552:                        cf.add(Opcode.NEWARRAY, Opcode.T_INT);
4553:                        for (int i = 0; i < dim.length; i++) {
4554:                            cf.add(Opcode.DUP);
4555:                            cf.pushInteger(i);
4556:                            cf.loadLocal(vars[i]);
4557:                            cf.add(Opcode.CHECKCAST, "java.lang.Number");
4558:                            cf.add(Opcode.INVOKEVIRTUAL, "java.lang.Number",
4559:                                    "intValue", "()", "I");
4560:                            cf.add(Opcode.IASTORE);
4561:                        }
4562:                        for (int i = 0; i < dim.length; i++) {
4563:                            cf.freeLocal(vars[i]);
4564:                        }
4565:
4566:                    } else {
4567:                        cf.loadLocal(tgt);
4568:                        cf.add(Opcode.CHECKCAST, "java.lang.Class");
4569:                        cf.pushInteger(dim.length);
4570:                        cf.add(Opcode.NEWARRAY, Opcode.T_INT);
4571:                        for (int i = 0; i < dim.length; i++) {
4572:                            cf.add(Opcode.DUP);
4573:                            cf.pushInteger(i);
4574:                            ((SimpleNode) dim[i]).accept(this , context);
4575:
4576:                            cf.add(Opcode.CHECKCAST, "java.lang.Number");
4577:                            cf.add(Opcode.INVOKEVIRTUAL, "java.lang.Number",
4578:                                    "intValue", "()", "I");
4579:                            cf.add(Opcode.IASTORE);
4580:                        }
4581:                    }
4582:                    cf.add(Opcode.INVOKESTATIC, "java.lang.reflect.Array",
4583:                            "newInstance", "(Ljava/lang/Class;[I)",
4584:                            "Ljava/lang/Object;");
4585:                    cf.add(Opcode.GOTO, else_end);
4586:                    else_.fix();
4587:                    cf.popStack();
4588:                }
4589:
4590:                for (int i = 0; i < dim.length; i++) {
4591:                    ((SimpleNode) dim[i]).accept(this , context);
4592:                    int _idx = cf.getLocal();
4593:                    cf.storeLocal(_idx);
4594:
4595:                    cf.loadLocal(tgt);
4596:                    cf.loadLocal(_idx);
4597:                    cf.loadLocal(ctx);
4598:                    cf
4599:                            .add(
4600:                                    Opcode.INVOKESTATIC,
4601:                                    "pnuts.lang.Runtime",
4602:                                    "getElement",
4603:                                    "(Ljava/lang/Object;Ljava/lang/Object;Lpnuts/lang/Context;)",
4604:                                    "Ljava/lang/Object;");
4605:                    cf.storeLocal(tgt);
4606:                }
4607:                cf.loadLocal(tgt);
4608:
4609:                else_end.fix();
4610:                cf.freeLocal(tgt);
4611:                return null;
4612:            }
4613:
4614:            public Object instanceof Expression(SimpleNode node, Context context) {
4615:                CompileContext cc = (CompileContext) context;
4616:                ClassFile cf = cc.cf;
4617:                int ctx = cc.getContextIndex();
4618:
4619:                Label next = cf.getLabel();
4620:                Label l_false = cf.getLabel();
4621:
4622:                resolveType(node.jjtGetChild(1), cc, ctx);
4623:                accept(node, 0, context);
4624:
4625:                cf.add(Opcode.INVOKEVIRTUAL, "java.lang.Class", "isInstance",
4626:                        "(Ljava/lang/Object;)", "Z");
4627:                cf.add(Opcode.IFEQ, l_false);
4628:                cf.add(Opcode.GETSTATIC, "java.lang.Boolean", "TRUE",
4629:                        "Ljava/lang/Boolean;");
4630:                cf.add(Opcode.GOTO, next);
4631:                l_false.fix();
4632:                cf.add(Opcode.GETSTATIC, "java.lang.Boolean", "FALSE",
4633:                        "Ljava/lang/Boolean;");
4634:                next.fix();
4635:                return null;
4636:            }
4637:
4638:            public Object assignment(SimpleNode node, Context context) {
4639:                SimpleNode lhs = node.jjtGetChild(0);
4640:                if (lhs.id == PnutsParserTreeConstants.JJTMULTIASSIGNLHS) {
4641:                    SimpleNode rhs = node.jjtGetChild(1);
4642:                    if (rhs.id == PnutsParserTreeConstants.JJTLISTELEMENTS) {
4643:                        return multiAssignFast(lhs, rhs, context);
4644:                    } else {
4645:                        return multiAssign(lhs, rhs, context);
4646:                    }
4647:                } else {
4648:                    return assign(node, context,
4649:                            PnutsParserTreeConstants.JJTASSIGNMENT);
4650:                }
4651:            }
4652:
4653:            Object multiAssignFast(SimpleNode lhs, SimpleNode rhs,
4654:                    Context context) {
4655:                CompileContext cc = (CompileContext) context;
4656:                int ctx = cc.getContextIndex();
4657:                ClassFile cf = cc.cf;
4658:                int n = lhs.jjtGetNumChildren();
4659:                int[] r_array = new int[n];
4660:                for (int i = 0; i < n; i++) {
4661:                    SimpleNode _rhs = rhs.jjtGetChild(i);
4662:                    int r = r_array[i] = cf.getLocal();
4663:                    _rhs.accept(this , context);
4664:                    cf.storeLocal(r);
4665:                }
4666:                for (int i = 0; i < n; i++) {
4667:                    SimpleNode _lhs = lhs.jjtGetChild(i);
4668:                    assignId(cf, PnutsParserTreeConstants.JJTASSIGNMENT, ctx,
4669:                            r_array[i], _lhs, cc, false, false);
4670:                }
4671:                cf.add(Opcode.ACONST_NULL);
4672:                for (int i = 0; i < n; i++) {
4673:                    cf.freeLocal(r_array[i]);
4674:                }
4675:                return null;
4676:            }
4677:
4678:            Object multiAssign(SimpleNode lhs, SimpleNode rhs, Context context) {
4679:                CompileContext cc = (CompileContext) context;
4680:                int ctx = cc.getContextIndex();
4681:                ClassFile cf = cc.cf;
4682:                int n = lhs.jjtGetNumChildren();
4683:                int expr = cf.getLocal();
4684:                int _rhs = cf.getLocal();
4685:                rhs.accept(this , context);
4686:                cf.storeLocal(expr);
4687:                for (int i = 0; i < n; i++) {
4688:                    cf.loadLocal(expr);
4689:                    cf.pushInteger(i);
4690:                    cf.loadLocal(ctx);
4691:                    cf.add(Opcode.INVOKESTATIC, "pnuts.lang.Runtime",
4692:                            "getElementAt",
4693:                            "(Ljava/lang/Object;ILpnuts/lang/Context;)",
4694:                            "Ljava/lang/Object;");
4695:                    cf.storeLocal(_rhs);
4696:                    SimpleNode _lhs = lhs.jjtGetChild(i);
4697:                    assignId(cf, PnutsParserTreeConstants.JJTASSIGNMENT, ctx,
4698:                            _rhs, _lhs, cc, false, true);
4699:                    cf.add(Opcode.POP);
4700:                }
4701:                cf.loadLocal(expr);
4702:                return null;
4703:            }
4704:
4705:            public Object assignmentTA(SimpleNode node, Context context) {
4706:                return assign(node, context,
4707:                        PnutsParserTreeConstants.JJTASSIGNMENTTA);
4708:            }
4709:
4710:            public Object assignmentMA(SimpleNode node, Context context) {
4711:                return assign(node, context,
4712:                        PnutsParserTreeConstants.JJTASSIGNMENTMA);
4713:            }
4714:
4715:            public Object assignmentDA(SimpleNode node, Context context) {
4716:                return assign(node, context,
4717:                        PnutsParserTreeConstants.JJTASSIGNMENTDA);
4718:            }
4719:
4720:            public Object assignmentPA(SimpleNode node, Context context) {
4721:                return assign(node, context,
4722:                        PnutsParserTreeConstants.JJTASSIGNMENTPA);
4723:            }
4724:
4725:            public Object assignmentSA(SimpleNode node, Context context) {
4726:                return assign(node, context,
4727:                        PnutsParserTreeConstants.JJTASSIGNMENTSA);
4728:            }
4729:
4730:            public Object assignmentLA(SimpleNode node, Context context) {
4731:                return assign(node, context,
4732:                        PnutsParserTreeConstants.JJTASSIGNMENTLA);
4733:            }
4734:
4735:            public Object assignmentRA(SimpleNode node, Context context) {
4736:                return assign(node, context,
4737:                        PnutsParserTreeConstants.JJTASSIGNMENTRA);
4738:            }
4739:
4740:            public Object assignmentRAA(SimpleNode node, Context context) {
4741:                return assign(node, context,
4742:                        PnutsParserTreeConstants.JJTASSIGNMENTRAA);
4743:            }
4744:
4745:            public Object assignmentAA(SimpleNode node, Context context) {
4746:                return assign(node, context,
4747:                        PnutsParserTreeConstants.JJTASSIGNMENTAA);
4748:            }
4749:
4750:            public Object assignmentEA(SimpleNode node, Context context) {
4751:                return assign(node, context,
4752:                        PnutsParserTreeConstants.JJTASSIGNMENTEA);
4753:            }
4754:
4755:            public Object assignmentOA(SimpleNode node, Context context) {
4756:                return assign(node, context,
4757:                        PnutsParserTreeConstants.JJTASSIGNMENTOA);
4758:            }
4759:
4760:            public Object preIncrNode(SimpleNode node, Context context) {
4761:                SimpleNode node0 = node.jjtGetChild(0);
4762:                node0.accept(this , context);
4763:                _assign(node0, context,
4764:                        PnutsParserTreeConstants.JJTASSIGNMENTPA | 0x8000,
4765:                        false, true);
4766:                return null;
4767:            }
4768:
4769:            public Object preDecrNode(SimpleNode node, Context context) {
4770:                SimpleNode node0 = node.jjtGetChild(0);
4771:                node0.accept(this , context);
4772:                _assign(node0, context,
4773:                        PnutsParserTreeConstants.JJTASSIGNMENTSA | 0x8000,
4774:                        false, true);
4775:                return null;
4776:            }
4777:
4778:            public Object postIncrNode(SimpleNode node, Context context) {
4779:                CompileContext cc = (CompileContext) context;
4780:                ClassFile cf = cc.cf;
4781:                accept(node, 0, context);
4782:                int ret = cf.getLocal();
4783:                cf.storeLocal(ret);
4784:                cf.loadLocal(ret);
4785:
4786:                _assign(node.jjtGetChild(0), cc,
4787:                        PnutsParserTreeConstants.JJTASSIGNMENTPA | 0x8000,
4788:                        false, false);
4789:                cf.loadLocal(ret);
4790:                cf.freeLocal(ret);
4791:                return null;
4792:            }
4793:
4794:            public Object postDecrNode(SimpleNode node, Context context) {
4795:                CompileContext cc = (CompileContext) context;
4796:                ClassFile cf = cc.cf;
4797:
4798:                accept(node, 0, context);
4799:                int ret = cf.getLocal();
4800:                cf.storeLocal(ret);
4801:                cf.loadLocal(ret);
4802:
4803:                _assign(node.jjtGetChild(0), context,
4804:                        PnutsParserTreeConstants.JJTASSIGNMENTSA | 0x8000,
4805:                        false, false);
4806:
4807:                cf.loadLocal(ret);
4808:                cf.freeLocal(ret);
4809:                return null;
4810:            }
4811:
4812:            public Object staticMethodNode(SimpleNode node, Context context) {
4813:                CompileContext cc = (CompileContext) context;
4814:                ClassFile cf = cc.cf;
4815:                int ctx = cc.getContextIndex();
4816:
4817:                addLineInfo(cc, ctx, node);
4818:
4819:                SimpleNode argNode = node.jjtGetChild(1);
4820:                int nargs = argNode.jjtGetNumChildren();
4821:
4822:                //	accept(node, 1, context);
4823:                _listElements(argNode, context);
4824:                int args = cf.getLocal();
4825:                cf.storeLocal(args);
4826:
4827:                SimpleNode c1 = node.jjtGetChild(0);
4828:                String pkgName = getPackageName(c1);
4829:
4830:                cf.add(Opcode.LDC, cf.addConstant(pkgName));
4831:                cf.loadLocal(ctx);
4832:
4833:                cf.add(Opcode.INVOKESTATIC, "pnuts.lang.Package", "find",
4834:                        "(Ljava/lang/String;Lpnuts/lang/Context;)",
4835:                        "Lpnuts/lang/Package;");
4836:                int pkg = cf.getLocal();
4837:                cf.add(Opcode.DUP);
4838:                cf.storeLocal(pkg);
4839:
4840:                Label l_null = cf.getLabel();
4841:                cf.add(Opcode.IFNULL, l_null);
4842:                cf.loadLocal(pkg);
4843:                cf.add(Opcode.LDC, cf.addConstant(node.str));
4844:                cf.loadLocal(ctx);
4845:                cf.add(Opcode.INVOKEVIRTUAL, "pnuts.lang.Package", "get",
4846:                        "(Ljava/lang/String;Lpnuts/lang/Context;)",
4847:                        "Ljava/lang/Object;");
4848:                int got = cf.getLocal();
4849:                cf.add(Opcode.DUP);
4850:                cf.storeLocal(got);
4851:
4852:                cf.add(Opcode.INSTANCEOF, "pnuts.lang.PnutsFunction");
4853:                Label l_else = cf.getLabel();
4854:                cf.add(Opcode.IFEQ, l_else);
4855:                cf.loadLocal(ctx);
4856:                cf.loadLocal(got);
4857:                cf.add(Opcode.CHECKCAST, "pnuts.lang.PnutsFunction");
4858:                cf.loadLocal(args);
4859:                cf
4860:                        .add(
4861:                                Opcode.INVOKESTATIC,
4862:                                "pnuts.lang.Runtime",
4863:                                "callFunction",
4864:                                "(Lpnuts/lang/Context;Lpnuts/lang/PnutsFunction;[Ljava/lang/Object;)",
4865:                                "Ljava/lang/Object;");
4866:                Label next = cf.getLabel();
4867:                cf.add(Opcode.GOTO, next);
4868:                l_else.fix();
4869:                cf.popStack();
4870:                cf.loadLocal(got);
4871:                cf.add(Opcode.INSTANCEOF, "java.lang.Class");
4872:                cf.add(Opcode.IFEQ, l_null);
4873:
4874:                boolean types_created = false;
4875:                for (int i = 0; i < nargs; i++) {
4876:                    SimpleNode n = argNode.jjtGetChild(i);
4877:                    if (n.id == PnutsParserTreeConstants.JJTCASTEXPRESSION) {
4878:                        if (!types_created) {
4879:                            cf.pushInteger(nargs);
4880:                            cf.add(Opcode.ANEWARRAY, "java.lang.Class");
4881:                            types_created = true;
4882:                        }
4883:                        cf.add(Opcode.DUP);
4884:                        cf.pushInteger(i);
4885:                        resolveType(n.jjtGetChild(0), cc, ctx);
4886:                        cf.add(Opcode.AASTORE);
4887:                    }
4888:                }
4889:                int types = 0;
4890:                if (types_created) {
4891:                    types = cf.getLocal();
4892:                    cf.storeLocal(types);
4893:                }
4894:
4895:                cf.loadLocal(ctx);
4896:                cf.loadLocal(got);
4897:                cf.add(Opcode.CHECKCAST, "java.lang.Class");
4898:                cf.loadLocal(args);
4899:                if (types_created) {
4900:                    cf.loadLocal(types);
4901:                } else {
4902:                    cf.add(Opcode.ACONST_NULL);
4903:                }
4904:                cf
4905:                        .add(
4906:                                Opcode.INVOKESTATIC,
4907:                                "pnuts.lang.Runtime",
4908:                                "newInstance",
4909:                                "(Lpnuts/lang/Context;Ljava/lang/Class;[Ljava/lang/Object;[Ljava/lang/Class;)",
4910:                                "Ljava/lang/Object;");
4911:
4912:                cf.add(Opcode.GOTO, next);
4913:
4914:                l_null.fix();
4915:                cf.popStack();
4916:                accept(node, 0, context);
4917:                int tgt = cf.getLocal();
4918:                cf.add(Opcode.DUP);
4919:                cf.storeLocal(tgt);
4920:
4921:                cf.add(Opcode.INSTANCEOF, "java.lang.Class");
4922:                Label ok = cf.getLabel();
4923:                cf.add(Opcode.IFNE, ok);
4924:                cf.add(Opcode.NEW, "pnuts.lang.PnutsException");
4925:                cf.add(Opcode.DUP);
4926:                cf.add(Opcode.LDC, cf.addConstant("illegal.staticCall"));
4927:                cf.add(Opcode.ICONST_3);
4928:                cf.add(Opcode.ANEWARRAY, "java.lang.Object");
4929:                cf.add(Opcode.DUP);
4930:                cf.add(Opcode.ICONST_0);
4931:                cf.add(Opcode.LDC, cf.addConstant(pkgName));
4932:                cf.add(Opcode.AASTORE);
4933:                cf.add(Opcode.DUP);
4934:                cf.add(Opcode.ICONST_1);
4935:                cf.add(Opcode.LDC, cf.addConstant(node.str));
4936:                cf.add(Opcode.AASTORE);
4937:                cf.add(Opcode.DUP);
4938:                cf.add(Opcode.ICONST_2);
4939:
4940:                if (hasValueOfPrimitive) {
4941:                    cf.pushInteger(nargs);
4942:                    cf.add(Opcode.INVOKESTATIC, "java.lang.Integer", "valueOf",
4943:                            "(I)", "Ljava/lang/Integer;");
4944:                } else {
4945:                    cf.add(Opcode.NEW, "java.lang.Integer");
4946:                    cf.add(Opcode.DUP);
4947:                    cf.pushInteger(nargs);
4948:                    cf.add(Opcode.INVOKESPECIAL, "java.lang.Integer", "<init>",
4949:                            "(I)", "V");
4950:                }
4951:
4952:                cf.add(Opcode.AASTORE);
4953:                cf.loadLocal(ctx);
4954:                cf
4955:                        .add(
4956:                                Opcode.INVOKESPECIAL,
4957:                                "pnuts.lang.PnutsException",
4958:                                "<init>",
4959:                                "(Ljava/lang/String;[Ljava/lang/Object;Lpnuts/lang/Context;)",
4960:                                "V");
4961:                cf.add(Opcode.ATHROW);
4962:                ok.fix();
4963:
4964:                types_created = false;
4965:                for (int i = 0; i < nargs; i++) {
4966:                    SimpleNode n = argNode.jjtGetChild(i);
4967:                    if (n.id == PnutsParserTreeConstants.JJTCASTEXPRESSION) {
4968:                        if (!types_created) {
4969:                            cf.pushInteger(nargs);
4970:                            cf.add(Opcode.ANEWARRAY, "java.lang.Class");
4971:                            types_created = true;
4972:                        }
4973:                        cf.add(Opcode.DUP);
4974:                        cf.pushInteger(i);
4975:                        resolveType(n.jjtGetChild(0), cc, ctx);
4976:                        cf.add(Opcode.AASTORE);
4977:                    }
4978:                }
4979:                types = 0;
4980:                if (types_created) {
4981:                    types = cf.getLocal();
4982:                    cf.storeLocal(types);
4983:                }
4984:                cf.loadLocal(ctx);
4985:                cf.loadLocal(tgt);
4986:                cf.add(Opcode.CHECKCAST, "java.lang.Class");
4987:                cf.add(Opcode.LDC, cf.addConstant(node.str));
4988:                cf.loadLocal(args);
4989:                if (types_created) {
4990:                    cf.loadLocal(types);
4991:                    cf.freeLocal(types);
4992:                } else {
4993:                    cf.add(Opcode.ACONST_NULL);
4994:                }
4995:                cf.add(Opcode.ACONST_NULL);
4996:
4997:                cf
4998:                        .add(
4999:                                Opcode.INVOKESTATIC,
5000:                                "pnuts.lang.Runtime",
5001:                                "callMethod",
5002:                                "(Lpnuts/lang/Context;Ljava/lang/Class;Ljava/lang/String;[Ljava/lang/Object;[Ljava/lang/Class;Ljava/lang/Object;)",
5003:                                "Ljava/lang/Object;");
5004:                next.fix();
5005:                return null;
5006:            }
5007:
5008:            public Object staticMemberNode(SimpleNode node, Context context) {
5009:                CompileContext cc = (CompileContext) context;
5010:                ClassFile cf = cc.cf;
5011:                int ctx = cc.getContextIndex();
5012:
5013:                addLineInfo(cc, ctx, node);
5014:
5015:                SimpleNode c1 = node.jjtGetChild(0);
5016:                Label next = cf.getLabel();
5017:
5018:                String pkgName = getPackageName(c1);
5019:
5020:                cf.add(Opcode.LDC, cf.addConstant(pkgName));
5021:                cf.loadLocal(ctx);
5022:                cf.add(Opcode.INVOKESTATIC, "pnuts.lang.Package", "find",
5023:                        "(Ljava/lang/String;Lpnuts/lang/Context;)",
5024:                        "Lpnuts/lang/Package;");
5025:                int pkg = cf.getLocal();
5026:                cf.add(Opcode.DUP);
5027:                cf.storeLocal(pkg);
5028:
5029:                Label l_null = cf.getLabel();
5030:                cf.add(Opcode.IFNULL, l_null);
5031:
5032:                cf.loadLocal(pkg);
5033:                cf.freeLocal(pkg);
5034:                cf.add(Opcode.LDC, cf.addConstant(node.str));
5035:                cf.loadLocal(ctx);
5036:                cf.add(Opcode.INVOKEVIRTUAL, "pnuts.lang.Package", "lookup",
5037:                        "(Ljava/lang/String;Lpnuts/lang/Context;)",
5038:                        "Lpnuts/lang/NamedValue;");
5039:
5040:                int val = cf.getLocal();
5041:                cf.add(Opcode.DUP);
5042:                cf.storeLocal(val);
5043:
5044:                Label undef = cf.getLabel();
5045:                cf.add(Opcode.IFNULL, undef);
5046:
5047:                cf.loadLocal(val);
5048:                cf.freeLocal(val);
5049:
5050:                cf.add(Opcode.INVOKEINTERFACE, "pnuts.lang.Value", "get", "()",
5051:                        "Ljava/lang/Object;");
5052:                cf.add(Opcode.GOTO, next);
5053:
5054:                undef.fix();
5055:                errorSymbol(cf, "not.defined", cf.addConstant(node.str), cc);
5056:                l_null.fix();
5057:
5058:                c1.accept(this , context);
5059:                int tgt = cf.getLocal();
5060:                cf.add(Opcode.DUP);
5061:                cf.storeLocal(tgt);
5062:
5063:                cf.add(Opcode.INSTANCEOF, "java.lang.Class");
5064:                Label err = cf.getLabel();
5065:                cf.add(Opcode.IFEQ, err);
5066:
5067:                cf.loadLocal(ctx);
5068:                cf.loadLocal(tgt);
5069:                cf.freeLocal(tgt);
5070:                cf.add(Opcode.CHECKCAST, "java.lang.Class");
5071:                cf.add(Opcode.LDC, cf.addConstant(node.str));
5072:                cf
5073:                        .add(
5074:                                Opcode.INVOKESTATIC,
5075:                                "pnuts.lang.Runtime",
5076:                                "getStaticField",
5077:                                "(Lpnuts/lang/Context;Ljava/lang/Class;Ljava/lang/String;)",
5078:                                "Ljava/lang/Object;");
5079:                cf.add(Opcode.GOTO, next);
5080:
5081:                err.fix();
5082:                error(cf, "packageOrClass.expected", new int[] { tgt }, cc);
5083:                next.fix();
5084:                return null;
5085:            }
5086:
5087:            public Object rangeNode(SimpleNode node, Context context) {
5088:                CompileContext cc = (CompileContext) context;
5089:                ClassFile cf = cc.cf;
5090:                int ctx = cc.getContextIndex();
5091:
5092:                accept(node, 0, context);
5093:                int tgt = cf.getLocal();
5094:                cf.storeLocal(tgt);
5095:
5096:                accept(node, 1, context);
5097:                int idx1 = cf.getLocal();
5098:                cf.storeLocal(idx1);
5099:
5100:                int idx2 = cf.getLocal();
5101:                if (node.jjtGetNumChildren() >= 3) {
5102:                    accept(node, 2, context);
5103:                } else {
5104:                    cf.add(Opcode.ACONST_NULL);
5105:                }
5106:                cf.storeLocal(idx2);
5107:
5108:                cf.loadLocal(tgt);
5109:                cf.freeLocal(tgt);
5110:                cf.loadLocal(idx1);
5111:                cf.freeLocal(idx1);
5112:                cf.loadLocal(idx2);
5113:                cf.freeLocal(idx2);
5114:                cf.loadLocal(ctx);
5115:                cf
5116:                        .add(
5117:                                Opcode.INVOKESTATIC,
5118:                                "pnuts.lang.Runtime",
5119:                                "getRange",
5120:                                "(Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Lpnuts/lang/Context;)",
5121:                                "Ljava/lang/Object;");
5122:                return null;
5123:            }
5124:
5125:            public Object forStatement(SimpleNode node, Context context) {
5126:                CompileContext cc = (CompileContext) context;
5127:                ClassFile cf = cc.cf;
5128:                int ctx = cc.getContextIndex();
5129:
5130:                addLineInfo(cc, ctx, node);
5131:
5132:                SimpleNode initNode = null;
5133:                SimpleNode condNode = null;
5134:                SimpleNode updateNode = null;
5135:                SimpleNode blockNode = null;
5136:
5137:                int j = 0;
5138:                SimpleNode n = node.jjtGetChild(j);
5139:
5140:                if (n.id == PnutsParserTreeConstants.JJTFORENUM) {
5141:                    SimpleNode n0 = n.jjtGetChild(0);
5142:                    if (n0.id == PnutsParserTreeConstants.JJTMULTIASSIGNLHS) {
5143:                        int num = n0.jjtGetNumChildren();
5144:                        String[] vars = new String[num];
5145:                        for (int i = 0; i < num; i++) {
5146:                            vars[i] = n0.jjtGetChild(i).str;
5147:                        }
5148:                        blockNode = node.jjtGetChild(1);
5149:                        doForeach(vars, n.jjtGetChild(1), blockNode, cc, cf);
5150:                        return null;
5151:                    }
5152:                    int nc = n.jjtGetNumChildren();
5153:                    blockNode = node.jjtGetChild(1);
5154:                    if (nc == 1) { // for (i : value)
5155:                        doForeach(new String[] { n.str }, n.jjtGetChild(0),
5156:                                blockNode, cc, cf);
5157:                    } else if (nc == 2) { // for (i : start .. end)
5158:                        doForeachRange(n.str, n.jjtGetChild(0), n
5159:                                .jjtGetChild(1), blockNode, cc, cf);
5160:                    } else {
5161:                    }
5162:                    return null;
5163:                }
5164:                /*
5165:                 * for(A;B;C) ...
5166:                 */
5167:                if (n.id == PnutsParserTreeConstants.JJTFORINIT) {
5168:                    initNode = n;
5169:                    j++;
5170:                }
5171:                n = node.jjtGetChild(j);
5172:                if (n.id != PnutsParserTreeConstants.JJTFORUPDATE
5173:                        && n.id != PnutsParserTreeConstants.JJTBLOCK) {
5174:                    condNode = n;
5175:                    j++;
5176:                }
5177:                n = node.jjtGetChild(j);
5178:                if (n.id == PnutsParserTreeConstants.JJTFORUPDATE) {
5179:                    updateNode = n;
5180:                    j++;
5181:                }
5182:
5183:                blockNode = node.jjtGetChild(j);
5184:
5185:                int last = cf.getLocal();
5186:                cf.add(Opcode.ACONST_NULL);
5187:                cf.storeLocal(last);
5188:
5189:                if (initNode != null) {
5190:                    int num = initNode.jjtGetNumChildren();
5191:                    String[] env = new String[num];
5192:                    for (int i = 0; i < env.length; i++) {
5193:                        SimpleNode sn = initNode.jjtGetChild(i);
5194:                        env[i] = sn.str;
5195:                    }
5196:                    cc.openScope(env);
5197:                    for (int i = 0; i < env.length; i++) {
5198:                        /**/
5199:                        Reference ref = cc.getReference(env[i]);
5200:                        if (DEBUG) {
5201:                            System.out.println("ref = " + ref);
5202:                        }
5203:                        SimpleNode sn = initNode.jjtGetChild(i);
5204:                        accept(sn, 0, context);
5205:                        if (ref.offset < 0) {
5206:                            cf.storeLocal(ref.index);
5207:                        } else {
5208:                            int tgt = cf.getLocal();
5209:                            cf.storeLocal(tgt);
5210:                            cf.add(Opcode.ACONST_NULL);
5211:                            cf.storeLocal(ref.index);
5212:                            ref.set(cf, tgt);
5213:                        }
5214:                        /**/
5215:
5216:                    }
5217:                } else {
5218:                    cc.openScope(new String[] {});
5219:                }
5220:
5221:                Label start = cf.getLabel(true);
5222:                Label cont = cf.getLabel();
5223:                Label next = cf.getLabel();
5224:                Label brk = cf.getLabel();
5225:
5226:                ControlEnv ctrl = cc.openControlEnv(node.id);
5227:                ctrl.continueLabel = cont;
5228:                ctrl.breakLabel = brk;
5229:
5230:                if (condNode != null) {
5231:                    condNode.accept(this , context);
5232:                    if (condNode.getAttribute("inlinedBoolean") != null) {
5233:                        cf.add(Opcode.IFEQ, next);
5234:                    } else {
5235:                        booleanCheck(condNode.id, cf, context);
5236:                        cf.add(Opcode.CHECKCAST, "java.lang.Boolean");
5237:                        cf.add(Opcode.INVOKEVIRTUAL, "java.lang.Boolean",
5238:                                "booleanValue", "()", "Z");
5239:                        cf.add(Opcode.IFEQ, next);
5240:                    }
5241:                }
5242:
5243:                blockNode.accept(this , context);
5244:                cont.fix();
5245:                cf.storeLocal(last);
5246:
5247:                if (updateNode != null) {
5248:                    int num = updateNode.jjtGetNumChildren();
5249:                    for (int i = 0; i < num; i++) {
5250:                        accept(updateNode, i, context);
5251:                        cf.add(Opcode.POP);
5252:                    }
5253:                }
5254:
5255:                cf.add(Opcode.GOTO, start);
5256:                next.fix();
5257:                cf.loadLocal(last);
5258:                cf.freeLocal(last);
5259:                cc.closeScope();
5260:                brk.fix();
5261:
5262:                cc.closeControlEnv();
5263:
5264:                return null;
5265:            }
5266:
5267:            public Object breakNode(SimpleNode node, Context context) {
5268:                CompileContext cc = (CompileContext) context;
5269:                ClassFile cf = cc.cf;
5270:
5271:                cc.leaveControlEnv();
5272:
5273:                if (node.jjtGetNumChildren() > 0) {
5274:                    accept(node, 0, context);
5275:                } else {
5276:                    cf.add(Opcode.ACONST_NULL);
5277:                }
5278:
5279:                Label brk = cc.getBreakLabel();
5280:                if (brk != null) {
5281:                    cf.add(Opcode.GOTO, brk);
5282:                } else {
5283:                    if (cc.inGeneratorBlock) {
5284:                        int value = cf.getLocal();
5285:                        cf.storeLocal(value);
5286:                        cf.add(Opcode.NEW, "pnuts.lang.Generator$Break");
5287:                        cf.add(Opcode.DUP);
5288:                        cf.loadLocal(value);
5289:                        cf.freeLocal(value);
5290:                        cf.add(Opcode.INVOKESPECIAL,
5291:                                "pnuts.lang.Generator$Break", "<init>",
5292:                                "(Ljava/lang/Object;)", "V");
5293:                        cf.add(Opcode.ATHROW);
5294:                    }
5295:                }
5296:                return null;
5297:            }
5298:
5299:            public Object continueNode(SimpleNode node, Context context) {
5300:                CompileContext cc = (CompileContext) context;
5301:                ClassFile cf = cc.cf;
5302:
5303:                cc.leaveControlEnv();
5304:
5305:                Label cnt = cc.getContinueLabel();
5306:                cf.add(Opcode.ACONST_NULL);
5307:                if (cnt != null) {
5308:                    cf.add(Opcode.GOTO, cnt);
5309:                } else {
5310:                    if (cc.inGeneratorBlock) {
5311:                        cf.add(Opcode.ARETURN);
5312:                    }
5313:                }
5314:                return null;
5315:            }
5316:
5317:            public Object returnNode(SimpleNode node, Context context) {
5318:                CompileContext cc = (CompileContext) context;
5319:                ClassFile cf = cc.cf;
5320:
5321:                cc.leaveFrame();
5322:
5323:                if (node.jjtGetNumChildren() > 0) {
5324:                    accept(node, 0, context);
5325:                } else {
5326:                    cf.add(Opcode.ACONST_NULL);
5327:                }
5328:
5329:                if (cc.env.parent != null) {
5330:                    if (cc.inGeneratorBlock) {
5331:                        int value = cf.getLocal();
5332:                        cf.storeLocal(value);
5333:                        cf.add(Opcode.NEW, "pnuts.lang.Jump");
5334:                        cf.add(Opcode.DUP);
5335:                        cf.loadLocal(value);
5336:                        cf.add(Opcode.INVOKESPECIAL, "pnuts.lang.Jump",
5337:                                "<init>", "(Ljava/lang/Object;)", "V");
5338:                        cf.add(Opcode.ATHROW);
5339:                    } else {
5340:                        cf.add(Opcode.GOTO, cc.returnLabel);
5341:                    }
5342:                } else {
5343:                    cf.add(Opcode.INVOKESTATIC, "pnuts.lang.Runtime", "jump",
5344:                            "(Ljava/lang/Object;)", "V");
5345:                    cf.add(Opcode.ACONST_NULL);
5346:                }
5347:                return null;
5348:            }
5349:
5350:            public Object yieldNode(SimpleNode node, Context context) {
5351:                throw new PnutsException(
5352:                        "yield must be used in a generator function", context);
5353:            }
5354:
5355:            public Object catchNode(SimpleNode node, Context context) {
5356:                CompileContext cc = (CompileContext) context;
5357:                ClassFile cf = cc.cf;
5358:                int ctx = cc.getContextIndex();
5359:
5360:                if (node.jjtGetNumChildren() == 0) {
5361:                    cf.add(Opcode.GETSTATIC, "pnuts.lang.PnutsFunction",
5362:                            "CATCH", "Lpnuts/lang/PnutsFunction;");
5363:                    return null;
5364:                }
5365:
5366:                int cls = cf.getLocal();
5367:                int func = cf.getLocal();
5368:
5369:                accept(node, 0, context);
5370:                cf.add(Opcode.CHECKCAST, "java.lang.Class");
5371:                cf.storeLocal(cls);
5372:
5373:                accept(node, 1, context);
5374:                cf.add(Opcode.CHECKCAST, "pnuts.lang.PnutsFunction");
5375:                cf.storeLocal(func);
5376:
5377:                Reference eref = cc.getReference(EXCEPTOIN_FIELD_SYMBOL);
5378:                if (cc.env.parent != null && eref != null) {
5379:                    int tmap = cf.getLocal();
5380:                    cf.add(Opcode.NEW, "pnuts.lang.Runtime$TypeMap");
5381:                    cf.add(Opcode.DUP);
5382:                    cf.loadLocal(cls);
5383:                    cf.loadLocal(func);
5384:
5385:                    getRef(eref, cc);
5386:
5387:                    cf.add(Opcode.CHECKCAST, "pnuts.lang.Runtime$TypeMap");
5388:
5389:                    cf
5390:                            .add(
5391:                                    Opcode.INVOKESPECIAL,
5392:                                    "pnuts.lang.Runtime$TypeMap",
5393:                                    "<init>",
5394:                                    "(Ljava/lang/Class;Ljava/lang/Object;Lpnuts/lang/Runtime$TypeMap;)",
5395:                                    "V");
5396:                    cf.storeLocal(tmap);
5397:                    eref.set(cf, tmap);
5398:                    cf.add(Opcode.ACONST_NULL);
5399:
5400:                } else {
5401:                    cf.loadLocal(cls);
5402:                    cf.loadLocal(func);
5403:                    cf.loadLocal(ctx);
5404:                    cf
5405:                            .add(
5406:                                    Opcode.INVOKESTATIC,
5407:                                    "pnuts.lang.Runtime",
5408:                                    "catchException",
5409:                                    "(Ljava/lang/Class;Lpnuts/lang/PnutsFunction;Lpnuts/lang/Context;)",
5410:                                    "V");
5411:                    cf.add(Opcode.ACONST_NULL);
5412:                }
5413:                cf.freeLocal(cls);
5414:                cf.freeLocal(func);
5415:                return null;
5416:            }
5417:
5418:            public Object throwNode(SimpleNode node, Context context) {
5419:                CompileContext cc = (CompileContext) context;
5420:                ClassFile cf = cc.cf;
5421:                int ctx = cc.getContextIndex();
5422:
5423:                addLineInfo(cc, ctx, node);
5424:
5425:                int n = node.jjtGetNumChildren();
5426:                if (n == 0) {
5427:                    cf.add(Opcode.GETSTATIC, "pnuts.lang.PnutsFunction",
5428:                            "THROW", "Lpnuts/lang/PnutsFunction;");
5429:                } else {
5430:                    accept(node, 0, context);
5431:                    int arg = cf.getLocal();
5432:                    cf.storeLocal(arg);
5433:                    cf.loadLocal(arg);
5434:                    cf.add(Opcode.INSTANCEOF, "java.lang.Throwable");
5435:                    Label throwable = cf.getLabel();
5436:                    cf.add(Opcode.IFNE, throwable);
5437:
5438:                    Label next = cf.getLabel();
5439:                    cf.add(Opcode.NEW, "pnuts.lang.PnutsException");
5440:                    cf.add(Opcode.DUP);
5441:                    cf.loadLocal(arg);
5442:                    cf.add(Opcode.INVOKESTATIC, "java.lang.String", "valueOf",
5443:                            "(Ljava/lang/Object;)", "Ljava/lang/String;");
5444:                    cf.loadLocal(cc.getContextIndex());
5445:                    cf.add(Opcode.INVOKESPECIAL, "pnuts.lang.PnutsException",
5446:                            "<init>",
5447:                            "(Ljava/lang/String;Lpnuts/lang/Context;)", "V");
5448:                    cf.add(Opcode.GOTO, next);
5449:                    throwable.fix();
5450:                    cf.loadLocal(arg);
5451:                    cf.add(Opcode.CHECKCAST, "java.lang.Throwable");
5452:
5453:                    cf.freeLocal(arg);
5454:                    next.fix();
5455:                    cf.add(Opcode.ATHROW);
5456:                }
5457:                return null;
5458:            }
5459:
5460:            public Object finallyNode(SimpleNode node, Context context) {
5461:                CompileContext cc = (CompileContext) context;
5462:                ClassFile cf = cc.cf;
5463:                int ctx = cc.getContextIndex();
5464:                int n = node.jjtGetNumChildren();
5465:                if (n == 0) {
5466:                    cf.add(Opcode.ACONST_NULL);
5467:                } else if (n == 1) {
5468:                    Frame env = cc.env;
5469:                    if (env.parent != null) {
5470:                        env.finallySet = true;
5471:                        int fin = cf.getLocal();
5472:                        cc.declare("!finally", fin, -1);
5473:                        accept(node, 0, context);
5474:                        cf.storeLocal(fin);
5475:                        cf.loadLocal(fin);
5476:                    } else {
5477:                        cf.loadLocal(ctx);
5478:                        int val = cf.getLocal();
5479:                        accept(node, 0, context);
5480:                        cf.storeLocal(val);
5481:                        cf.loadLocal(val);
5482:                        cf.add(Opcode.CHECKCAST, "pnuts.lang.PnutsFunction");
5483:                        cf
5484:                                .add(
5485:                                        Opcode.INVOKESTATIC,
5486:                                        "pnuts.lang.Runtime",
5487:                                        "setExitHook",
5488:                                        "(Lpnuts/lang/Context;Lpnuts/lang/PnutsFunction;)",
5489:                                        "V");
5490:                        cf.loadLocal(val);
5491:                    }
5492:                } else if (n == 2) {
5493:                    int value = cf.getLocal();
5494:                    int retAddr = cf.getLocal();
5495:                    Label catchStart = cf.getLabel(true);
5496:                    Label jsrTag = cf.getLabel();
5497:
5498:                    accept(node, 0, context);
5499:                    cf.add(Opcode.CHECKCAST, "pnuts.lang.PnutsFunction");
5500:                    cf.add(Opcode.GETSTATIC, cc.constClassName, "NO_PARAM",
5501:                            "[Ljava/lang/Object;");
5502:                    cf.loadLocal(ctx);
5503:                    cf.add(Opcode.INVOKEVIRTUAL, "pnuts.lang.PnutsFunction",
5504:                            "call",
5505:                            "([Ljava/lang/Object;Lpnuts/lang/Context;)",
5506:                            "Ljava/lang/Object;");
5507:                    cf.storeLocal(value);
5508:
5509:                    Label catchEnd = cf.getLabel(true);
5510:
5511:                    cf.add(Opcode.JSR, jsrTag);
5512:
5513:                    cf.loadLocal(value);
5514:                    cf.add(Opcode.ARETURN);
5515:
5516:                    Label finallyTag = cf.getLabel(true);
5517:
5518:                    cf.reserveStack(1);
5519:                    cf.add(Opcode.ATHROW);
5520:
5521:                    jsrTag.fix();
5522:
5523:                    cf.reserveStack(1);
5524:                    cf.storeLocal(retAddr);
5525:                    accept(node, 1, context);
5526:                    cf.add(Opcode.CHECKCAST, "pnuts.lang.PnutsFunction");
5527:                    cf.add(Opcode.GETSTATIC, cc.constClassName, "NO_PARAM",
5528:                            "[Ljava/lang/Object;");
5529:                    cf.loadLocal(ctx);
5530:                    cf.add(Opcode.INVOKEVIRTUAL, "pnuts.lang.PnutsFunction",
5531:                            "call",
5532:                            "([Ljava/lang/Object;Lpnuts/lang/Context;)",
5533:                            "Ljava/lang/Object;");
5534:                    cf.add(Opcode.POP);
5535:                    cf.add(Opcode.RET, retAddr);
5536:
5537:                    cf.addExceptionHandler(catchStart, catchEnd, finallyTag,
5538:                            null);
5539:                }
5540:                return null;
5541:            }
5542:
5543:            /*
5544:             * while or do..while
5545:             */
5546:            private Object conditionLoop(SimpleNode node, Context context,
5547:                    boolean isDoWhile) {
5548:                CompileContext cc = (CompileContext) context;
5549:                ClassFile cf = cc.cf;
5550:                int ctx = cc.getContextIndex();
5551:
5552:                addLineInfo(cc, ctx, node);
5553:
5554:                cf.add(Opcode.ACONST_NULL);
5555:                int last = cf.getLocal();
5556:                cf.storeLocal(last);
5557:
5558:                Label start = cf.getLabel(true);
5559:                Label next = cf.getLabel();
5560:                Label brk = cf.getLabel();
5561:                Label cont = cf.getLabel();
5562:
5563:                ControlEnv env;
5564:                if (isDoWhile) {
5565:                    env = cc
5566:                            .openControlEnv(PnutsParserTreeConstants.JJTDOSTATEMENT);
5567:                } else {
5568:                    env = cc
5569:                            .openControlEnv(PnutsParserTreeConstants.JJTWHILESTATEMENT);
5570:                }
5571:                env.breakLabel = brk;
5572:                env.continueLabel = cont;
5573:
5574:                if (isDoWhile) {
5575:                    if (traceMode) {
5576:                        addLineInfo(cc, ctx, node);
5577:                    }
5578:                    accept(node, 0, context);
5579:                    cont.fix();
5580:                    cf.storeLocal(last);
5581:                }
5582:
5583:                SimpleNode condNode = node.jjtGetChild(isDoWhile ? 1 : 0);
5584:                condNode.accept(this , context);
5585:
5586:                if (condNode.getAttribute("inlinedBoolean") != null) {
5587:                    cf.add(Opcode.IFEQ, next);
5588:                } else {
5589:                    booleanCheck(node.jjtGetChild(0).id, cf, context);
5590:                    cf.add(Opcode.CHECKCAST, "java.lang.Boolean");
5591:                    cf.add(Opcode.INVOKEVIRTUAL, "java.lang.Boolean",
5592:                            "booleanValue", "()", "Z");
5593:                    cf.add(Opcode.IFEQ, next);
5594:                }
5595:
5596:                if (!isDoWhile) {
5597:                    if (traceMode) {
5598:                        addLineInfo(cc, ctx, node);
5599:                    }
5600:                    accept(node, 1, context);
5601:                    cont.fix();
5602:                    cf.storeLocal(last);
5603:                }
5604:                cf.add(Opcode.GOTO, start);
5605:
5606:                next.fix();
5607:
5608:                cc.closeControlEnv();
5609:
5610:                cf.loadLocal(last);
5611:                cf.freeLocal(last);
5612:                brk.fix();
5613:                return null;
5614:            }
5615:
5616:            public Object doStatement(SimpleNode node, Context context) {
5617:                return conditionLoop(node, context, true);
5618:            }
5619:
5620:            public Object whileStatement(SimpleNode node, Context context) {
5621:                return conditionLoop(node, context, false);
5622:            }
5623:
5624:            private void doGenerator(String[] vars, int tgt,
5625:                    SimpleNode blockNode, CompileContext cc, ClassFile cf) {
5626:                String cls = className + "$"
5627:                        + (classCount++ & 0x7fffffffffffffffL);
5628:
5629:                String tmpVar;
5630:                if (vars.length > 1) {
5631:                    tmpVar = "_tmp";
5632:                    blockNode = GeneratorHelper.expandMultiAssign(vars, tmpVar,
5633:                            blockNode);
5634:                } else {
5635:                    tmpVar = vars[0];
5636:                }
5637:
5638:                ClassFile cf2 = new ClassFile(cls, "pnuts.lang.PnutsFunction",
5639:                        sourceFile, Constants.ACC_PUBLIC);
5640:                cf2.addInterface("pnuts.compiler.Compiled");
5641:                cc.classFiles.add(cf2);
5642:                CompileContext cc2 = (CompileContext) cc.clone();
5643:                cc2.returnLabel = cf2.getLabel();
5644:                cc2.cf = cf2;
5645:
5646:                cc2._openFrame(null, new String[] { tmpVar }, false);
5647:                cf2
5648:                        .openMethod(
5649:                                "exec",
5650:                                "([Ljava/lang/Object;Lpnuts/lang/Context;)Ljava/lang/Object;",
5651:                                Constants.ACC_PROTECTED);
5652:                cc2.setContextIndex(2);
5653:                cc2.inGeneratorBlock = true;
5654:
5655:                cf2.loadLocal(0);
5656:                cf2.add(Opcode.GETFIELD, cls, "$context$",
5657:                        "Lpnuts/lang/Context;");
5658:                cf2.storeLocal(2);
5659:
5660:                cc2._declare(tmpVar, 1, 0);
5661:
5662:                blockNode.accept(this , cc2);
5663:
5664:                cc2.returnLabel.fix();
5665:                cf2.add(Opcode.ARETURN);
5666:
5667:                cc2.inGeneratorBlock = false;
5668:                cf2.closeMethod();
5669:
5670:                StringBuffer arg = new StringBuffer("(");
5671:                int n_names = 0;
5672:                if (cc2.env.imports != null) {
5673:                    n_names = cc2.env.imports.size();
5674:                }
5675:                String names[] = new String[n_names];
5676:                int j = 0;
5677:                if (n_names > 0) {
5678:                    List imports = cc2.env.imports;
5679:                    for (int i = 0, n = imports.size(); i < n; i++) {
5680:                        String sym = (String) imports.get(i);
5681:                        names[j++] = sym;
5682:                        arg.append("[Ljava/lang/Object;");
5683:                    }
5684:                }
5685:
5686:                arg.append("Lpnuts/lang/Context;");
5687:                arg.append(")");
5688:
5689:                cf2.openMethod("<init>", arg + "V", Constants.ACC_PUBLIC);
5690:                cf2.add(Opcode.ALOAD_0);
5691:                cf2.add(Opcode.INVOKESPECIAL, "pnuts.lang.PnutsFunction",
5692:                        "<init>", "()", "V");
5693:
5694:                for (int i = 0; i < n_names; i++) {
5695:                    cf2.addField(names[i], "[Ljava/lang/Object;", (short) 0);
5696:                    cf2.add(Opcode.ALOAD_0);
5697:                    cf2.add(Opcode.ALOAD, 1 + i);
5698:                    cf2.add(Opcode.PUTFIELD, cf2.getClassName(), names[i],
5699:                            "[Ljava/lang/Object;");
5700:                }
5701:
5702:                cf2.addField("$context$", "Lpnuts/lang/Context;", (short) 0);
5703:                cf2.add(Opcode.ALOAD_0);
5704:                cf2.add(Opcode.ALOAD, 1 + n_names);
5705:                cf2.add(Opcode.PUTFIELD, cf2.getClassName(), "$context$",
5706:                        "Lpnuts/lang/Context;");
5707:
5708:                cf2.add(Opcode.RETURN);
5709:                cf2.closeMethod();
5710:
5711:                cf.loadLocal(tgt);
5712:                cf.add(Opcode.CHECKCAST, "pnuts.lang.Generator");
5713:                cf.add(Opcode.NEW, cls);
5714:                cf.add(Opcode.DUP);
5715:
5716:                ArrayList exports = (ArrayList) cc.env.exports.get(cc2.env);
5717:
5718:                cc2._closeFrame();
5719:
5720:                if (exports != null) {
5721:
5722:                    int size = exports.size();
5723:                    for (int i = 0; i < size; i++) {
5724:                        Reference ref = (Reference) exports.get(i);
5725:                        if (ref.index < 0) {
5726:                            cf.add(Opcode.ALOAD_0);
5727:                            cf.add(Opcode.GETFIELD, cf.getClassName(),
5728:                                    ref.symbol, "[Ljava/lang/Object;");
5729:                        } else if (ref.offset < 0) {
5730:                            cf.add(Opcode.ICONST_1);
5731:                            cf.add(Opcode.ANEWARRAY, "java.lang.Object");
5732:                            cf.add(Opcode.DUP);
5733:                            cf.add(Opcode.ICONST_0);
5734:                            cf.loadLocal(ref.index);
5735:                            cf.add(Opcode.AASTORE);
5736:                        } else {
5737:                            cf.loadLocal(ref.index);
5738:                            Label l1 = cf.getLabel();
5739:                            cf.add(Opcode.IFNONNULL, l1);
5740:                            cf.add(Opcode.ICONST_1);
5741:                            cf.add(Opcode.ANEWARRAY, "java.lang.Object");
5742:                            cf.storeLocal(ref.index);
5743:                            l1.fix();
5744:                            cf.loadLocal(ref.index);
5745:                            cf.add(Opcode.CHECKCAST, "[Ljava/lang/Object;");
5746:                        }
5747:                    }
5748:                }
5749:
5750:                cf.loadLocal(cc.getContextIndex());
5751:                cf
5752:                        .add(Opcode.INVOKESPECIAL, cls, "<init>", arg
5753:                                .toString(), "V");
5754:
5755:                cf.loadLocal(cc.getContextIndex());
5756:                cf
5757:                        .add(
5758:                                Opcode.INVOKESTATIC,
5759:                                "pnuts.lang.Runtime",
5760:                                "applyGenerator",
5761:                                "(Lpnuts/lang/Generator;Lpnuts/lang/PnutsFunction;Lpnuts/lang/Context;)",
5762:                                "Ljava/lang/Object;");
5763:            }
5764:
5765:            private void doForeach(String[] vars, SimpleNode collectionNode,
5766:                    SimpleNode blockNode, CompileContext cc, ClassFile cf) {
5767:                int ctx = cc.getContextIndex();
5768:                cc.openScope(vars);
5769:                /*
5770:                Reference count = cc.getReference(vars[0]);
5771:                cf.add(Opcode.ICONST_1);
5772:                cf.add(Opcode.ANEWARRAY, "java.lang.Object");
5773:                cf.storeLocal(count.index);
5774:                 */
5775:                Reference[] count = new Reference[vars.length];
5776:                for (int i = 0; i < vars.length; i++) {
5777:                    count[i] = cc.getReference(vars[i]);
5778:                    cf.add(Opcode.ICONST_1);
5779:                    cf.add(Opcode.ANEWARRAY, "java.lang.Object");
5780:                    cf.storeLocal(count[i].index);
5781:                }
5782:
5783:                Label next = cf.getLabel();
5784:                Label brk = cf.getLabel();
5785:
5786:                ControlEnv env = cc
5787:                        .openControlEnv(PnutsParserTreeConstants.JJTFORSTATEMENT);
5788:                env.breakLabel = brk;
5789:
5790:                int last = cf.getLocal();
5791:                cf.add(Opcode.ACONST_NULL);
5792:                cf.storeLocal(last);
5793:
5794:                collectionNode.accept(this , cc);
5795:                int tgt = cf.getLocal();
5796:                cf.add(Opcode.DUP);
5797:                cf.storeLocal(tgt);
5798:
5799:                Label nonnull = cf.getLabel();
5800:
5801:                cf.add(Opcode.IFNONNULL, nonnull);
5802:                cf.add(Opcode.GOTO, next);
5803:                nonnull.fix();
5804:
5805:                cf.loadLocal(tgt);
5806:                cf.add(Opcode.INSTANCEOF, "pnuts.lang.Generator");
5807:                Label fn = cf.getLabel();
5808:                cf.add(Opcode.IFNE, fn);
5809:
5810:                cf.loadLocal(tgt);
5811:                cf.loadLocal(cc.getContextIndex());
5812:                cf.add(Opcode.INVOKESTATIC, "pnuts.lang.Runtime",
5813:                        "toEnumeration",
5814:                        "(Ljava/lang/Object;Lpnuts/lang/Context;)",
5815:                        "Ljava/util/Enumeration;");
5816:                int tmp1 = cf.getLocal();
5817:                cf.storeLocal(tmp1);
5818:                cf.loadLocal(tmp1);
5819:
5820:                Label err = cf.getLabel();
5821:                cf.add(Opcode.IFNULL, err);
5822:
5823:                Label loop2 = cf.getLabel();
5824:                cf.add(Opcode.GOTO, loop2);
5825:                Label body = cf.getLabel(true);
5826:
5827:                cf.loadLocal(tmp1);
5828:                cf.add(Opcode.CHECKCAST, "java.util.Enumeration");
5829:                cf.add(Opcode.INVOKEINTERFACE, "java.util.Enumeration",
5830:                        "nextElement", "()", "Ljava/lang/Object;");
5831:
5832:                int tmp2 = cf.getLocal();
5833:                cf.storeLocal(tmp2);
5834:
5835:                if (vars.length > 1) { // multi-assignment
5836:                    int tmp3 = cf.getLocal();
5837:                    for (int i = 0; i < vars.length; i++) {
5838:                        cf.loadLocal(tmp2);
5839:                        cf.pushInteger(i);
5840:                        cf.loadLocal(ctx);
5841:                        cf.add(Opcode.INVOKESTATIC, "pnuts.lang.Runtime",
5842:                                "getElementAt",
5843:                                "(Ljava/lang/Object;ILpnuts/lang/Context;)",
5844:                                "Ljava/lang/Object;");
5845:                        cf.storeLocal(tmp3);
5846:                        count[i].set(cf, tmp3);
5847:                    }
5848:                } else {
5849:                    count[0].set(cf, tmp2);
5850:                }
5851:
5852:                Label cont = cf.getLabel();
5853:                env.continueLabel = cont;
5854:
5855:                blockNode.accept(this , cc);
5856:                cont.fix();
5857:                cf.storeLocal(last);
5858:
5859:                loop2.fix();
5860:                cf.loadLocal(tmp1);
5861:                cf.add(Opcode.CHECKCAST, "java.util.Enumeration");
5862:                cf.add(Opcode.INVOKEINTERFACE, "java.util.Enumeration",
5863:                        "hasMoreElements", "()", "Z");
5864:                cf.add(Opcode.IFEQ, next);
5865:                cf.add(Opcode.GOTO, body);
5866:
5867:                fn.fix();
5868:                doGenerator(vars, tgt, blockNode, cc, cf);
5869:                cf.storeLocal(last);
5870:                cf.add(Opcode.GOTO, next);
5871:
5872:                err.fix();
5873:                error(cf, "illegal.type.foreach", new int[] { tgt }, cc);
5874:
5875:                next.fix();
5876:                cf.loadLocal(last);
5877:                cf.freeLocal(last);
5878:                cf.freeLocal(tmp1);
5879:                cf.freeLocal(tmp2);
5880:                cf.freeLocal(tgt);
5881:
5882:                cc.closeControlEnv();
5883:
5884:                cc.closeScope();
5885:                brk.fix();
5886:            }
5887:
5888:            private void doForeachRange(String var, SimpleNode startNode,
5889:                    SimpleNode endNode, SimpleNode blockNode,
5890:                    CompileContext cc, ClassFile cf) {
5891:                cc.openScope(new String[] { var });
5892:                Reference count = cc.getReference(var);
5893:                cf.add(Opcode.ICONST_1);
5894:                cf.add(Opcode.ANEWARRAY, "java.lang.Object");
5895:                cf.storeLocal(count.index);
5896:
5897:                Label next = cf.getLabel();
5898:                Label brk = cf.getLabel();
5899:
5900:                ControlEnv env = cc
5901:                        .openControlEnv(PnutsParserTreeConstants.JJTFORSTATEMENT);
5902:                env.breakLabel = brk;
5903:
5904:                int last = cf.getLocal();
5905:                int tmp = cf.getLocal();
5906:                cf.add(Opcode.ACONST_NULL);
5907:                cf.storeLocal(last);
5908:
5909:                int start = cf.getLocal();
5910:                startNode.accept(this , cc);
5911:                cf.add(Opcode.CHECKCAST, "java.lang.Number");
5912:                cf.add(Opcode.INVOKEVIRTUAL, "java.lang.Number", "intValue",
5913:                        "()", "I");
5914:                cf.istoreLocal(start);
5915:
5916:                int end = cf.getLocal();
5917:                endNode.accept(this , cc);
5918:                cf.add(Opcode.CHECKCAST, "java.lang.Number");
5919:                cf.add(Opcode.INVOKEVIRTUAL, "java.lang.Number", "intValue",
5920:                        "()", "I");
5921:                cf.istoreLocal(end);
5922:
5923:                cf.iloadLocal(start);
5924:                cf.iloadLocal(end);
5925:                Label loop2 = cf.getLabel();
5926:                cf.add(Opcode.IF_ICMPGT, loop2);
5927:
5928:                Label loop1 = cf.getLabel(true);
5929:
5930:                cf.iloadLocal(start);
5931:                cf.iloadLocal(end);
5932:                cf.add(Opcode.IF_ICMPGT, next);
5933:
5934:                if (hasValueOfPrimitive) {
5935:                    cf.iloadLocal(start);
5936:                    cf.add(Opcode.INVOKESTATIC, "java.lang.Integer", "valueOf",
5937:                            "(I)", "Ljava/lang/Integer;");
5938:                } else {
5939:                    cf.add(Opcode.NEW, "java.lang.Integer");
5940:                    cf.add(Opcode.DUP);
5941:                    cf.iloadLocal(start);
5942:                    cf.add(Opcode.INVOKESPECIAL, "java.lang.Integer", "<init>",
5943:                            "(I)", "V");
5944:                }
5945:
5946:                cf.storeLocal(tmp);
5947:                count.set(cf, tmp);
5948:
5949:                Label cont = cf.getLabel();
5950:                env.continueLabel = cont;
5951:
5952:                blockNode.accept(this , cc);
5953:                cont.fix();
5954:                cf.storeLocal(last);
5955:
5956:                cf.add(Opcode.IINC, start, 1);
5957:                cf.add(Opcode.GOTO, loop1);
5958:
5959:                loop2.fix();
5960:
5961:                cf.iloadLocal(start);
5962:                cf.iloadLocal(end);
5963:                cf.add(Opcode.IF_ICMPLT, next);
5964:
5965:                if (hasValueOfPrimitive) {
5966:                    cf.iloadLocal(start);
5967:                    cf.add(Opcode.INVOKESTATIC, "java.lang.Integer", "valueOf",
5968:                            "(I)", "Ljava/lang/Integer;");
5969:                } else {
5970:                    cf.add(Opcode.NEW, "java.lang.Integer");
5971:                    cf.add(Opcode.DUP);
5972:                    cf.iloadLocal(start);
5973:                    cf.add(Opcode.INVOKESPECIAL, "java.lang.Integer", "<init>",
5974:                            "(I)", "V");
5975:                }
5976:
5977:                cf.storeLocal(tmp);
5978:                count.set(cf, tmp);
5979:
5980:                Label cont2 = cf.getLabel();
5981:                env.continueLabel = cont2;
5982:
5983:                blockNode.accept(this , cc);
5984:                cont2.fix();
5985:                cf.storeLocal(last);
5986:
5987:                cf.add(Opcode.IINC, start, -1);
5988:                cf.add(Opcode.GOTO, loop2);
5989:
5990:                next.fix();
5991:                cf.loadLocal(last);
5992:                cf.freeLocal(last);
5993:                cf.freeLocal(tmp);
5994:                cf.freeLocal(start);
5995:                cf.freeLocal(end);
5996:
5997:                cc.closeControlEnv();
5998:
5999:                cc.closeScope();
6000:                brk.fix();
6001:            }
6002:
6003:            public Object foreachStatement(SimpleNode node, Context context) {
6004:                CompileContext cc = (CompileContext) context;
6005:                ClassFile cf = cc.cf;
6006:                int ctx = cc.getContextIndex();
6007:
6008:                addLineInfo(cc, ctx, node);
6009:
6010:                doForeach(new String[] { node.str }, node.jjtGetChild(0), node
6011:                        .jjtGetChild(1), cc, cf);
6012:                return null;
6013:            }
6014:
6015:            public Object switchStatement(SimpleNode node, Context context) {
6016:                CompileContext cc = (CompileContext) context;
6017:                ClassFile cf = cc.cf;
6018:                int ctx = cc.getContextIndex();
6019:
6020:                addLineInfo(cc, ctx, node);
6021:
6022:                int n = node.jjtGetNumChildren();
6023:                accept(node, 0, context);
6024:                int tgt = cf.getLocal();
6025:                cf.storeLocal(tgt);
6026:
6027:                cc.openScope(new String[] {});
6028:
6029:                int match = cf.getLocal();
6030:                cf.add(Opcode.ICONST_0);
6031:                cf.istoreLocal(match);
6032:                int last = cf.getLocal();
6033:                cf.add(Opcode.ACONST_NULL);
6034:                cf.storeLocal(last);
6035:
6036:                Label next = cf.getLabel();
6037:
6038:                ControlEnv env = cc
6039:                        .openControlEnv(PnutsParserTreeConstants.JJTSWITCHSTATEMENT);
6040:                env.breakLabel = next;
6041:
6042:                for (int i = 1; i < n; i++) {
6043:                    SimpleNode _node = node.jjtGetChild(i);
6044:                    if (_node.jjtGetNumChildren() == 1) { // case
6045:                        cf.iloadLocal(match);
6046:                        Label hit = cf.getLabel();
6047:                        cf.add(Opcode.IFNE, hit);
6048:                        i++;
6049:                        accept(_node, 0, context);
6050:                        cf.loadLocal(tgt);
6051:                        cf.add(Opcode.INVOKESTATIC, "pnuts.lang.Runtime", "eq",
6052:                                "(Ljava/lang/Object;Ljava/lang/Object;)", "Z");
6053:                        Label cont = cf.getLabel();
6054:                        cf.add(Opcode.IFEQ, cont);
6055:                        cf.add(Opcode.ICONST_1); // match = 1
6056:                        cf.istoreLocal(match);
6057:                        hit.fix();
6058:                        accept(node, i, context);
6059:                        cf.storeLocal(last);
6060:                        cont.fix();
6061:                    } else { // default
6062:                        cf.add(Opcode.ICONST_1);
6063:                        cf.istoreLocal(match);
6064:                        accept(node, ++i, context);
6065:                        cf.storeLocal(last);
6066:                    }
6067:                }
6068:                cf.freeLocal(tgt);
6069:                cf.freeLocal(match);
6070:                cf.loadLocal(last);
6071:                next.fix();
6072:
6073:                cc.closeControlEnv();
6074:                cc.closeScope();
6075:
6076:                return null;
6077:            }
6078:
6079:            public Object switchBlock(SimpleNode node, Context context) {
6080:                CompileContext cc = (CompileContext) context;
6081:                ClassFile cf = cc.cf;
6082:
6083:                int n = node.jjtGetNumChildren();
6084:                if (n > 0) {
6085:                    int m = n - 1;
6086:                    for (int i = 0; i < m; i++) {
6087:                        accept(node, i, context);
6088:                        cf.add(Opcode.POP);
6089:                    }
6090:                    accept(node, m, context);
6091:                } else {
6092:                    cf.add(Opcode.ACONST_NULL);
6093:                }
6094:                return null;
6095:            }
6096:
6097:            public Object ternary(SimpleNode node, Context context) {
6098:                CompileContext cc = (CompileContext) context;
6099:                ClassFile cf = cc.cf;
6100:                SimpleNode condNode = node.jjtGetChild(0);
6101:                condNode.accept(this , context);
6102:
6103:                Label l_else = cf.getLabel();
6104:                Label next = cf.getLabel();
6105:
6106:                if (condNode.getAttribute("inlinedBoolean") != null) {
6107:                    cf.add(Opcode.IFEQ, l_else);
6108:                    accept(node, 1, context);
6109:                    cf.add(Opcode.GOTO, next);
6110:                    l_else.fix();
6111:                    cf.popStack();
6112:                } else {
6113:                    booleanCheck(node.jjtGetChild(0).id, cf, context);
6114:                    cf.add(Opcode.CHECKCAST, "java.lang.Boolean");
6115:                    cf.add(Opcode.INVOKEVIRTUAL, "java.lang.Boolean",
6116:                            "booleanValue", "()", "Z");
6117:                    cf.add(Opcode.IFEQ, l_else);
6118:                    accept(node, 1, context);
6119:                    cf.add(Opcode.GOTO, next);
6120:                    l_else.fix();
6121:                    cf.popStack();
6122:                }
6123:                accept(node, 2, context);
6124:                next.fix();
6125:                return null;
6126:            }
6127:
6128:            static String getPackageName(SimpleNode node) {
6129:                if (node.jjtGetNumChildren() > 0) {
6130:                    SimpleNode c1 = node.jjtGetChild(0);
6131:                    return getPackageName(c1) + "::" + node.str;
6132:                } else {
6133:                    return node.str;
6134:                }
6135:            }
6136:
6137:            static String gensym(Context context) {
6138:                return ((CompileContext) context).sym.gen();
6139:            }
6140:
6141:            protected Object accept(SimpleNode node, int idx, Context context) {
6142:                return node.jjtGetChild(idx).accept(this , context);
6143:            }
6144:
6145:            private Object assign(SimpleNode node, Context context, int id) {
6146:                accept(node, 1, context);
6147:                _assign(node.jjtGetChild(0), context, id, false, true);
6148:                return null;
6149:            }
6150:
6151:            private Object _assign(SimpleNode lhs, Context context, int id,
6152:                    boolean mutable, boolean nopop) {
6153:                CompileContext cc = (CompileContext) context;
6154:                ClassFile cf = cc.cf;
6155:                int ctx = cc.getContextIndex();
6156:                int rhs = cf.getLocal();
6157:                if ((id & 0x8000) == 0) {
6158:                    cf.storeLocal(rhs);
6159:                }
6160:
6161:                if (lhs.id == PnutsParserTreeConstants.JJTIDNODE) {
6162:                    assignId(cf, id, ctx, rhs, lhs, cc, mutable, nopop);
6163:                } else if (lhs.id == PnutsParserTreeConstants.JJTGLOBAL) {
6164:                    assignGlobal(cf, id, ctx, rhs, lhs, cc, nopop);
6165:                } else if (lhs.id == PnutsParserTreeConstants.JJTINDEXNODE) {
6166:                    assignIndex(cf, id, ctx, rhs, lhs, cc, nopop);
6167:                } else if (lhs.id == PnutsParserTreeConstants.JJTSTATICMEMBERNODE) {
6168:                    assignStaticMember(cf, id, ctx, rhs, lhs, cc, nopop);
6169:                } else if (lhs.id == PnutsParserTreeConstants.JJTMEMBERNODE) {
6170:                    assignMember(cf, id, ctx, rhs, lhs, cc, nopop);
6171:                } else if (lhs.id == PnutsParserTreeConstants.JJTRANGENODE
6172:                        && id == PnutsParserTreeConstants.JJTASSIGNMENT) {
6173:                    assignRange(cf, id, ctx, rhs, lhs, cc);
6174:                } else {
6175:                    throw new PnutsException("illegal.assign", new Object[] {},
6176:                            context);
6177:                }
6178:                cf.freeLocal(rhs);
6179:                return null;
6180:            }
6181:
6182:            boolean inControl(SimpleNode node, CompileContext cc) {
6183:                while (node != null) {
6184:                    if (node.id == PnutsParserTreeConstants.JJTFUNCTIONSTATEMENT
6185:                            || node.id == PnutsParserTreeConstants.JJTMETHODDEF) {
6186:                        return false;
6187:                    } else if (cc.inGeneratorBlock
6188:                            && (node.id == PnutsParserTreeConstants.JJTFOREACHSTATEMENT || node.id == PnutsParserTreeConstants.JJTFORSTATEMENT
6189:                                    && node.jjtGetChild(0).id == PnutsParserTreeConstants.JJTFORENUM)) {
6190:                        return false;
6191:                    } else if (node.id == PnutsParserTreeConstants.JJTSWITCHSTATEMENT
6192:                            || node.id == PnutsParserTreeConstants.JJTFOREACHSTATEMENT
6193:                            || node.id == PnutsParserTreeConstants.JJTFORSTATEMENT
6194:                            || node.id == PnutsParserTreeConstants.JJTWHILESTATEMENT
6195:                            || node.id == PnutsParserTreeConstants.JJTDOSTATEMENT
6196:                            || node.id == PnutsParserTreeConstants.JJTIFSTATEMENT) {
6197:                        return true;
6198:                    }
6199:                    node = node.jjtGetParent();
6200:                }
6201:                return false;
6202:            }
6203:
6204:            static boolean isConditionalNode(SimpleNode node) {
6205:                int id = node.jjtGetParent().id;
6206:                return id == PnutsParserTreeConstants.JJTIFSTATEMENT
6207:                        || id == PnutsParserTreeConstants.JJTELSEIFNODE
6208:                        || id == PnutsParserTreeConstants.JJTFORSTATEMENT
6209:                        || id == PnutsParserTreeConstants.JJTWHILESTATEMENT
6210:                        || id == PnutsParserTreeConstants.JJTDOSTATEMENT;
6211:
6212:            }
6213:
6214:            void assignId(ClassFile cf, int id, int ctx, int rhs,
6215:                    SimpleNode lhs, CompileContext cc, boolean mutable,
6216:                    boolean nopop) {
6217:                Reference ref = cc.findReference(lhs.str);
6218:                Frame env = cc.env;
6219:
6220:                if (cc.inGeneratorBlock) {
6221:                    if (ref == null) {
6222:                        if (cc.env != null && cc.env.parent != null) {
6223:                            int ret = -1;
6224:                            if (id != PnutsParserTreeConstants.JJTASSIGNMENT) {
6225:                                if ((id & 0x8000) == 0) {
6226:                                    cf.loadLocal(ctx);
6227:                                    cf.add(Opcode.LDC, cf.addConstant(lhs.str));
6228:                                    cf.add(Opcode.INVOKEVIRTUAL,
6229:                                            "pnuts.lang.Context", "getId",
6230:                                            "(Ljava/lang/String;)",
6231:                                            "Ljava/lang/Object;");
6232:                                    ret = cf.getLocal();
6233:                                    cf.storeLocal(ret);
6234:                                    cf.loadLocal(ret);
6235:                                    cf.loadLocal(rhs);
6236:                                }
6237:                                compute(cf, id, ctx);
6238:                                cf.storeLocal(rhs);
6239:                            }
6240:                            cf.loadLocal(ctx);
6241:                            cf.add(Opcode.INVOKEVIRTUAL, "pnuts.lang.Context",
6242:                                    "getCurrentPackage", "()",
6243:                                    "Lpnuts/lang/Package;");
6244:                            cf.add(Opcode.LDC, cf.addConstant(lhs.str));
6245:                            cf.loadLocal(rhs);
6246:                            cf.loadLocal(ctx);
6247:                            cf
6248:                                    .add(
6249:                                            Opcode.INVOKEVIRTUAL,
6250:                                            "pnuts.lang.Package",
6251:                                            "set",
6252:                                            "(Ljava/lang/String;Ljava/lang/Object;Lpnuts/lang/Context;)",
6253:                                            "V");
6254:                            if (nopop) {
6255:                                cf.loadLocal(rhs);
6256:                            }
6257:
6258:                            return;
6259:                        }
6260:                    }
6261:                }
6262:
6263:                if (cc.env.parent != null && !mutable) {
6264:                    int idx = 0;
6265:
6266:                    if (ref == null) {
6267:                        cc.declare(lhs.str);
6268:                        ref = cc.getReference(lhs.str);
6269:                    } else if (id == PnutsParserTreeConstants.JJTASSIGNMENT) {
6270:                        cc.redefine(lhs.str);
6271:                    }
6272:                    if (id != PnutsParserTreeConstants.JJTASSIGNMENT) {
6273:                        if ((id & 0x8000) == 0) {
6274:                            getRef(ref, cc);
6275:                            cf.loadLocal(rhs);
6276:                        }
6277:                        compute(cf, id, ctx);
6278:                        cf.storeLocal(rhs);
6279:                    }
6280:                    ref.set(cf, rhs);
6281:
6282:                    if (!inControl(lhs, cc)) {
6283:                        cc.setReference(lhs.str);
6284:                    }
6285:
6286:                    if (nopop) {
6287:                        cf.loadLocal(rhs);
6288:                    }
6289:                } else {
6290:                    if (ref != null) {
6291:                        if (id != PnutsParserTreeConstants.JJTASSIGNMENT) {
6292:                            if ((id & 0x8000) == 0) {
6293:                                getRef(ref, cc);
6294:                                cf.loadLocal(rhs);
6295:                            }
6296:                            compute(cf, id, ctx);
6297:                            cf.storeLocal(rhs);
6298:                        }
6299:                        ref.set(cf, rhs);
6300:                        if (nopop) {
6301:                            cf.loadLocal(rhs);
6302:                        }
6303:                    } else {
6304:                        int ret = -1;
6305:                        if (id != PnutsParserTreeConstants.JJTASSIGNMENT) {
6306:                            if ((id & 0x8000) == 0) {
6307:                                cf.loadLocal(ctx);
6308:                                cf.add(Opcode.LDC, cf.addConstant(lhs.str));
6309:                                cf.add(Opcode.INVOKEVIRTUAL,
6310:                                        "pnuts.lang.Context", "getId",
6311:                                        "(Ljava/lang/String;)",
6312:                                        "Ljava/lang/Object;");
6313:                                ret = cf.getLocal();
6314:                                cf.storeLocal(ret);
6315:                                cf.loadLocal(ret);
6316:                                cf.loadLocal(rhs);
6317:                            }
6318:                            compute(cf, id, ctx);
6319:                            cf.storeLocal(rhs);
6320:                        }
6321:                        cf.loadLocal(ctx);
6322:                        cf.add(Opcode.INVOKEVIRTUAL, "pnuts.lang.Context",
6323:                                "getCurrentPackage", "()",
6324:                                "Lpnuts/lang/Package;");
6325:                        cf.add(Opcode.LDC, cf.addConstant(lhs.str));
6326:                        cf.loadLocal(rhs);
6327:                        cf.loadLocal(ctx);
6328:                        cf
6329:                                .add(
6330:                                        Opcode.INVOKEVIRTUAL,
6331:                                        "pnuts.lang.Package",
6332:                                        "set",
6333:                                        "(Ljava/lang/String;Ljava/lang/Object;Lpnuts/lang/Context;)",
6334:                                        "V");
6335:                        if (nopop) {
6336:                            cf.loadLocal(rhs);
6337:                        }
6338:                    }
6339:                }
6340:            }
6341:
6342:            void assignMember(ClassFile cf, int id, int ctx, int rhs,
6343:                    SimpleNode lhs, CompileContext cc, boolean nopop) {
6344:                accept(lhs, 0, cc);
6345:                int tgt = cf.getLocal();
6346:                cf.storeLocal(tgt);
6347:                if (id != PnutsParserTreeConstants.JJTASSIGNMENT) {
6348:                    if ((id & 0x8000) == 0) {
6349:                        cf.loadLocal(ctx);
6350:                        cf.loadLocal(tgt);
6351:                        cf.add(Opcode.LDC, cf.addConstant(lhs.str));
6352:                        cf
6353:                                .add(
6354:                                        Opcode.INVOKESTATIC,
6355:                                        "pnuts.lang.Runtime",
6356:                                        "getField",
6357:                                        "(Lpnuts/lang/Context;Ljava/lang/Object;Ljava/lang/String;)",
6358:                                        "Ljava/lang/Object;");
6359:                        cf.loadLocal(rhs);
6360:                    }
6361:                    compute(cf, id, ctx);
6362:                    cf.storeLocal(rhs);
6363:                }
6364:
6365:                cf.loadLocal(ctx);
6366:                cf.loadLocal(tgt);
6367:                cf.freeLocal(tgt);
6368:                cf.add(Opcode.LDC, cf.addConstant(lhs.str));
6369:                cf.loadLocal(rhs);
6370:                cf
6371:                        .add(
6372:                                Opcode.INVOKESTATIC,
6373:                                "pnuts.lang.Runtime",
6374:                                "putField",
6375:                                "(Lpnuts/lang/Context;Ljava/lang/Object;Ljava/lang/String;Ljava/lang/Object;)",
6376:                                "V");
6377:                if (nopop) {
6378:                    cf.loadLocal(rhs);
6379:                }
6380:            }
6381:
6382:            void assignIndex(ClassFile cf, int id, int ctx, int rhs,
6383:                    SimpleNode lhs, CompileContext cc, boolean nopop) {
6384:                SimpleNode idxNode = lhs.jjtGetChild(1);
6385:                if (ConstraintsTransformer.isPredicate(idxNode)) {
6386:                    SimpleNode n = ConstraintsTransformer.buildFunc(idxNode);
6387:                    lhs.jjtAddChild(n, 1);
6388:                    n.jjtSetParent(lhs);
6389:                }
6390:                accept(lhs, 0, cc);
6391:                int tgt = cf.getLocal();
6392:                cf.storeLocal(tgt);
6393:
6394:                accept(lhs, 1, cc);
6395:                int idx = cf.getLocal();
6396:                cf.storeLocal(idx);
6397:
6398:                Label next = cf.getLabel();
6399:
6400:                cf.loadLocal(tgt);
6401:                cf.add(Opcode.INSTANCEOF, "java.lang.String");
6402:                Label l2 = cf.getLabel();
6403:                cf.add(Opcode.IFEQ, l2);
6404:                if (id != PnutsParserTreeConstants.JJTASSIGNMENT) {
6405:                    error(cf, "illegal.assign", cc);
6406:                } else {
6407:                    cf.loadLocal(tgt);
6408:                    cf.add(Opcode.CHECKCAST, "java.lang.String");
6409:                    cf.loadLocal(idx);
6410:                    cf.add(Opcode.CHECKCAST, "java.lang.Number");
6411:                    cf.loadLocal(rhs);
6412:
6413:                    cf.add(Opcode.INSTANCEOF, "java.lang.Character");
6414:                    Label ok = cf.getLabel();
6415:                    cf.add(Opcode.IFNE, ok);
6416:                    error(cf, "illegal.assign", cc);
6417:                    ok.fix();
6418:                    cf.loadLocal(rhs);
6419:
6420:                    cf
6421:                            .add(
6422:                                    Opcode.INVOKESTATIC,
6423:                                    "pnuts.lang.Runtime",
6424:                                    "replaceChar",
6425:                                    "(Ljava/lang/String;Ljava/lang/Number;Ljava/lang/Object;)",
6426:                                    "Ljava/lang/String;");
6427:
6428:                    SimpleNode ch = lhs.jjtGetChild(0);
6429:                    if (ch.id == PnutsParserTreeConstants.JJTIDNODE
6430:                            || ch.id == PnutsParserTreeConstants.JJTGLOBAL
6431:                            || ch.id == PnutsParserTreeConstants.JJTINDEXNODE
6432:                            || ch.id == PnutsParserTreeConstants.JJTMEMBERNODE
6433:                            || ch.id == PnutsParserTreeConstants.JJTSTATICMEMBERNODE) {
6434:                        if (ch.str != null) {
6435:                            if (cc.env.parent == null
6436:                                    || cc.getReference(ch.str) != null) {
6437:                                _assign(ch, cc, id, true, true);
6438:                            }
6439:                        }
6440:                    }
6441:                    cf.add(Opcode.GOTO, next);
6442:                }
6443:
6444:                l2.fix();
6445:
6446:                if (id == PnutsParserTreeConstants.JJTASSIGNMENT) {
6447:                    cf.loadLocal(tgt);
6448:                    cf.loadLocal(idx);
6449:                    cf.loadLocal(rhs);
6450:                    cf.loadLocal(ctx);
6451:                    cf
6452:                            .add(
6453:                                    Opcode.INVOKESTATIC,
6454:                                    "pnuts.lang.Runtime",
6455:                                    "setElement",
6456:                                    "(Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Lpnuts/lang/Context;)",
6457:                                    "V");
6458:                    if (nopop) {
6459:                        cf.loadLocal(rhs);
6460:                    }
6461:                } else {
6462:                    if ((id & 0x8000) == 0) {
6463:                        cf.loadLocal(tgt);
6464:                        cf.loadLocal(idx);
6465:                        cf.loadLocal(ctx);
6466:                        cf
6467:                                .add(
6468:                                        Opcode.INVOKESTATIC,
6469:                                        "pnuts.lang.Runtime",
6470:                                        "getElement",
6471:                                        "(Ljava/lang/Object;Ljava/lang/Object;Lpnuts/lang/Context;)",
6472:                                        "Ljava/lang/Object;");
6473:                        cf.loadLocal(rhs);
6474:                    }
6475:                    compute(cf, id, ctx);
6476:                    cf.storeLocal(rhs);
6477:                    cf.loadLocal(tgt);
6478:                    cf.loadLocal(idx);
6479:                    cf.loadLocal(rhs);
6480:                    cf.loadLocal(ctx);
6481:                    cf
6482:                            .add(
6483:                                    Opcode.INVOKESTATIC,
6484:                                    "pnuts.lang.Runtime",
6485:                                    "setElement",
6486:                                    "(Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Lpnuts/lang/Context;)",
6487:                                    "V");
6488:                    if (nopop) {
6489:                        cf.loadLocal(rhs);
6490:                    }
6491:                }
6492:                cf.freeLocal(tgt);
6493:                cf.freeLocal(idx);
6494:                next.fix();
6495:            }
6496:
6497:            void assignRange(ClassFile cf, int id, int ctx, int rhs,
6498:                    SimpleNode lhs, CompileContext cc) {
6499:                accept(lhs, 0, cc);
6500:                int tgt = cf.getLocal();
6501:                cf.storeLocal(tgt);
6502:
6503:                accept(lhs, 1, cc);
6504:                int idx1 = cf.getLocal();
6505:                cf.storeLocal(idx1);
6506:
6507:                int idx2 = cf.getLocal();
6508:                if (lhs.jjtGetNumChildren() >= 3) {
6509:                    accept(lhs, 2, cc);
6510:                } else {
6511:                    cf.add(Opcode.ACONST_NULL);
6512:                }
6513:                cf.storeLocal(idx2);
6514:
6515:                cf.loadLocal(tgt);
6516:                cf.loadLocal(idx1);
6517:                cf.freeLocal(idx1);
6518:                cf.loadLocal(idx2);
6519:                cf.freeLocal(idx2);
6520:                cf.loadLocal(rhs);
6521:
6522:                cf.loadLocal(cc.getContextIndex());
6523:                cf
6524:                        .add(
6525:                                Opcode.INVOKESTATIC,
6526:                                "pnuts.lang.Runtime",
6527:                                "setRange",
6528:                                "(Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Lpnuts/lang/Context;)",
6529:                                "Ljava/lang/Object;");
6530:
6531:                SimpleNode ch = lhs.jjtGetChild(0);
6532:                if (ch.id == PnutsParserTreeConstants.JJTIDNODE
6533:                        || ch.id == PnutsParserTreeConstants.JJTGLOBAL
6534:                        || ch.id == PnutsParserTreeConstants.JJTINDEXNODE
6535:                        || ch.id == PnutsParserTreeConstants.JJTMEMBERNODE
6536:                        || ch.id == PnutsParserTreeConstants.JJTSTATICMEMBERNODE) {
6537:                    int assigned = cf.getLocal();
6538:                    cf.storeLocal(assigned);
6539:                    cf.loadLocal(tgt);
6540:                    cf.freeLocal(tgt);
6541:                    cf.add(Opcode.INSTANCEOF, "java.lang.String");
6542:                    Label no = cf.getLabel();
6543:                    cf.add(Opcode.IFEQ, no);
6544:                    cf.loadLocal(assigned);
6545:                    _assign(ch, cc, id, true, true);
6546:                    cf.add(Opcode.POP);
6547:                    no.fix();
6548:                    cf.loadLocal(assigned);
6549:                    cf.freeLocal(assigned);
6550:                }
6551:            }
6552:
6553:            void assignStaticMember(ClassFile cf, int id, int ctx, int rhs,
6554:                    SimpleNode lhs, CompileContext cc, boolean nopop) {
6555:                SimpleNode c1 = lhs.jjtGetChild(0);
6556:                String pkgName = getPackageName(c1);
6557:                cf.add(Opcode.LDC, cf.addConstant(pkgName));
6558:                cf.loadLocal(ctx);
6559:                cf.add(Opcode.INVOKESTATIC, "pnuts.lang.Package", "find",
6560:                        "(Ljava/lang/String;Lpnuts/lang/Context;)",
6561:                        "Lpnuts/lang/Package;");
6562:                int tgt = cf.getLocal();
6563:                cf.storeLocal(tgt);
6564:                cf.loadLocal(tgt);
6565:
6566:                Label l_null = cf.getLabel();
6567:                cf.add(Opcode.IFNULL, l_null);
6568:
6569:                if (id != PnutsParserTreeConstants.JJTASSIGNMENT) {
6570:                    if ((id & 0x8000) == 0) {
6571:                        cf.loadLocal(tgt);
6572:                        cf.add(Opcode.LDC, cf.addConstant(lhs.str));
6573:                        cf.loadLocal(ctx);
6574:                        cf.add(Opcode.INVOKEVIRTUAL, "pnuts.lang.Package",
6575:                                "get",
6576:                                "(Ljava/lang/String;Lpnuts/lang/Context;)",
6577:                                "Ljava/lang/Object;");
6578:                        cf.loadLocal(rhs);
6579:                    }
6580:                    compute(cf, id, ctx);
6581:                    cf.storeLocal(rhs);
6582:                }
6583:                cf.loadLocal(tgt);
6584:                cf.add(Opcode.LDC, cf.addConstant(lhs.str));
6585:                cf.loadLocal(rhs);
6586:                cf.loadLocal(ctx);
6587:                cf
6588:                        .add(
6589:                                Opcode.INVOKEVIRTUAL,
6590:                                "pnuts.lang.Package",
6591:                                "set",
6592:                                "(Ljava/lang/String;Ljava/lang/Object;Lpnuts/lang/Context;)",
6593:                                "V");
6594:                if (nopop) {
6595:                    cf.loadLocal(rhs);
6596:                }
6597:
6598:                Label next = cf.getLabel();
6599:                cf.add(Opcode.GOTO, next);
6600:                l_null.fix();
6601:                if (nopop) {
6602:                    cf.popStack();
6603:                }
6604:                c1.accept(this , cc);
6605:                cf.add(Opcode.DUP);
6606:                cf.storeLocal(tgt);
6607:
6608:                cf.add(Opcode.INSTANCEOF, "java.lang.Class");
6609:                Label err = cf.getLabel();
6610:                cf.add(Opcode.IFEQ, err);
6611:                if (id != PnutsParserTreeConstants.JJTASSIGNMENT) {
6612:                    if ((id & 0x8000) == 0) {
6613:                        cf.loadLocal(ctx);
6614:                        cf.loadLocal(tgt);
6615:                        cf.add(Opcode.CHECKCAST, "java.lang.Class");
6616:                        cf.add(Opcode.LDC, cf.addConstant(lhs.str));
6617:                        cf
6618:                                .add(
6619:                                        Opcode.INVOKESTATIC,
6620:                                        "pnuts.lang.Runtime",
6621:                                        "getStaticField",
6622:                                        "(Lpnuts/lang/Context;Ljava/lang/Class;Ljava/lang/String;)",
6623:                                        "Ljava/lang/Object;");
6624:                        cf.loadLocal(rhs);
6625:                    }
6626:                    compute(cf, id, ctx);
6627:                    cf.storeLocal(rhs);
6628:                }
6629:                cf.loadLocal(ctx);
6630:                cf.loadLocal(tgt);
6631:                cf.freeLocal(tgt);
6632:                cf.add(Opcode.CHECKCAST, "java.lang.Class");
6633:                cf.add(Opcode.LDC, cf.addConstant(lhs.str));
6634:                cf.loadLocal(rhs);
6635:                cf
6636:                        .add(
6637:                                Opcode.INVOKESTATIC,
6638:                                "pnuts.lang.Runtime",
6639:                                "putStaticField",
6640:                                "(Lpnuts/lang/Context;Ljava/lang/Class;Ljava/lang/String;Ljava/lang/Object;)",
6641:                                "V");
6642:                if (nopop) {
6643:                    cf.loadLocal(rhs);
6644:                }
6645:                cf.add(Opcode.GOTO, next);
6646:                err.fix();
6647:                error(cf, "package.notFound", cc);
6648:                next.fix();
6649:            }
6650:
6651:            void assignGlobal(ClassFile cf, int id, int ctx, int rhs,
6652:                    SimpleNode lhs, CompileContext cc, boolean nopop) {
6653:                cf.add(Opcode.LDC, cf.addConstant(""));
6654:                cf.loadLocal(ctx);
6655:                cf.add(Opcode.INVOKESTATIC, "pnuts.lang.Package", "find",
6656:                        "(Ljava/lang/String;Lpnuts/lang/Context;)",
6657:                        "Lpnuts/lang/Package;");
6658:                int gbl = cf.getLocal();
6659:                cf.storeLocal(gbl);
6660:
6661:                if (id != PnutsParserTreeConstants.JJTASSIGNMENT) {
6662:                    if ((id & 0x8000) == 0) {
6663:                        cf.loadLocal(gbl);
6664:
6665:                        cf.add(Opcode.LDC, cf.addConstant(lhs.str));
6666:                        cf.loadLocal(ctx);
6667:                        cf.add(Opcode.INVOKEVIRTUAL, "pnuts.lang.Package",
6668:                                "get",
6669:                                "(Ljava/lang/String;Lpnuts/lang/Context;)",
6670:                                "Ljava/lang/Object;");
6671:                        cf.loadLocal(rhs);
6672:                        cf.freeLocal(gbl);
6673:                    }
6674:                    compute(cf, id, ctx);
6675:                    cf.storeLocal(rhs);
6676:                }
6677:                cf.loadLocal(gbl);
6678:                cf.add(Opcode.LDC, cf.addConstant(lhs.str));
6679:                cf.loadLocal(rhs);
6680:                cf.loadLocal(ctx);
6681:                cf
6682:                        .add(
6683:                                Opcode.INVOKEVIRTUAL,
6684:                                "pnuts.lang.Package",
6685:                                "set",
6686:                                "(Ljava/lang/String;Ljava/lang/Object;Lpnuts/lang/Context;)",
6687:                                "V");
6688:                if (nopop) {
6689:                    cf.loadLocal(rhs);
6690:                }
6691:            }
6692:
6693:            void error(ClassFile cf, String keyword, CompileContext cc) {
6694:                error(cf, keyword, (int[]) null, cc);
6695:            }
6696:
6697:            void errorSymbol(ClassFile cf, String keyword, int stringConstant,
6698:                    CompileContext cc) {
6699:                cf.add(Opcode.NEW, "pnuts.lang.PnutsException");
6700:                cf.add(Opcode.DUP);
6701:                cf.add(Opcode.LDC, cf.addConstant(keyword));
6702:                cf.pushInteger(1);
6703:                cf.add(Opcode.ANEWARRAY, "java.lang.Object");
6704:                cf.add(Opcode.DUP);
6705:                cf.pushInteger(0);
6706:                cf.add(Opcode.LDC, stringConstant);
6707:                cf.add(Opcode.AASTORE);
6708:                int ctx = cc.getContextIndex();
6709:                cf.loadLocal(ctx);
6710:                cf
6711:                        .add(
6712:                                Opcode.INVOKESPECIAL,
6713:                                "pnuts.lang.PnutsException",
6714:                                "<init>",
6715:                                "(Ljava/lang/String;[Ljava/lang/Object;Lpnuts/lang/Context;)",
6716:                                "V");
6717:                cf.add(Opcode.ATHROW);
6718:            }
6719:
6720:            void error(ClassFile cf, String keyword, int[] locals,
6721:                    CompileContext cc) {
6722:                cf.add(Opcode.NEW, "pnuts.lang.PnutsException");
6723:                cf.add(Opcode.DUP);
6724:                cf.add(Opcode.LDC, cf.addConstant(keyword));
6725:                if (locals == null) {
6726:                    cf.add(Opcode.GETSTATIC, cc.constClassName, "NO_PARAM",
6727:                            "[Ljava/lang/Object;");
6728:                } else {
6729:                    cf.pushInteger(locals.length);
6730:                    cf.add(Opcode.ANEWARRAY, "java.lang.Object");
6731:                    for (int i = 0; i < locals.length; i++) {
6732:                        cf.add(Opcode.DUP);
6733:                        cf.pushInteger(i);
6734:                        cf.loadLocal(locals[i]);
6735:                        cf.add(Opcode.AASTORE);
6736:                    }
6737:                }
6738:
6739:                int ctx = cc.getContextIndex();
6740:                cf.loadLocal(ctx);
6741:                cf
6742:                        .add(
6743:                                Opcode.INVOKESPECIAL,
6744:                                "pnuts.lang.PnutsException",
6745:                                "<init>",
6746:                                "(Ljava/lang/String;[Ljava/lang/Object;Lpnuts/lang/Context;)",
6747:                                "V");
6748:                cf.add(Opcode.ATHROW);
6749:            }
6750:
6751:            void compute(ClassFile cf, int id, int ctx) {
6752:                cf.loadLocal(ctx);
6753:                String method;
6754:                switch (id) {
6755:                case PnutsParserTreeConstants.JJTASSIGNMENTTA:
6756:                    method = "multiply";
6757:                    break;
6758:                case PnutsParserTreeConstants.JJTASSIGNMENTMA:
6759:                    method = "mod";
6760:                    break;
6761:                case PnutsParserTreeConstants.JJTASSIGNMENTDA:
6762:                    method = "divide";
6763:                    break;
6764:                case PnutsParserTreeConstants.JJTASSIGNMENTPA:
6765:                    method = "add";
6766:                    break;
6767:                case PnutsParserTreeConstants.JJTASSIGNMENTPA | 0x8000:
6768:                    cf.add(Opcode.INVOKESTATIC, "pnuts.lang.Runtime", "add1",
6769:                            "(Ljava/lang/Object;Lpnuts/lang/Context;)",
6770:                            "Ljava/lang/Object;");
6771:                    return;
6772:                case PnutsParserTreeConstants.JJTASSIGNMENTSA:
6773:                    method = "subtract";
6774:                    break;
6775:                case PnutsParserTreeConstants.JJTASSIGNMENTSA | 0x8000:
6776:                    cf.add(Opcode.INVOKESTATIC, "pnuts.lang.Runtime",
6777:                            "subtract1",
6778:                            "(Ljava/lang/Object;Lpnuts/lang/Context;)",
6779:                            "Ljava/lang/Object;");
6780:                    return;
6781:                case PnutsParserTreeConstants.JJTASSIGNMENTLA:
6782:                    method = "shiftLeft";
6783:                    break;
6784:                case PnutsParserTreeConstants.JJTASSIGNMENTRA:
6785:                    method = "shiftRight";
6786:                    break;
6787:                case PnutsParserTreeConstants.JJTASSIGNMENTRAA:
6788:                    method = "shiftArithmetic";
6789:                    break;
6790:                case PnutsParserTreeConstants.JJTASSIGNMENTAA:
6791:                    method = "and";
6792:                    break;
6793:                case PnutsParserTreeConstants.JJTASSIGNMENTEA:
6794:                    method = "xor";
6795:                    break;
6796:                case PnutsParserTreeConstants.JJTASSIGNMENTOA:
6797:                    method = "or";
6798:                    break;
6799:                default:
6800:                    throw new RuntimeException("never happen");
6801:                }
6802:                cf
6803:                        .add(
6804:                                Opcode.INVOKESTATIC,
6805:                                "pnuts.lang.Runtime",
6806:                                method,
6807:                                "(Ljava/lang/Object;Ljava/lang/Object;Lpnuts/lang/Context;)",
6808:                                "Ljava/lang/Object;");
6809:            }
6810:
6811:            /**
6812:             * Create a class loader to load compiled code.
6813:             */
6814:            static CodeLoader createCodeLoader(ClassLoader loader,
6815:                    boolean privileged) {
6816:                if (hasJava2Security && privileged) {
6817:                    return privilegedCodeLoaderFactory.create(loader);
6818:                } else {
6819:                    return codeLoaderFactory.create(loader);
6820:                }
6821:            }
6822:
6823:            public static CodeLoader createCodeLoader(ClassLoader loader) {
6824:                return createCodeLoader(loader, false);
6825:            }
6826:
6827:            static class CodeLoaderFactory {
6828:                public CodeLoader create(final ClassLoader parent) {
6829:                    ClassLoader cl = Pnuts.class.getClassLoader();
6830:                    if (cl != null) {
6831:                        if (parent != null && cl != parent) {
6832:                            return new CodeLoader(new MultiClassLoader(parent,
6833:                                    cl));
6834:                        } else {
6835:                            return new CodeLoader(cl);
6836:                        }
6837:                    } else {
6838:                        return new CodeLoader(parent);
6839:                    }
6840:                }
6841:            }
6842:
6843:            static class PrivilegedCodeLoaderFactory extends CodeLoaderFactory {
6844:                public CodeLoader create(final ClassLoader parent) {
6845:                    return (CodeLoader) AccessController
6846:                            .doPrivileged(new PrivilegedAction() {
6847:                                public Object run() {
6848:                                    ClassLoader cl = Pnuts.class
6849:                                            .getClassLoader();
6850:                                    if (cl != null) {
6851:                                        if (parent != null && cl != parent) {
6852:                                            return new CodeLoader(
6853:                                                    new MultiClassLoader(
6854:                                                            parent, cl));
6855:                                        } else {
6856:                                            return new CodeLoader(cl);
6857:                                        }
6858:                                    } else {
6859:                                        return new CodeLoader(parent);
6860:                                    }
6861:                                }
6862:                            });
6863:                }
6864:            }
6865:
6866:            /**
6867:             * Compile a parsed expression. The resulting bytecode is handled by a
6868:             * ClassFileHandler.
6869:             */
6870:            public Object compile(Pnuts pnuts, ClassFileHandler handler) {
6871:                CompileContext cc = new CompileContext();
6872:                return compile(pnuts, handler, cc);
6873:            }
6874:
6875:            Object compile(Pnuts pnuts, ClassFileHandler handler,
6876:                    CompileContext cc) {
6877:                automatic = false;
6878:                cc.scriptSource = pnuts.getScriptSource();
6879:
6880:                pnuts.accept(this , cc);
6881:                Object compileResult = handler.handle(cc.getClassFile());
6882:                List classFiles = cc.getClassFiles();
6883:                for (int i = 0, n = classFiles.size(); i < n; i++) {
6884:                    ClassFile cf = (ClassFile) classFiles.get(i);
6885:                    handler.handle(cf);
6886:                }
6887:                return compileResult;
6888:            }
6889:
6890:            /**
6891:             * Compile a parsed expression.
6892:             * 
6893:             * @param pnuts
6894:             *            a parsed expression to be compiled
6895:             * @param context
6896:             *            a context in which the expression is compiled.
6897:             * @return a Pnuts object
6898:             */
6899:            public Pnuts compile(Pnuts pnuts, final Context context) {
6900:                Throwable caught = null;
6901:                try {
6902:                    final CodeLoader loader = createCodeLoader(context
6903:                            .getClassLoader(), true);
6904:                    final CompileContext cc = new CompileContext(context);
6905:                    ClassFileHandler loadHandler = new ClassFileHandler() {
6906:                        public Object handle(ClassFile cf) {
6907:                            try {
6908:                                return cc.load(cf, loader);
6909:                            } catch (IOException e) {
6910:                                throw new PnutsException(e, context);
6911:                            }
6912:                        }
6913:                    };
6914:                    Class cls = (Class) compile(pnuts, loadHandler, cc);
6915:                    cc.resolve(loader);
6916:                    Runtime rt = (Runtime) cls.newInstance();
6917:
6918:                    return new CompiledScript(rt, pnuts);
6919:                } catch (Throwable t) {
6920:                    caught = t;
6921:                }
6922:                Runtime.checkException(context, caught);
6923:                throw new PnutsException(caught, context);
6924:            }
6925:
6926:            /**
6927:             * Compile an expression.
6928:             * 
6929:             * @param expression
6930:             *            an expression to be compiled.
6931:             * @return a Pnuts object.
6932:             */
6933:            public Pnuts compile(String expression) {
6934:                Context context = new Context();
6935:                try {
6936:                    return compile(Pnuts.parse(expression), context);
6937:                } catch (ParseException e) {
6938:                    Runtime.checkException(context, e);
6939:                    throw new PnutsException(e, context);
6940:                }
6941:            }
6942:
6943:            /**
6944:             * Compile an expression.
6945:             * 
6946:             * @param expression
6947:             *            an expression to be compiled
6948:             * @param context
6949:             *            a context in which the expression is compiled.
6950:             * @return a Pnuts object.
6951:             */
6952:            public Pnuts compile(String expression, Context context) {
6953:                try {
6954:                    return compile(Pnuts.parse(expression), context);
6955:                } catch (ParseException e) {
6956:                    Runtime.checkException(context, e);
6957:                    throw new PnutsException(e, context);
6958:                }
6959:            }
6960:
6961:            /**
6962:             * Compile a function group. The resulting bytecode is handled by a
6963:             * ClassFileHandler.
6964:             * 
6965:             * @param pf
6966:             *            a function group.
6967:             * @param handler
6968:             *            the resulting bytecode is handle by this object.
6969:             * @return the result of handler.getResult() method.
6970:             */
6971:            public Object compile(PnutsFunction pf, ClassFileHandler handler) {
6972:                CompileContext cc = new CompileContext();
6973:                PnutsFunction ret = null;
6974:                StringBuffer buf = new StringBuffer();
6975:                for (Enumeration e = getFunctions(pf); e.hasMoreElements();) {
6976:                    Function f = (Function) e.nextElement();
6977:                    if (f == null) {
6978:                        continue;
6979:                    }
6980:                    int nargs = f.getNumberOfParameter();
6981:                    String im[] = f.getImportEnv();
6982:                    buf.append("import(null);");
6983:                    for (int i = 0; i < im.length; i++) {
6984:                        buf.append("import " + im[i] + ";");
6985:                    }
6986:                    buf.append(pf.unparse(nargs));
6987:                    buf.append('\n');
6988:                }
6989:                try {
6990:                    String expr = buf.toString();
6991:                    if (DEBUG) {
6992:                        System.out.println(expr);
6993:                    }
6994:                    return compile(Pnuts.parse(expr), handler, cc);
6995:                } catch (ParseException pe) {
6996:                    throw new PnutsException(pe, cc);
6997:                }
6998:            }
6999:
7000:            /**
7001:             * Compile a function group
7002:             * 
7003:             * @param pf
7004:             *            a function group to be compiled.
7005:             * @return a compiled version of the function group
7006:             */
7007:            public PnutsFunction compile(PnutsFunction pf) {
7008:                return compile(pf, new Context());
7009:            }
7010:
7011:            /**
7012:             * Compile a function group
7013:             * 
7014:             * @param pf
7015:             *            a function group to be compiled.
7016:             * @param context
7017:             *            a context in which the function is compiled.
7018:             * @return a compiled version of the function group
7019:             */
7020:            public PnutsFunction compile(PnutsFunction pf, Context context) {
7021:                StringBuffer buf = new StringBuffer();
7022:                for (Enumeration e = getFunctions(pf); e.hasMoreElements();) {
7023:                    Function f = (Function) e.nextElement();
7024:                    if (f == null) { // function written in Java
7025:                        continue;
7026:                    }
7027:                    int nargs = f.getNumberOfParameter();
7028:                    String im[] = f.getImportEnv();
7029:                    buf.append("import(null);");
7030:                    for (int i = 0; i < im.length; i++) {
7031:                        buf.append("import " + im[i] + ";");
7032:                    }
7033:                    buf.append(pf.unparse(nargs));
7034:                    buf.append('\n');
7035:                }
7036:                Context c = (Context) context.clone();
7037:                return (PnutsFunction) compile(buf.toString(), context).run(c);
7038:            }
7039:
7040:            /**
7041:             * Check if an object is compiled
7042:             * 
7043:             * @param obj
7044:             *            an object to be checked
7045:             * @return true if the object is compiled
7046:             */
7047:            public static boolean isCompiled(Object obj) {
7048:                if (obj instanceof  Compiled) {
7049:                    return true;
7050:                }
7051:                if (obj instanceof  PnutsFunction) {
7052:                    for (Enumeration e = getFunctions((PnutsFunction) obj); e
7053:                            .hasMoreElements();) {
7054:                        Function f = (Function) e.nextElement();
7055:                        if (!(f instanceof  Compiled)) {
7056:                            return false;
7057:                        }
7058:                    }
7059:                    return true;
7060:                }
7061:                return false;
7062:            }
7063:
7064:            static String getClassName(SimpleNode node) {
7065:                int n = node.jjtGetNumChildren();
7066:                if (n > 1) {
7067:                    StringBuffer sbuf = new StringBuffer();
7068:                    sbuf.append(node.jjtGetChild(0).str);
7069:                    for (int i = 1; i < n; i++) {
7070:                        sbuf.append('.');
7071:                        sbuf.append(node.jjtGetChild(i).str);
7072:                    }
7073:                    return sbuf.toString();
7074:                } else {
7075:                    return node.jjtGetChild(0).str;
7076:                }
7077:            }
7078:
7079:            void resolveClassName(SimpleNode nameNode, CompileContext cc,
7080:                    int ctx) {
7081:                ClassFile cf = cc.cf;
7082:                int n = nameNode.jjtGetNumChildren();
7083:                if (n == 1) {
7084:                    String sym = nameNode.jjtGetChild(0).str;
7085:                    if (sym == INT_SYMBOL) {
7086:                        cf.add(Opcode.GETSTATIC, "java.lang.Integer", "TYPE",
7087:                                "Ljava/lang/Class;");
7088:                        return;
7089:                    } else if (sym == SHORT_SYMBOL) {
7090:                        cf.add(Opcode.GETSTATIC, "java.lang.Short", "TYPE",
7091:                                "Ljava/lang/Class;");
7092:                        return;
7093:                    } else if (sym == CHAR_SYMBOL) {
7094:                        cf.add(Opcode.GETSTATIC, "java.lang.Character", "TYPE",
7095:                                "Ljava/lang/Class;");
7096:                        return;
7097:                    } else if (sym == BYTE_SYMBOL) {
7098:                        cf.add(Opcode.GETSTATIC, "java.lang.Byte", "TYPE",
7099:                                "Ljava/lang/Class;");
7100:                        return;
7101:                    } else if (sym == LONG_SYMBOL) {
7102:                        cf.add(Opcode.GETSTATIC, "java.lang.Long", "TYPE",
7103:                                "Ljava/lang/Class;");
7104:                        return;
7105:                    } else if (sym == FLOAT_SYMBOL) {
7106:                        cf.add(Opcode.GETSTATIC, "java.lang.Float", "TYPE",
7107:                                "Ljava/lang/Class;");
7108:                        return;
7109:                    } else if (sym == DOUBLE_SYMBOL) {
7110:                        cf.add(Opcode.GETSTATIC, "java.lang.Double", "TYPE",
7111:                                "Ljava/lang/Class;");
7112:                        return;
7113:                    } else if (sym == BOOLEAN_SYMBOL) {
7114:                        cf.add(Opcode.GETSTATIC, "java.lang.Boolean", "TYPE",
7115:                                "Ljava/lang/Class;");
7116:                        return;
7117:                    } else if (sym == VOID_SYMBOL) {
7118:                        cf.add(Opcode.GETSTATIC, "java.lang.Void", "TYPE",
7119:                                "Ljava/lang/Class;");
7120:                        return;
7121:                    }
7122:                }
7123:
7124:                StringBuffer sbuf = new StringBuffer();
7125:                sbuf.append(nameNode.jjtGetChild(0).str);
7126:                for (int i = 1; i < n; i++) {
7127:                    sbuf.append('.');
7128:                    sbuf.append(nameNode.jjtGetChild(i).str);
7129:                }
7130:                String className = sbuf.toString();
7131:                Label nonnull = cf.getLabel();
7132:                int value = cf.getLocal();
7133:
7134:                cf.loadLocal(ctx);
7135:                int index = cf.getLocal();
7136:                cf.add(Opcode.LDC, cf.addConstant(className));
7137:                cf.storeLocal(index);
7138:                cf.loadLocal(index);
7139:                cf.add(Opcode.INVOKEVIRTUAL, "pnuts.lang.Context",
7140:                        "resolveClass", "(Ljava/lang/String;)",
7141:                        "Ljava/lang/Class;");
7142:
7143:                cf.storeLocal(value);
7144:                cf.loadLocal(value);
7145:                cf.add(Opcode.IFNONNULL, nonnull);
7146:                error(cf, "class.notFound", new int[] { index }, cc);
7147:                nonnull.fix();
7148:                cf.loadLocal(value);
7149:                cf.freeLocal(value);
7150:                cf.freeLocal(index);
7151:            }
7152:
7153:            void resolveType(SimpleNode typeNode, CompileContext cc, int ctx) {
7154:                ClassFile cf = cc.cf;
7155:                Class type = null;
7156:                if (typeNode.id == PnutsParserTreeConstants.JJTARRAYTYPE) {
7157:                    SimpleNode n = typeNode;
7158:                    int count = 0;
7159:                    while (n != null
7160:                            && n.id == PnutsParserTreeConstants.JJTARRAYTYPE) {
7161:                        count++;
7162:                        n = n.jjtGetChild(0);
7163:                    }
7164:                    if (n != null
7165:                            && n.id != PnutsParserTreeConstants.JJTCLASSNAME) {
7166:                        throw new RuntimeException();
7167:                    }
7168:                    resolveClassName(n, cc, ctx);
7169:                    cf.pushInteger(count);
7170:                    cf.add(Opcode.INVOKESTATIC, "pnuts.lang.Runtime",
7171:                            "arrayType", "(Ljava/lang/Class;I)",
7172:                            "Ljava/lang/Class;");
7173:
7174:                } else if (typeNode.id == PnutsParserTreeConstants.JJTCLASSNAME) {
7175:                    resolveClassName(typeNode, cc, ctx);
7176:                } else {
7177:                    error(cf, "class.expected", cc);
7178:                }
7179:            }
7180:
7181:            static void getRef(Reference ref, CompileContext cc) {
7182:                ref.get(cc.cf, cc.env.parent != null, cc.getContextIndex());
7183:            }
7184:
7185:            public ClassFile compileClassScript(SimpleNode classScriptNode,
7186:                    Object scriptSource, List helperClassFiles) {
7187:                CompileContext cc = new CompileContext();
7188:                cc.scriptSource = scriptSource;
7189:                classScript(classScriptNode, cc);
7190:                helperClassFiles.addAll(cc.getClassFiles());
7191:                return cc.cf;
7192:            }
7193:
7194:            public Object compileClassScript(Reader reader,
7195:                    Object scriptSource, ClassFileHandler handler)
7196:                    throws ParseException, IOException {
7197:                ParseEnvironment env = DefaultParseEnv
7198:                        .getInstance(scriptSource);
7199:                SimpleNode node = new PnutsParser(reader).ClassScript(env);
7200:                CompileContext cc = new CompileContext();
7201:                cc.scriptSource = scriptSource;
7202:                automatic = false;
7203:                node.accept(this , cc);
7204:                Object compileResult = handler.handle(cc.getClassFile());
7205:                List classFiles = cc.getClassFiles();
7206:                for (int i = 0, n = classFiles.size(); i < n; i++) {
7207:                    ClassFile cf = (ClassFile) classFiles.get(i);
7208:                    handler.handle(cf);
7209:                }
7210:                return compileResult;
7211:            }
7212:
7213:            public Object beanDef(SimpleNode node, Context context) {
7214:                CompileContext cc = (CompileContext) context;
7215:                ClassFile cf = cc.cf;
7216:                cc.beanEnv = new BeanEnv(cc.beanEnv);
7217:                int tableIndex = cf.getLocal();
7218:                //cc.beanEnv.tableIndex = tableIndex;
7219:                cf.add(Opcode.NEW, "java.util.HashMap");
7220:                cf.add(Opcode.DUP);
7221:                cf.add(Opcode.INVOKESPECIAL, "java.util.HashMap", "<init>",
7222:                        "()", "V");
7223:                cf.storeLocal(tableIndex);
7224:
7225:                int ctx = cc.getContextIndex();
7226:                int conf = cf.getLocal();
7227:                cf.loadLocal(ctx);
7228:                cf.add(Opcode.INVOKEVIRTUAL, "pnuts.lang.Context",
7229:                        "getConfiguration", "()", "Lpnuts/lang/Configuration;");
7230:                cf.storeLocal(conf);
7231:                cf.loadLocal(conf);
7232:                cf.loadLocal(ctx);
7233:                SimpleNode nameNode = node.jjtGetChild(0);
7234:                resolveClassName(nameNode, cc, ctx);
7235:                cf.add(Opcode.GETSTATIC, className, "NO_PARAM",
7236:                        "[Ljava/lang/Object;");
7237:                cf.add(Opcode.ACONST_NULL);
7238:                cf
7239:                        .add(
7240:                                Opcode.INVOKEVIRTUAL,
7241:                                "pnuts.lang.Configuration",
7242:                                "callConstructor",
7243:                                "(Lpnuts/lang/Context;Ljava/lang/Class;[Ljava/lang/Object;[Ljava/lang/Class;)",
7244:                                "Ljava/lang/Object;");
7245:                int target = cf.getLocal();
7246:                cf.storeLocal(target);
7247:                for (int i = 1; i < node.jjtGetNumChildren(); i++) {
7248:                    SimpleNode cn = node.jjtGetChild(i);
7249:                    String propertyName = cn.str;
7250:                    SimpleNode valueNode = cn.jjtGetChild(0);
7251:                    boolean bound = "::".equals(cn.info);
7252:                    if (bound) { /* experimental BIND feature */
7253:                        List memberNodes = new ArrayList();
7254:                        cn.info = memberNodes;
7255:                        markMemberNodeInBeanDef(cn, target, tableIndex,
7256:                                valueNode);
7257:                    }
7258:                    cf.loadLocal(conf);
7259:                    cf.loadLocal(ctx);
7260:                    cf.loadLocal(target);
7261:                    cf.add(Opcode.LDC, cf.addConstant(propertyName));
7262:                    valueNode.accept(this , context);
7263:                    cf
7264:                            .add(
7265:                                    Opcode.INVOKEVIRTUAL,
7266:                                    "pnuts.lang.Configuration",
7267:                                    "putField",
7268:                                    "(Lpnuts/lang/Context;Ljava/lang/Object;Ljava/lang/String;Ljava/lang/Object;)",
7269:                                    "V");
7270:                }
7271:                cf.loadLocal(tableIndex);
7272:                cf.loadLocal(ctx);
7273:                cf.add(Opcode.INVOKESTATIC, "pnuts.lang.Runtime",
7274:                        "setupPropertyChangeListeners",
7275:                        "(Ljava/util/Map;Lpnuts/lang/Context;)", "V");
7276:
7277:                cf.loadLocal(target);
7278:                cf.freeLocal(conf);
7279:                cf.freeLocal(target);
7280:                cc.beanEnv = cc.beanEnv.parent;
7281:                return null;
7282:            }
7283:
7284:            static void markMemberNodeInBeanDef(SimpleNode beanPropertyDef,
7285:                    int targetIndex, int tableIndex, SimpleNode node) {
7286:                if (node.id == PnutsParserTreeConstants.JJTMEMBERNODE) {
7287:                    node.info = new Object[] {
7288:                            new int[] { targetIndex, tableIndex },
7289:                            beanPropertyDef };
7290:                } else if (node.id != PnutsParserTreeConstants.JJTFUNCTIONSTATEMENT) {
7291:                    for (int i = 0; i < node.jjtGetNumChildren(); i++) {
7292:                        markMemberNodeInBeanDef(beanPropertyDef, targetIndex,
7293:                                tableIndex, node.jjtGetChild(i));
7294:                    }
7295:                }
7296:            }
7297:
7298:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.