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


0001:        // Copyright (c) 1999, 2000, 2001  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:
0011:        public class Compilation {
0012:            /** Used by LambdaExp.getSelectorValue if need to allocate new selector. */
0013:            int maxSelectorValue;
0014:
0015:            public ClassType curClass;
0016:            public ClassType mainClass;
0017:
0018:            public LambdaExp curLambda;
0019:            public ModuleExp mainLambda;
0020:            public Variable this Decl;
0021:
0022:            /** Contains "$instance" if the module is static; otherwise null. */
0023:            Field instanceField;
0024:
0025:            /** If true, minimize the number of classes generated.
0026:             * Do this even if it makes things a little slower. */
0027:            public static boolean fewerClasses;
0028:
0029:            /** If true, print out final expressions after optimizations etc. */
0030:            public static boolean debugPrintFinalExpr;
0031:
0032:            public static boolean usingCPStyle;
0033:            public static boolean usingTailCalls = false;
0034:
0035:            /** If moduleStatic > 0, (module-static #t) is implied by default.
0036:             * If moduleStatic < 0, (module-static #f) is implied by default. */
0037:            public static int moduleStatic = 0;
0038:
0039:            ClassType[] classes;
0040:            int numClasses;
0041:
0042:            /** True if the compiled result will be immediately loaded. */
0043:            boolean immediate;
0044:
0045:            /** The current method. */
0046:            public Method method;
0047:
0048:            public final CodeAttr getCode() {
0049:                return method.getCode();
0050:            }
0051:
0052:            int method_counter;
0053:
0054:            /* When multiple procedures are compiled into a single method,
0055:               we use a switch to jump to the correct part of the method. */
0056:            SwitchState fswitch;
0057:
0058:            Field fswitchIndex;
0059:            /** The actual parameter of the current CallFrame.step(CallContext) method. */
0060:            Variable callStackContext;
0061:
0062:            // Various standard classes
0063:            static public ClassType typeObject = Type.pointer_type;
0064:            static public ClassType scmBooleanType = ClassType
0065:                    .make("java.lang.Boolean");
0066:            static public ClassType typeString = ClassType
0067:                    .make("java.lang.String");
0068:            static public ClassType javaStringType = typeString;
0069:            static public ClassType scmSymbolType = typeString;
0070:            static public ClassType scmKeywordType = ClassType
0071:                    .make("gnu.expr.Keyword");
0072:            static public ClassType scmSequenceType = ClassType
0073:                    .make("gnu.lists.Sequence");
0074:            static public ClassType javaIntegerType = ClassType
0075:                    .make("java.lang.Integer");
0076:            static public ClassType scmListType = ClassType
0077:                    .make("gnu.lists.LList");
0078:            static public ClassType typePair = ClassType.make("gnu.lists.Pair");
0079:            static public ClassType scmPairType = typePair;
0080:            static public ClassType scmUndefinedType = ClassType
0081:                    .make("gnu.expr.Undefined");
0082:            public static final ArrayType objArrayType = ArrayType
0083:                    .make(typeObject);
0084:            public static final ArrayType symbolArrayType = ArrayType
0085:                    .make(scmSymbolType);
0086:            static public ClassType scmNamedType = ClassType
0087:                    .make("gnu.mapping.Named");
0088:            static public ClassType typeRunnable = ClassType
0089:                    .make("java.lang.Runnable");
0090:            static public ClassType typeObjectType = ClassType
0091:                    .make("gnu.bytecode.ObjectType");
0092:            static public ClassType typeClassType = ClassType.make(
0093:                    "gnu.bytecode.ClassType", typeObjectType);
0094:            static public ClassType typeProcedure = ClassType
0095:                    .make("gnu.mapping.Procedure");
0096:            static public ClassType typeInterpreter = ClassType
0097:                    .make("gnu.expr.Interpreter");
0098:            static public ClassType typeMacro = ClassType
0099:                    .make("kawa.lang.Macro");
0100:            static public ClassType typeEnvironment = ClassType
0101:                    .make("gnu.mapping.Environment");
0102:            static public ClassType typeLocation = ClassType
0103:                    .make("gnu.mapping.Location");
0104:            static public ClassType typeBinding = ClassType.make(
0105:                    "gnu.mapping.Binding", typeLocation);
0106:            static public final Method getLocationMethod = typeLocation
0107:                    .addMethod("get", Type.typeArray0, Type.pointer_type,
0108:                            Access.PUBLIC);
0109:            static public final Method getProcedureBindingMethod = typeBinding
0110:                    .addMethod("getProcedure", Type.typeArray0, typeProcedure,
0111:                            Access.PUBLIC);
0112:            static public final Field trueConstant = scmBooleanType.addField(
0113:                    "TRUE", scmBooleanType, Access.PUBLIC | Access.STATIC);
0114:            static public final Field falseConstant = scmBooleanType.addField(
0115:                    "FALSE", scmBooleanType, Access.PUBLIC | Access.STATIC);
0116:            static final Field voidConstant = typeInterpreter.addField(
0117:                    "voidObject", typeObject, Access.PUBLIC | Access.STATIC);
0118:            static final Field undefinedConstant = typeInterpreter.addField(
0119:                    "undefinedObject", scmUndefinedType, Access.PUBLIC
0120:                            | Access.STATIC);
0121:            static final Field emptyConstant = scmListType.addField("Empty",
0122:                    scmListType, Access.PUBLIC | Access.STATIC);
0123:            static final Field eofConstant = scmSequenceType.addField(
0124:                    "eofValue", typeObject, Access.PUBLIC | Access.STATIC);
0125:            static final Method setNameMethod = typeProcedure
0126:                    .getDeclaredMethod("setName", 1);
0127:            static Method initIntegerMethod;
0128:            static Method lookupGlobalMethod;
0129:            static Method defineGlobalMethod;
0130:            static Method defineFunctionMethod;
0131:            static Method putGlobalMethod;
0132:            static Method makeListMethod;
0133:
0134:            public static final Type[] int1Args = { Type.int_type };
0135:            public static final Type[] string1Arg = { javaStringType };
0136:            public static final Type[] sym1Arg = string1Arg;
0137:
0138:            static public final Method getBindingEnvironmentMethod = typeEnvironment
0139:                    .addMethod("getBinding", string1Arg, typeBinding,
0140:                            Access.PUBLIC);
0141:
0142:            static {
0143:                Type[] makeListArgs = { objArrayType, Type.int_type };
0144:                makeListMethod = scmListType.addMethod("makeList",
0145:                        makeListArgs, scmListType, Access.PUBLIC
0146:                                | Access.STATIC);
0147:                initIntegerMethod = javaIntegerType.addMethod("<init>",
0148:                        int1Args, Type.void_type, Access.PUBLIC);
0149:
0150:                lookupGlobalMethod = typeEnvironment.addMethod("lookup_global",
0151:                        sym1Arg, typeObject, Access.PUBLIC | Access.STATIC);
0152:                Type[] symObjArgs = { scmSymbolType, typeObject };
0153:                defineGlobalMethod = typeEnvironment.addMethod("define_global",
0154:                        symObjArgs, Type.void_type, Access.PUBLIC
0155:                                | Access.STATIC);
0156:                defineFunctionMethod = typeEnvironment.addMethod(
0157:                        "defineFunction", symObjArgs, Type.void_type,
0158:                        Access.PUBLIC | Access.STATIC);
0159:                putGlobalMethod = typeEnvironment.addMethod("put_global",
0160:                        symObjArgs, Type.void_type, Access.PUBLIC
0161:                                | Access.STATIC);
0162:            }
0163:
0164:            public static Method getCurrentEnvironmentMethod = typeEnvironment
0165:                    .addMethod("getCurrent", Type.typeArray0, typeEnvironment,
0166:                            Access.PUBLIC | Access.STATIC);
0167:
0168:            public static Type[] apply0args = Type.typeArray0;
0169:            public static Type[] apply1args = { typeObject };
0170:            public static Type[] apply2args = { typeObject, typeObject };
0171:            public static Type[] applyNargs = { objArrayType };
0172:
0173:            static Method checkArgCountMethod;
0174:
0175:            public static Method apply0method = typeProcedure.addMethod(
0176:                    "apply0", apply0args, typeObject, Access.PUBLIC
0177:                            | Access.FINAL);
0178:
0179:            public static Method apply1method;
0180:            public static Method apply2method;
0181:            public static Method apply3method;
0182:            public static Method apply4method;
0183:            public static Method applyNmethod;
0184:
0185:            static {
0186:                apply1method = typeProcedure.addMethod("apply1", apply1args,
0187:                        typeObject, Access.PUBLIC);
0188:                apply2method = typeProcedure.addMethod("apply2", apply2args,
0189:                        typeObject, Access.PUBLIC);
0190:                Type[] apply3args = { typeObject, typeObject, typeObject };
0191:                apply3method = typeProcedure.addMethod("apply3", apply3args,
0192:                        typeObject, Access.PUBLIC);
0193:                Type[] apply4args = { typeObject, typeObject, typeObject,
0194:                        typeObject };
0195:                apply4method = typeProcedure.addMethod("apply4", apply4args,
0196:                        typeObject, Access.PUBLIC);
0197:                applyNmethod = typeProcedure.addMethod("applyN", applyNargs,
0198:                        typeObject, Access.PUBLIC);
0199:                Type[] args = new Type[2];
0200:                args[0] = typeProcedure;
0201:                args[1] = Type.int_type;
0202:                checkArgCountMethod = typeProcedure.addMethod("checkArgCount",
0203:                        args, Type.void_type, Access.PUBLIC | Access.STATIC);
0204:            }
0205:
0206:            public static Method[] applymethods = { apply0method, apply1method,
0207:                    apply2method, apply3method, apply4method, applyNmethod };
0208:
0209:            public static ClassType typeProcedure0 = ClassType.make(
0210:                    "gnu.mapping.Procedure0", typeProcedure);
0211:            public static ClassType typeProcedure1 = ClassType.make(
0212:                    "gnu.mapping.Procedure1", typeProcedure);
0213:            public static ClassType typeProcedure2 = ClassType.make(
0214:                    "gnu.mapping.Procedure2", typeProcedure);
0215:            public static ClassType typeProcedure3 = ClassType.make(
0216:                    "gnu.mapping.Procedure3", typeProcedure);
0217:            public static ClassType typeProcedure4 = ClassType.make(
0218:                    "gnu.mapping.Procedure4", typeProcedure);
0219:            public static ClassType typeProcedureN = ClassType.make(
0220:                    "gnu.mapping.ProcedureN", typeProcedure);
0221:            public static ClassType typeModuleBody = ClassType.make(
0222:                    "gnu.expr.ModuleBody", typeProcedure0);
0223:            public static ClassType typeApplet = ClassType
0224:                    .make("java.applet.Applet");
0225:            public static ClassType typeServlet = ClassType
0226:                    .make("gnu.kawa.servlet.KawaServlet");
0227:
0228:            public static ClassType typeModuleMethod = ClassType.make(
0229:                    "gnu.expr.ModuleMethod", typeProcedureN);
0230:            public static ClassType typeApplyMethodProc = ClassType.make(
0231:                    "gnu.mapping.ApplyMethodProc", typeProcedureN);
0232:            public static ClassType typeApplyMethodContainer = ClassType
0233:                    .make("gnu.mapping.ApplyMethodContainer");
0234:
0235:            /* Classes, fields, and methods used wgen usingCPStyle". */
0236:            public static ClassType typeCallContext = ClassType
0237:                    .make("gnu.mapping.CallContext");
0238:            public static final ClassType typeConsumer = ClassType
0239:                    .make("gnu.lists.Consumer");
0240:            public static Method popCallContextMethod = typeCallContext
0241:                    .addMethod("pop", apply0args, Type.void_type, Access.PUBLIC);
0242:            public static ClassType typeValues = ClassType
0243:                    .make("gnu.mapping.Values");
0244:            public static Field noArgsField = typeValues.addField("noArgs",
0245:                    objArrayType, Access.PUBLIC | Access.STATIC);
0246:            public static Field pcCallContextField = typeCallContext.addField(
0247:                    "pc", Type.int_type, Access.PROTECTED);
0248:            public static ClassType typeCpsProcedure = ClassType
0249:                    .make("gnu.mapping.CpsProcedure");
0250:            public static ClassType typeCallFrame = ClassType
0251:                    .make("gnu.mapping.CallFrame");
0252:            public static ClassType typeCpsMethodProc = ClassType.make(
0253:                    "gnu.mapping.CpsMethodProc", typeCpsProcedure);
0254:            public static ClassType typeCpsMethodContainer = ClassType
0255:                    .make("gnu.mapping.CpsMethodContainer");
0256:            public static Field numArgsCallFrameField = typeCallFrame.addField(
0257:                    "numArgs", Type.int_type, Access.PROTECTED);
0258:            public static Field argsCallContextField = typeCallContext
0259:                    .addField("values", objArrayType, Access.PROTECTED);
0260:            public static Field procCallContextField = typeCallContext
0261:                    .addField("proc", typeProcedure, Access.PROTECTED);
0262:            public static Field callerCallFrameField = typeCallFrame.addField(
0263:                    "caller", typeCallFrame, Access.PROTECTED);
0264:            public static Field saved_pcCallFrameField = typeCallFrame
0265:                    .addField("saved_pc", Type.int_type, Access.PROTECTED);
0266:            private static Type[] applyCpsArgs = { typeCallContext };
0267:            public static Method applyCpsMethod = typeProcedure.addMethod(
0268:                    "apply", applyCpsArgs, Type.void_type, Access.PUBLIC);
0269:
0270:            public static ClassType[] typeProcedureArray = { typeProcedure0,
0271:                    typeProcedure1, typeProcedure2, typeProcedure3,
0272:                    typeProcedure4 };
0273:
0274:            Hashtable literalTable;
0275:            int literalsCount;
0276:
0277:            /** Rembembers stuff to do in <clinit> of main class. */
0278:            Initializer clinitChain;
0279:
0280:            /** Rembembers literals to initialize (in <clinit>). */
0281:            Literal literalsChain;
0282:
0283:            public static boolean generateMainDefault = false;
0284:            /** True if we should generate a main(String[]) method. */
0285:            public boolean generateMain = generateMainDefault;
0286:
0287:            LitTable litTable;
0288:
0289:            public static boolean generateAppletDefault = false;
0290:            /** True if we should generate an Applet. */
0291:            public boolean generateApplet = generateAppletDefault;
0292:
0293:            public static boolean generateServletDefault = false;
0294:            /** True if we should generate an Servlet. */
0295:            public boolean generateServlet = generateServletDefault;
0296:
0297:            public static final ClassType getMethodProcType(ClassType modClass) {
0298:                return usingTailCalls ? typeCpsMethodProc
0299:                        : true || modClass.getSuperclass().isSubtype(
0300:                                typeProcedure) ? typeModuleMethod
0301:                                : typeApplyMethodProc;
0302:            }
0303:
0304:            public final ClassType getModuleSuperType(ModuleExp module) {
0305:                ClassType sup = module.getSuperType();
0306:                return (sup != null ? sup : usingCPStyle() ? typeCallFrame
0307:                        : generateApplet ? typeApplet
0308:                                : generateServlet ? typeServlet
0309:                                        : typeModuleBody);
0310:            }
0311:
0312:            public Interpreter getInterpreter() {
0313:                return Interpreter.defaultInterpreter; // For now.  FIXME.
0314:            }
0315:
0316:            public Literal findLiteral(Object value) {
0317:                if (value == null)
0318:                    return Literal.nullLiteral;
0319:                Literal literal = (Literal) literalTable.get(value);
0320:                if (literal == null) {
0321:                    if (value instanceof  Boolean) {
0322:                        boolean val = ((Boolean) value).booleanValue();
0323:                        literal = new Literal(value, val ? trueConstant
0324:                                : falseConstant, this );
0325:                    } else if (value == Values.empty)
0326:                        literal = new Literal(value, voidConstant, this );
0327:                    else if (value == gnu.lists.LList.Empty)
0328:                        literal = new Literal(value, emptyConstant, this );
0329:                    else if (value == gnu.lists.Sequence.eofValue)
0330:                        literal = new Literal(value, eofConstant, this );
0331:                    else if (value instanceof  Undefined)
0332:                        literal = new Literal(value, undefinedConstant, this );
0333:                    else if (immediate) {
0334:                        literal = new Literal(value, this );
0335:                    } else {
0336:                        Type literalType = Type.make(value.getClass());
0337:                        if (literalType == Type.byte_ctype
0338:                                || literalType == Type.short_ctype)
0339:                            literalType = Type.int_ctype;
0340:                        literal = new Literal(value, literalType, this );
0341:                    }
0342:                }
0343:                return literal;
0344:            }
0345:
0346:            /** Emit code to "evaluate" a compile-time constant.
0347:             * This is the normal external interface.
0348:             * @param value the value to be compiled
0349:             */
0350:            public void compileConstant(Object value) {
0351:                gnu.bytecode.CodeAttr code = getCode();
0352:                if (value == null)
0353:                    code.emitPushNull();
0354:                else if (value instanceof  String && !immediate)
0355:                    code.emitPushString((String) value);
0356:                else {
0357:                    Literal literal = findLiteral(value);
0358:                    if (literal.field == null)
0359:                        literal.assign(this );
0360:                    code.emitGetStatic(literal.field);
0361:                }
0362:            }
0363:
0364:            public void compileConstant(Object value, Target target) {
0365:                if (target instanceof  IgnoreTarget)
0366:                    return;
0367:                if (target instanceof  ConsumerTarget) {
0368:                    if (value == Values.empty)
0369:                        return;
0370:                    // else FIXME
0371:                }
0372:                if (target instanceof  ConditionalTarget) {
0373:                    ConditionalTarget ctarg = (ConditionalTarget) target;
0374:                    getCode().emitGoto(
0375:                            getInterpreter().isTrue(value) ? ctarg.ifTrue
0376:                                    : ctarg.ifFalse);
0377:                    return;
0378:                }
0379:                if (target instanceof  StackTarget) {
0380:                    if (value == null) {
0381:                        getCode().emitPushNull();
0382:                        return;
0383:                    }
0384:
0385:                    Type type = ((StackTarget) target).getType();
0386:                    if (type instanceof  PrimType) {
0387:                        try {
0388:                            String signature = type.getSignature();
0389:                            CodeAttr code = getCode();
0390:                            char sig1 = (signature == null || signature
0391:                                    .length() != 1) ? ' ' : signature.charAt(0);
0392:                            if (value instanceof  Number) {
0393:                                Number num = (Number) value;
0394:                                switch (sig1) {
0395:                                case 'I':
0396:                                case 'C':
0397:                                    code.emitPushInt(num.intValue());
0398:                                    return;
0399:                                case 'S':
0400:                                    code.emitPushInt(num.shortValue());
0401:                                    return;
0402:                                case 'B':
0403:                                    code.emitPushInt(num.byteValue());
0404:                                    return;
0405:                                case 'J':
0406:                                    code.emitPushLong(num.longValue());
0407:                                    return;
0408:                                case 'F':
0409:                                    code.emitPushFloat(num.floatValue());
0410:                                    return;
0411:                                case 'D':
0412:                                    code.emitPushDouble(num.doubleValue());
0413:                                    return;
0414:                                }
0415:                            } else if (value instanceof  Character) {
0416:                                if (sig1 == 'C' || sig1 == 'I' || sig1 == 'J') {
0417:                                    code.emitPushInt(((Character) value)
0418:                                            .charValue());
0419:                                    return;
0420:                                } else if (sig1 == 'F') {
0421:                                    code.emitPushFloat(((Character) value)
0422:                                            .charValue());
0423:                                    return;
0424:                                } else if (sig1 == 'D') {
0425:                                    code.emitPushDouble(((Character) value)
0426:                                            .charValue());
0427:                                    return;
0428:                                }
0429:                            }
0430:                            if (sig1 == 'C') {
0431:                                code.emitPushInt((int) ((PrimType) type)
0432:                                        .charValue(value));
0433:                                return;
0434:                            }
0435:                            if (sig1 == 'Z') {
0436:                                boolean val = ((PrimType) type)
0437:                                        .booleanValue(value);
0438:                                code.emitPushBoolean(val);
0439:                                return;
0440:                            }
0441:                            if (sig1 == 'V' && value == Values.empty)
0442:                                return;
0443:                        } catch (ClassCastException ex) {
0444:                            // should print an ERROR.
0445:                        }
0446:                    }
0447:                    try {
0448:                        value = type.coerceFromObject(value);
0449:                    } catch (Exception ex) {
0450:                        if (value != Values.empty)
0451:                            error('w', "cannot convert literal (of type "
0452:                                    + value.getClass().getName() + ") to "
0453:                                    + type.getName());
0454:                    }
0455:                }
0456:                compileConstant(value);
0457:                target.compileFromStack(this , value == null ? target.getType()
0458:                        : Type.make(value.getClass()));
0459:            }
0460:
0461:            void dumpInitializers(Initializer inits, Method initMethod) {
0462:                Method save = method;
0463:                method = initMethod;
0464:                dumpInitializers(inits);
0465:                method = save;
0466:            }
0467:
0468:            private void dumpInitializers(Initializer inits) {
0469:                for (Initializer init = Initializer.reverse(inits); init != null; init = init.next)
0470:                    init.emit(this );
0471:            }
0472:
0473:            /** Search this Compilation for a ClassType with a given name.
0474:             * @param name the name of the class desired
0475:             * @return the matching ClassType, or null if none is found */
0476:            public ClassType findNamedClass(String name) {
0477:                for (int i = 0; i < numClasses; i++) {
0478:                    if (name.equals(classes[i].getName()))
0479:                        return classes[i];
0480:                }
0481:                return null;
0482:            }
0483:
0484:            /** If non-null: a prefix for generateClassName to prepend to names. */
0485:            public String classPrefix;
0486:
0487:            public static String mangleName(String name) {
0488:                return mangleName(name, false);
0489:            }
0490:
0491:            public static String mangleNameIfNeeded(String name) {
0492:                if (isValidJavaName(name))
0493:                    return name;
0494:                else
0495:                    return mangleName(name, true);
0496:            }
0497:
0498:            public static boolean isValidJavaName(String name) {
0499:                int len = name.length();
0500:                if (len == 0
0501:                        || !Character.isJavaIdentifierStart(name.charAt(0)))
0502:                    return false;
0503:                for (int i = len; --i > 0;)
0504:                    if (!Character.isJavaIdentifierPart(name.charAt(i)))
0505:                        return false;
0506:                return true;
0507:            }
0508:
0509:            /** Convert a string to a safe Java identifier.
0510:             * @param reversible if we should use an invertible mapping. */
0511:            public static String mangleName(String name, boolean reversible) {
0512:                int len = name.length();
0513:                StringBuffer mangled = new StringBuffer(len);
0514:                boolean upcaseNext = false;
0515:                for (int i = 0; i < len; i++) {
0516:                    char ch = name.charAt(i);
0517:                    if (upcaseNext) {
0518:                        ch = Character.toTitleCase(ch);
0519:                        upcaseNext = false;
0520:                    }
0521:                    if (Character.isDigit(ch)) {
0522:                        if (i == 0)
0523:                            mangled.append("$N");
0524:                        mangled.append(ch);
0525:                    } else if (Character.isLetter(ch) || ch == '_')
0526:                        mangled.append(ch);
0527:                    else if (ch == '$')
0528:                        mangled.append(reversible ? "$$" : "$");
0529:                    else {
0530:                        switch (ch) {
0531:                        case '+':
0532:                            mangled.append("$Pl");
0533:                            break;
0534:                        case '-':
0535:                            if (reversible)
0536:                                mangled.append("$Mn");
0537:                            else {
0538:                                char next = i + 1 < len ? name.charAt(i + 1)
0539:                                        : '\0';
0540:                                if (next == '>') {
0541:                                    mangled.append("$To$");
0542:                                    i++;
0543:                                } else if (!Character.isLowerCase(next))
0544:                                    mangled.append("$Mn");
0545:                            }
0546:                            break;
0547:                        case '*':
0548:                            mangled.append("$St");
0549:                            break;
0550:                        case '/':
0551:                            mangled.append("$Sl");
0552:                            break;
0553:                        case '=':
0554:                            mangled.append("$Eq");
0555:                            break;
0556:                        case '<':
0557:                            mangled.append("$Ls");
0558:                            break;
0559:                        case '>':
0560:                            mangled.append("$Gr");
0561:                            break;
0562:                        case '@':
0563:                            mangled.append("$At");
0564:                            break;
0565:                        case '~':
0566:                            mangled.append("$Tl");
0567:                            break;
0568:                        case '%':
0569:                            mangled.append("$Pc");
0570:                            break;
0571:                        case '.':
0572:                            mangled.append("$Dt");
0573:                            break;
0574:                        case ',':
0575:                            mangled.append("$Cm");
0576:                            break;
0577:                        case '(':
0578:                            mangled.append("$LP");
0579:                            break;
0580:                        case ')':
0581:                            mangled.append("$RP");
0582:                            break;
0583:                        case '[':
0584:                            mangled.append("$LB");
0585:                            break;
0586:                        case ']':
0587:                            mangled.append("$RB");
0588:                            break;
0589:                        case '{':
0590:                            mangled.append("$LC");
0591:                            break;
0592:                        case '}':
0593:                            mangled.append("$RC");
0594:                            break;
0595:                        case '\'':
0596:                            mangled.append("$Sq");
0597:                            break;
0598:                        case '"':
0599:                            mangled.append("$Dq");
0600:                            break;
0601:                        case '&':
0602:                            mangled.append("$Am");
0603:                            break;
0604:                        case '#':
0605:                            mangled.append("$Nm");
0606:                            break;
0607:                        case '?':
0608:                            char first = mangled.length() > 0 ? mangled
0609:                                    .charAt(0) : '\0';
0610:                            if (!reversible && i + 1 == len
0611:                                    && Character.isLowerCase(first)) {
0612:                                mangled.setCharAt(0, Character
0613:                                        .toTitleCase(first));
0614:                                mangled.insert(0, "is");
0615:                            } else
0616:                                mangled.append("$Qu");
0617:                            break;
0618:                        case '!':
0619:                            mangled.append("$Ex");
0620:                            break;
0621:                        case ':':
0622:                            mangled.append("$Cl");
0623:                            break;
0624:                        case ';':
0625:                            mangled.append("$SC");
0626:                            break;
0627:                        case '^':
0628:                            mangled.append("$Up");
0629:                            break;
0630:                        case '|':
0631:                            mangled.append("$VB");
0632:                            break;
0633:                        default:
0634:                            mangled.append('$');
0635:                            mangled.append(Character.forDigit((ch >> 12) & 15,
0636:                                    16));
0637:                            mangled.append(Character.forDigit((ch >> 8) & 15,
0638:                                    16));
0639:                            mangled.append(Character.forDigit((ch >> 4) & 15,
0640:                                    16));
0641:                            mangled.append(Character.forDigit((ch) & 15, 16));
0642:                        }
0643:                        if (!reversible)
0644:                            upcaseNext = true;
0645:                    }
0646:                }
0647:                String mname = mangled.toString();
0648:                return mname.equals(name) ? name : mname;
0649:            }
0650:
0651:            /** Demangle a three-character mangling starting with '$'.
0652:             * UNFINISHED!
0653:             */
0654:            public static char demangle2(char char1, char char2) {
0655:                switch (char1 << 16 | char2) {
0656:                case 'A' << 16 | 'm':
0657:                    return '&';
0658:                case 'A' << 16 | 't':
0659:                    return '@';
0660:                case 'C' << 16 | 'l':
0661:                    return ':';
0662:                case 'C' << 16 | 'm':
0663:                    return ',';
0664:                case 'D' << 16 | 'q':
0665:                    return '\"';
0666:                case 'D' << 16 | 't':
0667:                    return '.';
0668:                case 'E' << 16 | 'q':
0669:                    return '=';
0670:                case 'E' << 16 | 'x':
0671:                    return '!';
0672:                case 'G' << 16 | 'r':
0673:                    return '>';
0674:                case 'L' << 16 | 'B':
0675:                    return '[';
0676:                case 'L' << 16 | 'C':
0677:                    return '{';
0678:                case 'L' << 16 | 'P':
0679:                    return '(';
0680:                case 'L' << 16 | 's':
0681:                    return '<';
0682:                case 'M' << 16 | 'c':
0683:                    return '%';
0684:                case 'M' << 16 | 'n':
0685:                    return '-';
0686:                case 'N' << 16 | 'm':
0687:                    return '#';
0688:                case 'P' << 16 | 'c':
0689:                    return '%';
0690:                case 'P' << 16 | 'l':
0691:                    return '+';
0692:                case 'Q' << 16 | 'u':
0693:                    return '?';
0694:                case 'R' << 16 | 'B':
0695:                    return ']';
0696:                case 'R' << 16 | 'C':
0697:                    return '}';
0698:                case 'R' << 16 | 'P':
0699:                    return ')';
0700:                case 'S' << 16 | 'C':
0701:                    return ';';
0702:                case 'S' << 16 | 'l':
0703:                    return '/';
0704:                case 'S' << 16 | 'q':
0705:                    return '\\';
0706:                case 'S' << 16 | 't':
0707:                    return '*';
0708:                case 'T' << 16 | 'l':
0709:                    return '~';
0710:                case 'U' << 16 | 'p':
0711:                    return '^';
0712:                case 'V' << 16 | 'B':
0713:                    return '|';
0714:                }
0715:                return (char) (-1);
0716:            }
0717:
0718:            public static String demangleName(String name) {
0719:                return demangleName(name, false);
0720:            }
0721:
0722:            public static String demangleName(String name, boolean reversible) {
0723:                StringBuffer sbuf = new StringBuffer();
0724:                int len = name.length();
0725:                boolean mangled = false;
0726:                boolean predicate = false;
0727:                boolean downCaseNext = false;
0728:                for (int i = 0; i < len; i++) {
0729:                    char ch = name.charAt(i);
0730:                    if (downCaseNext && !reversible) {
0731:                        ch = Character.toLowerCase(ch);
0732:                        downCaseNext = false;
0733:                    }
0734:                    char d;
0735:                    if (!reversible && ch == 'i' && i == 0 && len > 2
0736:                            && name.charAt(i + 1) == 's'
0737:                            && !Character.isLowerCase(d = name.charAt(i + 2))) {
0738:                        mangled = true;
0739:                        predicate = true;
0740:                        i++;
0741:                        if (Character.isUpperCase(d)
0742:                                || Character.isTitleCase(d)) {
0743:                            sbuf.append(Character.toLowerCase(d));
0744:                            i++;
0745:                            continue;
0746:                        }
0747:                        continue;
0748:                    } else if (ch == '$' && i + 2 < len) {
0749:                        char c1 = name.charAt(i + 1);
0750:                        char c2 = name.charAt(i + 2);
0751:                        d = Compilation.demangle2(c1, c2);
0752:                        if (d != (char) (-1)) {
0753:                            sbuf.append(d);
0754:                            i += 2;
0755:                            mangled = true;
0756:                            downCaseNext = true;
0757:                            continue;
0758:                        } else if (c1 == 'T' && c2 == 'o' && i + 3 < len
0759:                                && name.charAt(i + 3) == '$') {
0760:                            sbuf.append("->");
0761:                            i += 3;
0762:                            mangled = true;
0763:                            downCaseNext = true;
0764:                            continue;
0765:                        }
0766:                    } else if (!reversible
0767:                            && i > 1
0768:                            && (Character.isUpperCase(ch) || Character
0769:                                    .isTitleCase(ch))
0770:                            && (Character.isLowerCase(name.charAt(i - 1)))) {
0771:                        sbuf.append('-');
0772:                        mangled = true;
0773:                        ch = Character.toLowerCase(ch);
0774:                    }
0775:                    sbuf.append(ch);
0776:                }
0777:                if (predicate)
0778:                    sbuf.append('?');
0779:                return mangled ? sbuf.toString() : name;
0780:            }
0781:
0782:            /** Generate an unused class name.
0783:             * @param hint the requested name (or prefix)
0784:             * @return a unique class name.
0785:             */
0786:            public String generateClassName(String hint) {
0787:                hint = mangleName(hint, true);
0788:                if (mainClass != null)
0789:                    hint = mainClass.getName() + '$' + hint;
0790:                else if (classPrefix != null)
0791:                    hint = classPrefix + hint;
0792:                if (findNamedClass(hint) == null)
0793:                    return hint;
0794:                for (int i = 0;; i++) {
0795:                    String new_hint = hint + i;
0796:                    if (findNamedClass(new_hint) == null)
0797:                        return new_hint;
0798:                }
0799:            }
0800:
0801:            /** Generate an unused name.
0802:             * @param hint the requested name (or prefix)
0803:             * @return a unique class name.
0804:             */
0805:            public String generateUniqueName(String hint) {
0806:                if (currentPackage.findNamedClass(hint) == null)
0807:                    return hint;
0808:                for (int i = 0;; i++) {
0809:                    String new_hint = hint + i;
0810:                    if (currentPackage.findNamedClass(new_hint) == null)
0811:                        return new_hint;
0812:                }
0813:            }
0814:
0815:            String source_filename;
0816:
0817:            /** Create a new Compilation environment.
0818:             * @param lexp top-level function
0819:             * @param classname name of top-level class to generate
0820:             * @param prefix prefix to pre-pend to the names of other (non-top) classes
0821:             * @param immediate true if the classes will be immediately loaded
0822:             */
0823:            public Compilation(ModuleExp lexp, String classname, String prefix,
0824:                    boolean immediate) {
0825:                source_filename = lexp.filename;
0826:                classPrefix = prefix;
0827:                this .immediate = immediate;
0828:                mainClass = new ClassType(classname);
0829:                mainLambda = lexp;
0830:
0831:                // Do various code re-writes and optimization.
0832:                PushApply.pushApply(lexp);
0833:                InlineCalls.inlineCalls(lexp);
0834:                ChainLambdas.chainLambdas(lexp, this );
0835:                FindTailCalls.findTailCalls(lexp);
0836:                lexp.setCanRead(true);
0837:                FindCapturedVars.findCapturedVars(lexp);
0838:
0839:                if (debugPrintFinalExpr) {
0840:                    OutPort dout = OutPort.outDefault();
0841:                    dout.println("[Compiling final " + lexp.getName()
0842:                            + " class=" + classname + ':');
0843:                    lexp.print(dout);
0844:                    dout.println(']');
0845:                    dout.flush();
0846:                }
0847:
0848:                mainClass = addClass(lexp, mainClass);
0849:                literalTable = new Hashtable(100);
0850:                try {
0851:                    addClass(lexp);
0852:                } catch (RuntimeException ex) {
0853:                    // Try to produce a localized error message.
0854:                    error('f', "Internal compiler exception: " + ex);
0855:                    throw ex;
0856:                }
0857:            }
0858:
0859:            /*
0860:            public void addClass (ClassType new_class)
0861:            {
0862:              if (source_filename != null)
0863:                new_class.setSourceFile (source_filename);
0864:              if (classes == null)
0865:                classes = new ClassType[20];
0866:              else if (numClasses >= classes.length)
0867:                {
0868:            ClassType[] new_classes = new ClassType[2 * classes.length];
0869:            System.arraycopy (classes, 0, new_classes, 0, numClasses);
0870:            classes = new_classes;
0871:                }
0872:              classes[numClasses++] = new_class;
0873:              new_class.access_flags |= Access.PUBLIC|Access.SUPER;
0874:            }
0875:             */
0876:
0877:            ClassType allocClass(ModuleExp module) {
0878:                String name = module.getJavaName();
0879:                name = generateClassName(name);
0880:                return addClass(module, new ClassType(name));
0881:            }
0882:
0883:            ClassType addClass(LambdaExp lexp, ClassType type) {
0884:                ClassType super Type;
0885:                if (lexp.isModuleBody()) {
0886:                    ModuleExp module = (ModuleExp) lexp;
0887:                    super Type = getModuleSuperType(module);
0888:                    ClassType[] interfaces = module.getInterfaces();
0889:                    if (interfaces != null)
0890:                        type.setInterfaces(interfaces);
0891:                } else
0892:                    super Type = (usingCPStyle ? typeCallFrame
0893:                            : lexp.isHandlingTailCalls() ? typeCpsProcedure
0894:                                    : (lexp.min_args != lexp.max_args || lexp.min_args > 4) ? typeProcedureN
0895:                                            : typeProcedureArray[lexp.min_args]);
0896:                type.setSuper(super Type);
0897:
0898:                lexp.type = type;
0899:                addClass(type);
0900:                return type;
0901:            }
0902:
0903:            public final Method getConstructor(LambdaExp lexp) {
0904:                return getConstructor(lexp.getHeapFrameType(), lexp);
0905:            }
0906:
0907:            public static final Method getConstructor(ClassType clas,
0908:                    LambdaExp lexp) {
0909:                Type[] args;
0910:                if (lexp instanceof  ClassExp && lexp.staticLinkField != null) {
0911:                    args = new Type[1];
0912:                    args[0] = lexp.staticLinkField.getType();
0913:                } else
0914:                    args = apply0args;
0915:                return clas.addMethod("<init>", Access.PUBLIC, args,
0916:                        Type.void_type);
0917:            }
0918:
0919:            public final void generateConstructor(LambdaExp lexp) {
0920:                generateConstructor(lexp.getHeapFrameType(), lexp);
0921:            }
0922:
0923:            public final void generateConstructor(ClassType clas, LambdaExp lexp) {
0924:                if (lexp instanceof  ClassExp
0925:                        && !((ClassExp) lexp).needsConstructor)
0926:                    return;
0927:
0928:                Method save_method = method;
0929:                ClassType save_class = curClass;
0930:                curClass = clas;
0931:                Method constructor_method = getConstructor(clas, lexp);
0932:                clas.constructor = constructor_method;
0933:                constructor_method.eraseCode();
0934:
0935:                Method super Constructor = clas.getSuperclass().addMethod(
0936:                        "<init>", Access.PUBLIC, apply0args, Type.void_type);
0937:                method = constructor_method;
0938:                constructor_method.init_param_slots();
0939:                CodeAttr code = getCode();
0940:                code.emitPushThis();
0941:                code.emitInvokeSpecial(super Constructor);
0942:
0943:                if (lexp instanceof  ClassExp && lexp.staticLinkField != null) {
0944:                    code.emitPushThis();
0945:                    code.emitLoad(code.getCurrentScope().getVariable(1));
0946:                    code.emitPutField(lexp.staticLinkField);
0947:                }
0948:
0949:                Initializer init;
0950:                lexp.initChain = Initializer.reverse(lexp.initChain);
0951:                while ((init = lexp.initChain) != null) {
0952:                    lexp.initChain = init.next;
0953:                    init.emit(this );
0954:                }
0955:
0956:                if (lexp instanceof  ClassExp) {
0957:                    ClassExp cexp = (ClassExp) lexp;
0958:                    LambdaExp initMethod = cexp.initMethod;
0959:                    if (initMethod != null) {
0960:                        code.emitPushThis();
0961:                        code.emitInvoke(initMethod.getMainMethod());
0962:                    }
0963:                }
0964:
0965:                code.emitReturn();
0966:                method = save_method;
0967:                curClass = save_class;
0968:            }
0969:
0970:            /** Generate ModuleBody's apply0 .. applyN methods.
0971:             * Use the applyMethods vector, which contains methods that implement
0972:             * the (public, readable) methods of the current module. */
0973:            public void generateApplyMethods(LambdaExp lexp) {
0974:                int numApplyMethods = lexp.applyMethods == null ? 0
0975:                        : lexp.applyMethods.size();
0976:                if (numApplyMethods == 0)
0977:                    return;
0978:                boolean generateApplyMethodContainer = !(curClass
0979:                        .getSuperclass().isSubtype(typeProcedure));
0980:                ClassType procType = getMethodProcType(curClass);
0981:                if (Compilation.usingTailCalls)
0982:                    curClass.addInterface(typeCpsMethodContainer);
0983:                else if (generateApplyMethodContainer)
0984:                    curClass.addInterface(typeApplyMethodContainer);
0985:                Method save_method = method;
0986:                CodeAttr code = null;
0987:                for (int i = Compilation.usingTailCalls ? 5 : 0; i < 6; i++) {
0988:                    // If i < 5, generate the method named ("apply"+i);
0989:                    // else generate "applyN".
0990:                    boolean needThisApply = false;
0991:                    SwitchState aswitch = null;
0992:                    String mname = null;
0993:                    Type[] applyArgs = null;
0994:
0995:                    for (int j = numApplyMethods; --j >= 0;) {
0996:                        LambdaExp source = (LambdaExp) lexp.applyMethods
0997:                                .elementAt(j);
0998:                        int min_args = source.min_args;
0999:                        if (source.isClassMethod())
1000:                            min_args++;
1001:                        // Select the subset of source.primMethods[*] that are suitable
1002:                        // for the current apply method.
1003:                        Method[] primMethods = source.primMethods;
1004:                        int numMethods = primMethods.length;
1005:                        boolean varArgs = source.max_args < 0
1006:                                || Compilation.usingTailCalls
1007:                                || source.max_args >= min_args + numMethods;
1008:                        int methodIndex;
1009:                        boolean skipThisProc = false;
1010:                        if (i < 5) // Handling apply0 .. apply4
1011:                        {
1012:                            methodIndex = i - min_args;
1013:                            if (methodIndex < 0
1014:                                    || methodIndex >= numMethods
1015:                                    || (methodIndex == numMethods - 1 && varArgs))
1016:                                skipThisProc = true;
1017:                            numMethods = 1;
1018:                            varArgs = false;
1019:                        } else // Handling applyN
1020:                        {
1021:                            methodIndex = 5 - min_args;
1022:                            if (methodIndex > 0 && numMethods <= methodIndex
1023:                                    && !varArgs)
1024:                                skipThisProc = true;
1025:                            methodIndex = numMethods - 1;
1026:                        }
1027:                        if (skipThisProc && !generateApplyMethodContainer)
1028:                            continue;
1029:                        if (!needThisApply) {
1030:                            // First LambdaExp we seen suitable for this i.
1031:                            if (i < 5) {
1032:                                mname = "apply" + i;
1033:                                applyArgs = new Type[i + 1];
1034:                                for (int k = i; k > 0; k--)
1035:                                    applyArgs[k] = typeObject;
1036:                            } else if (Compilation.usingTailCalls) {
1037:                                mname = "apply";
1038:                                applyArgs = new Type[2];
1039:                                applyArgs[1] = typeCallContext;
1040:                            } else {
1041:                                mname = "applyN";
1042:                                applyArgs = new Type[2];
1043:                                applyArgs[1] = objArrayType;
1044:                            }
1045:                            applyArgs[0] = procType;
1046:                            method = curClass
1047:                                    .addMethod(
1048:                                            mname,
1049:                                            applyArgs,
1050:                                            Compilation.usingTailCalls ? (Type) Type.void_type
1051:                                                    : (Type) Type.pointer_type,
1052:                                            Access.PUBLIC);
1053:                            method.init_param_slots();
1054:                            code = getCode();
1055:
1056:                            code.emitLoad(code.getArg(1)); // method
1057:                            code.emitGetField(procType
1058:                                    .getDeclaredField("selector"));
1059:                            aswitch = new SwitchState(code);
1060:
1061:                            needThisApply = true;
1062:                        }
1063:                        if (skipThisProc && generateApplyMethodContainer)
1064:                            continue;
1065:
1066:                        aswitch.addCase(source.getSelectorValue(this ), code);
1067:
1068:                        Method primMethod = primMethods[methodIndex];
1069:                        Type[] primArgTypes = primMethod.getParameterTypes();
1070:                        int nargs = primArgTypes.length;
1071:                        int singleArgs = varArgs ? (nargs - 1) : nargs;
1072:                        Variable counter = null;
1073:                        int pendingIfEnds = 0;
1074:
1075:                        if (i > 4 && numMethods > 1) {
1076:                            counter = code.addLocal(Type.int_type);
1077:                            code.emitLoad(code.getArg(2));
1078:                            code.emitArrayLength();
1079:                            if (min_args != 0) {
1080:                                code.emitPushInt(min_args);
1081:                                code.emitSub(Type.int_type);
1082:                            }
1083:                            code.emitStore(counter);
1084:                        }
1085:
1086:                        int argumentStart = 2;
1087:
1088:                        if (source.getNeedsClosureEnv())
1089:                            code.emitPushThis();
1090:
1091:                        if (source.isClassMethod()) {
1092:                            code.emitLoad(code.getArg(argumentStart++));
1093:                            Type ptype = primMethod.getDeclaringClass();
1094:                            ptype.emitCoerceFromObject(code);
1095:                        }
1096:
1097:                        Declaration var = source.firstDecl();
1098:                        for (int k = 0; k < singleArgs; k++) {
1099:                            if (counter != null && k >= min_args) {
1100:                                code.emitLoad(counter);
1101:                                code.emitIfIntLEqZero();
1102:                                code.emitInvoke(primMethods[k - min_args]);
1103:                                code.emitElse();
1104:                                pendingIfEnds++;
1105:                                code.emitInc(counter, (short) (-1));
1106:                            }
1107:
1108:                            if (i > 4) // applyN method
1109:                            {
1110:                                // Load Object[]args value:
1111:                                code.emitLoad(code.getArg(2));
1112:                                code.emitPushInt(k);
1113:                                code.emitArrayLoad(Type.pointer_type);
1114:                            } else
1115:                                // apply'i method
1116:                                code.emitLoad(code.getArg(k + argumentStart));
1117:                            Type ptype = var.getType();
1118:                            if (ptype != Type.pointer_type)
1119:                                StackTarget.convert(this , Type.pointer_type,
1120:                                        ptype);
1121:                            var = var.nextDecl();
1122:                        }
1123:
1124:                        if (varArgs) {
1125:                            Type lastArgType = primArgTypes[singleArgs];
1126:                            if (lastArgType instanceof  ArrayType) {
1127:                                Type elType = ((ArrayType) lastArgType)
1128:                                        .getComponentType();
1129:                                boolean mustConvert = !"java.lang.Object"
1130:                                        .equals(elType.getName());
1131:                                if (singleArgs == 0 && !mustConvert)
1132:                                    code.emitLoad(code.getArg(2)); // load args array.
1133:                                else {
1134:                                    code.pushScope();
1135:                                    if (counter == null) {
1136:                                        counter = code.addLocal(Type.int_type);
1137:                                        code.emitLoad(code.getArg(2));
1138:                                        code.emitArrayLength();
1139:                                        if (singleArgs != 0) {
1140:                                            code.emitPushInt(singleArgs);
1141:                                            code.emitSub(Type.int_type);
1142:                                        }
1143:                                        code.emitStore(counter);
1144:                                    }
1145:                                    code.emitLoad(counter);
1146:                                    code.emitNewArray(elType);
1147:                                    Label testLabel = new Label(code);
1148:                                    code.emitGoto(testLabel);
1149:                                    Label loopTopLabel = new Label(code);
1150:                                    loopTopLabel.define(code);
1151:
1152:                                    code.emitDup(1); // new array
1153:                                    code.emitLoad(counter);
1154:                                    code.emitLoad(code.getArg(2));
1155:                                    code.emitLoad(counter);
1156:                                    if (singleArgs != 0) {
1157:                                        code.emitPushInt(singleArgs);
1158:                                        code.emitAdd(Type.int_type);
1159:                                    }
1160:                                    code.emitArrayLoad(Type.pointer_type);
1161:                                    if (mustConvert) {
1162:                                        CheckedTarget.emitCheckedCoerce(this ,
1163:                                                source, source.getName(), -1,
1164:                                                elType);
1165:                                    }
1166:                                    code.emitArrayStore(elType);
1167:                                    testLabel.define(code);
1168:                                    code.emitInc(counter, (short) (-1));
1169:                                    code.emitLoad(counter);
1170:                                    code.emitGotoIfIntGeZero(loopTopLabel);
1171:                                    code.popScope();
1172:                                }
1173:                            } else if ("gnu.lists.LList".equals(lastArgType
1174:                                    .getName())) {
1175:                                code.emitLoad(code.getArg(2)); // load args array.
1176:                                code.emitPushInt(singleArgs);
1177:                                code
1178:                                        .emitInvokeStatic(Compilation.makeListMethod);
1179:                            } else if (lastArgType == typeCallContext)
1180:                                code.emitLoad(code.getArg(2));
1181:                            else
1182:                                throw new RuntimeException(
1183:                                        "unsupported #!rest type:"
1184:                                                + lastArgType);
1185:                        }
1186:
1187:                        code.emitInvoke(primMethod);
1188:                        while (--pendingIfEnds >= 0)
1189:                            code.emitFi();
1190:                        if (!usingTailCalls)
1191:                            Target.pushObject.compileFromStack(this , source
1192:                                    .getReturnType());
1193:                        code.emitReturn();
1194:                    }
1195:                    if (false && needThisApply) {
1196:                        aswitch.addDefault(code);
1197:                        if (usingTailCalls) {
1198:                            code.emitLoad(code.getArg(1));
1199:                            Method errMethod = typeCpsMethodProc
1200:                                    .getDeclaredMethod("applyError", 0);
1201:                            code.emitInvokeVirtual(errMethod);
1202:                        } else {
1203:                            int nargs = i > 4 ? 2 : i + 1;
1204:                            nargs++;
1205:                            for (int k = generateApplyMethodContainer ? 1 : 0; k < nargs; k++)
1206:                                code.emitLoad(code.getArg(k));
1207:                            if (generateApplyMethodContainer) {
1208:                                mname = mname + "Default";
1209:                                Method defMethod = typeApplyMethodProc
1210:                                        .getDeclaredMethod(mname, applyArgs);
1211:                                code.emitInvokeStatic(defMethod);
1212:                            } else {
1213:                                code.emitInvokeSpecial(curClass.getSuperclass()
1214:                                        .getDeclaredMethod(mname, applyArgs));
1215:                            }
1216:                        }
1217:                        code.emitReturn();
1218:                        aswitch.finish(code);
1219:                    } else if (needThisApply) {
1220:                        aswitch.finish(code);
1221:                    }
1222:                }
1223:                lexp.applyMethods = null;
1224:                method = save_method;
1225:            }
1226:
1227:            private Method startClassInit() {
1228:                method = curClass.addMethod("<clinit>", apply0args,
1229:                        Type.void_type, Access.PUBLIC | Access.STATIC);
1230:                method.init_param_slots();
1231:
1232:                CodeAttr code = getCode();
1233:
1234:                if (generateMain || generateApplet || generateServlet) {
1235:                    ClassType interpreterType = (ClassType) Type
1236:                            .make(getInterpreter().getClass());
1237:                    Method registerMethod = interpreterType.getDeclaredMethod(
1238:                            "registerEnvironment", 0);
1239:                    if (registerMethod != null)
1240:                        code.emitInvokeStatic(registerMethod);
1241:                }
1242:                return method;
1243:            }
1244:
1245:            /** Compiles a module to a class. */
1246:            public final ClassType addClass(ModuleExp module) {
1247:                String name;
1248:                ClassType new_class = module.type;
1249:                if (new_class == typeProcedure)
1250:                    new_class = allocClass(module);
1251:                curClass = new_class;
1252:
1253:                String filename = module.getFile();
1254:                module.type = new_class;
1255:                if (filename != null)
1256:                    new_class.setSourceFile(filename);
1257:
1258:                int arg_count;
1259:                char arg_letter;
1260:                LambdaExp saveLambda = curLambda;
1261:                curLambda = module;
1262:                Type[] arg_types;
1263:                if (module.isHandlingTailCalls() || usingCPStyle()) {
1264:                    arg_count = 1;
1265:                    arg_letter = '?';
1266:                    arg_types = new Type[1];
1267:                    arg_types[0] = typeCallContext;
1268:                } else if (module.min_args != module.max_args
1269:                        || module.min_args > 4
1270:                        || (fewerClasses && curClass == mainClass)) {
1271:                    arg_count = 1;
1272:                    arg_letter = 'N';
1273:                    arg_types = new Type[1];
1274:                    arg_types[0] = new ArrayType(typeObject);
1275:                } else {
1276:                    arg_count = module.min_args;
1277:                    arg_letter = Character.forDigit(arg_count, 10);
1278:                    arg_types = new Type[arg_count];
1279:                    for (int i = arg_count; --i >= 0;)
1280:                        arg_types[i] = typeObject;
1281:                }
1282:
1283:                CodeAttr code;
1284:                if (arg_letter == 'N' || arg_letter == '?') {
1285:                    method = curClass.addMethod("numArgs", apply0args,
1286:                            Type.int_type, Access.PUBLIC);
1287:                    method.init_param_slots();
1288:                    code = getCode();
1289:                    code.emitPushInt(module.min_args | (module.max_args << 12));
1290:                    code.emitReturn();
1291:                }
1292:
1293:                Expression body = module.body;
1294:                Variable heapFrame = module.heapFrame;
1295:
1296:                Method apply_method;
1297:                boolean staticModule = false;
1298:                Label classInitLabel = null;
1299:                Label classBodyLabel = null;
1300:
1301:                if (usingCPStyle()) {
1302:                    apply_method = curClass.addMethod("step", arg_types,
1303:                            Type.void_type, Access.PUBLIC | Access.FINAL);
1304:                } else if (module.isHandlingTailCalls()) {
1305:                    apply_method = curClass.addMethod("apply", arg_types,
1306:                            Type.void_type, Access.PUBLIC | Access.FINAL);
1307:                } else {
1308:                    staticModule = true;
1309:                    generateConstructor(module);
1310:                    instanceField = curClass.addField("$instance", curClass,
1311:                            Access.STATIC | Access.FINAL);
1312:                    apply_method = startClassInit();
1313:                    code = getCode();
1314:                    code.emitNew(curClass);
1315:                    code.emitDup(curClass);
1316:                    code.emitInvokeSpecial(curClass.constructor);
1317:                    code.emitPutStatic(instanceField);
1318:
1319:                    classInitLabel = new Label(code);
1320:                    classBodyLabel = new Label(code);
1321:                    code.emitGoto(classInitLabel);
1322:                    classBodyLabel.define(code);
1323:                }
1324:                method = apply_method;
1325:
1326:                // For each parameter, assign it to its proper slot.
1327:                // If a parameter !isSimple(), we cannot assign it to a local slot,
1328:                // so instead create an artificial Variable for the incoming argument.
1329:                // Below, we assign the value to the slot.
1330:                method.initCode();
1331:                code = getCode();
1332:                // if (usingCPStyle())   code.addParamLocals();
1333:
1334:                this Decl = method.getStaticFlag() ? null : module
1335:                        .declareThis(new_class);
1336:                module.closureEnv = module.this Variable;
1337:                module.heapFrame = module.this Variable;
1338:                module.allocChildClasses(this );
1339:
1340:                if (module.isHandlingTailCalls() || usingCPStyle()) {
1341:                    callStackContext = new Variable("$ctx", typeCallContext);
1342:                    Scope scope = module.scope;
1343:                    scope.addVariableAfter(this Decl, callStackContext);
1344:                    callStackContext.setParameter(true);
1345:                    callStackContext.setArtificial(true);
1346:                }
1347:
1348:                int line = module.getLine();
1349:                if (line > 0)
1350:                    code.putLineNumber(module.getFile(), line);
1351:
1352:                /*
1353:                if (arg_letter == 'N')
1354:                  {
1355:                argsArray.reserveLocal(1, code); // FIXME
1356:
1357:                if (true) // If generating code to check number of arguments
1358:                  {
1359:                    code.emitPushThis();
1360:                    code.emitLoad(argsArray);
1361:                    code.emitArrayLength();
1362:                    code.emitInvokeStatic(checkArgCountMethod);
1363:                  }
1364:                  }
1365:                 */
1366:
1367:                module.allocParameters(this );
1368:                module.enterFunction(this );
1369:                if (usingCPStyle()) {
1370:                    //code.emitLoad(code.getArg(1));
1371:                    code.emitLoad(callStackContext);
1372:                    code.emitGetField(pcCallContextField);
1373:                    fswitch = new SwitchState(code);
1374:                    Label l = new Label(code);
1375:                    l.define(code);
1376:                    fswitch.addCase(0, l, code);
1377:                }
1378:
1379:                try {
1380:                    module.compileBody(this );
1381:                } catch (Exception ex) {
1382:                    error('f', "internal error while compiling - caught: " + ex);
1383:                    ex.printStackTrace(System.err);
1384:                    System.exit(-1);
1385:                }
1386:                module.compileEnd(this );
1387:
1388:                if (Compilation.fewerClasses) // FIXME
1389:                    method.popScope(); // Undoes pushScope in method.initCode.
1390:
1391:                module.heapFrame = heapFrame; // Restore heapFrame.
1392:                module.compileChildMethods(this );
1393:                if (usingCPStyle() || (fewerClasses && curClass == mainClass)) {
1394:                    code = getCode();
1395:                    fswitch.finish(code);
1396:                }
1397:
1398:                if (Compilation.usingTailCalls && !staticModule)
1399:                    generateConstructor(module);
1400:
1401:                if (curClass == mainClass // && ! immediate
1402:                        && (staticModule || clinitChain != null
1403:                                || literalsChain != null || generateMain
1404:                                || generateApplet || generateServlet)) {
1405:                    Method save_method = method;
1406:
1407:                    if (staticModule)
1408:                        classInitLabel.define(code);
1409:                    else
1410:                        startClassInit();
1411:                    code = getCode();
1412:                    if (clinitChain != null) {
1413:                        Label lab0 = new Label(code);
1414:                        Label lab1 = new Label(code);
1415:                        Label lab2 = new Label(code);
1416:                        // These gotos are losing.  Should instead do a pre-pass (using
1417:                        // an ExpWalker) before compilation that collects all needed
1418:                        // constants.  Then we generate code to init the literals *first*,
1419:                        // before compiling anything else.  FIXME.
1420:                        code.emitGoto(lab1);
1421:                        lab0.define(code);
1422:                        dumpInitializers(clinitChain);
1423:                        code.emitGoto(lab2);
1424:                        lab1.define(code);
1425:                        Literal.emit(this );
1426:                        code.emitGoto(lab0);
1427:                        lab2.define(code);
1428:                    } else
1429:                        Literal.emit(this );
1430:
1431:                    if (staticModule)
1432:                        code.emitGoto(classBodyLabel);
1433:                    else
1434:                        code.emitReturn();
1435:                    method = save_method;
1436:                }
1437:
1438:                curLambda = saveLambda;
1439:
1440:                if (generateMain && curClass == mainClass) {
1441:                    Type[] args = { new ArrayType(javaStringType) };
1442:                    method = curClass.addMethod("main", Access.PUBLIC
1443:                            | Access.STATIC, args, Type.void_type);
1444:
1445:                    method.init_param_slots();
1446:                    code = getCode();
1447:                    code.emitNew(curClass);
1448:                    code.emitDup(curClass);
1449:                    code.emitInvokeSpecial(curClass.constructor);
1450:                    code.emitLoad(code.getArg(0));
1451:                    Method moduleMain = typeModuleBody.addMethod("runAsMain",
1452:                            Access.PUBLIC, args, Type.void_type);
1453:                    code.emitInvokeVirtual(moduleMain);
1454:                    code.emitReturn();
1455:                }
1456:
1457:                return new_class;
1458:            }
1459:
1460:            public static boolean usingCPStyle() {
1461:                return usingCPStyle;
1462:            }
1463:
1464:            public boolean usingTailCalls() {
1465:                return usingTailCalls;
1466:            }
1467:
1468:            int localFieldIndex;
1469:
1470:            public Field allocLocalField(Type type, String name) {
1471:                if (name == null)
1472:                    name = "tmp_" + (++localFieldIndex);
1473:                Field field = curClass.addField(name, type, 0);
1474:                return field;
1475:            }
1476:
1477:            /** Generate code to push the current CallContext on the JVM stack.
1478:             * Assumes that callStackContext has been set for the current function.
1479:             * (Later we should call a routine to get it via the current thread.) */
1480:            public final void loadCallContext() {
1481:                getCode().emitLoad(callStackContext);
1482:            }
1483:
1484:            public void freeLocalField(Field field) {
1485:                // FIXME
1486:            }
1487:
1488:            String filename;
1489:            int position;
1490:
1491:            public void error(char severity, String message) {
1492:                error(severity, filename, position >> 12, position
1493:                        & ((1 << 12) - 1), message);
1494:            }
1495:
1496:            public void error(char severity, String filename, int line,
1497:                    int column, String message) {
1498:                error(new gnu.text.SourceError(severity, filename, line,
1499:                        column, message));
1500:            }
1501:
1502:            public void error(gnu.text.SourceError err) {
1503:                // FIXME - use SourceMessages framework!
1504:                System.err.println(err);
1505:            }
1506:
1507:            /****************************************************************
1508:             * Compilation of Packages
1509:             ****************************************************************/
1510:
1511:            public Compilation() {
1512:                this .immediate = false;
1513:            }
1514:
1515:            Package currentPackage;
1516:
1517:            public void compile(Package root) {
1518:                for (Package pkg = root; pkg != null; pkg = pkg.next)
1519:                    allocate(pkg);
1520:
1521:                for (Package pkg = root; pkg != null; pkg = pkg.next)
1522:                    generate(pkg);
1523:            }
1524:
1525:            public void allocate(Package pkg) {
1526:                currentPackage = pkg;
1527:
1528:                classPrefix = pkg.name == null ? "" : pkg.name + ".";
1529:
1530:                // Do various code re-writes and optimization.
1531:                //PushApply.pushApply(pkg);
1532:                //InlineCalls.inlineCalls(pkg);
1533:                ChainLambdas.chainLambdas(pkg, this );
1534:                FindTailCalls.findTailCalls(pkg);
1535:                FindCapturedVars.findCapturedVars(pkg);
1536:
1537:                for (LambdaExp c = pkg.firstClass; c != null; c = c.nextSibling)
1538:                    ((ClassExp) c).declareParts(this );
1539:            }
1540:
1541:            /** Create a new Compilation environment.
1542:             * @param pkg the package to compile
1543:             */
1544:            public void generate(Package pkg) {
1545:                currentPackage = pkg;
1546:
1547:                source_filename = pkg.directory.getPath();
1548:                classPrefix = pkg.name + ".";
1549:
1550:                try {
1551:                    compileAll(pkg);
1552:                } catch (RuntimeException ex) {
1553:                    // Rethrow the error, since it is better handled at the Nice level.
1554:                    if (true)
1555:                        throw ex;
1556:
1557:                    // Try to produce a localized error message.
1558:                    error('f', "Internal compiler exception: " + ex);
1559:                    throw ex;
1560:                }
1561:            }
1562:
1563:            /** Compiles a module to a class. */
1564:            private final void compileAll(Package pkg) {
1565:                for (LambdaExp c = pkg.firstClass; c != null; c = c.nextSibling) {
1566:                    literalTable = new Hashtable(100);
1567:                    c.literalTable = literalTable;
1568:                    topLambda = c;
1569:                    // If the class has outer set, use that as the toplevel class.
1570:                    if (c.outer != null)
1571:                        topLambda = (LambdaExp) c.outer;
1572:                    topClass = (ClassType) topLambda.getType();
1573:                    c.compileChildMethods(this );
1574:                }
1575:
1576:                for (LambdaExp c = pkg.firstClass; c != null; c = c.nextSibling) {
1577:                    topLambda = c;
1578:                    // If the class has outer set, use that as the toplevel class.
1579:                    if (c.outer != null)
1580:                        topLambda = (LambdaExp) c.outer;
1581:                    literalTable = c.literalTable;
1582:                    topClass = (ClassType) topLambda.getType();
1583:
1584:                    curClass = topClass;
1585:                    c.generateClassInit(this );
1586:                    generateApplyMethods(c);
1587:                }
1588:            }
1589:
1590:            public LambdaExp topLambda;
1591:            ClassType topClass;
1592:
1593:            public void addClass(ClassType new_class) {
1594:                currentPackage.addClass(new_class);
1595:                new_class.access_flags |= Access.PUBLIC;
1596:            }
1597:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.