Source Code Cross Referenced for LambdaExp.java in  » Scripting » Kawa » gnu » expr » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » Scripting » Kawa » gnu.expr 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


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