Source Code Cross Referenced for LambdaExp.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.Vector;
0009:
0010:        /**
0011:         * Class used to implement Scheme lambda expressions.
0012:         * @author	Per Bothner
0013:         */
0014:
0015:        public class LambdaExp extends ScopeExp {
0016:            public String name;
0017:            public Expression body;
0018:            public int min_args;
0019:            // Maximum number of actual arguments;  -1 if variable.
0020:            public int max_args;
0021:
0022:            /** Set of visible top-level LambdaExps that need apply methods. */
0023:            Vector applyMethods;
0024:
0025:            //  public int plainArgs;
0026:            Variable argsArray;
0027:            // First argument that goes into argsArray.
0028:            private Declaration firstArgsArrayArg;
0029:
0030:            public Keyword[] keywords;
0031:            public Expression[] defaultArgs;
0032:
0033:            public java.util.Stack[] parameterCopies;
0034:
0035:            static int counter;
0036:            /** Unique id number, to ease print-outs and debugging. */
0037:            int id = ++counter;
0038:
0039:            /** A list of Declarations, chained using Declaration's nextCapturedVar.
0040:             * All the Declarations are allocated in the current heapFrame. */
0041:            Declaration capturedVars;
0042:
0043:            /** A local variable that points to the heap-allocated part of the frame.
0044:             * Each captured variable is a field in the heapFrame.  A procedure has
0045:             * a heapFrame iff it has a parameter or local variable that is
0046:             * referenced ("captured") by a non-inline inferior procedure.
0047:             * (I.e there is a least one non-inline procedure that encloses the
0048:             * reference but not the definition.)  Note that an inline procedure may
0049:             * have a heapFrame if it encloses a non-inline procedure.  This is
0050:             * necessary because we represent loops as tail-recursive inline procedures.
0051:             */
0052:            Variable heapFrame;
0053:
0054:            public LambdaExp firstChild;
0055:            public LambdaExp nextSibling;
0056:
0057:            /** A magic value to indicate there is no unique return continuation. */
0058:            final static ApplyExp unknownContinuation = new ApplyExp(
0059:                    (Expression) null, null);
0060:
0061:            /** The unique caller that calls this lambda.
0062:                The value is null, if no callers have been seen.
0063:                A value of unknownContinuation means there are multiple call sites.
0064:                Tail-recursive calls do not count as multiple call sites. (With a
0065:                little more analysis, we could also allow multiple non-self tail-calls
0066:                as long as they all are ultimately called from the same place.)
0067:                This is used to see if we can inline the function at its unique
0068:                call site. */
0069:            public ApplyExp returnContinuation;
0070:
0071:            public void forceGeneration() {
0072:                returnContinuation = unknownContinuation;
0073:            }
0074:
0075:            /** If non-null, a Declaration whose value is (only) this LambdaExp. */
0076:            public Declaration nameDecl;
0077:
0078:            /** If non-null, this is a Field that is used for implementing lexical closures.
0079:             * If getName() is "closureEnv", it is our parent's heapFrame,
0080:             * which is an instance of one of our siblings.
0081:             * (Otherwise, we use "this" as the implicit "closureEnv" field.) */
0082:            public Field closureEnvField;
0083:
0084:            /** Field in heapFrame.getType() that contains the static link.
0085:             * It is used by child functions to get to outer environments.
0086:             * Its value is this function's closureEnv value. */
0087:            public Field staticLinkField;
0088:
0089:            /** A variable that points to the closure environment passed in.
0090:             * It can be any one of:
0091:             * null, if no closure environment is needed;
0092:             * this, if this object is its parent's heapFrame;
0093:             * a local variable initialized from this.closureEnv;
0094:             * a parameter (only if !getCanRead()); or
0095:             * a copy of our caller's closureEnv or heapFrame (only if getInlineOnly()).
0096:             * See declareClosureEnv and closureEnvField. */
0097:            Variable closureEnv;
0098:
0099:            static final int INLINE_ONLY = 1;
0100:            static final int CAN_READ = 2;
0101:            static final int CAN_CALL = 4;
0102:            static final int IMPORTS_LEX_VARS = 8;
0103:            static final int NEEDS_STATIC_LINK = 16;
0104:            /* Used (future) by FindTailCalls. */
0105:            static final int CANNOT_INLINE = 32;
0106:            static final int CLASS_METHOD = 64;
0107:            static final int METHODS_COMPILED = 128;
0108:            static final int NO_FIELD = 256;
0109:            static final int DEFAULT_CAPTURES_ARG = 512;
0110:            public static final int SEQUENCE_RESULT = 1024;
0111:            protected static final int NEXT_AVAIL_FLAG = 2048;
0112:
0113:            /** True iff this lambda is only "called" inline. */
0114:            public final boolean getInlineOnly() {
0115:                return (flags & INLINE_ONLY) != 0;
0116:            }
0117:
0118:            public final void setInlineOnly(boolean inlineOnly) {
0119:                setFlag(inlineOnly, INLINE_ONLY);
0120:            }
0121:
0122:            public final boolean getNeedsClosureEnv() {
0123:                return (flags & (NEEDS_STATIC_LINK | IMPORTS_LEX_VARS)) != 0;
0124:            }
0125:
0126:            /** True if a child lambda uses lexical variables from outside.
0127:                Hence, a child heapFrame needs a staticLink to outer frames. */
0128:            public final boolean getNeedsStaticLink() {
0129:                return (flags & NEEDS_STATIC_LINK) != 0;
0130:            }
0131:
0132:            public final void setNeedsStaticLink(boolean needsStaticLink) {
0133:                if (needsStaticLink)
0134:                    flags |= NEEDS_STATIC_LINK;
0135:                else
0136:                    flags &= ~NEEDS_STATIC_LINK;
0137:            }
0138:
0139:            /** True iff this lambda "captures" (uses) lexical variables from outside. */
0140:            public final boolean getImportsLexVars() {
0141:                return (flags & IMPORTS_LEX_VARS) != 0;
0142:            }
0143:
0144:            public final void setImportsLexVars(boolean importsLexVars) {
0145:                if (importsLexVars)
0146:                    flags |= IMPORTS_LEX_VARS;
0147:                else
0148:                    flags &= ~IMPORTS_LEX_VARS;
0149:            }
0150:
0151:            public final void setImportsLexVars() {
0152:                int old = flags;
0153:                flags |= IMPORTS_LEX_VARS;
0154:
0155:                // If this needs an environment (closure), then its callers do too.
0156:                if ((old & IMPORTS_LEX_VARS) == 0 && nameDecl != null)
0157:                    setCallersNeedStaticLink();
0158:            }
0159:
0160:            public final void setNeedsStaticLink() {
0161:                int old = flags;
0162:                flags |= NEEDS_STATIC_LINK;
0163:
0164:                // If this needs an environment (closure), then its callers do too.
0165:                if ((old & NEEDS_STATIC_LINK) == 0 && nameDecl != null)
0166:                    setCallersNeedStaticLink();
0167:            }
0168:
0169:            void setCallersNeedStaticLink() {
0170:                LambdaExp outer = outerLambda();
0171:                for (ApplyExp app = nameDecl.firstCall; app != null; app = app.nextCall) {
0172:                    LambdaExp caller = app.context;
0173:                    for (; caller != outer; caller = caller.outerLambda())
0174:                        caller.setNeedsStaticLink();
0175:                }
0176:            }
0177:
0178:            public final boolean getCanRead() {
0179:                return (flags & CAN_READ) != 0;
0180:            }
0181:
0182:            public final void setCanRead(boolean read) {
0183:                if (read)
0184:                    flags |= CAN_READ;
0185:                else
0186:                    flags &= ~CAN_READ;
0187:            }
0188:
0189:            public final boolean getCanCall() {
0190:                return (flags & CAN_CALL) != 0;
0191:            }
0192:
0193:            public final void setCanCall(boolean called) {
0194:                if (called)
0195:                    flags |= CAN_CALL;
0196:                else
0197:                    flags &= ~CAN_CALL;
0198:            }
0199:
0200:            /** True if this is a method in an ClassExp. */
0201:            public final boolean isClassMethod() {
0202:                return (flags & CLASS_METHOD) != 0;
0203:            }
0204:
0205:            public final void setClassMethod(boolean isMethod) {
0206:                if (isMethod)
0207:                    flags |= CLASS_METHOD;
0208:                else
0209:                    flags &= ~CLASS_METHOD;
0210:            }
0211:
0212:            /** The name to give to a dummy implicit function that surrounds a file. */
0213:            public static String fileFunctionName = "atFileLevel";
0214:
0215:            /** True iff this is the dummy top-level function of a module body. */
0216:            public final boolean isModuleBody() {
0217:                return this  instanceof  ModuleExp;
0218:            }
0219:
0220:            /** True if a class is generated for this procedure.
0221:             * We don't need a class if this is only called inline.
0222:             * We also don't need a class if all callers are known, and we can
0223:             * invoke a method for this procedure.
0224:             * However, the last optimization is not available when using tail calls.
0225:             */
0226:            public final boolean isClassGenerated() {
0227:                return (!getInlineOnly() && (isModuleBody() || this  instanceof  ClassExp));
0228:            }
0229:
0230:            public final boolean isHandlingTailCalls() {
0231:                return (isModuleBody() && !((ModuleExp) this ).isStatic())
0232:                        || (Compilation.usingTailCalls && !isModuleBody() && !isClassMethod());
0233:            }
0234:
0235:            public final boolean variable_args() {
0236:                return max_args < 0;
0237:            }
0238:
0239:            ClassType type = Compilation.typeProcedure;
0240:
0241:            /** Return the ClassType of the Procedure this is being compiled into. */
0242:            public ClassType getCompiledClassType(Compilation comp) {
0243:                if (type == Compilation.typeProcedure)
0244:                    throw new Error("internal error: getCompiledClassType");
0245:                return type;
0246:            }
0247:
0248:            public Type getType() {
0249:                return type;
0250:            }
0251:
0252:            public Type[] getArgTypes() {
0253:                Type[] res = new Type[max_args];
0254:                int n = 0;
0255:                for (Declaration d = firstDecl(); d != null; d = d.nextDecl())
0256:                    res[n++] = d.getType();
0257:                return res;
0258:            }
0259:
0260:            /** Number of argument variable actually passed by the caller.
0261:             * For functions that accept more than 4 argument, or take a variable number,
0262:             * this is 1, since in that all arguments are passed in a single array. */
0263:            public int incomingArgs() {
0264:                // The max_args > 0 is a hack to handle LambdaProecdure, which
0265:                // currently always uses a single array argument.
0266:                return min_args == max_args && max_args <= 4 && max_args > 0 ? max_args
0267:                        : 1;
0268:            }
0269:
0270:            /** If non-zero, the selector field of the ModuleMethod for this. */
0271:            int selectorValue;
0272:
0273:            int getSelectorValue(Compilation comp) {
0274:                if (selectorValue == 0)
0275:                    selectorValue = ++comp.maxSelectorValue;
0276:                return selectorValue;
0277:            }
0278:
0279:            /** Methods used to implement this functions.
0280:             * primMethods[0] is used if the argument count is min_args;
0281:             * primMethods[1] is used if the argument count is min_args+1;
0282:             * primMethods[primMethods.length-1] is used otherwise.
0283:             */
0284:            Method[] primMethods;
0285:
0286:            /** Select the method used given an argument count. */
0287:            public final Method getMethod(int argCount) {
0288:                if (primMethods == null
0289:                        || (max_args >= 0 && argCount > max_args))
0290:                    return null;
0291:                int index = argCount - min_args;
0292:                if (index < 0)
0293:                    return null; // Too few arguments.
0294:                int length = primMethods.length;
0295:                return primMethods[index < length ? index : length - 1];
0296:            }
0297:
0298:            /** Get the method that contains the actual body of the procedure.
0299:             * (The other methods are just stubs that call that method.) */
0300:            public Method getMainMethod() {
0301:                Method[] methods = primMethods;
0302:                return methods == null ? null : methods[methods.length - 1];
0303:            }
0304:
0305:            /** Return the parameter type of the "keyword/rest" parameters. */
0306:            public final Type restArgType() {
0307:                if (min_args == max_args)
0308:                    return null;
0309:                if (primMethods == null)
0310:                    throw new Error("internal error - restArgType");
0311:                Method[] methods = primMethods;
0312:                if (max_args >= 0 && methods.length > max_args - min_args)
0313:                    return null;
0314:                Type[] types = methods[methods.length - 1].getParameterTypes();
0315:                return types[types.length - 1];
0316:            }
0317:
0318:            public void setName(String name) {
0319:                this .name = name;
0320:            }
0321:
0322:            public String getName() {
0323:                return name;
0324:            }
0325:
0326:            public LambdaExp outerLambda() {
0327:                return outer == null ? null : outer.currentLambda();
0328:            }
0329:
0330:            /** Return the closest outer non-inlined LambdaExp. */
0331:
0332:            public LambdaExp outerLambdaNotInline() {
0333:                for (ScopeExp exp = this ; (exp = exp.outer) != null;) {
0334:                    if (exp instanceof  LambdaExp) {
0335:                        LambdaExp result = (LambdaExp) exp;
0336:                        if (!result.getInlineOnly())
0337:                            return result;
0338:                    }
0339:                }
0340:                return null;
0341:            }
0342:
0343:            /** Return the englobing ClassExp or null. */
0344:
0345:            public ClassExp outerClass() {
0346:                for (ScopeExp exp = this ; exp != null; exp = exp.outer) {
0347:                    if (exp instanceof  ClassExp)
0348:                        return (ClassExp) exp;
0349:                }
0350:                return null;
0351:            }
0352:
0353:            /** For an INLINE_ONLY function, return the function it gets inlined in. */
0354:            public LambdaExp getCaller() {
0355:                return returnContinuation.context;
0356:            }
0357:
0358:            Variable this Variable;
0359:
0360:            public Variable declareThis(ClassType clas) {
0361:                if (this Variable == null) {
0362:                    this Variable = new Variable("this");
0363:                    scope.addVariableAfter(null, this Variable);
0364:                    this Variable.setParameter(true);
0365:                    this Variable.setArtificial(true);
0366:                }
0367:                if (this Variable.getType() == null)
0368:                    this Variable.setType(clas);
0369:                return this Variable;
0370:            }
0371:
0372:            public Variable declareClosureEnv() {
0373:                if (closureEnv == null && getNeedsClosureEnv()) {
0374:                    LambdaExp parent = outerLambda();
0375:                    if (parent instanceof  ClassExp)
0376:                        parent = parent.outerLambda();
0377:                    Variable parentFrame = parent.heapFrame != null ? parent.heapFrame
0378:                            : parent.closureEnv;
0379:                    if (isClassMethod())
0380:                        /*closureEnv =*/declareThis(type);
0381:                    else if (parent.heapFrame == null
0382:                            && !parent.getNeedsStaticLink()
0383:                            && !(parent instanceof  ModuleExp))
0384:                        closureEnv = null;
0385:                    else if (!isClassGenerated() && !getInlineOnly()) {
0386:                        Method primMethod = getMainMethod();
0387:                        if (!primMethod.getStaticFlag())
0388:                            /*closureEnv =*/declareThis(primMethod
0389:                                    .getDeclaringClass());
0390:                        else {
0391:                            Type envType = primMethod.getParameterTypes()[0];
0392:                            closureEnv = new Variable("closureEnv", envType);
0393:                            scope.addVariableAfter(null, closureEnv);
0394:                            closureEnv.setArtificial(true);
0395:                            closureEnv.setParameter(true);
0396:                        }
0397:                    } else {
0398:                        LambdaExp caller = getInlineOnly() ? getCaller() : null;
0399:                        if (parent == caller)
0400:                            closureEnv = parentFrame;
0401:                        else if (caller != null
0402:                                && parent == caller.outerLambdaNotInline())
0403:                            closureEnv = caller.closureEnv;
0404:                        else {
0405:                            closureEnv = new Variable("closureEnv", parentFrame
0406:                                    .getType());
0407:                            scope.addVariable(closureEnv);
0408:                            closureEnv.setArtificial(true);
0409:                        }
0410:                    }
0411:                }
0412:                return closureEnv;
0413:            }
0414:
0415:            public LambdaExp() {
0416:            }
0417:
0418:            public LambdaExp(int args) {
0419:                min_args = args;
0420:                max_args = args;
0421:            }
0422:
0423:            public LambdaExp(Expression body) {
0424:                this .body = body;
0425:            }
0426:
0427:            /** Generate code to load heapFrame on the JVM stack. */
0428:            public void loadHeapFrame(Compilation comp) {
0429:                gnu.bytecode.CodeAttr code = comp.getCode();
0430:                LambdaExp curLambda = comp.curLambda;
0431:                while (curLambda != this  && curLambda.getInlineOnly())
0432:                    curLambda = curLambda.returnContinuation.context;
0433:                if (this  == curLambda) {
0434:                    if (this .heapFrame == null)
0435:                        code.emitPushThis();
0436:                    else
0437:                        code.emitLoad(this .heapFrame);
0438:                } else {
0439:                    if (curLambda.closureEnv == null)
0440:                        code.emitPushThis();
0441:                    else
0442:                        code.emitLoad(curLambda.closureEnv);
0443:                    LambdaExp parent = curLambda.outerLambda();
0444:                    while (parent != this ) {
0445:                        if (parent.staticLinkField != null)
0446:                            code.emitGetField(parent.staticLinkField);
0447:                        //curLambda = parent;
0448:                        parent = parent.outerLambda();
0449:                    }
0450:                }
0451:            }
0452:
0453:            /** Get the i'the formal parameter. */
0454:            Declaration getArg(int i) {
0455:                for (Declaration var = firstDecl();; var = var.nextDecl()) {
0456:                    if (var == null)
0457:                        throw new Error("internal error - getArg");
0458:                    if (i == 0)
0459:                        return var;
0460:                    --i;
0461:                }
0462:            }
0463:
0464:            public void compileEnd(Compilation comp) {
0465:                gnu.bytecode.CodeAttr code = comp.getCode();
0466:                if (!getInlineOnly()) {
0467:                    if (comp.method.reachableHere()
0468:                            /* Work-around since reachableHere is not computed properly:
0469:                               Only return if the method is void or if there is a value
0470:                               on the stack.
0471:                             */
0472:                            && (code.SP > 0 || comp.method.getReturnType()
0473:                                    .isVoid())
0474:                            && (!Compilation.usingTailCalls || isModuleBody()
0475:                                    || isClassMethod() || isHandlingTailCalls())) {
0476:                        // The line of a method is by convention it's last one,
0477:                        // specifically to make this feature possible.
0478:                        if (getLine() > 0)
0479:                            code.putLineNumber(getFile(), getLine());
0480:
0481:                        code.emitReturn();
0482:                    }
0483:                    code.popScope(); // Undoes enterScope in allocParameters
0484:                }
0485:                if (!Compilation.fewerClasses) // FIXME
0486:                    code.popScope(); // Undoes pushScope in method.initCode.
0487:
0488:                if (applyMethods != null && applyMethods.size() > 0) {
0489:                    Method save_method = comp.method;
0490:                    ClassType save_class = comp.curClass;
0491:                    comp.curClass = getHeapFrameType();
0492:                    comp.generateApplyMethods(this );
0493:                    comp.method = save_method;
0494:                    comp.curClass = save_class;
0495:                }
0496:                if (heapFrame != null)
0497:                    comp.generateConstructor((ClassType) heapFrame.getType(),
0498:                            this );
0499:            }
0500:
0501:            Field allocFieldFor(Compilation comp) {
0502:                if (nameDecl != null && nameDecl.field != null)
0503:                    return nameDecl.field;
0504:                String name = getName();
0505:                String fname = name == null ? "lambda" : Compilation
0506:                        .mangleName(name);
0507:                int fflags = Access.FINAL;
0508:                if (nameDecl != null && nameDecl.context instanceof  ModuleExp) {
0509:                    if (nameDecl.getFlag(Declaration.STATIC_SPECIFIED)) {
0510:                        fflags |= Access.STATIC;
0511:                        // If there is no instanceField, then the field gets initialized in
0512:                        // <init>, not <clinit>, which is bad for a "static final" field.
0513:                        if (!((ModuleExp) nameDecl.context).isStatic())
0514:                            fflags &= ~Access.FINAL;
0515:                    }
0516:                    if (!nameDecl.isPrivate())
0517:                        fflags |= Access.PUBLIC;
0518:                } else {
0519:                    fname = fname + "$Fn" + ++comp.localFieldIndex;
0520:                    if (!getNeedsClosureEnv())
0521:                        fflags = (fflags | Access.STATIC) & ~Access.FINAL;
0522:                }
0523:                ClassType frameType = getHeapLambda().getHeapFrameType();
0524:                Type rtype = Compilation.getMethodProcType(frameType);
0525:                Field field = frameType.addField(fname, rtype, fflags);
0526:                if (nameDecl != null)
0527:                    nameDecl.field = field;
0528:                return field;
0529:            }
0530:
0531:            final void addApplyMethod(LambdaExp lexp) {
0532:                if (applyMethods == null) {
0533:                    applyMethods = new Vector();
0534:                    if (heapFrame != null)
0535:                        ((ClassType) heapFrame.getType())
0536:                                .setSuper(Compilation.typeModuleBody);
0537:                    else
0538:                        type.setSuper(Compilation.typeModuleBody);
0539:                }
0540:                applyMethods.addElement(lexp);
0541:            }
0542:
0543:            public Field compileSetField(Compilation comp) {
0544:                if (comp.usingCPStyle())
0545:                    compile(comp, Type.pointer_type);
0546:                else {
0547:                    compileAsMethod(comp);
0548:                    getHeapLambda().addApplyMethod(this );
0549:                }
0550:
0551:                return (new ProcInitializer(this , comp)).field;
0552:            }
0553:
0554:            public void compile(Compilation comp, Target target) {
0555:                if (target instanceof  IgnoreTarget) {
0556:                    if (getInlineOnly())
0557:                        return;
0558:                    // else Causes failures.  Better to remove unneeded LambdaExp earlier. FIXME
0559:                }
0560:                Type rtype;
0561:                CodeAttr code = comp.getCode();
0562:
0563:                if (comp.usingCPStyle()) {
0564:                    //	Label func_start = new Label(code);
0565:                    Label func_end = new Label(code);
0566:                    LambdaExp saveLambda = comp.curLambda;
0567:                    comp.curLambda = this ;
0568:                    type = saveLambda.type;
0569:                    closureEnv = saveLambda.closureEnv;
0570:                    /*
0571:                    if (comp.usingCPStyle())
0572:                    {
0573:                    heapFrame = comp.thisDecl;
0574:                    for (Declaration var = firstDecl();
0575:                     var != null; var = var.nextDecl())
0576:                      var.assignField(comp);
0577:                    }
0578:                     */
0579:                    gnu.bytecode.SwitchState fswitch = comp.fswitch;
0580:                    int pc = comp.fswitch.getMaxValue() + 1;
0581:                    code.emitGoto(func_end);
0582:                    Type[] stackTypes = code.saveStackTypeState(true);
0583:
0584:                    fswitch.addCase(pc, code);
0585:                    /*
0586:                    code.emitPushThis();
0587:                    code.emitGetField(comp.argsCallContextField);
0588:                    code.emitStore(comp.argsArray);
0589:                     */
0590:                    allocParameters(comp);
0591:                    enterFunction(comp);
0592:
0593:                    compileBody(comp);
0594:                    compileEnd(comp);
0595:                    comp.curLambda = saveLambda;
0596:                    func_end.define(code);
0597:                    code.restoreStackTypeState(stackTypes);
0598:                    ClassType ctype = comp.curClass;
0599:                    rtype = ctype;
0600:                    /*
0601:                    code.emitNew(ctype);
0602:                    code.emitDup(ctype);
0603:                    code.emitInvokeSpecial(ctype.constructor);
0604:                    code.emitDup(ctype);
0605:                    code.emitPushInt(pc);
0606:                    code.emitPutField(comp.saved_pcCallFrameField);
0607:                    if (isHandlingTailCalls())
0608:                      {
0609:                        // Set name field.
0610:                        if (name != null)
0611:                          {
0612:                    	code.emitDup(ctype);
0613:                    	code.emitPushString(name);
0614:                    	code.emitInvokeVirtual(comp.setNameMethod);
0615:                          }
0616:                        // Set numArgs field.
0617:                        code.emitDup(ctype);
0618:                        code.emitPushInt(min_args | (max_args << 12));
0619:                        code.emitPutField(comp.numArgsCallFrameField);
0620:                        // Set static link field to this CallFrame.
0621:                        code.emitDup(ctype);
0622:                        code.emitPushThis();
0623:                        code.emitPutField(comp.callerCallFrameField);
0624:                      }
0625:                     */
0626:                } else {
0627:                    LambdaExp outer = outerLambda();
0628:                    rtype = comp.typeModuleMethod;
0629:                    if ((flags & NO_FIELD) != 0) {
0630:                        compileAsMethod(comp);
0631:                        ProcInitializer.emitLoadModuleMethod(this , comp);
0632:                    } else {
0633:                        Field field = compileSetField(comp);
0634:                        if (field.getStaticFlag())
0635:                            code.emitGetStatic(field);
0636:                        else {
0637:                            LambdaExp parent = comp.curLambda;
0638:                            Variable frame = parent.heapFrame != null ? parent.heapFrame
0639:                                    : parent.closureEnv;
0640:                            code.emitLoad(frame);
0641:                            code.emitGetField(field);
0642:                        }
0643:                    }
0644:                }
0645:                target.compileFromStack(comp, rtype);
0646:            }
0647:
0648:            public ClassType getHeapFrameType() {
0649:                if (this  instanceof  ModuleExp || this  instanceof  ClassExp)
0650:                    return (ClassType) getType();
0651:                else
0652:                    return (ClassType) heapFrame.getType();
0653:            }
0654:
0655:            public LambdaExp getHeapLambda() {
0656:                ScopeExp exp = outer;
0657:
0658:                if (getNeedsClosureEnv())
0659:                    for (;; exp = exp.outer) {
0660:                        if (exp == null)
0661:                            return null;
0662:                        if (exp instanceof  ModuleExp
0663:                                || (exp instanceof  ClassExp && ((ClassExp) exp).needsConstructor)
0664:                                || (exp instanceof  LambdaExp && ((LambdaExp) exp).heapFrame != null))
0665:                            return (LambdaExp) exp;
0666:                    }
0667:
0668:                // No need for heap, return the englobing class
0669:                ClassExp res = currentClass();
0670:
0671:                /*
0672:                  For user classes, needsConstructor is false, but their outer
0673:                  class (lambda) is the package class.
0674:                 */
0675:                if (res.needsConstructor)
0676:                    return res;
0677:                else
0678:                    return res.outerLambda();
0679:
0680:            }
0681:
0682:            void addMethodFor(Compilation comp, ObjectType closureEnvType) {
0683:                LambdaExp heapLambda = getHeapLambda();
0684:                ClassType ctype = heapLambda.getHeapFrameType();
0685:                addMethodFor(ctype, comp, closureEnvType);
0686:            }
0687:
0688:            void addMethodFor(ClassType ctype, Compilation comp,
0689:                    ObjectType closureEnvType) {
0690:                // generate_unique_name (new_class, child.getName());
0691:                String name = getName();
0692:                LambdaExp outer = outerLambda();
0693:
0694:                int key_args = keywords == null ? 0 : keywords.length;
0695:                int opt_args = defaultArgs == null ? 0 : defaultArgs.length
0696:                        - key_args;
0697:                int numStubs = ((flags & DEFAULT_CAPTURES_ARG) != 0)
0698:                        || Compilation.usingTailCalls ? 0 : opt_args;
0699:                boolean varArgs = max_args < 0
0700:                        || min_args + numStubs < max_args;
0701:                primMethods = new Method[numStubs + 1];
0702:
0703:                boolean isStatic;
0704:                boolean isInitMethod = false;
0705:                if (isClassMethod()) {
0706:                    if (outer instanceof  ClassExp) {
0707:                        ClassExp cl = (ClassExp) outer;
0708:                        isStatic = cl.isMakingClassPair()
0709:                                && closureEnvType != null;
0710:                        if (this  == cl.initMethod)
0711:                            isInitMethod = true;
0712:                    } else
0713:                        isStatic = false;
0714:                } else if (this Variable != null || closureEnvType == ctype)
0715:                    isStatic = false;
0716:                else if (nameDecl == null)
0717:                    isStatic = true;
0718:                else if (nameDecl.getFlag(Declaration.NONSTATIC_SPECIFIED))
0719:                    isStatic = false;
0720:                else if (nameDecl.getFlag(Declaration.STATIC_SPECIFIED))
0721:                    isStatic = true;
0722:                else if (nameDecl.context instanceof  ModuleExp) {
0723:                    ModuleExp mexp = (ModuleExp) nameDecl.context;
0724:                    isStatic = mexp.getSuperType() == null
0725:                            && mexp.getInterfaces() == null;
0726:                } else
0727:                    isStatic = true;
0728:
0729:                StringBuffer nameBuf = new StringBuffer(60);
0730:                if (!(outer.isModuleBody() || outer instanceof  ClassExp)
0731:                        || name == null) {
0732:                    nameBuf.append("lambda");
0733:                    nameBuf.append(+(++comp.method_counter));
0734:                }
0735:                if (name != null)
0736:                    nameBuf.append(Compilation.mangleName(name));
0737:                if (getFlag(SEQUENCE_RESULT))
0738:                    nameBuf.append("$C");
0739:                if (Compilation.usingTailCalls && !isInitMethod
0740:                        && !isClassMethod())
0741:                    nameBuf.append("$T");
0742:
0743:                int mflags = (isStatic ? Access.STATIC : 0);
0744:                if (nameDecl != null)
0745:                    if (nameDecl.isSpecifiedPrivate())
0746:                        mflags |= Access.PRIVATE;
0747:                    else if (!nameDecl.isPrivate())
0748:                        mflags |= Access.PUBLIC;
0749:
0750:                if (isInitMethod) {
0751:                    // Make it provide to prevent inherited $finit$ from overriding
0752:                    // the current one - and thus preventing its execution.
0753:                    mflags = (mflags & ~(Access.PUBLIC | Access.PROTECTED))
0754:                            + Access.PRIVATE;
0755:                }
0756:                if (ctype.isInterface())
0757:                    mflags |= Access.ABSTRACT;
0758:                if (!isStatic)
0759:                    if (isClassMethod())
0760:                        declareThis(ctype);
0761:                    else
0762:                        closureEnv = declareThis(ctype);
0763:
0764:                Type rtype = (getFlag(SEQUENCE_RESULT) || (Compilation.usingTailCalls && !isClassMethod())) ? Type.void_type
0765:                        : getReturnType().getImplementationType();
0766:                int extraArg = (closureEnvType != null && closureEnvType != ctype) ? 1
0767:                        : 0;
0768:                if (Compilation.usingTailCalls && !isInitMethod
0769:                        && !isClassMethod()) {
0770:                    Type[] atypes = new Type[1 + extraArg];
0771:                    if (extraArg > 0)
0772:                        atypes[0] = closureEnvType;
0773:                    atypes[extraArg] = Compilation.typeCallContext;
0774:                    primMethods[0] = ctype.addMethod(nameBuf.toString(),
0775:                            atypes, rtype, mflags);
0776:                    argsArray = new Variable("argsArray",
0777:                            Compilation.objArrayType);
0778:                    return;
0779:                }
0780:                for (int i = 0; i <= numStubs; i++) {
0781:                    int plainArgs = min_args + i;
0782:                    int numArgs = plainArgs;
0783:                    if (i == numStubs && varArgs)
0784:                        numArgs++;
0785:                    Type[] atypes = new Type[extraArg + numArgs];
0786:                    if (extraArg > 0)
0787:                        atypes[0] = closureEnvType;
0788:                    Declaration var = firstDecl();
0789:                    for (int itype = 0; itype < plainArgs; var = var.nextDecl())
0790:                        atypes[extraArg + itype++] = var.getType()
0791:                                .getImplementationType();
0792:                    if (plainArgs < numArgs) {
0793:                        nameBuf.append("$V");
0794:                        name = nameBuf.toString();
0795:                        Type lastType = var.getType();
0796:                        String lastTypeName = lastType.getName();
0797:                        if (key_args > 0
0798:                                || numStubs < opt_args
0799:                                || !("gnu.lists.LList".equals(lastTypeName) || "java.lang.Object[]"
0800:                                        .equals(lastTypeName))) {
0801:                            lastType = Compilation.objArrayType;
0802:                            argsArray = new Variable("argsArray",
0803:                                    Compilation.objArrayType);
0804:                        }
0805:                        firstArgsArrayArg = var;
0806:                        atypes[atypes.length - 1] = lastType;
0807:                    }
0808:
0809:                    boolean classSpecified = (outer instanceof  ClassExp || (outer instanceof  ModuleExp && (((ModuleExp) outer)
0810:                            .getFlag(ModuleExp.SUPERTYPE_SPECIFIED))));
0811:                    name = nameBuf.toString();
0812:                    {
0813:                        // If the base class or interfaces were not explicitly
0814:                        // specified, then any existing matching method (such as "run"
0815:                        // or "apply") is a conflict.  So rename the method.
0816:                        int renameCount = 0;
0817:                        int len = nameBuf.length();
0818:                        retry: for (;;) {
0819:                            for (ClassType t = ctype; t != null; t = t
0820:                                    .getSuperclass()) {
0821:                                if (t.getDeclaredMethod(name, atypes) != null) {
0822:                                    nameBuf.setLength(len);
0823:                                    nameBuf.append('$');
0824:                                    nameBuf.append(++renameCount);
0825:                                    name = nameBuf.toString();
0826:                                    continue retry;
0827:                                }
0828:                                if (classSpecified)
0829:                                    break;
0830:                            }
0831:                            break;
0832:                        }
0833:                    }
0834:                    primMethods[i] = ctype.addMethod(name, atypes, rtype,
0835:                            mflags);
0836:                }
0837:
0838:                addAttributes(getMainMethod());
0839:            }
0840:
0841:            // Can we merge this with allocParameters?
0842:            public void allocChildClasses(Compilation comp) {
0843:                if (this  instanceof  ModuleExp)
0844:                    ((ModuleExp) this ).allocFields(comp);
0845:                else {
0846:                    Method main = getMainMethod();
0847:
0848:                    Declaration decl = firstDecl();
0849:                    if (isHandlingTailCalls()) {
0850:                        firstArgsArrayArg = decl;
0851:                        if (!Compilation.usingTailCalls) // FIXME
0852:                            scope.addVariable(null, comp.typeCallContext,
0853:                                    "$ctx");
0854:                    }
0855:                    for (;;) {
0856:                        if (decl == firstArgsArrayArg && argsArray != null) {
0857:                            scope.addVariable(argsArray);
0858:                            argsArray.setParameter(true);
0859:                            argsArray.setArtificial(true);
0860:                        }
0861:                        if (decl == null)
0862:                            break;
0863:                        Variable var = decl.var;
0864:                        // i is the register to use for the current parameter
0865:                        if (decl.isSimple() && !decl.isIndirectBinding()) {
0866:                            // For a simple parameter not captured by an inferior lambda,
0867:                            // just allocate it in the incoming register.
0868:                            var = decl.allocateVariable(null);
0869:                            //var.allocateLocal(code);
0870:                        } else {
0871:                            // This variable was captured by an inner lambda.
0872:                            // Its home location is in the heapFrame.
0873:                            // Later, we copy it from its incoming register
0874:                            // to its home location heapFrame.  Here we just create and
0875:                            // assign a Variable for the incoming (register) value.
0876:                            String vname = Compilation.mangleName(
0877:                                    decl.getName()).intern();
0878:                            var = decl.var = scope.addVariable(null, decl
0879:                                    .getType(), vname);
0880:                            //scope.addVariableAfter(var, decl);
0881:                            var.setArtificial(true);
0882:                            var.setParameter(true);
0883:                            //var.allocateLocal(code);
0884:                        }
0885:                        decl = decl.nextDecl();
0886:                    }
0887:                }
0888:
0889:                declareClosureEnv();
0890:
0891:                if (comp.usingCPStyle() && comp.curClass == comp.mainClass)
0892:                    return;
0893:
0894:                allocFrame(comp);
0895:
0896:                for (LambdaExp child = firstChild; child != null; child = child.nextSibling) {
0897:                    if (child.isClassGenerated()) {
0898:                        if (child.min_args != child.max_args
0899:                                || child.min_args > 4
0900:                                || child.isHandlingTailCalls()) {
0901:                            child.argsArray = new Variable("argsArray",
0902:                                    comp.objArrayType);
0903:                            child.firstArgsArrayArg = child.firstDecl();
0904:                        }
0905:                    } else if (!child.getInlineOnly()) {
0906:                        boolean method_static;
0907:                        ObjectType closureEnvType;
0908:                        if (!child.getNeedsClosureEnv())
0909:                            closureEnvType = null;
0910:                        else if (this  instanceof  ClassExp)
0911:                            closureEnvType = getCompiledClassType(comp);
0912:                        else if ("$finit$".equals(getName()))
0913:                            closureEnvType = outerLambda()
0914:                                    .getCompiledClassType(comp);
0915:                        else {
0916:                            LambdaExp owner = this ;
0917:                            while (owner.heapFrame == null)
0918:                                owner = owner.outerLambda();
0919:                            closureEnvType = (ClassType) owner.heapFrame
0920:                                    .getType();
0921:                        }
0922:                        child.addMethodFor(comp, closureEnvType);
0923:                    }
0924:                }
0925:            }
0926:
0927:            public void allocFrame(Compilation comp) {
0928:                if (heapFrame != null) {
0929:                    ClassType frameType;
0930:                    if (this  instanceof  ModuleExp || this  instanceof  ClassExp)
0931:                        frameType = getCompiledClassType(comp);
0932:                    else {
0933:                        ClassExp outerClass = outerClass();
0934:                        if (outerClass != null) {
0935:                            String name = getName();
0936:                            if (name == null)
0937:                                name = "lambda";
0938:                            // At least for constructors ("<init>") we need to make sure
0939:                            // that the name is valid.
0940:                            name = Compilation.mangleName(name);
0941:                            // Use the outer class as a prefix name.
0942:                            name = outerClass.getName() + "$" + name;
0943:                            // Make sure the name is unique.
0944:                            name = comp.generateUniqueName(name);
0945:                            frameType = new ClassType(name);
0946:                            if (outerClass.getFile() != null)
0947:                                frameType.setSourceFile(outerClass.getFile());
0948:                        } else
0949:                            frameType = new ClassType(comp
0950:                                    .generateClassName("frame"));
0951:                        if (Compilation.usingTailCalls) // FIXME
0952:                            frameType.setSuper(Type.pointer_type);
0953:                        else
0954:                            frameType.setSuper(Compilation.typeModuleBody);
0955:                        comp.addClass(frameType);
0956:                    }
0957:                    heapFrame.setType(frameType);
0958:                }
0959:            }
0960:
0961:            void allocParameters(Compilation comp) {
0962:                CodeAttr code = comp.getCode();
0963:
0964:                int i = 0;
0965:                int j = 0;
0966:
0967:                if (isHandlingTailCalls() && !isModuleBody()
0968:                        && !comp.usingCPStyle()) {
0969:                    comp.callStackContext = new Variable("$ctx",
0970:                            comp.typeCallContext);
0971:                    // Variable thisVar = isStaic? = null : declareThis(comp.curClass);
0972:                    scope.addVariableAfter(this Variable, comp.callStackContext);
0973:                    comp.callStackContext.setParameter(true);
0974:                    comp.callStackContext.setArtificial(true);
0975:                }
0976:
0977:                code.locals.enterScope(scope);
0978:
0979:                if (argsArray != null && isHandlingTailCalls()) {
0980:                    code.emitLoad(comp.callStackContext);
0981:                    code.emitInvoke(comp.typeCallContext.getDeclaredMethod(
0982:                            "getArgs", 0));
0983:                    code.emitStore(argsArray);
0984:                }
0985:
0986:                for (Declaration decl = firstDecl(); decl != null;) {
0987:                    Variable var = decl.var;
0988:                    // If the only reason we are using an argsArray is because there
0989:                    // are more than 4 arguments, copy the arguments in local register.
0990:                    // Then forget about the args array.  We do this first, before
0991:                    // the label that tail-recursion branches back to.
0992:                    // This way, a self-tail-call knows where to leave the argumnents.
0993:                    if (argsArray != null && min_args == max_args
0994:                            && primMethods == null && !isHandlingTailCalls()) {
0995:                        code.emitLoad(argsArray);
0996:                        code.emitPushInt(j);
0997:                        code.emitArrayLoad(Type.pointer_type);
0998:                        decl.getType().emitCoerceFromObject(code);
0999:                        code.emitStore(decl.getVariable());
1000:                    }
1001:                    j++;
1002:                    i++;
1003:                    decl = decl.nextDecl();
1004:                }
1005:                if (heapFrame != null)
1006:                    heapFrame.allocateLocal(code);
1007:            }
1008:
1009:            static Method searchForKeywordMethod3;
1010:            static Method searchForKeywordMethod4;
1011:
1012:            /** Rembembers stuff to do in <init> of this class. */
1013:            Initializer initChain;
1014:            /** Rembembers stuff to do in <clinit> of this class. */
1015:            Initializer clinitChain;
1016:
1017:            void addInitializer(Initializer elem) {
1018:                elem.next = this .initChain;
1019:                this .initChain = elem;
1020:            }
1021:
1022:            void addClassInitializer(Initializer elem) {
1023:                elem.next = this .clinitChain;
1024:                this .clinitChain = elem;
1025:            }
1026:
1027:            private Field instanceField;
1028:
1029:            Field getInstanceField() {
1030:                if (instanceField == null) {
1031:                    instanceField = type.addField("$instance", type,
1032:                            Access.STATIC | Access.FINAL | Access.PUBLIC);
1033:                }
1034:                return instanceField;
1035:            }
1036:
1037:            /** Rembembers literals to initialize (in <clinit>). */
1038:            Literal literalsChain;
1039:            java.util.Hashtable literalTable;
1040:
1041:            void generateClassInit(Compilation comp) {
1042:                if (instanceField == null && clinitChain == null
1043:                        && literalsChain == null)
1044:                    return;
1045:
1046:                Method method = type.addMethod("<clinit>", Type.typeArray0,
1047:                        Type.void_type, Access.PUBLIC | Access.STATIC);
1048:                method.init_param_slots();
1049:
1050:                CodeAttr code = method.getCode();
1051:
1052:                // These gotos are losing.  Should instead do a pre-pass (using
1053:                // an ExpWalker) before compilation that collects all needed
1054:                // constants.  Then we generate code to init the literals *first*,
1055:                // before compiling anything else.  FIXME.
1056:                Label lab0 = new Label(code);
1057:                Label lab1 = new Label(code);
1058:                Label lab2 = new Label(code);
1059:
1060:                code.emitGoto(lab2);
1061:
1062:                lab0.define(code);
1063:
1064:                if (clinitChain != null) {
1065:                    Label lastClinit = new Label(code);
1066:                    code.emitGoto(lastClinit);
1067:                    Label previous = null;
1068:
1069:                    /* Dumping initializers can add new initializers,
1070:                       so we loop until none is added.
1071:                       The order of execution is reversed, the last ones being required
1072:                       by the first ones.
1073:                     */
1074:                    while (clinitChain != null) {
1075:                        Label current = new Label(code);
1076:                        current.define(code);
1077:
1078:                        Initializer chain = clinitChain;
1079:                        clinitChain = null;
1080:                        comp.dumpInitializers(chain, method);
1081:
1082:                        if (previous != null)
1083:                            code.emitGoto(previous);
1084:                        else
1085:                            method.getCode().emitReturn();
1086:
1087:                        if (clinitChain == null) {
1088:                            lastClinit.define(code);
1089:                            code.emitGoto(current);
1090:                        } else
1091:                            previous = current;
1092:                    }
1093:                } else
1094:                    method.getCode().emitReturn();
1095:
1096:                lab1.define(code);
1097:                comp.literalsChain = literalsChain;
1098:                // reset the litTable to force emission of the literals
1099:                // litTable should not be a field in compilation
1100:                comp.litTable = null;
1101:                comp.method = method;
1102:                Literal.emit(comp);
1103:                code.emitGoto(lab0);
1104:
1105:                lab2.define(code);
1106:                if (instanceField != null) {
1107:                    comp.generateConstructor(this );
1108:                    //ClassType type = getHeapFrameType(); // Is this more correct?
1109:                    if (type.constructor != null) {
1110:                        code.emitNew(type);
1111:                        code.emitDup(type);
1112:                        code.emitInvokeSpecial(type.constructor);
1113:                        code.emitPutStatic(instanceField);
1114:                    }
1115:                } else if (this  instanceof  ClassExp)
1116:                    // generateConstructor might have been called earlier, but we call it 
1117:                    // again because the super-class (gnu.expr.ModuleBody)
1118:                    // seems to be found late.
1119:                    comp.generateConstructor(this );
1120:                code.emitGoto(lab1);
1121:            }
1122:
1123:            void enterFunction(Compilation comp) {
1124:                CodeAttr code = comp.getCode();
1125:
1126:                // Tail-calls loop back to here!
1127:                scope.setStartPC(code.getPC());
1128:
1129:                if (closureEnv != null && !closureEnv.isParameter()
1130:                        && !comp.usingCPStyle()) {
1131:                    if (getInlineOnly())
1132:                        outerLambda().loadHeapFrame(comp);
1133:                    else {
1134:                        code.emitPushThis();
1135:                        Field field = closureEnvField;
1136:                        if (field == null)
1137:                            field = outerLambda().closureEnvField;
1138:                        code.emitGetField(field);
1139:                    }
1140:                    code.emitStore(closureEnv);
1141:                }
1142:                if (heapFrame != null && !comp.usingCPStyle()) {
1143:                    ClassType frameType = (ClassType) heapFrame.getType();
1144:                    for (Declaration decl = capturedVars; decl != null; decl = decl.nextCapturedVar) {
1145:                        if (decl.field != null)
1146:                            continue;
1147:                        String dname = comp.mangleName(decl.getName());
1148:                        String mname = dname;
1149:                        // Check for existing field with same name.
1150:                        for (int i = 0;;) {
1151:                            Field fld = frameType.getField(mname);
1152:                            if (fld == null)
1153:                                break;
1154:                            mname = dname + '_' + ++i;
1155:                        }
1156:                        Type dtype = decl.getType();
1157:                        decl.field = frameType.addField(mname, decl.getType());
1158:                    }
1159:                    if (closureEnv != null && heapFrame != null)
1160:                        staticLinkField = frameType.addField("staticLink",
1161:                                closureEnv.getType());
1162:                    if (!(this  instanceof  ModuleExp)
1163:                            && !(this  instanceof  ClassExp)) {
1164:                        code.emitNew(frameType);
1165:                        code.emitDup(frameType);
1166:                        Method constructor = comp.getConstructor(frameType,
1167:                                this );
1168:                        code.emitInvokeSpecial(constructor);
1169:
1170:                        // In a constructor, the closure (this) is not valid until the
1171:                        // end, so it shouldn't be used (presumably it is not used
1172:                        // anyway).
1173:                        // There might be a deeper change that would make this test
1174:                        // unnecessary.
1175:                        if (staticLinkField != null
1176:                                && !(this  instanceof  ConstructorExp)) {
1177:                            code.emitDup(heapFrame.getType());
1178:                            code.emitLoad(closureEnv);
1179:                            code.emitPutField(staticLinkField);
1180:                        }
1181:                        code.emitStore(heapFrame);
1182:                    }
1183:                }
1184:
1185:                Variable argsArray = this .argsArray;
1186:                if (min_args == max_args && !comp.fewerClasses
1187:                        && primMethods == null && !isHandlingTailCalls())
1188:                    argsArray = null;
1189:
1190:                // For each non-artificial parameter, copy it from its incoming
1191:                // location (a local variable register, or the argsArray) into
1192:                // its home location, if they are different.
1193:                int i = 0;
1194:                int opt_i = 0;
1195:                int key_i = 0;
1196:                int key_args = keywords == null ? 0 : keywords.length;
1197:                int opt_args = defaultArgs == null ? 0 : defaultArgs.length
1198:                        - key_args;
1199:                if (this  instanceof  ModuleExp)
1200:                    return;
1201:                // If plainArgs>=0, it is the number of arguments *not* in argsArray.
1202:                int plainArgs = -1;
1203:                int defaultStart = 0;
1204:                Method mainMethod = getMainMethod();
1205:
1206:                for (Declaration param = firstDecl(); param != null; param = param
1207:                        .nextDecl()) {
1208:                    if (param == firstArgsArrayArg && argsArray != null) {
1209:                        if (primMethods != null && !Compilation.usingTailCalls) {
1210:                            plainArgs = i;
1211:                            defaultStart = plainArgs - min_args;
1212:                        } else {
1213:                            plainArgs = 0;
1214:                            defaultStart = 0;
1215:                        }
1216:                    }
1217:                    if (plainArgs >= 0 || !param.isSimple()
1218:                            || param.isIndirectBinding()) {
1219:                        Type paramType = param.getType();
1220:                        Type stackType = (mainMethod == null || plainArgs >= 0 ? Type.pointer_type
1221:                                : paramType);
1222:                        // If the parameter is captured by an inferior lambda,
1223:                        // then the incoming parameter needs to be copied into its
1224:                        // slot in the heapFrame.  Thus we emit an aaload instruction.
1225:                        // Unfortunately, it expects the new value *last*,
1226:                        // so first push the heapFrame array and the array index.
1227:                        if (!param.isSimple())
1228:                            param.loadOwningObject(comp);
1229:                        // This part of the code pushes the incoming argument.
1230:                        if (plainArgs < 0) {
1231:                            // Simple case:  Use Incoming register.
1232:                            code.emitLoad(param.getVariable());
1233:                        } else if (i < min_args) { // This is a required parameter, in argsArray[i].
1234:                            code.emitLoad(argsArray);
1235:                            code.emitPushInt(i);
1236:                            code.emitArrayLoad(Type.pointer_type);
1237:                        } else if (i < min_args + opt_args) { // An optional parameter
1238:                            code.emitPushInt(i - plainArgs);
1239:                            code.emitLoad(argsArray);
1240:                            code.emitArrayLength();
1241:                            code.emitIfIntLt();
1242:                            code.emitLoad(argsArray);
1243:                            code.emitPushInt(i - plainArgs);
1244:                            code.emitArrayLoad(Type.pointer_type);
1245:                            code.emitElse();
1246:                            defaultArgs[defaultStart + opt_i++].compile(comp,
1247:                                    paramType);
1248:                            code.emitFi();
1249:                        } else if (max_args < 0 && i == min_args + opt_args) {
1250:                            // This is the "rest" parameter (i.e. following a "."):
1251:                            // Convert argsArray[i .. ] to a list.
1252:                            code.emitLoad(argsArray);
1253:                            code.emitPushInt(i - plainArgs);
1254:                            code.emitInvokeStatic(Compilation.makeListMethod);
1255:                            stackType = comp.scmListType;
1256:                        } else { // Keyword argument.
1257:                            code.emitLoad(argsArray);
1258:                            code.emitPushInt(min_args + opt_args - plainArgs);
1259:                            comp.compileConstant(keywords[key_i++]);
1260:                            Expression defaultArg = defaultArgs[defaultStart
1261:                                    + opt_i++];
1262:                            // We can generate better code if the defaultArg expression
1263:                            // has no side effects.  For simplicity and safety, we just
1264:                            // special case literals, which handles most cases.
1265:                            if (defaultArg instanceof  QuoteExp) {
1266:                                if (searchForKeywordMethod4 == null) {
1267:                                    Type[] argts = new Type[4];
1268:                                    argts[0] = Compilation.objArrayType;
1269:                                    argts[1] = Type.int_type;
1270:                                    argts[2] = Type.pointer_type;
1271:                                    argts[3] = Type.pointer_type;
1272:                                    searchForKeywordMethod4 = Compilation.scmKeywordType
1273:                                            .addMethod("searchForKeyword",
1274:                                                    argts, Type.pointer_type,
1275:                                                    Access.PUBLIC
1276:                                                            | Access.STATIC);
1277:                                }
1278:                                defaultArg.compile(comp, paramType);
1279:                                code.emitInvokeStatic(searchForKeywordMethod4);
1280:                            } else {
1281:                                if (searchForKeywordMethod3 == null) {
1282:                                    Type[] argts = new Type[3];
1283:                                    argts[0] = Compilation.objArrayType;
1284:                                    argts[1] = Type.int_type;
1285:                                    argts[2] = Type.pointer_type;
1286:                                    searchForKeywordMethod3 = Compilation.scmKeywordType
1287:                                            .addMethod("searchForKeyword",
1288:                                                    argts, Type.pointer_type,
1289:                                                    Access.PUBLIC
1290:                                                            | Access.STATIC);
1291:                                }
1292:                                code.emitInvokeStatic(searchForKeywordMethod3);
1293:                                code.emitDup(1);
1294:                                comp.compileConstant(Special.dfault);
1295:                                code.emitIfEq();
1296:                                code.emitPop(1);
1297:                                defaultArg.compile(comp, paramType);
1298:                                code.emitFi();
1299:                            }
1300:                        }
1301:                        // Now finish copying the incoming argument into its
1302:                        // home location.
1303:                        if (paramType != stackType)
1304:                            CheckedTarget.emitCheckedCoerce(comp, this , i,
1305:                                    paramType);
1306:                        if (param.isIndirectBinding())
1307:                            param.pushIndirectBinding(comp);
1308:                        if (param.isSimple())
1309:                            code.emitStore(param.getVariable());
1310:                        else
1311:                            code.emitPutField(param.field);
1312:                    }
1313:                    i++;
1314:                }
1315:            }
1316:
1317:            void compileChildMethods(Compilation comp) {
1318:                for (LambdaExp child = firstChild; child != null;) {
1319:                    if (!child.getCanRead() && !child.getInlineOnly()
1320:                            && !child.isHandlingTailCalls()) {
1321:                        child.compileAsMethod(comp);
1322:                    }
1323:                    child = child.nextSibling;
1324:                }
1325:            }
1326:
1327:            void compileAsMethod(Compilation comp) {
1328:                if ((flags & METHODS_COMPILED) != 0)
1329:                    return;
1330:                flags |= METHODS_COMPILED;
1331:                Method save_method = comp.method;
1332:                LambdaExp save_lambda = comp.curLambda;
1333:                Variable saveStackContext = comp.callStackContext;
1334:                comp.curLambda = this ;
1335:
1336:                if (primMethods == null) {
1337:                    // This happens for lambdas that are not toplevel nor contained
1338:                    // in a toplevel lambda (eg: global variables values).
1339:                    outer = (ClassExp) comp.topLambda;
1340:                    addMethodFor(comp.topClass, comp, null);
1341:                    compileAsMethod(comp);
1342:                }
1343:
1344:                Method method = primMethods[0];
1345:                boolean isStatic = method.getStaticFlag();
1346:                int numStubs = primMethods.length - 1;
1347:                Type restArgType = restArgType();
1348:
1349:                int[] saveDeclFlags = null;
1350:                if (numStubs > 0) {
1351:                    saveDeclFlags = new int[min_args + numStubs];
1352:                    int k = 0;
1353:                    for (Declaration decl = firstDecl(); k < min_args
1354:                            + numStubs; decl = decl.nextDecl())
1355:                        saveDeclFlags[k++] = decl.flags;
1356:                }
1357:
1358:                for (int i = 0; i <= numStubs; i++) {
1359:                    comp.method = primMethods[i];
1360:                    if (i < numStubs) {
1361:                        comp.method.init_param_slots();
1362:                        CodeAttr code = comp.getCode();
1363:                        int toCall = i + 1;
1364:                        while (toCall < numStubs
1365:                                && defaultArgs[toCall] instanceof  QuoteExp)
1366:                            toCall++;
1367:                        int this Arg = isStatic ? 0 : 1;
1368:                        boolean varArgs = toCall == numStubs
1369:                                && restArgType != null;
1370:                        Declaration decl;
1371:                        Variable var = code.getArg(0);
1372:                        if (!isStatic) {
1373:                            code.emitPushThis();
1374:                            if (getNeedsClosureEnv())
1375:                                closureEnv = var;
1376:                            var = code.getArg(1);
1377:                        }
1378:                        decl = firstDecl();
1379:                        for (int j = 0; j < min_args + i; j++, decl = decl
1380:                                .nextDecl()) {
1381:                            decl.flags |= Declaration.IS_SIMPLE;
1382:                            decl.var = var;
1383:                            code.emitLoad(var);
1384:                            var = var.nextVar();
1385:                        }
1386:                        for (int j = i; j < toCall; j++, decl = decl.nextDecl()) {
1387:                            Target paramTarget = StackTarget.getInstance(decl
1388:                                    .getType());
1389:                            defaultArgs[j].compile(comp, paramTarget);
1390:                        }
1391:                        if (varArgs) {
1392:                            Expression arg;
1393:                            String lastTypeName = restArgType.getName();
1394:                            if ("gnu.lists.LList".equals(lastTypeName))
1395:                                arg = new QuoteExp(gnu.lists.LList.Empty);
1396:                            else if ("java.lang.Object[]".equals(lastTypeName))
1397:                                arg = new QuoteExp(Values.noArgs);
1398:                            else
1399:                                // FIXME
1400:                                throw new Error("unimplemented #!rest type");
1401:                            arg.compile(comp, restArgType);
1402:                        }
1403:                        if (isStatic)
1404:                            code.emitInvokeStatic(primMethods[toCall]);
1405:                        else
1406:                            code.emitInvokeVirtual(primMethods[toCall]);
1407:                        code.emitReturn();
1408:                        closureEnv = null;
1409:                    } else {
1410:                        if (saveDeclFlags != null) {
1411:                            int k = 0;
1412:                            for (Declaration decl = firstDecl(); k < min_args
1413:                                    + numStubs; decl = decl.nextDecl()) {
1414:                                decl.flags = saveDeclFlags[k++];
1415:                                decl.var = null;
1416:                            }
1417:                        }
1418:                        if (comp.curClass.isInterface()
1419:                                && comp.method.isAbstract()) {
1420:                            // Interface method. Skip code generation.
1421:                        } else {
1422:                            comp.method.initCode();
1423:                            allocChildClasses(comp);
1424:                            allocParameters(comp);
1425:                            enterFunction(comp);
1426:
1427:                            compileBody(comp);
1428:                            compileEnd(comp);
1429:                        }
1430:                    }
1431:                }
1432:
1433:                compileChildMethods(comp);
1434:                comp.method = save_method;
1435:                comp.curLambda = save_lambda;
1436:                comp.callStackContext = saveStackContext;
1437:            }
1438:
1439:            public void compileBody(Compilation comp) {
1440:                Target target;
1441:                if (isHandlingTailCalls()) {
1442:                    CodeAttr code = comp.getCode();
1443:                    Variable ctxVar = comp.callStackContext;
1444:                    code.emitLoad(ctxVar);
1445:                    code.emitGetField(comp.typeCallContext
1446:                            .getDeclaredField("consumer"));
1447:                    Scope scope = code.getCurrentScope();
1448:                    Variable result = scope.addVariable(code,
1449:                            Compilation.typeConsumer, "$result");
1450:                    code.emitStore(result);
1451:                    target = new ConsumerTarget(result);
1452:                } else
1453:                    target = Target.pushValue(comp.method.getReturnType());
1454:                body.compileWithPosition(comp, target);
1455:            }
1456:
1457:            /** A cache if this has already been evaluated. */
1458:            Procedure this Value;
1459:
1460:            protected Expression walk(ExpWalker walker) {
1461:                return walker.walkLambdaExp(this );
1462:            }
1463:
1464:            protected void walkChildren(ExpWalker walker) {
1465:                walkChildrenOnly(walker);
1466:                walkProperties(walker);
1467:            }
1468:
1469:            protected final void walkChildrenOnly(ExpWalker walker) {
1470:                LambdaExp save = walker.currentLambda;
1471:                walker.currentLambda = this ;
1472:                try {
1473:                    walker.walkDefaultArgs(this );
1474:                    if (walker.exitValue == null && body != null)
1475:                        body = body.walk(walker);
1476:                } finally {
1477:                    walker.currentLambda = save;
1478:                }
1479:            }
1480:
1481:            protected final void walkProperties(ExpWalker walker) {
1482:                if (properties != null) {
1483:                    int len = properties.length;
1484:                    for (int i = 1; i < len; i += 2) {
1485:                        Object val = properties[i];
1486:                        if (val instanceof  Expression) {
1487:                            properties[i] = ((Expression) properties[i])
1488:                                    .walk(walker);
1489:                        }
1490:                    }
1491:                }
1492:            }
1493:
1494:            public void print(OutPort out) {
1495:                out.startLogicalBlock("(Lambda/", ")", 2);
1496:                if (name != null) {
1497:                    out.print(name);
1498:                    out.print('/');
1499:                }
1500:                out.print(id);
1501:                out.print('/');
1502:                out.writeSpaceFill();
1503:                printLineColumn(out);
1504:                out.print('(');
1505:                Special prevMode = null;
1506:                int i = 0;
1507:                int opt_i = 0;
1508:                int key_args = keywords == null ? 0 : keywords.length;
1509:                int opt_args = defaultArgs == null ? 0 : defaultArgs.length
1510:                        - key_args;
1511:                for (Declaration decl = firstDecl(); decl != null; decl = decl
1512:                        .nextDecl()) {
1513:                    Special mode;
1514:                    if (i < min_args)
1515:                        mode = null;
1516:                    else if (i < min_args + opt_args)
1517:                        mode = Special.optional;
1518:                    else if (max_args < 0 && i == min_args + opt_args)
1519:                        mode = Special.rest;
1520:                    else
1521:                        mode = Special.key;
1522:                    if (i > 0)
1523:                        out.writeSpaceFill();
1524:                    if (mode != prevMode) {
1525:                        out.print(mode);
1526:                        out.writeSpaceFill();
1527:                    }
1528:                    Expression defaultArg = null;
1529:                    if ((mode == Special.optional || mode == Special.key)
1530:                            && defaultArgs != null)
1531:                        defaultArg = defaultArgs[opt_i++];
1532:                    if (defaultArg != null)
1533:                        out.print('(');
1534:                    out.print(decl.getName());
1535:                    if (defaultArg != null && defaultArg != QuoteExp.falseExp) {
1536:                        out.print(' ');
1537:                        defaultArg.print(out);
1538:                        out.print(')');
1539:                    }
1540:                    i++;
1541:                    prevMode = mode;
1542:                }
1543:                out.print(')');
1544:                out.writeSpaceLinear();
1545:                if (body == null)
1546:                    out.print("<null body>");
1547:                else
1548:                    body.print(out);
1549:                out.endLogicalBlock(")");
1550:            }
1551:
1552:            protected final String getExpClassName() {
1553:                String cname = getClass().getName();
1554:                int index = cname.lastIndexOf('.');
1555:                if (index >= 0)
1556:                    cname = cname.substring(index + 1);
1557:                return cname;
1558:            }
1559:
1560:            public String toString() {
1561:                String str = getExpClassName() + ':' + name + '/' + id + '/';
1562:
1563:                int l = getLine();
1564:                if (l <= 0 && body != null)
1565:                    l = body.getLine();
1566:                if (l > 0)
1567:                    str = str + "l:" + l;
1568:
1569:                return str;
1570:            }
1571:
1572:            /** If non-null, a sequence of (key, value)-pairs.
1573:             * These will be used to call setProperty at run-time. */
1574:            Object[] properties;
1575:
1576:            public Object getProperty(Object key, Object defaultValue) {
1577:                if (properties != null) {
1578:                    for (int i = properties.length; (i -= 2) >= 0;) {
1579:                        if (properties[i] == key)
1580:                            return properties[i + 1];
1581:                    }
1582:                }
1583:                return defaultValue;
1584:            }
1585:
1586:            public synchronized void setProperty(Object key, Object value) {
1587:                properties = Procedure.setProperty(properties, key, value);
1588:            }
1589:
1590:            /** If non-null, the type of values returned by this function.
1591:             * If null, the return type has not been set or calculated yet. */
1592:            protected Type returnType;
1593:
1594:            /** The return type of this function, i.e the type of its returned values. */
1595:            public final Type getReturnType() {
1596:                if (returnType == null) {
1597:                    returnType = Type.pointer_type; // To guards against cycles.
1598:                    returnType = body.getType();
1599:                }
1600:                return returnType;
1601:            }
1602:
1603:            /* Set teh return type of this function. */
1604:            public final void setReturnType(Type returnType) {
1605:                this .returnType = returnType;
1606:            }
1607:
1608:            /**
1609:               List attributes that should be added to the main primitive method
1610:               generated for this lambdaExp.
1611:             */
1612:            public void addBytecodeAttribute(Attribute a) {
1613:                a.setNext(attributes);
1614:                attributes = a;
1615:            }
1616:
1617:            private gnu.bytecode.Attribute attributes;
1618:
1619:            void addAttributes(AttrContainer bytecode) {
1620:                for (Attribute a = attributes; a != null;) {
1621:                    Attribute next = a.getNext();
1622:                    a.addToFrontOf(bytecode);
1623:                    a = next;
1624:                }
1625:            }
1626:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.