Source Code Cross Referenced for Compilation.java in  » Scripting » Kawa » gnu » expr » 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 » Kawa » gnu.expr 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        // Copyright (c) 1999, 2000-2005, 2006 Per M.A. Bothner.
0002:        // This is free software;  for terms and warranty disclaimer see ./COPYING.
0003:
0004:        package gnu.expr;
0005:
0006:        import gnu.bytecode.*;
0007:        import gnu.mapping.*;
0008:        import java.util.*;
0009:        import java.io.*;
0010:        import kawa.Shell;
0011:        import gnu.text.*;
0012:        import java.util.zip.*;
0013:        import java.util.Stack;
0014:
0015:        /** State for a single expression or module.
0016:         * For each top-level thing (expression or file) we compile or evaluate
0017:         * we create a new Compilation.
0018:         */
0019:
0020:        public class Compilation implements  SourceLocator {
0021:            /** True if the form is too complex to evaluate,and we must compile it.
0022:             * This is because it contains a construct we know how to compile, but not
0023:             * evaluate, and it it outside a function (which we always compile).
0024:             * This can be a let scope, or primitive procedure. */
0025:            public boolean mustCompile;
0026:
0027:            /** Used by LambdaExp.getSelectorValue if need to allocate new selector. */
0028:            int maxSelectorValue;
0029:
0030:            public ClassType curClass;
0031:            public ClassType mainClass;
0032:            /** Generated class that extends ModuleBody.  Normally same as mainClass. */
0033:            public ClassType moduleClass;
0034:
0035:            public LambdaExp curLambda;
0036:            public ModuleExp mainLambda;
0037:            public Variable this Decl;
0038:
0039:            /** Contains "$instance" if the module is static; otherwise null. */
0040:            Variable moduleInstanceVar;
0041:
0042:            /** A code, one of the following constants, indicating how far along
0043:             * we are in the parsing/compilation process.
0044:             * These codes are even integers for completed stages and odd integers
0045:             * for begun but not completed stages. */
0046:            private int state;
0047:
0048:            /** Returns a code indicating how far along
0049:             * we are in the parsing/compilation process. */
0050:            public int getState() {
0051:                return state;
0052:            }
0053:
0054:            public void setState(int state) {
0055:                this .state = state;
0056:            }
0057:
0058:            /** State code for initial pre-parse looking for module name. */
0059:            public static final int PROLOG_PARSING = 1;
0060:            /** We have determined the module name and class, but not finished parsing. */
0061:            public static final int PROLOG_PARSED = 2;
0062:            /** State code indicating the entire module has been parsed. */
0063:            public static final int BODY_PARSED = 4;
0064:            /** State code for lexical bindings having been resolved. */
0065:            public static final int RESOLVED = 6;
0066:            /** State code when various inlining and optimization passes are done. */
0067:            public static final int WALKED = 8;
0068:            /** State code that various compile-only data has been determined. */
0069:            public static final int COMPILE_SETUP = 10;
0070:            /** State code indicating the bytecode has been generated. */
0071:            public static final int COMPILED = 12;
0072:            /** State code indicating that bytecode has been written to its target. */
0073:            public static final int CLASS_WRITTEN = 14;
0074:            public static final int ERROR_SEEN = 100;
0075:
0076:            public ModuleInfo minfo;
0077:            public Lexer lexer;
0078:
0079:            boolean pedantic;
0080:
0081:            public boolean isPedantic() {
0082:                return pedantic;
0083:            }
0084:
0085:            /** Used to access the "main" instance.
0086:             * This is used for two different purposes, which may be confusing:
0087:             * <ul>
0088:             * <li>
0089:             * If we're compiling a static module, then {@code moduleInstanceMainField}
0090:             * is a field in {@code mainClass} named {@code "$instance"} that
0091:             * points to the single instance of the module.</li>
0092:             * <li>
0093:             * If {@code moduleClass!=mainClass} (typically because we've specified
0094:             * {@code module-extends}) <em>and</em> the module is non-static then
0095:             * {@code moduleInstanceMainField} is a field in {@code moduleClass}
0096:             * named {@code "$main"} that points back to {@code mainClass}.</li></ul>
0097:             */
0098:            Field moduleInstanceMainField;
0099:
0100:            public java.util.Stack pendingImports;
0101:
0102:            public void pushPendingImport(ModuleInfo info, ScopeExp defs) {
0103:                if (pendingImports == null)
0104:                    pendingImports = new java.util.Stack();
0105:                pendingImports.push(info);
0106:                pendingImports.push(defs);
0107:                Expression posExp = new ReferenceExp((Object) null);
0108:                posExp.setLine(this );
0109:                pendingImports.push(posExp);
0110:            }
0111:
0112:            /** If true, minimize the number of classes generated.
0113:             * Do this even if it makes things a little slower. */
0114:            public static boolean fewerClasses;
0115:
0116:            /** If true, print out expressions after parsing and before optimizations. */
0117:            public static boolean debugPrintExpr = false;
0118:
0119:            /** If true, print out final expressions after optimizations etc. */
0120:            public static boolean debugPrintFinalExpr;
0121:
0122:            public static Options options = new Options();
0123:            public Options currentOptions = new Options(options);
0124:            static {
0125:                options.add("warn-undefined-variable", Options.BOOLEAN_OPTION,
0126:                        "warn if no compiler-visible binding for a variable");
0127:                options.add("warn-invoke-unknown-method",
0128:                        Options.BOOLEAN_OPTION,
0129:                        "warn if invoke calls an unknown method");
0130:                options.add("warn-as-error", Options.BOOLEAN_OPTION,
0131:                        "Make all warnings into errors");
0132:            }
0133:
0134:            /** Get a named boolean option. */
0135:            public final boolean getBooleanOption(String key,
0136:                    boolean defaultValue) {
0137:                return currentOptions.getBoolean(key, defaultValue);
0138:            }
0139:
0140:            /** Get a named boolean option. */
0141:            public final boolean getBooleanOption(String key) {
0142:                return currentOptions.getBoolean(key);
0143:            }
0144:
0145:            /** The default calling convention.
0146:             * One of the following CALL_WITHG_xxx values. */
0147:            public static int defaultCallConvention;
0148:            public static final int CALL_WITH_UNSPECIFIED = 0;
0149:            /** Plain calling convention, using regular Java parameters and returns. */
0150:            public static final int CALL_WITH_RETURN = 1;
0151:            /** Function results are written to the current CallContext's Consumer. */
0152:            public static final int CALL_WITH_CONSUMER = 2;
0153:            /** Like CALL_WITH_CONSUMER, but handle full on-stack-growing tail-calls. */
0154:            public static final int CALL_WITH_TAILCALLS = 3;
0155:            /** Support for full continuations.  Not implemented. */
0156:            public static final int CALL_WITH_CONTINUATIONS = 4;
0157:
0158:            public boolean usingCPStyle() {
0159:                return defaultCallConvention == CALL_WITH_CONTINUATIONS;
0160:            }
0161:
0162:            public boolean usingTailCalls() {
0163:                return defaultCallConvention >= CALL_WITH_TAILCALLS;
0164:            }
0165:
0166:            /** If moduleStatic > 0, (module-static #t) is implied by default.
0167:             * If moduleStatic == 2, <clinit> calls run.
0168:             * If moduleStatic < 0, (module-static #f) is implied by default. */
0169:            public static int moduleStatic = 0;
0170:
0171:            ClassType[] classes;
0172:            int numClasses;
0173:
0174:            /** When immediate, the ClassLoader we will load the compiled
0175:             * classes from. */
0176:            ArrayClassLoader loader;
0177:
0178:            /** True if the compiled result will be immediately loaded. */
0179:            public boolean immediate;
0180:
0181:            /** The current method. */
0182:            public Method method;
0183:
0184:            Method clinitMethod;
0185:
0186:            public final CodeAttr getCode() {
0187:                return method.getCode();
0188:            }
0189:
0190:            int method_counter;
0191:
0192:            /* When multiple procedures are compiled into a single method,
0193:               we use a switch to jump to the correct part of the method. */
0194:            SwitchState fswitch;
0195:
0196:            Field fswitchIndex;
0197:
0198:            // Various standard classes
0199:            static public ClassType typeObject = Type.pointer_type;
0200:            static public ClassType scmBooleanType = ClassType
0201:                    .make("java.lang.Boolean");
0202:            static public ClassType typeString = ClassType
0203:                    .make("java.lang.String");
0204:            static public ClassType javaStringType = typeString;
0205:            static public ClassType scmKeywordType = ClassType
0206:                    .make("gnu.expr.Keyword");
0207:            static public ClassType scmSequenceType = ClassType
0208:                    .make("gnu.lists.Sequence");
0209:            static public ClassType javaIntegerType = ClassType
0210:                    .make("java.lang.Integer");
0211:            static public ClassType scmListType = ClassType
0212:                    .make("gnu.lists.LList");
0213:            static public ClassType typePair = ClassType.make("gnu.lists.Pair");
0214:            static public ClassType scmPairType = typePair;
0215:            public static final ArrayType objArrayType = ArrayType
0216:                    .make(typeObject);
0217:            static public ClassType scmNamedType = ClassType
0218:                    .make("gnu.mapping.Named");
0219:            static public ClassType typeRunnable = ClassType
0220:                    .make("java.lang.Runnable");
0221:            public static ClassType typeType = ClassType
0222:                    .make("gnu.bytecode.Type");
0223:            public static ClassType typeObjectType = ClassType.make(
0224:                    "gnu.bytecode.ObjectType", typeType);
0225:            public static ClassType typeClass = Type.java_lang_Class_type;
0226:            static public ClassType typeClassType = ClassType.make(
0227:                    "gnu.bytecode.ClassType", typeObjectType);
0228:            static public ClassType typeProcedure = ClassType
0229:                    .make("gnu.mapping.Procedure");
0230:            static public ClassType typeLanguage = ClassType
0231:                    .make("gnu.expr.Language");
0232:            static public ClassType typeEnvironment = ClassType
0233:                    .make("gnu.mapping.Environment");
0234:            static public ClassType typeLocation = ClassType
0235:                    .make("gnu.mapping.Location");
0236:            static public ClassType typeSymbol = ClassType
0237:                    .make("gnu.mapping.Symbol");
0238:            static public final Method getSymbolValueMethod = typeLanguage
0239:                    .getDeclaredMethod("getSymbolValue", 1);
0240:            static public final Method getSymbolProcedureMethod = typeLanguage
0241:                    .getDeclaredMethod("getSymbolProcedure", 1);
0242:            static public final Method getLocationMethod = typeLocation
0243:                    .addMethod("get", Type.typeArray0, Type.pointer_type,
0244:                            Access.PUBLIC);
0245:            static public final Method getProcedureBindingMethod = typeSymbol
0246:                    .addMethod("getProcedure", Type.typeArray0, typeProcedure,
0247:                            Access.PUBLIC);
0248:            static public final Field trueConstant = scmBooleanType
0249:                    .getDeclaredField("TRUE");
0250:            static public final Field falseConstant = scmBooleanType
0251:                    .getDeclaredField("FALSE");
0252:
0253:            static final Method setNameMethod = typeProcedure
0254:                    .getDeclaredMethod("setName", 1);
0255:            static Method makeListMethod;
0256:
0257:            public static final Type[] int1Args = { Type.int_type };
0258:            public static final Type[] string1Arg = { javaStringType };
0259:            public static final Type[] sym1Arg = string1Arg;
0260:
0261:            static public final Method getLocation1EnvironmentMethod = typeEnvironment
0262:                    .getDeclaredMethod("getLocation", 1);
0263:            static public final Method getLocation2EnvironmentMethod;
0264:            static {
0265:                Type[] args = { typeSymbol, Type.pointer_type };
0266:                getLocation2EnvironmentMethod = typeEnvironment.addMethod(
0267:                        "getLocation", args, typeLocation, Access.PUBLIC
0268:                                | Access.FINAL);
0269:            }
0270:
0271:            static {
0272:                Type[] makeListArgs = { objArrayType, Type.int_type };
0273:                makeListMethod = scmListType.addMethod("makeList",
0274:                        makeListArgs, scmListType, Access.PUBLIC
0275:                                | Access.STATIC);
0276:            }
0277:
0278:            public static Method getCurrentEnvironmentMethod = typeEnvironment
0279:                    .addMethod("getCurrent", Type.typeArray0, typeEnvironment,
0280:                            Access.PUBLIC | Access.STATIC);
0281:
0282:            public static Type[] apply0args = Type.typeArray0;
0283:            public static Type[] apply1args = { typeObject };
0284:            public static Type[] apply2args = { typeObject, typeObject };
0285:            public static Type[] applyNargs = { objArrayType };
0286:
0287:            static Method checkArgCountMethod;
0288:
0289:            public static Method apply0method = typeProcedure.addMethod(
0290:                    "apply0", apply0args, typeObject, Access.PUBLIC
0291:                            | Access.FINAL);
0292:
0293:            public static Method apply1method;
0294:            public static Method apply2method;
0295:            public static Method apply3method;
0296:            public static Method apply4method;
0297:            public static Method applyNmethod;
0298:
0299:            static {
0300:                apply1method = typeProcedure.addMethod("apply1", apply1args,
0301:                        typeObject, Access.PUBLIC);
0302:                apply2method = typeProcedure.addMethod("apply2", apply2args,
0303:                        typeObject, Access.PUBLIC);
0304:                Type[] apply3args = { typeObject, typeObject, typeObject };
0305:                apply3method = typeProcedure.addMethod("apply3", apply3args,
0306:                        typeObject, Access.PUBLIC);
0307:                Type[] apply4args = { typeObject, typeObject, typeObject,
0308:                        typeObject };
0309:                apply4method = typeProcedure.addMethod("apply4", apply4args,
0310:                        typeObject, Access.PUBLIC);
0311:                applyNmethod = typeProcedure.addMethod("applyN", applyNargs,
0312:                        typeObject, Access.PUBLIC);
0313:                Type[] args = new Type[2];
0314:                args[0] = typeProcedure;
0315:                args[1] = Type.int_type;
0316:                checkArgCountMethod = typeProcedure.addMethod("checkArgCount",
0317:                        args, Type.void_type, Access.PUBLIC | Access.STATIC);
0318:            }
0319:
0320:            public static Method[] applymethods = { apply0method, apply1method,
0321:                    apply2method, apply3method, apply4method, applyNmethod };
0322:
0323:            public static ClassType typeProcedure0 = ClassType.make(
0324:                    "gnu.mapping.Procedure0", typeProcedure);
0325:            public static ClassType typeProcedure1 = ClassType.make(
0326:                    "gnu.mapping.Procedure1", typeProcedure);
0327:            public static ClassType typeProcedure2 = ClassType.make(
0328:                    "gnu.mapping.Procedure2", typeProcedure);
0329:            public static ClassType typeProcedure3 = ClassType.make(
0330:                    "gnu.mapping.Procedure3", typeProcedure);
0331:            public static ClassType typeProcedure4 = ClassType.make(
0332:                    "gnu.mapping.Procedure4", typeProcedure);
0333:            public static ClassType typeProcedureN = ClassType.make(
0334:                    "gnu.mapping.ProcedureN", typeProcedure);
0335:            public static ClassType typeModuleBody = ClassType.make(
0336:                    "gnu.expr.ModuleBody", typeProcedure0);
0337:            public static ClassType typeModuleWithContext = ClassType.make(
0338:                    "gnu.expr.ModuleWithContext", typeModuleBody);
0339:            public static ClassType typeApplet = ClassType
0340:                    .make("java.applet.Applet");
0341:            public static ClassType typeServlet = ClassType
0342:                    .make("gnu.kawa.servlet.KawaServlet");
0343:
0344:            /* Classes, fields, and methods used wgen usingCPStyle". */
0345:            public static ClassType typeCallContext = ClassType
0346:                    .make("gnu.mapping.CallContext");
0347:            public static final ClassType typeConsumer = ClassType
0348:                    .make("gnu.lists.Consumer");
0349:            public static Method getCallContextInstanceMethod = typeCallContext
0350:                    .getDeclaredMethod("getInstance", 0);
0351:            public static ClassType typeValues = ClassType
0352:                    .make("gnu.mapping.Values");
0353:            public static Field noArgsField = typeValues
0354:                    .getDeclaredField("noArgs");
0355:            public static Field pcCallContextField = typeCallContext
0356:                    .getDeclaredField("pc");
0357:            public static ClassType typeMethodProc = ClassType.make(
0358:                    "gnu.mapping.MethodProc", typeProcedureN);
0359:            public static ClassType typeModuleMethod = ClassType.make(
0360:                    "gnu.expr.ModuleMethod", typeMethodProc);
0361:            //  public static Field numArgsCallFrameField = typeCallFrame.getDeclaredField("numArgs");
0362:            public static Field argsCallContextField = typeCallContext
0363:                    .getDeclaredField("values");
0364:            public static Field procCallContextField = typeCallContext
0365:                    .getDeclaredField("proc");
0366:            private static Type[] applyCpsArgs = { typeCallContext };
0367:            public static Method applyCpsMethod = typeProcedure.addMethod(
0368:                    "apply", applyCpsArgs, Type.void_type, Access.PUBLIC);
0369:
0370:            public static ClassType[] typeProcedureArray = { typeProcedure0,
0371:                    typeProcedure1, typeProcedure2, typeProcedure3,
0372:                    typeProcedure4 };
0373:
0374:            /** Rembembers stuff to do in <clinit> of main class. */
0375:            Initializer clinitChain;
0376:
0377:            public static boolean generateMainDefault = false;
0378:            /** True if we should generate a main(String[]) method. */
0379:            public boolean generateMain = generateMainDefault;
0380:
0381:            LitTable litTable;
0382:
0383:            public static boolean generateAppletDefault = false;
0384:            /** True if we should generate an Applet. */
0385:            public boolean generateApplet = generateAppletDefault;
0386:
0387:            public static boolean generateServletDefault = false;
0388:            /** True if we should generate an Servlet. */
0389:            public boolean generateServlet = generateServletDefault;
0390:
0391:            public final ClassType getModuleType() {
0392:                return (defaultCallConvention >= Compilation.CALL_WITH_CONSUMER ? typeModuleWithContext
0393:                        : typeModuleBody);
0394:            }
0395:
0396:            /** Emit code to "evaluate" a compile-time constant.
0397:             * This is the normal external interface.
0398:             * @param value the value to be compiled
0399:             */
0400:            public void compileConstant(Object value) {
0401:                gnu.bytecode.CodeAttr code = getCode();
0402:                if (value == null)
0403:                    code.emitPushNull();
0404:                else if (value instanceof  String && !immediate)
0405:                    code.emitPushString((String) value);
0406:                else
0407:                    code.emitGetStatic(compileConstantToField(value));
0408:            }
0409:
0410:            public Field compileConstantToField(Object value) {
0411:                Literal literal = litTable.findLiteral(value);
0412:                if (literal.field == null)
0413:                    literal.assign(litTable);
0414:                return literal.field;
0415:            }
0416:
0417:            public static boolean inlineOk = true;
0418:
0419:            public boolean inlineOk(Expression proc) {
0420:                if (proc instanceof  LambdaExp) {
0421:                    // The compiler gets confused if we turn off inlining for nested
0422:                    // procedures - and they can't be rebound anyway.
0423:                    if (!(((LambdaExp) proc).currentLambda() instanceof  ModuleExp))
0424:                        return true;
0425:                }
0426:                return inlineOk;
0427:            }
0428:
0429:            public boolean inlineOk(Procedure proc) {
0430:                return inlineOk;
0431:            }
0432:
0433:            public void compileConstant(Object value, Target target) {
0434:                if (target instanceof  IgnoreTarget)
0435:                    return;
0436:                if (value instanceof  Values) {
0437:                    Object[] values = ((Values) value).getValues();
0438:                    int len = values.length;
0439:                    if (target instanceof  ConsumerTarget) {
0440:                        for (int i = 0; i < len; i++) {
0441:                            compileConstant(values[i], target);
0442:                        }
0443:                        return;
0444:                    } else if (target instanceof  SeriesTarget) {
0445:                        SeriesTarget starget = (SeriesTarget) target;
0446:                        Label saveDone = starget.done;
0447:                        if (len > 0) {
0448:                            starget.done = null;
0449:                            for (int i = 0; i < len; i++) {
0450:                                if (i + 1 == len)
0451:                                    starget.done = saveDone;
0452:                                compileConstant(values[i], target);
0453:                            }
0454:                        } else if (saveDone != null
0455:                                && getCode().reachableHere())
0456:                            getCode().emitGoto(saveDone);
0457:                        return;
0458:                    }
0459:                }
0460:                if (target instanceof  ConditionalTarget) {
0461:                    ConditionalTarget ctarg = (ConditionalTarget) target;
0462:                    getCode().emitGoto(
0463:                            getLanguage().isTrue(value) ? ctarg.ifTrue
0464:                                    : ctarg.ifFalse);
0465:                    return;
0466:                }
0467:                if (target instanceof  StackTarget) {
0468:                    Type type = ((StackTarget) target).getType();
0469:                    if (type instanceof  PrimType) {
0470:                        try {
0471:                            String signature = type.getSignature();
0472:                            CodeAttr code = getCode();
0473:                            char sig1 = (signature == null || signature
0474:                                    .length() != 1) ? ' ' : signature.charAt(0);
0475:                            if (value instanceof  Number) {
0476:                                Number num = (Number) value;
0477:                                switch (sig1) {
0478:                                case 'I':
0479:                                    code.emitPushInt(num.intValue());
0480:                                    return;
0481:                                case 'S':
0482:                                    code.emitPushInt(num.shortValue());
0483:                                    return;
0484:                                case 'B':
0485:                                    code.emitPushInt(num.byteValue());
0486:                                    return;
0487:                                case 'J':
0488:                                    code.emitPushLong(num.longValue());
0489:                                    return;
0490:                                case 'F':
0491:                                    code.emitPushFloat(num.floatValue());
0492:                                    return;
0493:                                case 'D':
0494:                                    code.emitPushDouble(num.doubleValue());
0495:                                    return;
0496:                                }
0497:                            }
0498:                            if (sig1 == 'C') {
0499:                                code.emitPushInt((int) ((PrimType) type)
0500:                                        .charValue(value));
0501:                                return;
0502:                            }
0503:                            if (sig1 == 'Z') {
0504:                                boolean val = PrimType.booleanValue(value);
0505:                                code.emitPushInt(val ? 1 : 0);
0506:                                return;
0507:                            }
0508:                        } catch (ClassCastException ex) {
0509:                            // should print an ERROR.
0510:                        }
0511:                    }
0512:                    try {
0513:                        value = type.coerceFromObject(value);
0514:                    } catch (Exception ex) {
0515:                        StringBuffer sbuf = new StringBuffer();
0516:                        if (value == Values.empty)
0517:                            sbuf.append("cannot convert void to ");
0518:                        else {
0519:                            sbuf.append("cannot convert literal (of type ");
0520:                            sbuf.append(value.getClass().getName());
0521:                            sbuf.append(") to ");
0522:                        }
0523:                        sbuf.append(type.getName());
0524:                        error('w', sbuf.toString());
0525:                    }
0526:                }
0527:                compileConstant(value);
0528:                target.compileFromStack(this , value == null ? target.getType()
0529:                        : Type.make(value.getClass()));
0530:            }
0531:
0532:            private void dumpInitializers(Initializer inits) {
0533:                for (Initializer init = Initializer.reverse(inits); init != null; init = init.next)
0534:                    init.emit(this );
0535:            }
0536:
0537:            /** Search this Compilation for a ClassType with a given name.
0538:             * @param name the name of the class desired
0539:             * @return the matching ClassType, or null if none is found */
0540:            public ClassType findNamedClass(String name) {
0541:                for (int i = 0; i < numClasses; i++) {
0542:                    if (name.equals(classes[i].getName()))
0543:                        return classes[i];
0544:                }
0545:                return null;
0546:            }
0547:
0548:            public static String classPrefixDefault = "";
0549:            /** If non-null: a prefix for generateClassName to prepend to names. */
0550:            public String classPrefix = classPrefixDefault;
0551:
0552:            /** Recusive helper function to reverse order of words in hostname. */
0553:            private static void putURLWords(String name, StringBuffer sbuf) {
0554:                int dot = name.indexOf('.');
0555:                if (dot > 0) {
0556:                    putURLWords(name.substring(dot + 1), sbuf);
0557:                    sbuf.append('.');
0558:                    name = name.substring(0, dot);
0559:                }
0560:                sbuf.append(name);
0561:            }
0562:
0563:            /** Map a URI to a package/class name.
0564:             * Similar to the JAXB mangling, and that in the Java language spec.
0565:             */
0566:            public static String mangleURI(String name) {
0567:                boolean hasSlash = name.indexOf('/') >= 0;
0568:                int len = name.length();
0569:                if (len > 6 && name.startsWith("class:"))
0570:                    return name.substring(6);
0571:                // Remove "http:" or "urn:".
0572:                if (len > 5 && name.charAt(4) == ':'
0573:                        && name.substring(0, 4).equalsIgnoreCase("http")) {
0574:                    name = name.substring(5);
0575:                    len -= 5;
0576:                    hasSlash = true;
0577:                } else if (len > 4 && name.charAt(3) == ':'
0578:                        && name.substring(0, 3).equalsIgnoreCase("uri")) {
0579:                    name = name.substring(4);
0580:                    len -= 4;
0581:                }
0582:                int start = 0;
0583:                StringBuffer sbuf = new StringBuffer();
0584:                for (;;) {
0585:                    int slash = name.indexOf('/', start);
0586:                    int end = slash < 0 ? len : slash;
0587:                    boolean first = sbuf.length() == 0;
0588:                    if (first && hasSlash) {
0589:                        // Remove initial "www.".
0590:                        String host = name.substring(start, end);
0591:                        if (end - start > 4 && host.startsWith("www."))
0592:                            host = host.substring(4);
0593:                        // Reverse order of words in "host" part.
0594:                        putURLWords(host, sbuf);
0595:                    } else if (start != end) {
0596:                        if (!first)
0597:                            sbuf.append('.');
0598:                        if (end == len) {
0599:                            int dot = name.lastIndexOf('.', len);
0600:                            if (dot > start + 1 && !first) {
0601:                                // Remove file extension:
0602:                                int extLen = len - dot;
0603:                                if (extLen <= 4
0604:                                        || (extLen == 5 && name
0605:                                                .endsWith("html"))) {
0606:                                    len -= extLen;
0607:                                    end = len;
0608:                                    name = name.substring(0, len);
0609:                                }
0610:                            }
0611:                        }
0612:                        sbuf.append(name.substring(start, end));
0613:                    }
0614:                    if (slash < 0)
0615:                        break;
0616:                    start = slash + 1;
0617:                }
0618:                return sbuf.toString();
0619:            }
0620:
0621:            public static String mangleName(String name) {
0622:                return mangleName(name, -1);
0623:            }
0624:
0625:            public static String mangleNameIfNeeded(String name) {
0626:                if (isValidJavaName(name))
0627:                    return name;
0628:                else
0629:                    return mangleName(name, 0);
0630:            }
0631:
0632:            public static boolean isValidJavaName(String name) {
0633:                int len = name.length();
0634:                if (len == 0
0635:                        || !Character.isJavaIdentifierStart(name.charAt(0)))
0636:                    return false;
0637:                for (int i = len; --i > 0;)
0638:                    if (!Character.isJavaIdentifierPart(name.charAt(i)))
0639:                        return false;
0640:                return true;
0641:            }
0642:
0643:            /** Convert a string to a safe Java identifier.
0644:             * @param reversible if we should use an invertible mapping.
0645:             */
0646:            public static String mangleName(String name, boolean reversible) {
0647:                return mangleName(name, reversible ? 1 : -1);
0648:            }
0649:
0650:            /** Convert a string to a safe Java identifier.
0651:             * @param kind -1 - non-reversible;
0652:             *  0: reversible, except that '$' is not mapped;
0653:             *  1: reversible
0654:             */
0655:            public static String mangleName(String name, int kind) {
0656:                boolean reversible = kind >= 0;
0657:                int len = name.length();
0658:                if (len == 6 && name.equals("*init*")) // Constructor methods.
0659:                    return "<init>";
0660:                StringBuffer mangled = new StringBuffer(len);
0661:                boolean upcaseNext = false;
0662:                for (int i = 0; i < len; i++) {
0663:                    char ch = name.charAt(i);
0664:                    if (upcaseNext) {
0665:                        ch = Character.toTitleCase(ch);
0666:                        upcaseNext = false;
0667:                    }
0668:                    if (Character.isDigit(ch)) {
0669:                        if (i == 0)
0670:                            mangled.append("$N");
0671:                        mangled.append(ch);
0672:                    } else if (Character.isLetter(ch) || ch == '_')
0673:                        mangled.append(ch);
0674:                    else if (ch == '$')
0675:                        mangled.append(kind > 1 ? "$$" : "$");
0676:                    else {
0677:                        switch (ch) {
0678:                        case '+':
0679:                            mangled.append("$Pl");
0680:                            break;
0681:                        case '-':
0682:                            if (reversible)
0683:                                mangled.append("$Mn");
0684:                            else {
0685:                                char next = i + 1 < len ? name.charAt(i + 1)
0686:                                        : '\0';
0687:                                if (next == '>') {
0688:                                    mangled.append("$To$");
0689:                                    i++;
0690:                                } else if (!Character.isLowerCase(next))
0691:                                    mangled.append("$Mn");
0692:                            }
0693:                            break;
0694:                        case '*':
0695:                            mangled.append("$St");
0696:                            break;
0697:                        case '/':
0698:                            mangled.append("$Sl");
0699:                            break;
0700:                        case '=':
0701:                            mangled.append("$Eq");
0702:                            break;
0703:                        case '<':
0704:                            mangled.append("$Ls");
0705:                            break;
0706:                        case '>':
0707:                            mangled.append("$Gr");
0708:                            break;
0709:                        case '@':
0710:                            mangled.append("$At");
0711:                            break;
0712:                        case '~':
0713:                            mangled.append("$Tl");
0714:                            break;
0715:                        case '%':
0716:                            mangled.append("$Pc");
0717:                            break;
0718:                        case '.':
0719:                            mangled.append("$Dt");
0720:                            break;
0721:                        case ',':
0722:                            mangled.append("$Cm");
0723:                            break;
0724:                        case '(':
0725:                            mangled.append("$LP");
0726:                            break;
0727:                        case ')':
0728:                            mangled.append("$RP");
0729:                            break;
0730:                        case '[':
0731:                            mangled.append("$LB");
0732:                            break;
0733:                        case ']':
0734:                            mangled.append("$RB");
0735:                            break;
0736:                        case '{':
0737:                            mangled.append("$LC");
0738:                            break;
0739:                        case '}':
0740:                            mangled.append("$RC");
0741:                            break;
0742:                        case '\'':
0743:                            mangled.append("$Sq");
0744:                            break;
0745:                        case '"':
0746:                            mangled.append("$Dq");
0747:                            break;
0748:                        case '&':
0749:                            mangled.append("$Am");
0750:                            break;
0751:                        case '#':
0752:                            mangled.append("$Nm");
0753:                            break;
0754:                        case '?':
0755:                            char first = mangled.length() > 0 ? mangled
0756:                                    .charAt(0) : '\0';
0757:                            if (!reversible && i + 1 == len
0758:                                    && Character.isLowerCase(first)) {
0759:                                mangled.setCharAt(0, Character
0760:                                        .toTitleCase(first));
0761:                                mangled.insert(0, "is");
0762:                            } else
0763:                                mangled.append("$Qu");
0764:                            break;
0765:                        case '!':
0766:                            mangled.append("$Ex");
0767:                            break;
0768:                        case ':':
0769:                            mangled.append("$Cl");
0770:                            break;
0771:                        case ';':
0772:                            mangled.append("$SC");
0773:                            break;
0774:                        case '^':
0775:                            mangled.append("$Up");
0776:                            break;
0777:                        case '|':
0778:                            mangled.append("$VB");
0779:                            break;
0780:                        default:
0781:                            mangled.append('$');
0782:                            mangled.append(Character.forDigit((ch >> 12) & 15,
0783:                                    16));
0784:                            mangled.append(Character.forDigit((ch >> 8) & 15,
0785:                                    16));
0786:                            mangled.append(Character.forDigit((ch >> 4) & 15,
0787:                                    16));
0788:                            mangled.append(Character.forDigit((ch) & 15, 16));
0789:                        }
0790:                        if (!reversible)
0791:                            upcaseNext = true;
0792:                    }
0793:                }
0794:                String mname = mangled.toString();
0795:                return mname.equals(name) ? name : mname;
0796:            }
0797:
0798:            /** Demangle a three-character mangling starting with '$'.
0799:             * UNFINISHED!
0800:             */
0801:            public static char demangle2(char char1, char char2) {
0802:                switch (char1 << 16 | char2) {
0803:                case 'A' << 16 | 'm':
0804:                    return '&';
0805:                case 'A' << 16 | 't':
0806:                    return '@';
0807:                case 'C' << 16 | 'l':
0808:                    return ':';
0809:                case 'C' << 16 | 'm':
0810:                    return ',';
0811:                case 'D' << 16 | 'q':
0812:                    return '\"';
0813:                case 'D' << 16 | 't':
0814:                    return '.';
0815:                case 'E' << 16 | 'q':
0816:                    return '=';
0817:                case 'E' << 16 | 'x':
0818:                    return '!';
0819:                case 'G' << 16 | 'r':
0820:                    return '>';
0821:                case 'L' << 16 | 'B':
0822:                    return '[';
0823:                case 'L' << 16 | 'C':
0824:                    return '{';
0825:                case 'L' << 16 | 'P':
0826:                    return '(';
0827:                case 'L' << 16 | 's':
0828:                    return '<';
0829:                case 'M' << 16 | 'c':
0830:                    return '%';
0831:                case 'M' << 16 | 'n':
0832:                    return '-';
0833:                case 'N' << 16 | 'm':
0834:                    return '#';
0835:                case 'P' << 16 | 'c':
0836:                    return '%';
0837:                case 'P' << 16 | 'l':
0838:                    return '+';
0839:                case 'Q' << 16 | 'u':
0840:                    return '?';
0841:                case 'R' << 16 | 'B':
0842:                    return ']';
0843:                case 'R' << 16 | 'C':
0844:                    return '}';
0845:                case 'R' << 16 | 'P':
0846:                    return ')';
0847:                case 'S' << 16 | 'C':
0848:                    return ';';
0849:                case 'S' << 16 | 'l':
0850:                    return '/';
0851:                case 'S' << 16 | 'q':
0852:                    return '\\';
0853:                case 'S' << 16 | 't':
0854:                    return '*';
0855:                case 'T' << 16 | 'l':
0856:                    return '~';
0857:                case 'U' << 16 | 'p':
0858:                    return '^';
0859:                case 'V' << 16 | 'B':
0860:                    return '|';
0861:                }
0862:                return (char) (-1);
0863:            }
0864:
0865:            public static String demangleName(String name) {
0866:                return demangleName(name, false);
0867:            }
0868:
0869:            public static String demangleName(String name, boolean reversible) {
0870:                StringBuffer sbuf = new StringBuffer();
0871:                int len = name.length();
0872:                boolean mangled = false;
0873:                boolean predicate = false;
0874:                boolean downCaseNext = false;
0875:                for (int i = 0; i < len; i++) {
0876:                    char ch = name.charAt(i);
0877:                    if (downCaseNext && !reversible) {
0878:                        ch = Character.toLowerCase(ch);
0879:                        downCaseNext = false;
0880:                    }
0881:                    char d;
0882:                    if (!reversible && ch == 'i' && i == 0 && len > 2
0883:                            && name.charAt(i + 1) == 's'
0884:                            && !Character.isLowerCase(d = name.charAt(i + 2))) {
0885:                        mangled = true;
0886:                        predicate = true;
0887:                        i++;
0888:                        if (Character.isUpperCase(d)
0889:                                || Character.isTitleCase(d)) {
0890:                            sbuf.append(Character.toLowerCase(d));
0891:                            i++;
0892:                            continue;
0893:                        }
0894:                        continue;
0895:                    } else if (ch == '$' && i + 2 < len) {
0896:                        char c1 = name.charAt(i + 1);
0897:                        char c2 = name.charAt(i + 2);
0898:                        d = Compilation.demangle2(c1, c2);
0899:                        if (d != (char) (-1)) {
0900:                            sbuf.append(d);
0901:                            i += 2;
0902:                            mangled = true;
0903:                            downCaseNext = true;
0904:                            continue;
0905:                        } else if (c1 == 'T' && c2 == 'o' && i + 3 < len
0906:                                && name.charAt(i + 3) == '$') {
0907:                            sbuf.append("->");
0908:                            i += 3;
0909:                            mangled = true;
0910:                            downCaseNext = true;
0911:                            continue;
0912:                        }
0913:                    } else if (!reversible
0914:                            && i > 1
0915:                            && (Character.isUpperCase(ch) || Character
0916:                                    .isTitleCase(ch))
0917:                            && (Character.isLowerCase(name.charAt(i - 1)))) {
0918:                        sbuf.append('-');
0919:                        mangled = true;
0920:                        ch = Character.toLowerCase(ch);
0921:                    }
0922:                    sbuf.append(ch);
0923:                }
0924:                if (predicate)
0925:                    sbuf.append('?');
0926:                return mangled ? sbuf.toString() : name;
0927:            }
0928:
0929:            /** Generate an unused class name.
0930:             * @param hint the requested name (or prefix)
0931:             * @return a unique class name.
0932:             */
0933:            public String generateClassName(String hint) {
0934:                hint = mangleName(hint, true);
0935:                if (mainClass != null)
0936:                    hint = mainClass.getName() + '$' + hint;
0937:                else if (classPrefix != null)
0938:                    hint = classPrefix + hint;
0939:                if (findNamedClass(hint) == null)
0940:                    return hint;
0941:                for (int i = 0;; i++) {
0942:                    String new_hint = hint + i;
0943:                    if (findNamedClass(new_hint) == null)
0944:                        return new_hint;
0945:                }
0946:            }
0947:
0948:            public Compilation(boolean immediate, SourceMessages messages) {
0949:                this (messages);
0950:                this .immediate = immediate;
0951:            }
0952:
0953:            public Compilation(SourceMessages messages) {
0954:                this .messages = messages;
0955:                lexical = new NameLookup(getLanguage());
0956:            }
0957:
0958:            public Compilation(Language language, SourceMessages messages) {
0959:                this (language, messages, new NameLookup(language));
0960:            }
0961:
0962:            public Compilation(Language language, SourceMessages messages,
0963:                    NameLookup lexical) {
0964:                this .language = language;
0965:                this .messages = messages;
0966:                this .lexical = lexical;
0967:            }
0968:
0969:            /** Shared processing for both compiling/eval. */
0970:            public void walkModule(ModuleExp mexp) {
0971:                if (debugPrintExpr) {
0972:                    OutPort dout = OutPort.errDefault();
0973:                    dout.println("[Module:" + mexp.getName());
0974:                    mexp.print(dout);
0975:                    dout.println(']');
0976:                    dout.flush();
0977:                }
0978:
0979:                InlineCalls.inlineCalls(mexp, this );
0980:                PushApply.pushApply(mexp);
0981:                ChainLambdas.chainLambdas(mexp, this );
0982:                FindTailCalls.findTailCalls(mexp, this );
0983:            }
0984:
0985:            public void outputClass(String directory) throws IOException {
0986:                char dirSep = File.separatorChar;
0987:                for (int iClass = 0; iClass < numClasses; iClass++) {
0988:                    ClassType clas = classes[iClass];
0989:                    String out_name = (directory
0990:                            + clas.getName().replace('.', dirSep) + ".class");
0991:                    String parent = new File(out_name).getParent();
0992:                    if (parent != null)
0993:                        new File(parent).mkdirs();
0994:                    clas.writeToFile(out_name);
0995:
0996:                    clas.cleanupAfterCompilation();
0997:                }
0998:
0999:                minfo.comp = null;
1000:                mainLambda.body = null;
1001:                mainLambda = null;
1002:                litTable = null;
1003:            }
1004:
1005:            public void compileToArchive(ModuleExp mexp, String fname)
1006:                    throws java.io.IOException {
1007:                boolean makeJar = false;
1008:                if (fname.endsWith(".zip"))
1009:                    makeJar = false;
1010:                else if (fname.endsWith(".jar"))
1011:                    makeJar = true;
1012:                else {
1013:                    fname = fname + ".zip";
1014:                    makeJar = false;
1015:                }
1016:
1017:                process(COMPILED);
1018:
1019:                File zar_file = new File(fname);
1020:                if (zar_file.exists())
1021:                    zar_file.delete();
1022:                ZipOutputStream zout;
1023:                /* #ifdef JAVA2 */
1024:                if (makeJar)
1025:                    zout = new java.util.jar.JarOutputStream(
1026:                            new FileOutputStream(zar_file));
1027:                else
1028:                /* #endif */
1029:                {
1030:                    zout = new ZipOutputStream(new FileOutputStream(zar_file));
1031:                    zout.setMethod(ZipOutputStream.STORED); // no compression
1032:                }
1033:
1034:                byte[][] classBytes = new byte[numClasses][];
1035:                CRC32 zcrc = new CRC32();
1036:                for (int iClass = 0; iClass < numClasses; iClass++) {
1037:                    ClassType clas = classes[iClass];
1038:                    classBytes[iClass] = clas.writeToArray();
1039:                    ZipEntry zent = new ZipEntry(clas.getName().replace('.',
1040:                            '/')
1041:                            + ".class");
1042:
1043:                    zent.setSize(classBytes[iClass].length);
1044:                    zcrc.reset();
1045:                    zcrc.update(classBytes[iClass], 0,
1046:                            classBytes[iClass].length);
1047:                    zent.setCrc(zcrc.getValue());
1048:
1049:                    zout.putNextEntry(zent);
1050:                    zout.write(classBytes[iClass]);
1051:                }
1052:                zout.close();
1053:            }
1054:
1055:            // FIXME - make this settable, as it does make .class files bigger.
1056:            public static boolean emitSourceDebugExtAttr = true;
1057:
1058:            private void registerClass(ClassType new_class) {
1059:                if (classes == null)
1060:                    classes = new ClassType[20];
1061:                else if (numClasses >= classes.length) {
1062:                    ClassType[] new_classes = new ClassType[2 * classes.length];
1063:                    System.arraycopy(classes, 0, new_classes, 0, numClasses);
1064:                    classes = new_classes;
1065:                }
1066:                new_class.access_flags |= new_class.isInterface() ? Access.PUBLIC
1067:                        : Access.PUBLIC | Access.SUPER;
1068:                if (new_class == mainClass && numClasses > 0) {
1069:                    // Ensure mainClass is written first when writing an archive.
1070:                    new_class = classes[0];
1071:                    classes[0] = mainClass;
1072:                }
1073:                classes[numClasses++] = new_class;
1074:            }
1075:
1076:            public void addClass(ClassType new_class) {
1077:                if (mainLambda.filename != null) {
1078:                    if (emitSourceDebugExtAttr)
1079:                        new_class.setStratum(getLanguage().getName());
1080:                    new_class.setSourceFile(mainLambda.filename);
1081:                }
1082:                registerClass(new_class);
1083:                /* #ifdef JAVA5 */
1084:                // new_class.setClassfileVersionJava5();
1085:                /* #endif */
1086:            }
1087:
1088:            public void addMainClass(ModuleExp module) {
1089:                mustCompile = true;
1090:
1091:                mainClass = module.classFor(this );
1092:
1093:                ClassType type = mainClass;
1094:                ClassType[] interfaces = module.getInterfaces();
1095:                if (interfaces != null)
1096:                    type.setInterfaces(interfaces);
1097:                ClassType sup = module.getSuperType();
1098:                if (sup == null) {
1099:                    if (generateApplet)
1100:                        sup = typeApplet;
1101:                    else if (generateServlet)
1102:                        sup = typeServlet;
1103:                    else
1104:                        sup = getModuleType();
1105:                }
1106:                if (!generateServlet)
1107:                    type.addInterface(typeRunnable);
1108:                type.setSuper(sup);
1109:
1110:                module.type = type;
1111:                addClass(type);
1112:                getConstructor(mainClass, module);
1113:            }
1114:
1115:            public final Method getConstructor(LambdaExp lexp) {
1116:                return getConstructor(lexp.getHeapFrameType(), lexp);
1117:            }
1118:
1119:            public static final Method getConstructor(ClassType clas,
1120:                    LambdaExp lexp) {
1121:                Method meth = clas.getDeclaredMethod("<init>", 0);
1122:                if (meth != null)
1123:                    return meth;
1124:                Type[] args;
1125:                if (lexp instanceof  ClassExp && lexp.staticLinkField != null) {
1126:                    args = new Type[1];
1127:                    args[0] = lexp.staticLinkField.getType();
1128:                } else
1129:                    args = apply0args;
1130:                return clas.addMethod("<init>", Access.PUBLIC, args,
1131:                        Type.void_type);
1132:            }
1133:
1134:            public final void generateConstructor(LambdaExp lexp) {
1135:                generateConstructor(lexp.getHeapFrameType(), lexp);
1136:            }
1137:
1138:            public final void generateConstructor(ClassType clas, LambdaExp lexp) {
1139:                Method save_method = method;
1140:                Variable callContextSave = callContextVar;
1141:                callContextVar = null;
1142:                ClassType save_class = curClass;
1143:                curClass = clas;
1144:                Method constructor_method = getConstructor(clas, lexp);
1145:                clas.constructor = constructor_method;
1146:                method = constructor_method;
1147:                CodeAttr code = constructor_method.startCode();
1148:
1149:                if (lexp instanceof  ClassExp && lexp.staticLinkField != null) {
1150:                    code.emitPushThis();
1151:                    code.emitLoad(code.getCurrentScope().getVariable(1));
1152:                    code.emitPutField(lexp.staticLinkField);
1153:                }
1154:                Method super Constructor = clas.getSuperclass().addMethod(
1155:                        "<init>", Access.PUBLIC, apply0args, Type.void_type);
1156:                code.emitPushThis();
1157:                code.emitInvokeSpecial(super Constructor);
1158:
1159:                if (curClass == mainClass
1160:                // Optimization: No pointing in calling register if we aren't
1161:                        // compiling a named module.
1162:                        && minfo != null && minfo.sourcePath != null) {
1163:                    code.emitPushThis();
1164:                    code.emitInvokeStatic(ClassType.make("gnu.expr.ModuleInfo")
1165:                            .getDeclaredMethod("register", 1));
1166:                }
1167:
1168:                if (lexp.initChain != null) {
1169:                    // Create dummy lambda, for its closureEnv.  This may be needed
1170:                    // if init.value contains a reference that uses our heap frame.
1171:                    LambdaExp save = curLambda;
1172:                    curLambda = new LambdaExp();
1173:                    curLambda.closureEnv = code.getArg(0);
1174:                    curLambda.outer = save;
1175:                    Initializer init;
1176:                    while ((init = lexp.initChain) != null) {
1177:                        lexp.initChain = null;
1178:                        dumpInitializers(init);
1179:                    }
1180:                    curLambda = save;
1181:                }
1182:
1183:                if (lexp instanceof  ClassExp) {
1184:                    ClassExp cexp = (ClassExp) lexp;
1185:                    callInitMethods(cexp.getCompiledClassType(this ),
1186:                            new Vector(10));
1187:                }
1188:
1189:                code.emitReturn();
1190:                method = save_method;
1191:                curClass = save_class;
1192:                callContextVar = callContextSave;
1193:            }
1194:
1195:            /** In an <init> for a generated ClassExp, emit $finit$ calls.
1196:             * This recursively traverses superclasses, and also calls their $finit$.
1197:             * @param clas Class to search for $finit$, and to search supertypes.
1198:             * @param seen array of seen classes, to avoid duplicate $finit$ calls.
1199:             */
1200:            void callInitMethods(ClassType clas, Vector seen) {
1201:                if (clas == null)
1202:                    return;
1203:
1204:                String name = clas.getName();
1205:                if ("java.lang.Object".equals(name))
1206:                    return;
1207:                // Check for duplicates.
1208:                for (int i = seen.size(); --i >= 0;)
1209:                    if (((ClassType) seen.elementAt(i)).getName() == name)
1210:                        return;
1211:                seen.addElement(clas);
1212:
1213:                // Recusive call to emit $finit$ of super-types.  However, don't do that
1214:                // for clas.getSuperclass(), because our <init> will automatically call
1215:                // the super-class's <init>, which will call its $finit$.
1216:                ClassType[] interfaces = clas.getInterfaces();
1217:                if (interfaces != null) {
1218:                    int n = interfaces.length;
1219:                    for (int i = 0; i < n; i++)
1220:                        callInitMethods(interfaces[i], seen);
1221:                }
1222:
1223:                int clEnvArgs = 1;
1224:                if (clas instanceof  PairClassType)
1225:                    clas = ((PairClassType) clas).instanceType;
1226:                else if (clas.isInterface()) {
1227:                    try {
1228:                        clas = ((ClassType) Type.make(Class.forName(clas
1229:                                .getName()
1230:                                + "$class")));
1231:                    } catch (Throwable ex) {
1232:                        return;
1233:                    }
1234:                } else
1235:                    clEnvArgs = 0;
1236:                Method meth = clas.getDeclaredMethod("$finit$", clEnvArgs);
1237:                if (meth != null) {
1238:                    CodeAttr code = getCode();
1239:                    code.emitPushThis();
1240:                    code.emitInvoke(meth);
1241:                }
1242:            }
1243:
1244:            public void generateMatchMethods(LambdaExp lexp) {
1245:                int numApplyMethods = lexp.applyMethods == null ? 0
1246:                        : lexp.applyMethods.size();
1247:                if (numApplyMethods == 0)
1248:                    return;
1249:                Method save_method = method;
1250:                ClassType save_class = curClass;
1251:                ClassType procType = typeModuleMethod;
1252:                curClass = lexp.getHeapFrameType();
1253:                if (!(curClass.getSuperclass().isSubtype(typeModuleBody)))
1254:                    curClass = moduleClass;
1255:                CodeAttr code = null;
1256:                for (int i = 0; i <= 5; i++) {
1257:                    boolean needThisMatch = false;
1258:                    SwitchState aswitch = null;
1259:                    String mname = null;
1260:                    Type[] matchArgs = null;
1261:                    for (int j = numApplyMethods; --j >= 0;) {
1262:                        LambdaExp source = (LambdaExp) lexp.applyMethods
1263:                                .elementAt(j);
1264:                        // Select the subset of source.primMethods[*] that are suitable
1265:                        // for the current apply method.
1266:                        Method[] primMethods = source.primMethods;
1267:                        int numMethods = primMethods.length;
1268:                        boolean varArgs = source.max_args < 0
1269:                                || source.max_args >= source.min_args
1270:                                        + numMethods;
1271:                        int methodIndex;
1272:                        if (i < 5) // Handling match0 .. match4
1273:                        {
1274:                            methodIndex = i - source.min_args;
1275:                            if (methodIndex < 0
1276:                                    || methodIndex >= numMethods
1277:                                    || (methodIndex == numMethods - 1 && varArgs))
1278:                                continue;
1279:                            numMethods = 1;
1280:                            varArgs = false;
1281:                        } else // Handling matchN
1282:                        {
1283:                            methodIndex = 5 - source.min_args;
1284:                            if (methodIndex > 0 && numMethods <= methodIndex
1285:                                    && !varArgs)
1286:                                continue;
1287:                            methodIndex = numMethods - 1;
1288:                        }
1289:                        if (!needThisMatch) {
1290:                            // First LambdaExp we seen suitable for this i.
1291:                            if (i < 5) {
1292:                                mname = "match" + i;
1293:                                matchArgs = new Type[i + 2];
1294:                                for (int k = i; k >= 0; k--)
1295:                                    matchArgs[k + 1] = typeObject;
1296:                                matchArgs[i + 1] = typeCallContext;
1297:                            } else {
1298:                                mname = "matchN";
1299:                                matchArgs = new Type[3];
1300:                                matchArgs[1] = objArrayType;
1301:                                matchArgs[2] = typeCallContext;
1302:                            }
1303:                            matchArgs[0] = procType;
1304:                            method = curClass.addMethod(mname, matchArgs,
1305:                                    Type.int_type, Access.PUBLIC);
1306:                            code = method.startCode();
1307:
1308:                            code.emitLoad(code.getArg(1)); // method
1309:                            code.emitGetField(procType.getField("selector"));
1310:                            aswitch = new SwitchState(code);
1311:
1312:                            needThisMatch = true;
1313:                        }
1314:
1315:                        aswitch.addCase(source.getSelectorValue(this ), code);
1316:
1317:                        int line = source.getLineNumber();
1318:                        if (line > 0)
1319:                            code.putLineNumber(source.getFileName(), line);
1320:
1321:                        Variable ctxVar = code.getArg(i == 5 ? 3 : i + 2);
1322:
1323:                        if (i < 5) {
1324:                            Declaration var = source.firstDecl();
1325:                            for (int k = 1; k <= i; k++) {
1326:                                code.emitLoad(ctxVar);
1327:                                code.emitLoad(code.getArg(k + 1));
1328:                                Type ptype = var.getType();
1329:                                if (ptype != Type.pointer_type) {
1330:                                    if (ptype instanceof  TypeValue) {
1331:                                        Label trueLabel = new Label(code), falseLabel = new Label(
1332:                                                code);
1333:                                        ConditionalTarget ctarget = new ConditionalTarget(
1334:                                                trueLabel, falseLabel,
1335:                                                getLanguage());
1336:                                        code.emitDup();
1337:                                        ((TypeValue) ptype).emitIsInstance(
1338:                                                null, this , ctarget);
1339:                                        falseLabel.define(code);
1340:                                        code
1341:                                                .emitPushInt(MethodProc.NO_MATCH_BAD_TYPE
1342:                                                        | k);
1343:                                        code.emitReturn();
1344:                                        trueLabel.define(code);
1345:                                    } else if (ptype instanceof  ClassType
1346:                                            && ptype != Type.pointer_type
1347:                                            && ptype != Type.tostring_type) // FIXME
1348:                                    {
1349:                                        code.emitDup();
1350:                                        ptype.emitIsInstance(code);
1351:                                        code.emitIfIntEqZero();
1352:                                        code
1353:                                                .emitPushInt(MethodProc.NO_MATCH_BAD_TYPE
1354:                                                        | k);
1355:                                        code.emitReturn();
1356:                                        code.emitFi();
1357:                                    }
1358:                                }
1359:                                code.emitPutField(typeCallContext
1360:                                        .getField("value" + k));
1361:                                var = var.nextDecl();
1362:                            }
1363:                        } else {
1364:                            // FIXME - need to check
1365:                            code.emitLoad(ctxVar);
1366:                            code.emitLoad(code.getArg(2));
1367:                            code.emitPutField(typeCallContext
1368:                                    .getField("values"));
1369:                        }
1370:                        code.emitLoad(ctxVar);
1371:                        if (defaultCallConvention < Compilation.CALL_WITH_CONSUMER)
1372:                            code.emitLoad(code.getArg(1)); // proc
1373:                        else
1374:                            code.emitLoad(code.getArg(0)); // this (module)
1375:                        code.emitPutField(procCallContextField);
1376:                        code.emitLoad(ctxVar);
1377:                        if (defaultCallConvention >= CALL_WITH_CONSUMER)
1378:                            code.emitPushInt(source.getSelectorValue(this )
1379:                                    + methodIndex);
1380:                        else
1381:                            code.emitPushInt(i);
1382:                        code.emitPutField(pcCallContextField);
1383:                        code.emitPushInt(0);
1384:                        code.emitReturn();
1385:                    }
1386:                    if (needThisMatch) {
1387:                        aswitch.addDefault(code);
1388:                        int nargs = i > 4 ? 2 : i + 1;
1389:                        nargs++;
1390:                        for (int k = 0; k <= nargs; k++)
1391:                            code.emitLoad(code.getArg(k));
1392:                        Method defMethod = (typeModuleBody.getDeclaredMethod(
1393:                                mname, matchArgs.length));
1394:                        code.emitInvokeSpecial(defMethod);
1395:                        code.emitReturn();
1396:                        aswitch.finish(code);
1397:                    }
1398:                }
1399:                method = save_method;
1400:                curClass = save_class;
1401:            }
1402:
1403:            /** Generate ModuleBody's <tt>apply(CallContext)</tt> method
1404:             * Use the <tt>applyMethods</tt> vector, which contains methods that
1405:             * implement the (public, readable) methods of the current module. */
1406:            public void generateApplyMethodsWithContext(LambdaExp lexp) {
1407:                int numApplyMethods = lexp.applyMethods == null ? 0
1408:                        : lexp.applyMethods.size();
1409:                if (numApplyMethods == 0)
1410:                    return;
1411:                ClassType save_class = curClass;
1412:                curClass = lexp.getHeapFrameType();
1413:                if (!(curClass.getSuperclass().isSubtype(typeModuleWithContext)))
1414:                    curClass = moduleClass;
1415:                ClassType procType = typeModuleMethod;
1416:                Method save_method = method;
1417:                CodeAttr code = null;
1418:                Type[] applyArgs = { typeCallContext };
1419:
1420:                // First LambdaExp we seen suitable for this i.
1421:                method = curClass.addMethod("apply", applyArgs,
1422:                        (Type) Type.void_type, Access.PUBLIC);
1423:                code = method.startCode();
1424:                Variable ctxVar = code.getArg(1);
1425:
1426:                code.emitLoad(ctxVar);
1427:                code.emitGetField(pcCallContextField);
1428:                SwitchState aswitch = new SwitchState(code);
1429:
1430:                for (int j = 0; j < numApplyMethods; ++j) {
1431:                    LambdaExp source = (LambdaExp) lexp.applyMethods
1432:                            .elementAt(j);
1433:                    Method[] primMethods = source.primMethods;
1434:                    int numMethods = primMethods.length;
1435:
1436:                    for (int i = 0; i < numMethods; i++) {
1437:                        // Select the subset of source.primMethods[*] that are suitable
1438:                        // for the current apply method.
1439:                        boolean varArgs = (i == numMethods - 1 && (source.max_args < 0 || source.max_args >= source.min_args
1440:                                + numMethods));
1441:                        int methodIndex = i;
1442:
1443:                        aswitch
1444:                                .addCase(source.getSelectorValue(this ) + i,
1445:                                        code);
1446:
1447:                        int line = source.getLineNumber();
1448:                        if (line > 0)
1449:                            code.putLineNumber(source.getFileName(), line);
1450:
1451:                        Method primMethod = primMethods[methodIndex];
1452:                        Type[] primArgTypes = primMethod.getParameterTypes();
1453:                        int singleArgs = source.min_args + methodIndex;
1454:                        Variable counter = null;
1455:                        int pendingIfEnds = 0;
1456:
1457:                        if (i > 4 && numMethods > 1) // FIXME
1458:                        {
1459:                            counter = code.addLocal(Type.int_type);
1460:                            code.emitLoad(ctxVar);
1461:                            code.emitGetField(typeCallContext
1462:                                    .getDeclaredField("count"));
1463:                            if (source.min_args != 0) {
1464:                                code.emitPushInt(source.min_args);
1465:                                code.emitSub(Type.int_type);
1466:                            }
1467:                            code.emitStore(counter);
1468:                        }
1469:
1470:                        int needsThis = primMethod.getStaticFlag() ? 0 : 1;
1471:                        int explicitFrameArg = singleArgs + (varArgs ? 2 : 1) < primArgTypes.length ? 1
1472:                                : 0;
1473:                        if (needsThis + explicitFrameArg > 0) {
1474:                            code.emitPushThis();
1475:                            if (curClass == moduleClass
1476:                                    && mainClass != moduleClass)
1477:                                code.emitGetField(moduleInstanceMainField);
1478:                        }
1479:
1480:                        Declaration var = source.firstDecl();
1481:                        for (int k = 0; k < singleArgs; k++) {
1482:                            if (counter != null && k >= source.min_args) {
1483:                                code.emitLoad(counter);
1484:                                code.emitIfIntLEqZero();
1485:                                code.emitLoad(ctxVar);
1486:                                code
1487:                                        .emitInvoke(primMethods[k
1488:                                                - source.min_args]);
1489:                                code.emitElse();
1490:                                pendingIfEnds++;
1491:                                code.emitInc(counter, (short) (-1));
1492:                            }
1493:
1494:                            code.emitLoad(ctxVar);
1495:                            if (k <= 4 && !varArgs && source.max_args <= 4)
1496:                                code.emitGetField(typeCallContext
1497:                                        .getDeclaredField("value" + (k + 1)));
1498:                            else {
1499:                                code.emitGetField(typeCallContext
1500:                                        .getDeclaredField("values"));
1501:                                code.emitPushInt(k);
1502:                                code.emitArrayLoad(Type.pointer_type);
1503:                            }
1504:                            Type ptype = var.getType();
1505:                            if (ptype != Type.pointer_type)
1506:                                CheckedTarget.emitCheckedCoerce(this , source,
1507:                                        k + 1, ptype);
1508:                            var = var.nextDecl();
1509:                        }
1510:
1511:                        if (varArgs) {
1512:                            Type lastArgType = primArgTypes[explicitFrameArg
1513:                                    + singleArgs];
1514:                            if (lastArgType instanceof  ArrayType) {
1515:                                Type elType = ((ArrayType) lastArgType)
1516:                                        .getComponentType();
1517:                                boolean mustConvert = !"java.lang.Object"
1518:                                        .equals(elType.getName());
1519:                                if (mustConvert)
1520:                                    new Error(
1521:                                            "not implemented mustConvert restarg");
1522:                                code.emitLoad(ctxVar);
1523:                                code.emitPushInt(singleArgs);
1524:                                code.emitInvokeVirtual(typeCallContext
1525:                                        .getDeclaredMethod("getRestArgsArray",
1526:                                                1));
1527:                            } else if ("gnu.lists.LList".equals(lastArgType
1528:                                    .getName())) {
1529:                                code.emitLoad(ctxVar);
1530:                                code.emitPushInt(singleArgs);
1531:                                code
1532:                                        .emitInvokeVirtual(typeCallContext
1533:                                                .getDeclaredMethod(
1534:                                                        "getRestArgsList", 1));
1535:                            } else if (lastArgType == typeCallContext)
1536:                                code.emitLoad(ctxVar);
1537:                            else
1538:                                throw new RuntimeException(
1539:                                        "unsupported #!rest type:"
1540:                                                + lastArgType);
1541:                        }
1542:                        code.emitLoad(ctxVar); // get $ctx
1543:                        code.emitInvoke(primMethod);
1544:                        while (--pendingIfEnds >= 0)
1545:                            code.emitFi();
1546:                        if (defaultCallConvention < Compilation.CALL_WITH_CONSUMER)
1547:                            Target.pushObject.compileFromStack(this , source
1548:                                    .getReturnType());
1549:                        code.emitReturn();
1550:                    }
1551:                }
1552:                aswitch.addDefault(code);
1553:                Method errMethod = typeModuleMethod.getDeclaredMethod(
1554:                        "applyError", 0);
1555:                code.emitInvokeStatic(errMethod);
1556:                code.emitReturn();
1557:                aswitch.finish(code);
1558:                method = save_method;
1559:                curClass = save_class;
1560:            }
1561:
1562:            /** Generate ModuleBody's <tt>apply0</tt>...<tt>applyN</tt> methods.
1563:             * Use the <tt>applyMethods</tt> vector, which contains methods that
1564:             * implement the (public, readable) methods of the current module.
1565:             */
1566:            public void generateApplyMethodsWithoutContext(LambdaExp lexp) {
1567:                int numApplyMethods = lexp.applyMethods == null ? 0
1568:                        : lexp.applyMethods.size();
1569:                if (numApplyMethods == 0)
1570:                    return;
1571:                ClassType save_class = curClass;
1572:                curClass = lexp.getHeapFrameType();
1573:                ClassType procType = typeModuleMethod;
1574:                if (!(curClass.getSuperclass().isSubtype(typeModuleBody)))
1575:                    curClass = moduleClass;
1576:                Method save_method = method;
1577:                CodeAttr code = null;
1578:                for (int i = defaultCallConvention >= Compilation.CALL_WITH_CONSUMER ? 5
1579:                        : 0; i < 6; i++) {
1580:                    // If i < 5, generate the method named ("apply"+i);
1581:                    // else generate "applyN".
1582:                    boolean needThisApply = false;
1583:                    SwitchState aswitch = null;
1584:                    String mname = null;
1585:                    Type[] applyArgs = null;
1586:
1587:                    for (int j = numApplyMethods; --j >= 0;) {
1588:                        LambdaExp source = (LambdaExp) lexp.applyMethods
1589:                                .elementAt(j);
1590:                        // Select the subset of source.primMethods[*] that are suitable
1591:                        // for the current apply method.
1592:                        Method[] primMethods = source.primMethods;
1593:                        int numMethods = primMethods.length;
1594:                        boolean varArgs = source.max_args < 0
1595:                                || source.max_args >= source.min_args
1596:                                        + numMethods;
1597:                        int methodIndex;
1598:                        boolean skipThisProc = false;
1599:                        if (i < 5) // Handling apply0 .. apply4
1600:                        {
1601:                            methodIndex = i - source.min_args;
1602:                            if (methodIndex < 0
1603:                                    || methodIndex >= numMethods
1604:                                    || (methodIndex == numMethods - 1 && varArgs))
1605:                                skipThisProc = true;
1606:                            numMethods = 1;
1607:                            varArgs = false;
1608:                        } else // Handling applyN
1609:                        {
1610:                            methodIndex = 5 - source.min_args;
1611:                            if (methodIndex > 0 && numMethods <= methodIndex
1612:                                    && !varArgs)
1613:                                skipThisProc = true;
1614:                            methodIndex = numMethods - 1;
1615:                        }
1616:                        if (skipThisProc)
1617:                            continue;
1618:                        if (!needThisApply) {
1619:                            // First LambdaExp we seen suitable for this i.
1620:                            if (i < 5) {
1621:                                mname = "apply" + i;
1622:                                applyArgs = new Type[i + 1];
1623:                                for (int k = i; k > 0; k--)
1624:                                    applyArgs[k] = typeObject;
1625:                            } else {
1626:                                mname = "applyN";
1627:                                applyArgs = new Type[2];
1628:                                applyArgs[1] = objArrayType;
1629:                            }
1630:                            applyArgs[0] = procType;
1631:                            method = curClass
1632:                                    .addMethod(
1633:                                            mname,
1634:                                            applyArgs,
1635:                                            defaultCallConvention >= Compilation.CALL_WITH_CONSUMER ? (Type) Type.void_type
1636:                                                    : (Type) Type.pointer_type,
1637:                                            Access.PUBLIC);
1638:                            code = method.startCode();
1639:
1640:                            code.emitLoad(code.getArg(1)); // method
1641:                            code.emitGetField(procType.getField("selector"));
1642:                            aswitch = new SwitchState(code);
1643:
1644:                            needThisApply = true;
1645:                        }
1646:
1647:                        aswitch.addCase(source.getSelectorValue(this ), code);
1648:
1649:                        int line = source.getLineNumber();
1650:                        if (line > 0)
1651:                            code.putLineNumber(source.getFileName(), line);
1652:
1653:                        Method primMethod = primMethods[methodIndex];
1654:                        Type[] primArgTypes = primMethod.getParameterTypes();
1655:                        int singleArgs = source.min_args + methodIndex;
1656:                        Variable counter = null;
1657:                        int pendingIfEnds = 0;
1658:
1659:                        if (i > 4 && numMethods > 1) {
1660:                            counter = code.addLocal(Type.int_type);
1661:                            code.emitLoad(code.getArg(2));
1662:                            code.emitArrayLength();
1663:                            if (source.min_args != 0) {
1664:                                code.emitPushInt(source.min_args);
1665:                                code.emitSub(Type.int_type);
1666:                            }
1667:                            code.emitStore(counter);
1668:                        }
1669:
1670:                        int needsThis = primMethod.getStaticFlag() ? 0 : 1;
1671:                        int explicitFrameArg = singleArgs + (varArgs ? 1 : 0) < primArgTypes.length ? 1
1672:                                : 0;
1673:                        if (needsThis + explicitFrameArg > 0) {
1674:                            code.emitPushThis();
1675:                            if (curClass == moduleClass
1676:                                    && mainClass != moduleClass)
1677:                                code.emitGetField(moduleInstanceMainField);
1678:                        }
1679:
1680:                        Declaration var = source.firstDecl();
1681:                        for (int k = 0; k < singleArgs; k++) {
1682:                            if (counter != null && k >= source.min_args) {
1683:                                code.emitLoad(counter);
1684:                                code.emitIfIntLEqZero();
1685:                                code
1686:                                        .emitInvoke(primMethods[k
1687:                                                - source.min_args]);
1688:                                code.emitElse();
1689:                                pendingIfEnds++;
1690:                                code.emitInc(counter, (short) (-1));
1691:                            }
1692:
1693:                            Variable pvar = null;
1694:                            if (i <= 4) // apply'i method
1695:                            {
1696:                                pvar = code.getArg(k + 2);
1697:                                code.emitLoad(pvar);
1698:                            } else // applyN method
1699:                            {
1700:                                // Load Object[]args value:
1701:                                code.emitLoad(code.getArg(2));
1702:                                code.emitPushInt(k);
1703:                                code.emitArrayLoad(Type.pointer_type);
1704:                            }
1705:                            Type ptype = var.getType();
1706:                            if (ptype != Type.pointer_type)
1707:                                CheckedTarget.emitCheckedCoerce(this , source,
1708:                                        k + 1, ptype, pvar);
1709:                            var = var.nextDecl();
1710:                        }
1711:
1712:                        if (varArgs) {
1713:                            Type lastArgType = primArgTypes[explicitFrameArg
1714:                                    + singleArgs];
1715:                            if (lastArgType instanceof  ArrayType) {
1716:                                Type elType = ((ArrayType) lastArgType)
1717:                                        .getComponentType();
1718:                                boolean mustConvert = !"java.lang.Object"
1719:                                        .equals(elType.getName());
1720:                                if (singleArgs == 0 && !mustConvert)
1721:                                    code.emitLoad(code.getArg(2)); // load args array.
1722:                                else {
1723:                                    code.pushScope();
1724:                                    if (counter == null) {
1725:                                        counter = code.addLocal(Type.int_type);
1726:                                        code.emitLoad(code.getArg(2));
1727:                                        code.emitArrayLength();
1728:                                        if (singleArgs != 0) {
1729:                                            code.emitPushInt(singleArgs);
1730:                                            code.emitSub(Type.int_type);
1731:                                        }
1732:                                        code.emitStore(counter);
1733:                                    }
1734:                                    code.emitLoad(counter);
1735:                                    code.emitNewArray(elType);
1736:                                    Label testLabel = new Label(code);
1737:                                    code.emitGoto(testLabel);
1738:                                    Label loopTopLabel = new Label(code);
1739:                                    loopTopLabel.define(code);
1740:
1741:                                    code.emitDup(1); // new array
1742:                                    code.emitLoad(counter);
1743:                                    code.emitLoad(code.getArg(2));
1744:                                    code.emitLoad(counter);
1745:                                    if (singleArgs != 0) {
1746:                                        code.emitPushInt(singleArgs);
1747:                                        code.emitAdd(Type.int_type);
1748:                                    }
1749:                                    code.emitArrayLoad(Type.pointer_type);
1750:                                    if (mustConvert) {
1751:                                        CheckedTarget.emitCheckedCoerce(this ,
1752:                                                source, source.getName(), 0,
1753:                                                elType, null);
1754:                                    }
1755:                                    code.emitArrayStore(elType);
1756:                                    testLabel.define(code);
1757:                                    code.emitInc(counter, (short) (-1));
1758:                                    code.emitLoad(counter);
1759:                                    code.emitGotoIfIntGeZero(loopTopLabel);
1760:                                    code.popScope();
1761:                                }
1762:                            } else if ("gnu.lists.LList".equals(lastArgType
1763:                                    .getName())) {
1764:                                code.emitLoad(code.getArg(2)); // load args array.
1765:                                code.emitPushInt(singleArgs);
1766:                                code
1767:                                        .emitInvokeStatic(Compilation.makeListMethod);
1768:                            } else if (lastArgType == typeCallContext)
1769:                                code.emitLoad(code.getArg(2));
1770:                            else
1771:                                throw new RuntimeException(
1772:                                        "unsupported #!rest type:"
1773:                                                + lastArgType);
1774:                        }
1775:                        code.emitInvoke(primMethod);
1776:                        while (--pendingIfEnds >= 0)
1777:                            code.emitFi();
1778:                        if (defaultCallConvention < Compilation.CALL_WITH_CONSUMER)
1779:                            Target.pushObject.compileFromStack(this , source
1780:                                    .getReturnType());
1781:                        code.emitReturn();
1782:                    }
1783:                    if (needThisApply) {
1784:                        aswitch.addDefault(code);
1785:                        if (defaultCallConvention >= Compilation.CALL_WITH_CONSUMER) {
1786:                            Method errMethod = typeModuleMethod
1787:                                    .getDeclaredMethod("applyError", 0);
1788:                            code.emitInvokeStatic(errMethod);
1789:                        } else {
1790:                            int nargs = i > 4 ? 2 : i + 1;
1791:                            nargs++;
1792:                            for (int k = 0; k < nargs; k++)
1793:                                code.emitLoad(code.getArg(k));
1794:                            code.emitInvokeSpecial(typeModuleBody
1795:                                    .getDeclaredMethod(mname, applyArgs));
1796:                        }
1797:                        code.emitReturn();
1798:                        aswitch.finish(code);
1799:                    }
1800:                }
1801:                method = save_method;
1802:                curClass = save_class;
1803:            }
1804:
1805:            private Method startClassInit() {
1806:                method = curClass.addMethod("<clinit>", apply0args,
1807:                        Type.void_type, Access.PUBLIC | Access.STATIC);
1808:
1809:                CodeAttr code = method.startCode();
1810:
1811:                if (generateMain || generateApplet || generateServlet) {
1812:                    ClassType languageType = (ClassType) Type
1813:                            .make(getLanguage().getClass());
1814:                    Method registerMethod = languageType.getDeclaredMethod(
1815:                            "registerEnvironment", 0);
1816:                    if (registerMethod != null)
1817:                        code.emitInvokeStatic(registerMethod);
1818:                }
1819:                return method;
1820:            }
1821:
1822:            /** Parse/walk/compile this module as needed and requested.
1823:             * This method does not process any dependent modules (expect indirectly,
1824:             * such as may be done by a require form).
1825:             * @param wantedState the desired value of getState().
1826:             */
1827:            public void process(int wantedState) {
1828:                Compilation saveCompilation = Compilation.getCurrent();
1829:                try {
1830:                    Compilation.setCurrent(this );
1831:                    ModuleExp mexp = getModule();
1832:                    if (wantedState >= BODY_PARSED
1833:                            && getState() < BODY_PARSED - 1) {
1834:                        setState(BODY_PARSED - 1);
1835:                        language.parse(this , 0);
1836:                        lexer.close();
1837:                        lexer = null;
1838:                        setState(messages.seenErrors() ? ERROR_SEEN
1839:                                : BODY_PARSED);
1840:                        if (pendingImports != null)
1841:                            return;
1842:                    }
1843:                    if (wantedState >= RESOLVED && getState() < RESOLVED) {
1844:                        addMainClass(mexp);
1845:                        language.resolve(this );
1846:                        setState(messages.seenErrors() ? ERROR_SEEN : RESOLVED);
1847:                    }
1848:                    if (wantedState >= WALKED && getState() < WALKED) {
1849:                        walkModule(mexp);
1850:                        setState(messages.seenErrors() ? ERROR_SEEN : WALKED);
1851:                    }
1852:                    if (wantedState >= COMPILE_SETUP
1853:                            && getState() < COMPILE_SETUP) {
1854:                        litTable = new LitTable(this );
1855:                        mexp.setCanRead(true);
1856:                        FindCapturedVars.findCapturedVars(mexp, this );
1857:                        mexp.allocFields(this );
1858:                        mexp.allocChildMethods(this );
1859:                        setState(messages.seenErrors() ? ERROR_SEEN
1860:                                : COMPILE_SETUP);
1861:                    }
1862:                    if (wantedState >= COMPILED && getState() < COMPILED) {
1863:                        generateBytecode();
1864:                        setState(messages.seenErrors() ? ERROR_SEEN : COMPILED);
1865:                    }
1866:                    if (wantedState >= CLASS_WRITTEN
1867:                            && getState() < CLASS_WRITTEN) {
1868:                        ModuleManager manager = ModuleManager.getInstance();
1869:                        outputClass(manager.getCompilationDirectory());
1870:                        setState(CLASS_WRITTEN);
1871:                    }
1872:                } catch (gnu.text.SyntaxException ex) {
1873:                    setState(ERROR_SEEN);
1874:                    if (ex.getMessages() != getMessages())
1875:                        throw new RuntimeException("confussing syntax error: "
1876:                                + ex);
1877:                    // otherwise ignore it - it's already been recorded in messages.
1878:                } catch (java.io.IOException ex) {
1879:                    ex.printStackTrace();
1880:                    error('f', "caught " + ex);
1881:                    setState(ERROR_SEEN);
1882:                } finally {
1883:                    Compilation.setCurrent(saveCompilation);
1884:                }
1885:            }
1886:
1887:            /** The guts of compiling a module to one or more classes.
1888:             * Assumes walkModule has been done.
1889:             */
1890:            void generateBytecode() {
1891:                ModuleExp module = getModule();
1892:                if (debugPrintFinalExpr) {
1893:                    OutPort dout = OutPort.errDefault();
1894:                    dout.println("[Compiling final " + module.getName()
1895:                            + " to " + mainClass.getName() + ":");
1896:                    module.print(dout);
1897:                    dout.println(']');
1898:                    dout.flush();
1899:                }
1900:
1901:                ClassType neededSuper = getModuleType();
1902:                if (mainClass.getSuperclass().isSubtype(neededSuper))
1903:                    moduleClass = mainClass;
1904:                else {
1905:                    moduleClass = new ClassType(generateClassName("frame"));
1906:                    moduleClass.setSuper(neededSuper);
1907:                    addClass(moduleClass);
1908:                    generateConstructor(moduleClass, module);
1909:                }
1910:
1911:                curClass = module.type;
1912:                int arg_count;
1913:                LambdaExp saveLambda = curLambda;
1914:                curLambda = module;
1915:                Type[] arg_types;
1916:                if (module.isHandlingTailCalls()) {
1917:                    arg_count = 1;
1918:                    arg_types = new Type[1];
1919:                    arg_types[0] = typeCallContext;
1920:                } else if (module.min_args != module.max_args
1921:                        || module.min_args > 4
1922:                        || (fewerClasses && curClass == mainClass)) {
1923:                    arg_count = 1;
1924:                    arg_types = new Type[1];
1925:                    arg_types[0] = new ArrayType(typeObject);
1926:                } else {
1927:                    arg_count = module.min_args;
1928:                    arg_types = new Type[arg_count];
1929:                    for (int i = arg_count; --i >= 0;)
1930:                        arg_types[i] = typeObject;
1931:                }
1932:
1933:                CodeAttr code;
1934:                Variable heapFrame = module.heapFrame;
1935:                boolean staticModule = module.isStatic();
1936:                Method apply_method;
1937:
1938:                apply_method = curClass.addMethod("run", arg_types,
1939:                        Type.void_type, Access.PUBLIC + Access.FINAL);
1940:                method = apply_method;
1941:                // For each parameter, assign it to its proper slot.
1942:                // If a parameter !isSimple(), we cannot assign it to a local slot,
1943:                // so instead create an artificial Variable for the incoming argument.
1944:                // Below, we assign the value to the slot.
1945:                method.initCode();
1946:                code = getCode();
1947:                // if (usingCPStyle())   code.addParamLocals();
1948:
1949:                this Decl = method.getStaticFlag() ? null : module
1950:                        .declareThis(module.type);
1951:                module.closureEnv = module.this Variable;
1952:                module.heapFrame = module.isStatic() ? null
1953:                        : module.this Variable;
1954:                module.allocChildClasses(this );
1955:
1956:                if (module.isHandlingTailCalls() || usingCPStyle()) {
1957:                    callContextVar = new Variable("$ctx", typeCallContext);
1958:                    module.getVarScope().addVariableAfter(this Decl,
1959:                            callContextVar);
1960:                    callContextVar.setParameter(true);
1961:                }
1962:
1963:                int line = module.getLineNumber();
1964:                if (line > 0)
1965:                    code.putLineNumber(module.getFileName(), line);
1966:
1967:                module.allocParameters(this );
1968:                module.enterFunction(this );
1969:                if (usingCPStyle()) {
1970:                    loadCallContext();
1971:                    code.emitGetField(pcCallContextField);
1972:                    fswitch = new SwitchState(code);
1973:                    Label l = new Label(code);
1974:                    l.define(code);
1975:                    fswitch.addCase(0, l, code);
1976:                }
1977:
1978:                module.compileBody(this );
1979:                module.compileChildMethods(this );
1980:
1981:                Label startLiterals = null;
1982:                Label afterLiterals = null;
1983:                Method initMethod = null;
1984:
1985:                if (curClass == mainClass) {
1986:                    Method save_method = method;
1987:                    Variable callContextSave = callContextVar;
1988:                    callContextVar = null;
1989:
1990:                    initMethod = startClassInit();
1991:                    clinitMethod = initMethod;
1992:                    code = getCode();
1993:
1994:                    startLiterals = new Label(code);
1995:                    afterLiterals = new Label(code);
1996:                    code.fixupChain(afterLiterals, startLiterals);
1997:
1998:                    if (staticModule) {
1999:                        generateConstructor(module);
2000:
2001:                        code.emitNew(moduleClass);
2002:                        code.emitDup(moduleClass);
2003:                        code.emitInvokeSpecial(moduleClass.constructor);
2004:                        moduleInstanceMainField = moduleClass.addField(
2005:                                "$instance", mainClass, Access.STATIC
2006:                                        | Access.PUBLIC | Access.FINAL);
2007:                        code.emitPutStatic(moduleInstanceMainField);
2008:                    }
2009:                    Initializer init;
2010:                    while ((init = clinitChain) != null) {
2011:                        clinitChain = null;
2012:                        dumpInitializers(init);
2013:                    }
2014:
2015:                    if (!immediate && module.staticInitRun()) {
2016:                        code.emitGetStatic(moduleInstanceMainField);
2017:                        code.emitInvokeInterface(typeRunnable
2018:                                .getDeclaredMethod("run", 0));
2019:                    }
2020:                    code.emitReturn();
2021:
2022:                    if (moduleClass != mainClass && !staticModule
2023:                            && !generateMain && !immediate) {
2024:                        // Compare the run methods in ModuleBody.
2025:                        method = curClass.addMethod("run", Access.PUBLIC,
2026:                                Type.typeArray0, Type.void_type);
2027:                        code = method.startCode();
2028:                        Variable ctxVar = code.addLocal(typeCallContext);
2029:                        Variable saveVar = code.addLocal(typeConsumer);
2030:                        Variable exceptionVar = code
2031:                                .addLocal(Type.throwable_type);
2032:                        // ctx = CallContext.getInstance();
2033:                        code.emitInvokeStatic(getCallContextInstanceMethod);
2034:                        code.emitStore(ctxVar);
2035:                        Field consumerFld = typeCallContext
2036:                                .getDeclaredField("consumer");
2037:                        // save = ctx.consumer;
2038:                        code.emitLoad(ctxVar);
2039:                        code.emitGetField(consumerFld);
2040:                        code.emitStore(saveVar);
2041:                        // ctx.consumer = VoidConsumer.instance:
2042:                        code.emitLoad(ctxVar);
2043:                        code.emitGetStatic(ClassType.make(
2044:                                "gnu.lists.VoidConsumer").getDeclaredField(
2045:                                "instance"));
2046:                        code.emitPutField(consumerFld);
2047:                        // try {
2048:                        code.emitTryStart(false, Type.void_type);
2049:                        // this.apply(ctx):
2050:                        code.emitPushThis();
2051:                        code.emitLoad(ctxVar);
2052:                        code.emitInvokeVirtual(save_method);
2053:                        // exception = null
2054:                        code.emitPushNull();
2055:                        code.emitStore(exceptionVar);
2056:                        // } catch (Throwable th) { exception = th; }
2057:                        code.emitTryEnd();
2058:                        code.emitCatchStart(exceptionVar);
2059:                        code.emitCatchEnd();
2060:                        code.emitTryCatchEnd();
2061:                        // MooduleBody.runCleanup(ctx, ex, save);
2062:                        code.emitLoad(ctxVar);
2063:                        code.emitLoad(exceptionVar);
2064:                        code.emitLoad(saveVar);
2065:                        code.emitInvokeStatic(typeModuleBody.getDeclaredMethod(
2066:                                "runCleanup", 3));
2067:                        code.emitReturn();
2068:                    }
2069:
2070:                    method = save_method;
2071:                    callContextVar = callContextSave;
2072:                }
2073:
2074:                module.compileEnd(this );
2075:
2076:                curLambda = saveLambda;
2077:
2078:                if (Compilation.fewerClasses) // FIXME
2079:                    method.popScope(); // Undoes pushScope in method.initCode.
2080:
2081:                module.heapFrame = heapFrame; // Restore heapFrame.
2082:                if (usingCPStyle() || (fewerClasses && curClass == mainClass)) {
2083:                    code = getCode();
2084:                    fswitch.finish(code);
2085:                }
2086:
2087:                if (startLiterals != null || callContextVar != null) {
2088:                    method = initMethod;
2089:                    code = getCode();
2090:
2091:                    Label endLiterals = new Label(code);
2092:                    code.fixupChain(startLiterals, endLiterals);
2093:
2094:                    if (callContextVarForInit != null) {
2095:                        code.emitInvokeStatic(getCallContextInstanceMethod);
2096:                        code.emitStore(callContextVarForInit);
2097:                    }
2098:
2099:                    try {
2100:                        if (immediate) {
2101:                            code
2102:                                    .emitPushInt(registerForImmediateLiterals(this ));
2103:                            code.emitInvokeStatic(ClassType.make(
2104:                                    "gnu.expr.Compilation").getDeclaredMethod(
2105:                                    "setupLiterals", 1));
2106:                        } else
2107:                            litTable.emit();
2108:                    } catch (Throwable ex) {
2109:                        error('e', "Literals: Internal error:" + ex);
2110:                    }
2111:                    code.fixupChain(endLiterals, afterLiterals);
2112:                }
2113:
2114:                if (generateMain && curClass == mainClass) {
2115:                    Type[] args = { new ArrayType(javaStringType) };
2116:                    method = curClass.addMethod("main", Access.PUBLIC
2117:                            | Access.STATIC, args, Type.void_type);
2118:
2119:                    code = method.startCode();
2120:
2121:                    if (Shell.defaultFormatName != null) {
2122:                        code.emitPushString(Shell.defaultFormatName);
2123:                        code.emitInvokeStatic(ClassType.make("kawa.Shell")
2124:                                .getDeclaredMethod("setDefaultFormat", 1));
2125:                    }
2126:                    code.emitLoad(code.getArg(0));
2127:                    code.emitInvokeStatic(typeModuleBody.getDeclaredMethod(
2128:                            "processArgs", 1));
2129:                    if (moduleInstanceMainField != null)
2130:                        code.emitGetStatic(moduleInstanceMainField);
2131:                    else {
2132:                        code.emitNew(curClass);
2133:                        code.emitDup(curClass);
2134:                        code.emitInvokeSpecial(curClass.constructor);
2135:                    }
2136:                    code.emitInvokeVirtual(typeModuleBody.getDeclaredMethod(
2137:                            "runAsMain", 0));
2138:                    code.emitReturn();
2139:                }
2140:
2141:                String uri;
2142:                if (minfo != null && (uri = minfo.getNamespaceUri()) != null) {
2143:                    // Need to generate a ModuleSet for this class, so XQuery can find
2144:                    // this module and other modules in the same namespace.
2145:                    ModuleManager manager = ModuleManager.getInstance();
2146:                    String mainPrefix = mainClass.getName();
2147:                    int dot = mainPrefix.lastIndexOf('.');
2148:                    if (dot < 0) {
2149:                        mainPrefix = "";
2150:                    } else {
2151:                        String mainPackage = mainPrefix.substring(0, dot);
2152:                        try {
2153:                            manager.loadPackageInfo(mainPackage);
2154:                        } catch (ClassNotFoundException ex) {
2155:                            // Do nothing.
2156:                        } catch (Throwable ex) {
2157:                            error('e', "error loading map for " + mainPackage
2158:                                    + " - " + ex);
2159:                        }
2160:                        mainPrefix = mainPrefix.substring(0, dot + 1);
2161:                    }
2162:                    ClassType mapClass = new ClassType(mainPrefix
2163:                            + ModuleSet.MODULES_MAP);
2164:                    ClassType typeModuleSet = ClassType
2165:                            .make("gnu.expr.ModuleSet");
2166:                    mapClass.setSuper(typeModuleSet);
2167:                    registerClass(mapClass);
2168:
2169:                    method = mapClass.addMethod("<init>", Access.PUBLIC,
2170:                            apply0args, Type.void_type);
2171:                    Method super Constructor = typeModuleSet.addMethod("<init>",
2172:                            Access.PUBLIC, apply0args, Type.void_type);
2173:                    code = method.startCode();
2174:                    code.emitPushThis();
2175:                    code.emitInvokeSpecial(super Constructor);
2176:                    code.emitReturn();
2177:
2178:                    ClassType typeModuleManager = ClassType
2179:                            .make("gnu.expr.ModuleManager");
2180:                    Type[] margs = { typeModuleManager };
2181:                    method = mapClass.addMethod("register", margs,
2182:                            Type.void_type, Access.PUBLIC);
2183:                    code = method.startCode();
2184:                    Method reg = typeModuleManager.getDeclaredMethod(
2185:                            "register", 3);
2186:
2187:                    for (ModuleInfo mi = manager.firstModule(); mi != null; mi = mi
2188:                            .nextModule()) {
2189:                        String miClassName = mi.className;
2190:                        if (miClassName == null
2191:                                || !miClassName.startsWith(mainPrefix))
2192:                            continue;
2193:                        String moduleSource = mi.sourcePath;
2194:                        String moduleUri = mi.getNamespaceUri();
2195:                        code.emitLoad(code.getArg(1));
2196:                        compileConstant(miClassName);
2197:                        if (!Path.valueOf(moduleSource).isAbsolute())
2198:                            try {
2199:                                // If the source path was relative, emit it as relative.
2200:                                // But make it relative to the compilation directory,
2201:                                // to allows sources to be moved along with binaries.
2202:                                char sep = File.separatorChar;
2203:                                String path = manager.getCompilationDirectory();
2204:                                path = path + mainPrefix.replace('.', sep);
2205:                                path = Path.toURL(path).toString();
2206:                                int plen = path.length();
2207:                                if (plen > 0 && path.charAt(plen - 1) != sep)
2208:                                    path = path + sep;
2209:                                moduleSource = Path.relativize(mi
2210:                                        .getSourceAbsPathname(), path);
2211:                            } catch (Throwable ex) {
2212:                                throw new WrappedException(
2213:                                        "exception while fixing up '"
2214:                                                + moduleSource + '\'', ex);
2215:                            }
2216:                        compileConstant(moduleSource);
2217:                        compileConstant(moduleUri);
2218:                        code.emitInvokeVirtual(reg);
2219:                    }
2220:                    code.emitReturn();
2221:                }
2222:            }
2223:
2224:            int localFieldIndex;
2225:
2226:            public Field allocLocalField(Type type, String name) {
2227:                if (name == null)
2228:                    name = "tmp_" + (++localFieldIndex);
2229:                Field field = curClass.addField(name, type, 0);
2230:                return field;
2231:            }
2232:
2233:            /** If non-null, contains the value of the current CallContext. */
2234:            Variable callContextVar;
2235:            Variable callContextVarForInit;
2236:
2237:            /** Generate code to push the current CallContext on the JVM stack. */
2238:            public final void loadCallContext() {
2239:                CodeAttr code = getCode();
2240:                if (callContextVar != null && !callContextVar.dead())
2241:                    code.emitLoad(callContextVar);
2242:                // We're cautious about re-using a previously extracted CallContext,
2243:                // because it's tricky to manage the variables safely.
2244:                // A possible solution is to inject a Variable into the current scope,
2245:                // and making sure each separate straight-line block has its own scope.
2246:                // (If the current scope is in the same "basic block" as an outer scope,
2247:                // we can use that instead.)  FIXME
2248:                else if (method == clinitMethod) {
2249:                    // The variable is initialized just after literals.
2250:                    callContextVar = new Variable("$ctx", typeCallContext);
2251:                    // To make sure it doesn't clash with variables that have already
2252:                    // allocated and freed for previous initialzier.
2253:                    callContextVar.reserveLocal(code.getMaxLocals(), code);
2254:                    code.emitLoad(callContextVar);
2255:                    callContextVarForInit = callContextVar;
2256:                } else {
2257:                    code.emitInvokeStatic(getCallContextInstanceMethod);
2258:                    code.emitDup();
2259:                    callContextVar = new Variable("$ctx", typeCallContext);
2260:                    code.getCurrentScope().addVariable(code, callContextVar);
2261:                    code.emitStore(callContextVar);
2262:                }
2263:            }
2264:
2265:            public void freeLocalField(Field field) {
2266:                // FIXME
2267:            }
2268:
2269:            /** This may not make sense, except for Lisp-like languages.
2270:             * For those, 'input' an s-expression  from the reader. */
2271:            public Expression parse(Object input) {
2272:                throw new Error("unimeplemented parse");
2273:            }
2274:
2275:            protected Language language;
2276:
2277:            public Language getLanguage() {
2278:                return language;
2279:            }
2280:
2281:            public LambdaExp currentLambda() {
2282:                return current_scope.currentLambda();
2283:            }
2284:
2285:            public final ModuleExp getModule() {
2286:                return mainLambda;
2287:            }
2288:
2289:            public void setModule(ModuleExp mexp) {
2290:                mainLambda = mexp;
2291:            }
2292:
2293:            public boolean isStatic() {
2294:                return mainLambda.isStatic();
2295:            }
2296:
2297:            /** The same as getModule, until we allow nested modules. */
2298:            public ModuleExp currentModule() {
2299:                return current_scope.currentModule();
2300:            }
2301:
2302:            /** Note that we have seen a construct that must be compiled, not evaluated.
2303:             * If we are not inside a lambda (which is always compiled), but
2304:             * only inside the outer-most ModuleExp, note that it must be compiled.
2305:             */
2306:            public void mustCompileHere() {
2307:                mustCompile = true;
2308:            }
2309:
2310:            public ScopeExp currentScope() {
2311:                return current_scope;
2312:            }
2313:
2314:            /** Set <code>currentScope()</code>.
2315:             * Also update the <code>nesting</code> object.
2316:             */
2317:            public void setCurrentScope(ScopeExp scope) {
2318:                int scope_nesting = ScopeExp.nesting(scope);
2319:                int current_nesting = ScopeExp.nesting(current_scope);
2320:                while (current_nesting > scope_nesting) {
2321:                    pop(current_scope);
2322:                    current_nesting--;
2323:                }
2324:                ScopeExp sc = scope;
2325:                while (scope_nesting > current_nesting) {
2326:                    sc = sc.outer;
2327:                    scope_nesting--;
2328:                }
2329:                while (sc != current_scope) {
2330:                    pop(current_scope);
2331:                    sc = sc.outer;
2332:                }
2333:                pushChain(scope, sc);
2334:            }
2335:
2336:            void pushChain(ScopeExp scope, ScopeExp limit) {
2337:                if (scope != limit) {
2338:                    pushChain(scope.outer, limit);
2339:                    pushScope(scope);
2340:                    lexical.push(scope);
2341:                }
2342:            }
2343:
2344:            public ModuleExp pushNewModule(Lexer lexer) {
2345:                this .lexer = lexer;
2346:                return pushNewModule(lexer.getName());
2347:            }
2348:
2349:            public ModuleExp pushNewModule(String filename) {
2350:                ModuleExp module = new ModuleExp();
2351:                if (filename != null)
2352:                    module.setFile(filename);
2353:                if (Compilation.generateAppletDefault)
2354:                    module.setFlag(ModuleExp.SUPERTYPE_SPECIFIED);
2355:                if (immediate) {
2356:                    module.setFlag(ModuleExp.IMMEDIATE);
2357:                    new ModuleInfo().setCompilation(this );
2358:                }
2359:                mainLambda = module;
2360:                push(module);
2361:                return module;
2362:            }
2363:
2364:            public void push(ScopeExp scope) {
2365:                pushScope(scope);
2366:                lexical.push(scope);
2367:            }
2368:
2369:            public final void pushScope(ScopeExp scope) {
2370:                if (!mustCompile
2371:                // We set mustCompile if we see a LambdaExp - not because we must
2372:                        // but because it is usually desirable.
2373:                        && (scope.mustCompile() || (scope instanceof  LambdaExp && !(scope instanceof  ModuleExp))))
2374:                    mustCompileHere();
2375:                scope.outer = current_scope;
2376:                current_scope = scope;
2377:            }
2378:
2379:            public void pop(ScopeExp scope) {
2380:                lexical.pop(scope);
2381:                current_scope = scope.outer;
2382:            }
2383:
2384:            public final void pop() {
2385:                pop(current_scope);
2386:            }
2387:
2388:            public void push(Declaration decl) {
2389:                lexical.push(decl);
2390:            }
2391:
2392:            public Declaration lookup(Object name, int namespace) {
2393:                return lexical.lookup(name, namespace);
2394:            }
2395:
2396:            /** Called for classes referenced in bytecode.
2397:             * Since this only does something when immediate, we only care about
2398:             * classes referenced in the bytecode when immediate.
2399:             * It is used to ensure that we can inherit from classes defines when in
2400:             * immediate mode (in Scheme using define-class or similar).
2401:             */
2402:            public void usedClass(Type type) {
2403:                while (type instanceof  ArrayType)
2404:                    type = ((ArrayType) type).getComponentType();
2405:                if (!immediate || !(type instanceof  ClassType))
2406:                    return;
2407:                ClassType clas = (ClassType) type;
2408:                if (loader != null && clas.isExisting()) {
2409:                    loader.addClass(clas.getReflectClass());
2410:                }
2411:            }
2412:
2413:            public SourceMessages getMessages() {
2414:                return messages;
2415:            }
2416:
2417:            public void setMessages(SourceMessages messages) {
2418:                this .messages = messages;
2419:            }
2420:
2421:            public void error(char severity, String message,
2422:                    SourceLocator location) {
2423:                String file = location.getFileName();
2424:                int line = location.getLineNumber();
2425:                int column = location.getColumnNumber();
2426:                if (file == null || line <= 0) {
2427:                    file = getFileName();
2428:                    line = getLineNumber();
2429:                    column = getColumnNumber();
2430:                }
2431:
2432:                if (severity == 'w' && getBooleanOption("warn-as-error", false))
2433:                    severity = 'e';
2434:                messages.error(severity, file, line, column, message);
2435:            }
2436:
2437:            public void error(char severity, String message) {
2438:                if (severity == 'w' && getBooleanOption("warn-as-error", false))
2439:                    severity = 'e';
2440:
2441:                messages.error(severity, this , message);
2442:            }
2443:
2444:            public void error(char severity, Declaration decl, String msg1,
2445:                    String msg2) {
2446:                error(severity, msg1 + decl.getName() + msg2, null, decl);
2447:            }
2448:
2449:            public void error(char severity, String message, String code,
2450:                    Declaration decl) {
2451:                if (severity == 'w' && getBooleanOption("warn-as-error", false))
2452:                    severity = 'e';
2453:
2454:                String filename = getFileName();
2455:                int line = getLineNumber();
2456:                int column = getColumnNumber();
2457:                int decl_line = decl.getLineNumber();
2458:                if (decl_line > 0) {
2459:                    filename = decl.getFileName();
2460:                    line = decl_line;
2461:                    column = decl.getColumnNumber();
2462:                }
2463:                messages.error(severity, filename, line, column, message, code);
2464:            }
2465:
2466:            /**
2467:             * Handle syntax errors (at rewrite time).
2468:             * @param message an error message to print out
2469:             * @return an ErrorExp
2470:             */
2471:            public Expression syntaxError(String message) {
2472:                error('e', message);
2473:                return new ErrorExp(message);
2474:            }
2475:
2476:            public final int getLineNumber() {
2477:                return messages.getLineNumber();
2478:            }
2479:
2480:            public final int getColumnNumber() {
2481:                return messages.getColumnNumber();
2482:            }
2483:
2484:            public final String getFileName() {
2485:                return messages.getFileName();
2486:            }
2487:
2488:            public String getPublicId() {
2489:                return messages.getPublicId();
2490:            }
2491:
2492:            public String getSystemId() {
2493:                return messages.getSystemId();
2494:            }
2495:
2496:            public boolean isStableSourceLocation() {
2497:                return false;
2498:            }
2499:
2500:            public void setFile(String filename) {
2501:                messages.setFile(filename);
2502:            }
2503:
2504:            public void setLine(int line) {
2505:                messages.setLine(line);
2506:            }
2507:
2508:            public void setColumn(int column) {
2509:                messages.setColumn(column);
2510:            }
2511:
2512:            public final void setLine(Expression position) {
2513:                messages.setLocation(position);
2514:            }
2515:
2516:            public void setLine(Object location) {
2517:                if (location instanceof  SourceLocator)
2518:                    messages.setLocation((SourceLocator) location);
2519:            }
2520:
2521:            public final void setLocation(SourceLocator position) {
2522:                messages.setLocation(position);
2523:            }
2524:
2525:            public void setLine(String filename, int line, int column) {
2526:                messages.setLine(filename, line, column);
2527:            }
2528:
2529:            /** A help vector for building expressions. */
2530:            public Stack exprStack;
2531:
2532:            public void letStart() {
2533:                pushScope(new LetExp(null));
2534:            }
2535:
2536:            public Declaration letVariable(Object name, Type type,
2537:                    Expression init) {
2538:                LetExp let = (LetExp) current_scope;
2539:                Declaration decl = let.addDeclaration(name, type);
2540:                decl.noteValue(init);
2541:                return decl;
2542:            }
2543:
2544:            public void letEnter() {
2545:                LetExp let = (LetExp) current_scope;
2546:                int ndecls = let.countDecls();
2547:                Expression[] inits = new Expression[ndecls];
2548:                int i = 0;
2549:                for (Declaration decl = let.firstDecl(); decl != null; decl = decl
2550:                        .nextDecl())
2551:                    inits[i++] = decl.getValue();
2552:                let.inits = inits;
2553:                lexical.push(let);
2554:            }
2555:
2556:            public LetExp letDone(Expression body) {
2557:                LetExp let = (LetExp) current_scope;
2558:                let.body = body;
2559:                pop(let);
2560:                return let;
2561:            }
2562:
2563:            private void checkLoop() {
2564:                if (((LambdaExp) current_scope).getName() != "%do%loop")
2565:                    throw new Error("internal error - bad loop state");
2566:            }
2567:
2568:            /** Start a new loop.
2569:             * (We could make this implied by the first loopVaribale call ???) */
2570:            public void loopStart() {
2571:                LambdaExp loopLambda = new LambdaExp();
2572:                Expression[] inits = { loopLambda };
2573:                LetExp let = new LetExp(inits);
2574:                String fname = "%do%loop";
2575:                Declaration fdecl = let.addDeclaration(fname);
2576:                fdecl.noteValue(loopLambda);
2577:                loopLambda.setName(fname);
2578:                let.outer = current_scope;
2579:                loopLambda.outer = let;
2580:                current_scope = loopLambda;
2581:            }
2582:
2583:            public Declaration loopVariable(Object name, Type type,
2584:                    Expression init) {
2585:                checkLoop();
2586:                LambdaExp loopLambda = (LambdaExp) current_scope;
2587:                Declaration decl = loopLambda.addDeclaration(name, type);
2588:                if (exprStack == null)
2589:                    exprStack = new Stack();
2590:                exprStack.push(init);
2591:                loopLambda.min_args++;
2592:                return decl;
2593:            }
2594:
2595:            /** Done handling loop variables, and pushes them into the lexical scope.
2596:             * Ready to parse the loop condition. */
2597:            public void loopEnter() {
2598:                checkLoop();
2599:                LambdaExp loopLambda = (LambdaExp) current_scope;
2600:                int ninits = loopLambda.min_args;
2601:                loopLambda.max_args = ninits;
2602:                Expression[] inits = new Expression[ninits];
2603:                for (int i = ninits; --i >= 0;)
2604:                    inits[i] = (Expression) exprStack.pop();
2605:                LetExp let = (LetExp) loopLambda.outer;
2606:                Declaration fdecl = let.firstDecl(); // The decls for loopLambda.
2607:                let.setBody(new ApplyExp(new ReferenceExp(fdecl), inits));
2608:                lexical.push(loopLambda);
2609:            }
2610:
2611:            public void loopCond(Expression cond) {
2612:                checkLoop();
2613:                exprStack.push(cond);
2614:            }
2615:
2616:            public void loopBody(Expression body) {
2617:                LambdaExp loopLambda = (LambdaExp) current_scope;
2618:                loopLambda.body = body;
2619:            }
2620:
2621:            public Expression loopRepeat(Expression[] exps) {
2622:                LambdaExp loopLambda = (LambdaExp) current_scope;
2623:                ScopeExp let = loopLambda.outer;
2624:                Declaration fdecl = let.firstDecl(); // The decls for loopLambda.
2625:                Expression cond = (Expression) exprStack.pop();
2626:                Expression recurse = new ApplyExp(new ReferenceExp(fdecl), exps);
2627:                loopLambda.body = new IfExp(cond, new BeginExp(loopLambda.body,
2628:                        recurse), QuoteExp.voidExp);
2629:                lexical.pop(loopLambda);
2630:                current_scope = let.outer;
2631:                return let;
2632:            }
2633:
2634:            public Expression loopRepeat() {
2635:                return loopRepeat(Expression.noExpressions);
2636:            }
2637:
2638:            public Expression loopRepeat(Expression exp) {
2639:                Expression[] args = { exp };
2640:                return loopRepeat(args);
2641:            }
2642:
2643:            /** If non-null, a helper method generated by getForNameHelper. */
2644:            Method forNameHelper;
2645:
2646:            public void loadClassRef(ClassType clas) {
2647:                // Try an optimization
2648:                if (clas == mainClass && mainLambda.isStatic()
2649:                // moduleInstanceMainField may not have been set yet.
2650:                        && moduleInstanceMainField != null) {
2651:                    CodeAttr code = getCode();
2652:                    code.emitGetStatic(moduleInstanceMainField);
2653:                    code.emitInvokeVirtual(Type.pointer_type.getDeclaredMethod(
2654:                            "getClass", 0));
2655:                } else
2656:                    loadClassRef(clas.getName());
2657:            }
2658:
2659:            /** Generate code to load a named Class without initializing it.
2660:             */
2661:            public void loadClassRef(String className) {
2662:                CodeAttr code = getCode();
2663:                if (curClass.getClassfileMajorVersion() >= 49) // Java5 feature
2664:                    code.emitPushClass(className);
2665:                else {
2666:                    code.emitPushString(className);
2667:                    code.emitInvokeStatic(getForNameHelper());
2668:                }
2669:            }
2670:
2671:            /** Generate a method to find a named Class without initializing it.
2672:             * Generate a static helper method "class$" like javac generates for
2673:             * 'CLASS.class', but does not initialize CLASS.  Also, we don't bother
2674:             * catching exceptions, since the JVM doesn't require us to.  I.e. generates:
2675:             * public static class $(String name)
2676:             * { return Class.forName(name, false,
2677:             *                        Class.forName(THISCLASSNAME).getClassLoader()); }
2678:             * Note that we want the result to use the same ClassLoader as the caller,
2679:             * which is why we generate a static helper method.
2680:             */
2681:            public Method getForNameHelper() {
2682:                if (forNameHelper == null) {
2683:                    /* #ifdef JAVA2 */
2684:                    Method save_method = method;
2685:                    method = curClass.addMethod("class$", Access.PUBLIC
2686:                            | Access.STATIC, string1Arg, typeClass);
2687:                    forNameHelper = method;
2688:                    CodeAttr code = method.startCode();
2689:                    code.emitLoad(code.getArg(0));
2690:                    code.emitPushInt(0);
2691:                    code.emitPushString(mainClass.getName());
2692:                    code.emitInvokeStatic(typeClass.getDeclaredMethod(
2693:                            "forName", 1));
2694:                    code.emitInvokeVirtual(typeClass.getDeclaredMethod(
2695:                            "getClassLoader", 0));
2696:                    code.emitInvokeStatic(typeClass.getDeclaredMethod(
2697:                            "forName", 3));
2698:                    code.emitReturn();
2699:                    method = save_method;
2700:                    /* #else */
2701:                    // forNameHelper = typeClass.getDeclaredMethod("forName", 1);
2702:                    /* #endif */
2703:                }
2704:                return forNameHelper;
2705:            }
2706:
2707:            public Object resolve(Object name, boolean function) {
2708:                Environment env = Environment.getCurrent();
2709:                Symbol symbol;
2710:                if (name instanceof  String)
2711:                    symbol = env.defaultNamespace().lookup((String) name);
2712:                else
2713:                    symbol = (Symbol) name;
2714:                if (symbol == null)
2715:                    return null;
2716:                if (function && getLanguage().hasSeparateFunctionNamespace())
2717:                    return env.getFunction(symbol, null);
2718:                return env.get(symbol, null);
2719:            }
2720:
2721:            /** A key we can pass from the compiler to identity a Compilation. */
2722:            private int keyUninitialized;
2723:            /** Chain of immediate Compilation whose setupLiterals hasn't been called. */
2724:            private static Compilation chainUninitialized;
2725:            /** Next in chain headed by chainUninitialized. */
2726:            private Compilation nextUninitialized;
2727:
2728:            /** Call-back from compiled code to initialize literals in immediate mode.
2729:             * In non-immediate mode (i.e. generating class files) the compiler emits
2730:             * code to "re-construct" literal values.  However, in immediate mode
2731:             * that would be wasteful, plus we would get values that are similar (equals)
2732:             * to but not necessarily identical (eq) to the compile-time literal.
2733:             * So we need to pass the literal values to the compiled code, by using
2734:             * reflection to initialize various static fields.  This method does that.
2735:             * It is called at the start of the generated static initializer, which
2736:             * helps makes things more consistent between immediate and non-immediate
2737:             * mode.
2738:             */
2739:            public static void setupLiterals(int key) {
2740:                Compilation comp = Compilation.findForImmediateLiterals(key);
2741:                try {
2742:                    Class clas = comp.loader
2743:                            .loadClass(comp.mainClass.getName());
2744:
2745:                    /* Pass literal values to the compiled code. */
2746:                    for (Literal init = comp.litTable.literalsChain; init != null; init = init.next) {
2747:                        /* DEBUGGING:
2748:                        OutPort out = OutPort.errDefault();
2749:                        out.print("init["+init.index+"]=");
2750:                        out.print(init.value);
2751:                        out.println();
2752:                         */
2753:                        clas.getDeclaredField(init.field.getName()).set(null,
2754:                                init.value);
2755:                    }
2756:                } catch (Throwable ex) {
2757:                    throw new WrappedException("internal error", ex);
2758:                }
2759:            }
2760:
2761:            public static synchronized int registerForImmediateLiterals(
2762:                    Compilation comp) {
2763:                int i = 0;
2764:                for (Compilation c = chainUninitialized; c != null; c = c.nextUninitialized) {
2765:                    if (i <= c.keyUninitialized)
2766:                        i = c.keyUninitialized + 1;
2767:                }
2768:                comp.keyUninitialized = i;
2769:                comp.nextUninitialized = chainUninitialized;
2770:                chainUninitialized = comp;
2771:                return i;
2772:            }
2773:
2774:            public static synchronized Compilation findForImmediateLiterals(
2775:                    int key) {
2776:                Compilation prev = null;
2777:                for (Compilation comp = chainUninitialized;;) {
2778:                    Compilation next = comp.nextUninitialized;
2779:                    if (comp.keyUninitialized == key) {
2780:                        if (prev == null)
2781:                            chainUninitialized = next;
2782:                        else
2783:                            prev.nextUninitialized = next;
2784:                        return comp;
2785:                    }
2786:                    prev = comp;
2787:                    comp = next;
2788:                }
2789:            }
2790:
2791:            /** Current lexical scope - map name to Declaration. */
2792:            public NameLookup lexical;
2793:
2794:            protected ScopeExp current_scope;
2795:
2796:            protected SourceMessages messages;
2797:
2798:            private static final ThreadLocation current = new ThreadLocation(
2799:                    "current-compilation");
2800:
2801:            public static Compilation getCurrent() {
2802:                return (Compilation) current.get();
2803:            }
2804:
2805:            public static void setCurrent(Compilation comp) {
2806:                current.set(comp);
2807:            }
2808:
2809:            public String toString() {
2810:                return "<compilation " + mainLambda + ">";
2811:            }
2812:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.