Source Code Cross Referenced for Lower.java in  » 6.0-JDK-Modules-sun » javac-compiler » com » sun » tools » javac » comp » 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 » 6.0 JDK Modules sun » javac compiler » com.sun.tools.javac.comp 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /*
0002:         * Copyright 1999-2006 Sun Microsystems, Inc.  All Rights Reserved.
0003:         * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
0004:         *
0005:         * This code is free software; you can redistribute it and/or modify it
0006:         * under the terms of the GNU General Public License version 2 only, as
0007:         * published by the Free Software Foundation.  Sun designates this
0008:         * particular file as subject to the "Classpath" exception as provided
0009:         * by Sun in the LICENSE file that accompanied this code.
0010:         *
0011:         * This code is distributed in the hope that it will be useful, but WITHOUT
0012:         * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
0013:         * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
0014:         * version 2 for more details (a copy is included in the LICENSE file that
0015:         * accompanied this code).
0016:         *
0017:         * You should have received a copy of the GNU General Public License version
0018:         * 2 along with this work; if not, write to the Free Software Foundation,
0019:         * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
0020:         *
0021:         * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
0022:         * CA 95054 USA or visit www.sun.com if you need additional information or
0023:         * have any questions.
0024:         */
0025:
0026:        package com.sun.tools.javac.comp;
0027:
0028:        import java.util.*;
0029:
0030:        import com.sun.tools.javac.code.*;
0031:        import com.sun.tools.javac.jvm.*;
0032:        import com.sun.tools.javac.tree.*;
0033:        import com.sun.tools.javac.util.*;
0034:        import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition;
0035:        import com.sun.tools.javac.util.List;
0036:
0037:        import com.sun.tools.javac.code.Symbol.*;
0038:        import com.sun.tools.javac.tree.JCTree.*;
0039:        import com.sun.tools.javac.code.Type.*;
0040:
0041:        import com.sun.tools.javac.jvm.Target;
0042:
0043:        import static com.sun.tools.javac.code.Flags.*;
0044:        import static com.sun.tools.javac.code.Kinds.*;
0045:        import static com.sun.tools.javac.code.TypeTags.*;
0046:        import static com.sun.tools.javac.jvm.ByteCodes.*;
0047:
0048:        /** This pass translates away some syntactic sugar: inner classes,
0049:         *  class literals, assertions, foreach loops, etc.
0050:         *
0051:         *  <p><b>This is NOT part of any API supported by Sun Microsystems.  If
0052:         *  you write code that depends on this, you do so at your own risk.
0053:         *  This code and its internal interfaces are subject to change or
0054:         *  deletion without notice.</b>
0055:         */
0056:        @Version("@(#)Lower.java	1.173 07/06/14")
0057:        public class Lower extends TreeTranslator {
0058:            protected static final Context.Key<Lower> lowerKey = new Context.Key<Lower>();
0059:
0060:            public static Lower instance(Context context) {
0061:                Lower instance = context.get(lowerKey);
0062:                if (instance == null)
0063:                    instance = new Lower(context);
0064:                return instance;
0065:            }
0066:
0067:            private Name.Table names;
0068:            private Log log;
0069:            private Symtab syms;
0070:            private Resolve rs;
0071:            private Check chk;
0072:            private Attr attr;
0073:            private TreeMaker make;
0074:            private DiagnosticPosition make_pos;
0075:            private ClassWriter writer;
0076:            private ClassReader reader;
0077:            private ConstFold cfolder;
0078:            private Target target;
0079:            private Source source;
0080:            private boolean allowEnums;
0081:            private final Name dollarAssertionsDisabled;
0082:            private final Name classDollar;
0083:            private Types types;
0084:            private boolean debugLower;
0085:
0086:            protected Lower(Context context) {
0087:                context.put(lowerKey, this );
0088:                names = Name.Table.instance(context);
0089:                log = Log.instance(context);
0090:                syms = Symtab.instance(context);
0091:                rs = Resolve.instance(context);
0092:                chk = Check.instance(context);
0093:                attr = Attr.instance(context);
0094:                make = TreeMaker.instance(context);
0095:                writer = ClassWriter.instance(context);
0096:                reader = ClassReader.instance(context);
0097:                cfolder = ConstFold.instance(context);
0098:                target = Target.instance(context);
0099:                source = Source.instance(context);
0100:                allowEnums = source.allowEnums();
0101:                dollarAssertionsDisabled = names.fromString(target
0102:                        .syntheticNameChar()
0103:                        + "assertionsDisabled");
0104:                classDollar = names.fromString("class"
0105:                        + target.syntheticNameChar());
0106:
0107:                types = Types.instance(context);
0108:                Options options = Options.instance(context);
0109:                debugLower = options.get("debuglower") != null;
0110:            }
0111:
0112:            /** The currently enclosing class.
0113:             */
0114:            ClassSymbol currentClass;
0115:
0116:            /** A queue of all translated classes.
0117:             */
0118:            ListBuffer<JCTree> translated;
0119:
0120:            /** Environment for symbol lookup, set by translateTopLevelClass.
0121:             */
0122:            Env<AttrContext> attrEnv;
0123:
0124:            /** A hash table mapping syntax trees to their ending source positions.
0125:             */
0126:            Map<JCTree, Integer> endPositions;
0127:
0128:            /**************************************************************************
0129:             * Global mappings
0130:             *************************************************************************/
0131:
0132:            /** A hash table mapping local classes to their definitions.
0133:             */
0134:            Map<ClassSymbol, JCClassDecl> classdefs;
0135:
0136:            /** A hash table mapping virtual accessed symbols in outer subclasses
0137:             *  to the actually referred symbol in superclasses.
0138:             */
0139:            Map<Symbol, Symbol> actualSymbols;
0140:
0141:            /** The current method definition.
0142:             */
0143:            JCMethodDecl currentMethodDef;
0144:
0145:            /** The current method symbol.
0146:             */
0147:            MethodSymbol currentMethodSym;
0148:
0149:            /** The currently enclosing outermost class definition.
0150:             */
0151:            JCClassDecl outermostClassDef;
0152:
0153:            /** The currently enclosing outermost member definition.
0154:             */
0155:            JCTree outermostMemberDef;
0156:
0157:            /** A navigator class for assembling a mapping from local class symbols
0158:             *  to class definition trees.
0159:             *  There is only one case; all other cases simply traverse down the tree.
0160:             */
0161:            class ClassMap extends TreeScanner {
0162:
0163:                /** All encountered class defs are entered into classdefs table.
0164:                 */
0165:                public void visitClassDef(JCClassDecl tree) {
0166:                    classdefs.put(tree.sym, tree);
0167:                    super .visitClassDef(tree);
0168:                }
0169:            }
0170:
0171:            ClassMap classMap = new ClassMap();
0172:
0173:            /** Map a class symbol to its definition.
0174:             *  @param c    The class symbol of which we want to determine the definition.
0175:             */
0176:            JCClassDecl classDef(ClassSymbol c) {
0177:                // First lookup the class in the classdefs table.
0178:                JCClassDecl def = classdefs.get(c);
0179:                if (def == null && outermostMemberDef != null) {
0180:                    // If this fails, traverse outermost member definition, entering all
0181:                    // local classes into classdefs, and try again.
0182:                    classMap.scan(outermostMemberDef);
0183:                    def = classdefs.get(c);
0184:                }
0185:                if (def == null) {
0186:                    // If this fails, traverse outermost class definition, entering all
0187:                    // local classes into classdefs, and try again.
0188:                    classMap.scan(outermostClassDef);
0189:                    def = classdefs.get(c);
0190:                }
0191:                return def;
0192:            }
0193:
0194:            /** A hash table mapping class symbols to lists of free variables.
0195:             *  accessed by them. Only free variables of the method immediately containing
0196:             *  a class are associated with that class.
0197:             */
0198:            Map<ClassSymbol, List<VarSymbol>> freevarCache;
0199:
0200:            /** A navigator class for collecting the free variables accessed
0201:             *  from a local class.
0202:             *  There is only one case; all other cases simply traverse down the tree.
0203:             */
0204:            class FreeVarCollector extends TreeScanner {
0205:
0206:                /** The owner of the local class.
0207:                 */
0208:                Symbol owner;
0209:
0210:                /** The local class.
0211:                 */
0212:                ClassSymbol clazz;
0213:
0214:                /** The list of owner's variables accessed from within the local class,
0215:                 *  without any duplicates.
0216:                 */
0217:                List<VarSymbol> fvs;
0218:
0219:                FreeVarCollector(ClassSymbol clazz) {
0220:                    this .clazz = clazz;
0221:                    this .owner = clazz.owner;
0222:                    this .fvs = List.nil();
0223:                }
0224:
0225:                /** Add free variable to fvs list unless it is already there.
0226:                 */
0227:                private void addFreeVar(VarSymbol v) {
0228:                    for (List<VarSymbol> l = fvs; l.nonEmpty(); l = l.tail)
0229:                        if (l.head == v)
0230:                            return;
0231:                    fvs = fvs.prepend(v);
0232:                }
0233:
0234:                /** Add all free variables of class c to fvs list
0235:                 *  unless they are already there.
0236:                 */
0237:                private void addFreeVars(ClassSymbol c) {
0238:                    List<VarSymbol> fvs = freevarCache.get(c);
0239:                    if (fvs != null) {
0240:                        for (List<VarSymbol> l = fvs; l.nonEmpty(); l = l.tail) {
0241:                            addFreeVar(l.head);
0242:                        }
0243:                    }
0244:                }
0245:
0246:                /** If tree refers to a variable in owner of local class, add it to
0247:                 *  free variables list.
0248:                 */
0249:                public void visitIdent(JCIdent tree) {
0250:                    result = tree;
0251:                    visitSymbol(tree.sym);
0252:                }
0253:
0254:                // where
0255:                private void visitSymbol(Symbol _sym) {
0256:                    Symbol sym = _sym;
0257:                    if (sym.kind == VAR || sym.kind == MTH) {
0258:                        while (sym != null && sym.owner != owner)
0259:                            sym = proxies.lookup(proxyName(sym.name)).sym;
0260:                        if (sym != null && sym.owner == owner) {
0261:                            VarSymbol v = (VarSymbol) sym;
0262:                            if (v.getConstValue() == null) {
0263:                                addFreeVar(v);
0264:                            }
0265:                        } else {
0266:                            if (outerThisStack.head != null
0267:                                    && outerThisStack.head != _sym)
0268:                                visitSymbol(outerThisStack.head);
0269:                        }
0270:                    }
0271:                }
0272:
0273:                /** If tree refers to a class instance creation expression
0274:                 *  add all free variables of the freshly created class.
0275:                 */
0276:                public void visitNewClass(JCNewClass tree) {
0277:                    ClassSymbol c = (ClassSymbol) tree.constructor.owner;
0278:                    addFreeVars(c);
0279:                    if (tree.encl == null && c.hasOuterInstance()
0280:                            && outerThisStack.head != null)
0281:                        visitSymbol(outerThisStack.head);
0282:                    super .visitNewClass(tree);
0283:                }
0284:
0285:                /** If tree refers to a qualified this or super expression
0286:                 *  for anything but the current class, add the outer this
0287:                 *  stack as a free variable.
0288:                 */
0289:                public void visitSelect(JCFieldAccess tree) {
0290:                    if ((tree.name == names._this  || tree.name == names._super )
0291:                            && tree.selected.type.tsym != clazz
0292:                            && outerThisStack.head != null)
0293:                        visitSymbol(outerThisStack.head);
0294:                    super .visitSelect(tree);
0295:                }
0296:
0297:                /** If tree refers to a superclass constructor call,
0298:                 *  add all free variables of the superclass.
0299:                 */
0300:                public void visitApply(JCMethodInvocation tree) {
0301:                    if (TreeInfo.name(tree.meth) == names._super ) {
0302:                        addFreeVars((ClassSymbol) TreeInfo.symbol(tree.meth).owner);
0303:                        Symbol constructor = TreeInfo.symbol(tree.meth);
0304:                        ClassSymbol c = (ClassSymbol) constructor.owner;
0305:                        if (c.hasOuterInstance()
0306:                                && tree.meth.getTag() != JCTree.SELECT
0307:                                && outerThisStack.head != null)
0308:                            visitSymbol(outerThisStack.head);
0309:                    }
0310:                    super .visitApply(tree);
0311:                }
0312:            }
0313:
0314:            /** Return the variables accessed from within a local class, which
0315:             *  are declared in the local class' owner.
0316:             *  (in reverse order of first access).
0317:             */
0318:            List<VarSymbol> freevars(ClassSymbol c) {
0319:                if ((c.owner.kind & (VAR | MTH)) != 0) {
0320:                    List<VarSymbol> fvs = freevarCache.get(c);
0321:                    if (fvs == null) {
0322:                        FreeVarCollector collector = new FreeVarCollector(c);
0323:                        collector.scan(classDef(c));
0324:                        fvs = collector.fvs;
0325:                        freevarCache.put(c, fvs);
0326:                    }
0327:                    return fvs;
0328:                } else {
0329:                    return List.nil();
0330:                }
0331:            }
0332:
0333:            Map<TypeSymbol, EnumMapping> enumSwitchMap = new LinkedHashMap<TypeSymbol, EnumMapping>();
0334:
0335:            EnumMapping mapForEnum(DiagnosticPosition pos, TypeSymbol enumClass) {
0336:                EnumMapping map = enumSwitchMap.get(enumClass);
0337:                if (map == null)
0338:                    enumSwitchMap.put(enumClass, map = new EnumMapping(pos,
0339:                            enumClass));
0340:                return map;
0341:            }
0342:
0343:            /** This map gives a translation table to be used for enum
0344:             *  switches.
0345:             *
0346:             *  <p>For each enum that appears as the type of a switch
0347:             *  expression, we maintain an EnumMapping to assist in the
0348:             *  translation, as exemplified by the following example:
0349:             *
0350:             *  <p>we translate
0351:             *  <pre>
0352:             *          switch(colorExpression) {
0353:             *          case red: stmt1;
0354:             *          case green: stmt2;
0355:             *          }
0356:             *  </pre>
0357:             *  into
0358:             *  <pre>
0359:             *          switch(Outer$0.$EnumMap$Color[colorExpression.ordinal()]) {
0360:             *          case 1: stmt1;
0361:             *          case 2: stmt2
0362:             *          }
0363:             *  </pre>
0364:             *  with the auxilliary table intialized as follows:
0365:             *  <pre>
0366:             *          class Outer$0 {
0367:             *              synthetic final int[] $EnumMap$Color = new int[Color.values().length];
0368:             *              static {
0369:             *                  try { $EnumMap$Color[red.ordinal()] = 1; } catch (NoSuchFieldError ex) {}
0370:             *                  try { $EnumMap$Color[green.ordinal()] = 2; } catch (NoSuchFieldError ex) {}
0371:             *              }
0372:             *          }
0373:             *  </pre>
0374:             *  class EnumMapping provides mapping data and support methods for this translation.
0375:             */
0376:            class EnumMapping {
0377:                EnumMapping(DiagnosticPosition pos, TypeSymbol forEnum) {
0378:                    this .forEnum = forEnum;
0379:                    this .values = new LinkedHashMap<VarSymbol, Integer>();
0380:                    this .pos = pos;
0381:                    Name varName = names.fromString(target.syntheticNameChar()
0382:                            + "SwitchMap"
0383:                            + target.syntheticNameChar()
0384:                            + writer.xClassName(forEnum.type).toString()
0385:                                    .replace('/', '.').replace('.',
0386:                                            target.syntheticNameChar()));
0387:                    ClassSymbol outerCacheClass = outerCacheClass();
0388:                    this .mapVar = new VarSymbol(STATIC | SYNTHETIC | FINAL,
0389:                            varName, new ArrayType(syms.intType,
0390:                                    syms.arrayClass), outerCacheClass);
0391:                    enterSynthetic(pos, mapVar, outerCacheClass.members());
0392:                }
0393:
0394:                DiagnosticPosition pos = null;
0395:
0396:                // the next value to use
0397:                int next = 1; // 0 (unused map elements) go to the default label
0398:
0399:                // the enum for which this is a map
0400:                final TypeSymbol forEnum;
0401:
0402:                // the field containing the map
0403:                final VarSymbol mapVar;
0404:
0405:                // the mapped values
0406:                final Map<VarSymbol, Integer> values;
0407:
0408:                JCLiteral forConstant(VarSymbol v) {
0409:                    Integer result = values.get(v);
0410:                    if (result == null)
0411:                        values.put(v, result = next++);
0412:                    return make.Literal(result);
0413:                }
0414:
0415:                // generate the field initializer for the map
0416:                void translate() {
0417:                    make.at(pos.getStartPosition());
0418:                    JCClassDecl owner = classDef((ClassSymbol) mapVar.owner);
0419:
0420:                    // synthetic static final int[] $SwitchMap$Color = new int[Color.values().length];
0421:                    MethodSymbol valuesMethod = lookupMethod(pos, names.values,
0422:                            forEnum.type, List.<Type> nil());
0423:                    JCExpression size = make // Color.values().length
0424:                            .Select(make.App(make.QualIdent(valuesMethod)),
0425:                                    syms.lengthVar);
0426:                    JCExpression mapVarInit = make
0427:                            .NewArray(make.Type(syms.intType), List.of(size),
0428:                                    null)
0429:                            .setType(
0430:                                    new ArrayType(syms.intType, syms.arrayClass));
0431:
0432:                    // try { $SwitchMap$Color[red.ordinal()] = 1; } catch (java.lang.NoSuchFieldError ex) {}
0433:                    ListBuffer<JCStatement> stmts = new ListBuffer<JCStatement>();
0434:                    Symbol ordinalMethod = lookupMethod(pos, names.ordinal,
0435:                            forEnum.type, List.<Type> nil());
0436:                    List<JCCatch> catcher = List.<JCCatch> nil().prepend(
0437:                            make.Catch(make.VarDef(new VarSymbol(PARAMETER,
0438:                                    names.ex, syms.noSuchFieldErrorType,
0439:                                    syms.noSymbol), null), make.Block(0, List
0440:                                    .<JCStatement> nil())));
0441:                    for (Map.Entry<VarSymbol, Integer> e : values.entrySet()) {
0442:                        VarSymbol enumerator = e.getKey();
0443:                        Integer mappedValue = e.getValue();
0444:                        JCExpression assign = make.Assign(
0445:                                make
0446:                                        .Indexed(mapVar, make.App(make.Select(
0447:                                                make.QualIdent(enumerator),
0448:                                                ordinalMethod))),
0449:                                make.Literal(mappedValue))
0450:                                .setType(syms.intType);
0451:                        JCStatement exec = make.Exec(assign);
0452:                        JCStatement _try = make.Try(make
0453:                                .Block(0, List.of(exec)), catcher, null);
0454:                        stmts.append(_try);
0455:                    }
0456:
0457:                    owner.defs = owner.defs.prepend(
0458:                            make.Block(STATIC, stmts.toList())).prepend(
0459:                            make.VarDef(mapVar, mapVarInit));
0460:                }
0461:            }
0462:
0463:            /**************************************************************************
0464:             * Tree building blocks
0465:             *************************************************************************/
0466:
0467:            /** Equivalent to make.at(pos.getStartPosition()) with side effect of caching
0468:             *  pos as make_pos, for use in diagnostics.
0469:             **/
0470:            TreeMaker make_at(DiagnosticPosition pos) {
0471:                make_pos = pos;
0472:                return make.at(pos);
0473:            }
0474:
0475:            /** Make an attributed tree representing a literal. This will be an
0476:             *  Ident node in the case of boolean literals, a Literal node in all
0477:             *  other cases.
0478:             *  @param type       The literal's type.
0479:             *  @param value      The literal's value.
0480:             */
0481:            JCExpression makeLit(Type type, Object value) {
0482:                return make.Literal(type.tag, value).setType(
0483:                        type.constType(value));
0484:            }
0485:
0486:            /** Make an attributed tree representing null.
0487:             */
0488:            JCExpression makeNull() {
0489:                return makeLit(syms.botType, null);
0490:            }
0491:
0492:            /** Make an attributed class instance creation expression.
0493:             *  @param ctype    The class type.
0494:             *  @param args     The constructor arguments.
0495:             */
0496:            JCNewClass makeNewClass(Type ctype, List<JCExpression> args) {
0497:                JCNewClass tree = make.NewClass(null, null, make
0498:                        .QualIdent(ctype.tsym), args, null);
0499:                tree.constructor = rs.resolveConstructor(make_pos, attrEnv,
0500:                        ctype, TreeInfo.types(args), null, false, false);
0501:                tree.type = ctype;
0502:                return tree;
0503:            }
0504:
0505:            /** Make an attributed unary expression.
0506:             *  @param optag    The operators tree tag.
0507:             *  @param arg      The operator's argument.
0508:             */
0509:            JCUnary makeUnary(int optag, JCExpression arg) {
0510:                JCUnary tree = make.Unary(optag, arg);
0511:                tree.operator = rs.resolveUnaryOperator(make_pos, optag,
0512:                        attrEnv, arg.type);
0513:                tree.type = tree.operator.type.getReturnType();
0514:                return tree;
0515:            }
0516:
0517:            /** Make an attributed binary expression.
0518:             *  @param optag    The operators tree tag.
0519:             *  @param lhs      The operator's left argument.
0520:             *  @param rhs      The operator's right argument.
0521:             */
0522:            JCBinary makeBinary(int optag, JCExpression lhs, JCExpression rhs) {
0523:                JCBinary tree = make.Binary(optag, lhs, rhs);
0524:                tree.operator = rs.resolveBinaryOperator(make_pos, optag,
0525:                        attrEnv, lhs.type, rhs.type);
0526:                tree.type = tree.operator.type.getReturnType();
0527:                return tree;
0528:            }
0529:
0530:            /** Make an attributed assignop expression.
0531:             *  @param optag    The operators tree tag.
0532:             *  @param lhs      The operator's left argument.
0533:             *  @param rhs      The operator's right argument.
0534:             */
0535:            JCAssignOp makeAssignop(int optag, JCTree lhs, JCTree rhs) {
0536:                JCAssignOp tree = make.Assignop(optag, lhs, rhs);
0537:                tree.operator = rs.resolveBinaryOperator(make_pos, tree
0538:                        .getTag()
0539:                        - JCTree.ASGOffset, attrEnv, lhs.type, rhs.type);
0540:                tree.type = lhs.type;
0541:                return tree;
0542:            }
0543:
0544:            /** Convert tree into string object, unless it has already a
0545:             *  reference type..
0546:             */
0547:            JCExpression makeString(JCExpression tree) {
0548:                if (tree.type.tag >= CLASS) {
0549:                    return tree;
0550:                } else {
0551:                    Symbol valueOfSym = lookupMethod(tree.pos(), names.valueOf,
0552:                            syms.stringType, List.of(tree.type));
0553:                    return make.App(make.QualIdent(valueOfSym), List.of(tree));
0554:                }
0555:            }
0556:
0557:            /** Create an empty anonymous class definition and enter and complete
0558:             *  its symbol. Return the class definition's symbol.
0559:             *  and create
0560:             *  @param flags    The class symbol's flags
0561:             *  @param owner    The class symbol's owner
0562:             */
0563:            ClassSymbol makeEmptyClass(long flags, ClassSymbol owner) {
0564:                // Create class symbol.
0565:                ClassSymbol c = reader.defineClass(names.empty, owner);
0566:                c.flatname = chk.localClassName(c);
0567:                c.sourcefile = owner.sourcefile;
0568:                c.completer = null;
0569:                c.members_field = new Scope(c);
0570:                c.flags_field = flags;
0571:                ClassType ctype = (ClassType) c.type;
0572:                ctype.super type_field = syms.objectType;
0573:                ctype.interfaces_field = List.nil();
0574:
0575:                JCClassDecl odef = classDef(owner);
0576:
0577:                // Enter class symbol in owner scope and compiled table.
0578:                enterSynthetic(odef.pos(), c, owner.members());
0579:                chk.compiled.put(c.flatname, c);
0580:
0581:                // Create class definition tree.
0582:                JCClassDecl cdef = make.ClassDef(make.Modifiers(flags),
0583:                        names.empty, List.<JCTypeParameter> nil(), null, List
0584:                                .<JCExpression> nil(), List.<JCTree> nil());
0585:                cdef.sym = c;
0586:                cdef.type = c.type;
0587:
0588:                // Append class definition tree to owner's definitions.
0589:                odef.defs = odef.defs.prepend(cdef);
0590:
0591:                return c;
0592:            }
0593:
0594:            /**************************************************************************
0595:             * Symbol manipulation utilities
0596:             *************************************************************************/
0597:
0598:            /** Report a conflict between a user symbol and a synthetic symbol.
0599:             */
0600:            private void duplicateError(DiagnosticPosition pos, Symbol sym) {
0601:                if (!sym.type.isErroneous()) {
0602:                    log.error(pos, "synthetic.name.conflict", sym, sym
0603:                            .location());
0604:                }
0605:            }
0606:
0607:            /** Enter a synthetic symbol in a given scope, but complain if there was already one there.
0608:             *  @param pos           Position for error reporting.
0609:             *  @param sym           The symbol.
0610:             *  @param s             The scope.
0611:             */
0612:            private void enterSynthetic(DiagnosticPosition pos, Symbol sym,
0613:                    Scope s) {
0614:                if (sym.name != names.error && sym.name != names.empty) {
0615:                    for (Scope.Entry e = s.lookup(sym.name); e.scope == s; e = e
0616:                            .next()) {
0617:                        if (sym != e.sym && sym.kind == e.sym.kind) {
0618:                            // VM allows methods and variables with differing types
0619:                            if ((sym.kind & (MTH | VAR)) != 0
0620:                                    && !types.erasure(sym.type).equals(
0621:                                            types.erasure(e.sym.type)))
0622:                                continue;
0623:                            duplicateError(pos, e.sym);
0624:                            break;
0625:                        }
0626:                    }
0627:                }
0628:                s.enter(sym);
0629:            }
0630:
0631:            /** Look up a synthetic name in a given scope.
0632:             *  @param scope	    The scope.
0633:             *  @param name	    The name.
0634:             */
0635:            private Symbol lookupSynthetic(Name name, Scope s) {
0636:                Symbol sym = s.lookup(name).sym;
0637:                return (sym == null || (sym.flags() & SYNTHETIC) == 0) ? null
0638:                        : sym;
0639:            }
0640:
0641:            /** Look up a method in a given scope.
0642:             */
0643:            private MethodSymbol lookupMethod(DiagnosticPosition pos,
0644:                    Name name, Type qual, List<Type> args) {
0645:                return rs.resolveInternalMethod(pos, attrEnv, qual, name, args,
0646:                        null);
0647:            }
0648:
0649:            /** Look up a constructor.
0650:             */
0651:            private MethodSymbol lookupConstructor(DiagnosticPosition pos,
0652:                    Type qual, List<Type> args) {
0653:                return rs.resolveInternalConstructor(pos, attrEnv, qual, args,
0654:                        null);
0655:            }
0656:
0657:            /** Look up a field.
0658:             */
0659:            private VarSymbol lookupField(DiagnosticPosition pos, Type qual,
0660:                    Name name) {
0661:                return rs.resolveInternalField(pos, attrEnv, qual, name);
0662:            }
0663:
0664:            /**************************************************************************
0665:             * Access methods
0666:             *************************************************************************/
0667:
0668:            /** Access codes for dereferencing, assignment,
0669:             *  and pre/post increment/decrement.
0670:             *  Access codes for assignment operations are determined by method accessCode
0671:             *  below.
0672:             *
0673:             *  All access codes for accesses to the current class are even.
0674:             *  If a member of the superclass should be accessed instead (because
0675:             *  access was via a qualified super), add one to the corresponding code
0676:             *  for the current class, making the number odd.
0677:             *  This numbering scheme is used by the backend to decide whether
0678:             *  to issue an invokevirtual or invokespecial call.
0679:             *
0680:             *  @see Gen.visitSelect(Select tree)
0681:             */
0682:            private static final int DEREFcode = 0, ASSIGNcode = 2,
0683:                    PREINCcode = 4, PREDECcode = 6, POSTINCcode = 8,
0684:                    POSTDECcode = 10, FIRSTASGOPcode = 12;
0685:
0686:            /** Number of access codes
0687:             */
0688:            private static final int NCODES = accessCode(ByteCodes.lushrl) + 2;
0689:
0690:            /** A mapping from symbols to their access numbers.
0691:             */
0692:            private Map<Symbol, Integer> accessNums;
0693:
0694:            /** A mapping from symbols to an array of access symbols, indexed by
0695:             *  access code.
0696:             */
0697:            private Map<Symbol, MethodSymbol[]> accessSyms;
0698:
0699:            /** A mapping from (constructor) symbols to access constructor symbols.
0700:             */
0701:            private Map<Symbol, MethodSymbol> accessConstrs;
0702:
0703:            /** A queue for all accessed symbols.
0704:             */
0705:            private ListBuffer<Symbol> accessed;
0706:
0707:            /** Map bytecode of binary operation to access code of corresponding
0708:             *  assignment operation. This is always an even number.
0709:             */
0710:            private static int accessCode(int bytecode) {
0711:                if (ByteCodes.iadd <= bytecode && bytecode <= ByteCodes.lxor)
0712:                    return (bytecode - iadd) * 2 + FIRSTASGOPcode;
0713:                else if (bytecode == ByteCodes.string_add)
0714:                    return (ByteCodes.lxor + 1 - iadd) * 2 + FIRSTASGOPcode;
0715:                else if (ByteCodes.ishll <= bytecode
0716:                        && bytecode <= ByteCodes.lushrl)
0717:                    return (bytecode - ishll + ByteCodes.lxor + 2 - iadd) * 2
0718:                            + FIRSTASGOPcode;
0719:                else
0720:                    return -1;
0721:            }
0722:
0723:            /** return access code for identifier,
0724:             *  @param tree     The tree representing the identifier use.
0725:             *  @param enclOp   The closest enclosing operation node of tree,
0726:             *                  null if tree is not a subtree of an operation.
0727:             */
0728:            private static int accessCode(JCTree tree, JCTree enclOp) {
0729:                if (enclOp == null)
0730:                    return DEREFcode;
0731:                else if (enclOp.getTag() == JCTree.ASSIGN
0732:                        && tree == TreeInfo.skipParens(((JCAssign) enclOp).lhs))
0733:                    return ASSIGNcode;
0734:                else if (JCTree.PREINC <= enclOp.getTag()
0735:                        && enclOp.getTag() <= JCTree.POSTDEC
0736:                        && tree == TreeInfo.skipParens(((JCUnary) enclOp).arg))
0737:                    return (enclOp.getTag() - JCTree.PREINC) * 2 + PREINCcode;
0738:                else if (JCTree.BITOR_ASG <= enclOp.getTag()
0739:                        && enclOp.getTag() <= JCTree.MOD_ASG
0740:                        && tree == TreeInfo
0741:                                .skipParens(((JCAssignOp) enclOp).lhs))
0742:                    return accessCode(((OperatorSymbol) ((JCAssignOp) enclOp).operator).opcode);
0743:                else
0744:                    return DEREFcode;
0745:            }
0746:
0747:            /** Return binary operator that corresponds to given access code.
0748:             */
0749:            private OperatorSymbol binaryAccessOperator(int acode) {
0750:                for (Scope.Entry e = syms.predefClass.members().elems; e != null; e = e.sibling) {
0751:                    if (e.sym instanceof  OperatorSymbol) {
0752:                        OperatorSymbol op = (OperatorSymbol) e.sym;
0753:                        if (accessCode(op.opcode) == acode)
0754:                            return op;
0755:                    }
0756:                }
0757:                return null;
0758:            }
0759:
0760:            /** Return tree tag for assignment operation corresponding
0761:             *  to given binary operator.
0762:             */
0763:            private static int treeTag(OperatorSymbol operator) {
0764:                switch (operator.opcode) {
0765:                case ByteCodes.ior:
0766:                case ByteCodes.lor:
0767:                    return JCTree.BITOR_ASG;
0768:                case ByteCodes.ixor:
0769:                case ByteCodes.lxor:
0770:                    return JCTree.BITXOR_ASG;
0771:                case ByteCodes.iand:
0772:                case ByteCodes.land:
0773:                    return JCTree.BITAND_ASG;
0774:                case ByteCodes.ishl:
0775:                case ByteCodes.lshl:
0776:                case ByteCodes.ishll:
0777:                case ByteCodes.lshll:
0778:                    return JCTree.SL_ASG;
0779:                case ByteCodes.ishr:
0780:                case ByteCodes.lshr:
0781:                case ByteCodes.ishrl:
0782:                case ByteCodes.lshrl:
0783:                    return JCTree.SR_ASG;
0784:                case ByteCodes.iushr:
0785:                case ByteCodes.lushr:
0786:                case ByteCodes.iushrl:
0787:                case ByteCodes.lushrl:
0788:                    return JCTree.USR_ASG;
0789:                case ByteCodes.iadd:
0790:                case ByteCodes.ladd:
0791:                case ByteCodes.fadd:
0792:                case ByteCodes.dadd:
0793:                case ByteCodes.string_add:
0794:                    return JCTree.PLUS_ASG;
0795:                case ByteCodes.isub:
0796:                case ByteCodes.lsub:
0797:                case ByteCodes.fsub:
0798:                case ByteCodes.dsub:
0799:                    return JCTree.MINUS_ASG;
0800:                case ByteCodes.imul:
0801:                case ByteCodes.lmul:
0802:                case ByteCodes.fmul:
0803:                case ByteCodes.dmul:
0804:                    return JCTree.MUL_ASG;
0805:                case ByteCodes.idiv:
0806:                case ByteCodes.ldiv:
0807:                case ByteCodes.fdiv:
0808:                case ByteCodes.ddiv:
0809:                    return JCTree.DIV_ASG;
0810:                case ByteCodes.imod:
0811:                case ByteCodes.lmod:
0812:                case ByteCodes.fmod:
0813:                case ByteCodes.dmod:
0814:                    return JCTree.MOD_ASG;
0815:                default:
0816:                    throw new AssertionError();
0817:                }
0818:            }
0819:
0820:            /** The name of the access method with number `anum' and access code `acode'.
0821:             */
0822:            Name accessName(int anum, int acode) {
0823:                return names.fromString("access" + target.syntheticNameChar()
0824:                        + anum + acode / 10 + acode % 10);
0825:            }
0826:
0827:            /** Return access symbol for a private or protected symbol from an inner class.
0828:             *  @param sym        The accessed private symbol.
0829:             *  @param tree       The accessing tree.
0830:             *  @param enclOp     The closest enclosing operation node of tree,
0831:             *                    null if tree is not a subtree of an operation.
0832:             *  @param protAccess Is access to a protected symbol in another
0833:             *                    package?
0834:             *  @param refSuper   Is access via a (qualified) C.super?
0835:             */
0836:            MethodSymbol accessSymbol(Symbol sym, JCTree tree, JCTree enclOp,
0837:                    boolean protAccess, boolean refSuper) {
0838:                ClassSymbol accOwner = refSuper && protAccess
0839:                // For access via qualified super (T.super.x), place the
0840:                // access symbol on T.
0841:                ? (ClassSymbol) ((JCFieldAccess) tree).selected.type.tsym
0842:                        // Otherwise pretend that the owner of an accessed
0843:                        // protected symbol is the enclosing class of the current
0844:                        // class which is a subclass of the symbol's owner.
0845:                        : accessClass(sym, protAccess, tree);
0846:
0847:                Symbol vsym = sym;
0848:                if (sym.owner != accOwner) {
0849:                    vsym = sym.clone(accOwner);
0850:                    actualSymbols.put(vsym, sym);
0851:                }
0852:
0853:                Integer anum // The access number of the access method.
0854:                = accessNums.get(vsym);
0855:                if (anum == null) {
0856:                    anum = accessed.length();
0857:                    accessNums.put(vsym, anum);
0858:                    accessSyms.put(vsym, new MethodSymbol[NCODES]);
0859:                    accessed.append(vsym);
0860:                    // System.out.println("accessing " + vsym + " in " + vsym.location());
0861:                }
0862:
0863:                int acode; // The access code of the access method.
0864:                List<Type> argtypes; // The argument types of the access method.
0865:                Type restype; // The result type of the access method.
0866:                List<Type> thrown; // The thrown execeptions of the access method.
0867:                switch (vsym.kind) {
0868:                case VAR:
0869:                    acode = accessCode(tree, enclOp);
0870:                    if (acode >= FIRSTASGOPcode) {
0871:                        OperatorSymbol operator = binaryAccessOperator(acode);
0872:                        if (operator.opcode == string_add)
0873:                            argtypes = List.of(syms.objectType);
0874:                        else
0875:                            argtypes = operator.type.getParameterTypes().tail;
0876:                    } else if (acode == ASSIGNcode)
0877:                        argtypes = List.of(vsym.erasure(types));
0878:                    else
0879:                        argtypes = List.nil();
0880:                    restype = vsym.erasure(types);
0881:                    thrown = List.nil();
0882:                    break;
0883:                case MTH:
0884:                    acode = DEREFcode;
0885:                    argtypes = vsym.erasure(types).getParameterTypes();
0886:                    restype = vsym.erasure(types).getReturnType();
0887:                    thrown = vsym.type.getThrownTypes();
0888:                    break;
0889:                default:
0890:                    throw new AssertionError();
0891:                }
0892:
0893:                // For references via qualified super, increment acode by one,
0894:                // making it odd.
0895:                if (protAccess && refSuper)
0896:                    acode++;
0897:
0898:                // Instance access methods get instance as first parameter.
0899:                // For protected symbols this needs to be the instance as a member
0900:                // of the type containing the accessed symbol, not the class
0901:                // containing the access method.
0902:                if ((vsym.flags() & STATIC) == 0) {
0903:                    argtypes = argtypes.prepend(vsym.owner.erasure(types));
0904:                }
0905:                MethodSymbol[] accessors = accessSyms.get(vsym);
0906:                MethodSymbol accessor = accessors[acode];
0907:                if (accessor == null) {
0908:                    accessor = new MethodSymbol(STATIC | SYNTHETIC, accessName(
0909:                            anum.intValue(), acode), new MethodType(argtypes,
0910:                            restype, thrown, syms.methodClass), accOwner);
0911:                    enterSynthetic(tree.pos(), accessor, accOwner.members());
0912:                    accessors[acode] = accessor;
0913:                }
0914:                return accessor;
0915:            }
0916:
0917:            /** The qualifier to be used for accessing a symbol in an outer class.
0918:             *  This is either C.sym or C.this.sym, depending on whether or not
0919:             *  sym is static.
0920:             *  @param sym   The accessed symbol.
0921:             */
0922:            JCExpression accessBase(DiagnosticPosition pos, Symbol sym) {
0923:                return (sym.flags() & STATIC) != 0 ? access(make.at(
0924:                        pos.getStartPosition()).QualIdent(sym.owner))
0925:                        : makeOwnerThis(pos, sym, true);
0926:            }
0927:
0928:            /** Do we need an access method to reference private symbol?
0929:             */
0930:            boolean needsPrivateAccess(Symbol sym) {
0931:                if ((sym.flags() & PRIVATE) == 0 || sym.owner == currentClass) {
0932:                    return false;
0933:                } else if (sym.name == names.init
0934:                        && (sym.owner.owner.kind & (VAR | MTH)) != 0) {
0935:                    // private constructor in local class: relax protection
0936:                    sym.flags_field &= ~PRIVATE;
0937:                    return false;
0938:                } else {
0939:                    return true;
0940:                }
0941:            }
0942:
0943:            /** Do we need an access method to reference symbol in other package?
0944:             */
0945:            boolean needsProtectedAccess(Symbol sym, JCTree tree) {
0946:                if ((sym.flags() & PROTECTED) == 0
0947:                        || sym.owner.owner == currentClass.owner || // fast special case
0948:                        sym.packge() == currentClass.packge())
0949:                    return false;
0950:                if (!currentClass.isSubClass(sym.owner, types))
0951:                    return true;
0952:                if ((sym.flags() & STATIC) != 0
0953:                        || tree.getTag() != JCTree.SELECT
0954:                        || TreeInfo.name(((JCFieldAccess) tree).selected) == names._super )
0955:                    return false;
0956:                return !((JCFieldAccess) tree).selected.type.tsym.isSubClass(
0957:                        currentClass, types);
0958:            }
0959:
0960:            /** The class in which an access method for given symbol goes.
0961:             *  @param sym        The access symbol
0962:             *  @param protAccess Is access to a protected symbol in another
0963:             *                    package?
0964:             */
0965:            ClassSymbol accessClass(Symbol sym, boolean protAccess, JCTree tree) {
0966:                if (protAccess) {
0967:                    Symbol qualifier = null;
0968:                    ClassSymbol c = currentClass;
0969:                    if (tree.getTag() == JCTree.SELECT
0970:                            && (sym.flags() & STATIC) == 0) {
0971:                        qualifier = ((JCFieldAccess) tree).selected.type.tsym;
0972:                        while (!qualifier.isSubClass(c, types)) {
0973:                            c = c.owner.enclClass();
0974:                        }
0975:                        return c;
0976:                    } else {
0977:                        while (!c.isSubClass(sym.owner, types)) {
0978:                            c = c.owner.enclClass();
0979:                        }
0980:                    }
0981:                    return c;
0982:                } else {
0983:                    // the symbol is private
0984:                    return sym.owner.enclClass();
0985:                }
0986:            }
0987:
0988:            /** Ensure that identifier is accessible, return tree accessing the identifier.
0989:             *  @param sym      The accessed symbol.
0990:             *  @param tree     The tree referring to the symbol.
0991:             *  @param enclOp   The closest enclosing operation node of tree,
0992:             *                  null if tree is not a subtree of an operation.
0993:             *  @param refSuper Is access via a (qualified) C.super?
0994:             */
0995:            JCExpression access(Symbol sym, JCExpression tree,
0996:                    JCExpression enclOp, boolean refSuper) {
0997:                // Access a free variable via its proxy, or its proxy's proxy
0998:                while (sym.kind == VAR && sym.owner.kind == MTH
0999:                        && sym.owner.enclClass() != currentClass) {
1000:                    // A constant is replaced by its constant value.
1001:                    Object cv = ((VarSymbol) sym).getConstValue();
1002:                    if (cv != null) {
1003:                        make.at(tree.pos);
1004:                        return makeLit(sym.type, cv);
1005:                    }
1006:                    // Otherwise replace the variable by its proxy.
1007:                    sym = proxies.lookup(proxyName(sym.name)).sym;
1008:                    assert sym != null && (sym.flags_field & FINAL) != 0;
1009:                    tree = make.at(tree.pos).Ident(sym);
1010:                }
1011:                JCExpression base = (tree.getTag() == JCTree.SELECT) ? ((JCFieldAccess) tree).selected
1012:                        : null;
1013:                switch (sym.kind) {
1014:                case TYP:
1015:                    if (sym.owner.kind != PCK) {
1016:                        // Convert type idents to
1017:                        // <flat name> or <package name> . <flat name>
1018:                        Name flatname = Convert.shortName(sym.flatName());
1019:                        while (base != null && TreeInfo.symbol(base) != null
1020:                                && TreeInfo.symbol(base).kind != PCK) {
1021:                            base = (base.getTag() == JCTree.SELECT) ? ((JCFieldAccess) base).selected
1022:                                    : null;
1023:                        }
1024:                        if (tree.getTag() == JCTree.IDENT) {
1025:                            ((JCIdent) tree).name = flatname;
1026:                        } else if (base == null) {
1027:                            tree = make.at(tree.pos).Ident(sym);
1028:                            ((JCIdent) tree).name = flatname;
1029:                        } else {
1030:                            ((JCFieldAccess) tree).selected = base;
1031:                            ((JCFieldAccess) tree).name = flatname;
1032:                        }
1033:                    }
1034:                    break;
1035:                case MTH:
1036:                case VAR:
1037:                    if (sym.owner.kind == TYP) {
1038:
1039:                        // Access methods are required for
1040:                        //  - private members,
1041:                        //  - protected members in a superclass of an
1042:                        //    enclosing class contained in another package.
1043:                        //  - all non-private members accessed via a qualified super.
1044:                        boolean protAccess = refSuper
1045:                                && !needsPrivateAccess(sym)
1046:                                || needsProtectedAccess(sym, tree);
1047:                        boolean accReq = protAccess || needsPrivateAccess(sym);
1048:
1049:                        // A base has to be supplied for
1050:                        //  - simple identifiers accessing variables in outer classes.
1051:                        boolean baseReq = base == null
1052:                                && sym.owner != syms.predefClass
1053:                                && !sym.isMemberOf(currentClass, types);
1054:
1055:                        if (accReq || baseReq) {
1056:                            make.at(tree.pos);
1057:
1058:                            // Constants are replaced by their constant value.
1059:                            if (sym.kind == VAR) {
1060:                                Object cv = ((VarSymbol) sym).getConstValue();
1061:                                if (cv != null)
1062:                                    return makeLit(sym.type, cv);
1063:                            }
1064:
1065:                            // Private variables and methods are replaced by calls
1066:                            // to their access methods.
1067:                            if (accReq) {
1068:                                List<JCExpression> args = List.nil();
1069:                                if ((sym.flags() & STATIC) == 0) {
1070:                                    // Instance access methods get instance
1071:                                    // as first parameter.
1072:                                    if (base == null)
1073:                                        base = makeOwnerThis(tree.pos(), sym,
1074:                                                true);
1075:                                    args = args.prepend(base);
1076:                                    base = null; // so we don't duplicate code
1077:                                }
1078:                                Symbol access = accessSymbol(sym, tree, enclOp,
1079:                                        protAccess, refSuper);
1080:                                JCExpression receiver = make.Select(
1081:                                        base != null ? base : make
1082:                                                .QualIdent(access.owner),
1083:                                        access);
1084:                                return make.App(receiver, args);
1085:
1086:                                // Other accesses to members of outer classes get a
1087:                                // qualifier.
1088:                            } else if (baseReq) {
1089:                                return make.at(tree.pos).Select(
1090:                                        accessBase(tree.pos(), sym), sym)
1091:                                        .setType(tree.type);
1092:                            }
1093:                        }
1094:                    }
1095:                }
1096:                return tree;
1097:            }
1098:
1099:            /** Ensure that identifier is accessible, return tree accessing the identifier.
1100:             *  @param tree     The identifier tree.
1101:             */
1102:            JCExpression access(JCExpression tree) {
1103:                Symbol sym = TreeInfo.symbol(tree);
1104:                return sym == null ? tree : access(sym, tree, null, false);
1105:            }
1106:
1107:            /** Return access constructor for a private constructor,
1108:             *  or the constructor itself, if no access constructor is needed.
1109:             *  @param pos	 The position to report diagnostics, if any.
1110:             *  @param constr    The private constructor.
1111:             */
1112:            Symbol accessConstructor(DiagnosticPosition pos, Symbol constr) {
1113:                if (needsPrivateAccess(constr)) {
1114:                    ClassSymbol accOwner = constr.owner.enclClass();
1115:                    MethodSymbol aconstr = accessConstrs.get(constr);
1116:                    if (aconstr == null) {
1117:                        List<Type> argtypes = constr.type.getParameterTypes();
1118:                        if ((accOwner.flags_field & ENUM) != 0)
1119:                            argtypes = argtypes.prepend(syms.intType).prepend(
1120:                                    syms.stringType);
1121:                        aconstr = new MethodSymbol(SYNTHETIC, names.init,
1122:                                new MethodType(argtypes
1123:                                        .append(accessConstructorTag().erasure(
1124:                                                types)), constr.type
1125:                                        .getReturnType(), constr.type
1126:                                        .getThrownTypes(), syms.methodClass),
1127:                                accOwner);
1128:                        enterSynthetic(pos, aconstr, accOwner.members());
1129:                        accessConstrs.put(constr, aconstr);
1130:                        accessed.append(constr);
1131:                    }
1132:                    return aconstr;
1133:                } else {
1134:                    return constr;
1135:                }
1136:            }
1137:
1138:            /** Return an anonymous class nested in this toplevel class.
1139:             */
1140:            ClassSymbol accessConstructorTag() {
1141:                ClassSymbol topClass = currentClass.outermostClass();
1142:                Name flatname = names.fromString(""
1143:                        + topClass.getQualifiedName()
1144:                        + target.syntheticNameChar() + "1");
1145:                ClassSymbol ctag = chk.compiled.get(flatname);
1146:                if (ctag == null)
1147:                    ctag = makeEmptyClass(STATIC | SYNTHETIC, topClass);
1148:                return ctag;
1149:            }
1150:
1151:            /** Add all required access methods for a private symbol to enclosing class.
1152:             *  @param sym       The symbol.
1153:             */
1154:            void makeAccessible(Symbol sym) {
1155:                JCClassDecl cdef = classDef(sym.owner.enclClass());
1156:                assert cdef != null : "class def not found: " + sym + " in "
1157:                        + sym.owner;
1158:                if (sym.name == names.init) {
1159:                    cdef.defs = cdef.defs.prepend(accessConstructorDef(
1160:                            cdef.pos, sym, accessConstrs.get(sym)));
1161:                } else {
1162:                    MethodSymbol[] accessors = accessSyms.get(sym);
1163:                    for (int i = 0; i < NCODES; i++) {
1164:                        if (accessors[i] != null)
1165:                            cdef.defs = cdef.defs.prepend(accessDef(cdef.pos,
1166:                                    sym, accessors[i], i));
1167:                    }
1168:                }
1169:            }
1170:
1171:            /** Construct definition of an access method.
1172:             *  @param pos        The source code position of the definition.
1173:             *  @param vsym       The private or protected symbol.
1174:             *  @param accessor   The access method for the symbol.
1175:             *  @param acode      The access code.
1176:             */
1177:            JCTree accessDef(int pos, Symbol vsym, MethodSymbol accessor,
1178:                    int acode) {
1179:                //	System.err.println("access " + vsym + " with " + accessor);//DEBUG
1180:                currentClass = vsym.owner.enclClass();
1181:                make.at(pos);
1182:                JCMethodDecl md = make.MethodDef(accessor, null);
1183:
1184:                // Find actual symbol
1185:                Symbol sym = actualSymbols.get(vsym);
1186:                if (sym == null)
1187:                    sym = vsym;
1188:
1189:                JCExpression ref; // The tree referencing the private symbol.
1190:                List<JCExpression> args; // Any additional arguments to be passed along.
1191:                if ((sym.flags() & STATIC) != 0) {
1192:                    ref = make.Ident(sym);
1193:                    args = make.Idents(md.params);
1194:                } else {
1195:                    ref = make.Select(make.Ident(md.params.head), sym);
1196:                    args = make.Idents(md.params.tail);
1197:                }
1198:                JCStatement stat; // The statement accessing the private symbol.
1199:                if (sym.kind == VAR) {
1200:                    // Normalize out all odd access codes by taking floor modulo 2:
1201:                    int acode1 = acode - (acode & 1);
1202:
1203:                    JCExpression expr; // The access method's return value.
1204:                    switch (acode1) {
1205:                    case DEREFcode:
1206:                        expr = ref;
1207:                        break;
1208:                    case ASSIGNcode:
1209:                        expr = make.Assign(ref, args.head);
1210:                        break;
1211:                    case PREINCcode:
1212:                    case POSTINCcode:
1213:                    case PREDECcode:
1214:                    case POSTDECcode:
1215:                        expr = makeUnary(((acode1 - PREINCcode) >> 1)
1216:                                + JCTree.PREINC, ref);
1217:                        break;
1218:                    default:
1219:                        expr = make.Assignop(
1220:                                treeTag(binaryAccessOperator(acode1)), ref,
1221:                                args.head);
1222:                        ((JCAssignOp) expr).operator = binaryAccessOperator(acode1);
1223:                    }
1224:                    stat = make.Return(expr.setType(sym.type));
1225:                } else {
1226:                    stat = make.Call(make.App(ref, args));
1227:                }
1228:                md.body = make.Block(0, List.of(stat));
1229:
1230:                // Make sure all parameters, result types and thrown exceptions
1231:                // are accessible.
1232:                for (List<JCVariableDecl> l = md.params; l.nonEmpty(); l = l.tail)
1233:                    l.head.vartype = access(l.head.vartype);
1234:                md.restype = access(md.restype);
1235:                for (List<JCExpression> l = md.thrown; l.nonEmpty(); l = l.tail)
1236:                    l.head = access(l.head);
1237:
1238:                return md;
1239:            }
1240:
1241:            /** Construct definition of an access constructor.
1242:             *  @param pos        The source code position of the definition.
1243:             *  @param constr     The private constructor.
1244:             *  @param accessor   The access method for the constructor.
1245:             */
1246:            JCTree accessConstructorDef(int pos, Symbol constr,
1247:                    MethodSymbol accessor) {
1248:                make.at(pos);
1249:                JCMethodDecl md = make.MethodDef(accessor, accessor
1250:                        .externalType(types), null);
1251:                JCIdent callee = make.Ident(names._this );
1252:                callee.sym = constr;
1253:                callee.type = constr.type;
1254:                md.body = make.Block(0, List.<JCStatement> of(make.Call(make
1255:                        .App(callee, make.Idents(md.params.reverse().tail
1256:                                .reverse())))));
1257:                return md;
1258:            }
1259:
1260:            /**************************************************************************
1261:             * Free variables proxies and this$n
1262:             *************************************************************************/
1263:
1264:            /** A scope containing all free variable proxies for currently translated
1265:             *  class, as well as its this$n symbol (if needed).
1266:             *  Proxy scopes are nested in the same way classes are.
1267:             *  Inside a constructor, proxies and any this$n symbol are duplicated
1268:             *  in an additional innermost scope, where they represent the constructor
1269:             *  parameters.
1270:             */
1271:            Scope proxies;
1272:
1273:            /** A stack containing the this$n field of the currently translated
1274:             *  classes (if needed) in innermost first order.
1275:             *  Inside a constructor, proxies and any this$n symbol are duplicated
1276:             *  in an additional innermost scope, where they represent the constructor
1277:             *  parameters.
1278:             */
1279:            List<VarSymbol> outerThisStack;
1280:
1281:            /** The name of a free variable proxy.
1282:             */
1283:            Name proxyName(Name name) {
1284:                return names.fromString("val" + target.syntheticNameChar()
1285:                        + name);
1286:            }
1287:
1288:            /** Proxy definitions for all free variables in given list, in reverse order.
1289:             *  @param pos        The source code position of the definition.
1290:             *  @param freevars   The free variables.
1291:             *  @param owner      The class in which the definitions go.
1292:             */
1293:            List<JCVariableDecl> freevarDefs(int pos, List<VarSymbol> freevars,
1294:                    Symbol owner) {
1295:                long flags = FINAL | SYNTHETIC;
1296:                if (owner.kind == TYP && target.usePrivateSyntheticFields())
1297:                    flags |= PRIVATE;
1298:                List<JCVariableDecl> defs = List.nil();
1299:                for (List<VarSymbol> l = freevars; l.nonEmpty(); l = l.tail) {
1300:                    VarSymbol v = l.head;
1301:                    VarSymbol proxy = new VarSymbol(flags, proxyName(v.name), v
1302:                            .erasure(types), owner);
1303:                    proxies.enter(proxy);
1304:                    JCVariableDecl vd = make.at(pos).VarDef(proxy, null);
1305:                    vd.vartype = access(vd.vartype);
1306:                    defs = defs.prepend(vd);
1307:                }
1308:                return defs;
1309:            }
1310:
1311:            /** The name of a this$n field
1312:             *  @param type   The class referenced by the this$n field
1313:             */
1314:            Name outerThisName(Type type, Symbol owner) {
1315:                Type t = type.getEnclosingType();
1316:                int nestingLevel = 0;
1317:                while (t.tag == CLASS) {
1318:                    t = t.getEnclosingType();
1319:                    nestingLevel++;
1320:                }
1321:                Name result = names.fromString("this"
1322:                        + target.syntheticNameChar() + nestingLevel);
1323:                while (owner.kind == TYP
1324:                        && ((ClassSymbol) owner).members().lookup(result).scope != null)
1325:                    result = names.fromString(result.toString()
1326:                            + target.syntheticNameChar());
1327:                return result;
1328:            }
1329:
1330:            /** Definition for this$n field.
1331:             *  @param pos        The source code position of the definition.
1332:             *  @param owner      The class in which the definition goes.
1333:             */
1334:            JCVariableDecl outerThisDef(int pos, Symbol owner) {
1335:                long flags = FINAL | SYNTHETIC;
1336:                if (owner.kind == TYP && target.usePrivateSyntheticFields())
1337:                    flags |= PRIVATE;
1338:                Type target = types.erasure(owner.enclClass().type
1339:                        .getEnclosingType());
1340:                VarSymbol outerThis = new VarSymbol(flags, outerThisName(
1341:                        target, owner), target, owner);
1342:                outerThisStack = outerThisStack.prepend(outerThis);
1343:                JCVariableDecl vd = make.at(pos).VarDef(outerThis, null);
1344:                vd.vartype = access(vd.vartype);
1345:                return vd;
1346:            }
1347:
1348:            /** Return a list of trees that load the free variables in given list,
1349:             *  in reverse order.
1350:             *  @param pos          The source code position to be used for the trees.
1351:             *  @param freevars     The list of free variables.
1352:             */
1353:            List<JCExpression> loadFreevars(DiagnosticPosition pos,
1354:                    List<VarSymbol> freevars) {
1355:                List<JCExpression> args = List.nil();
1356:                for (List<VarSymbol> l = freevars; l.nonEmpty(); l = l.tail)
1357:                    args = args.prepend(loadFreevar(pos, l.head));
1358:                return args;
1359:            }
1360:
1361:            //where
1362:            JCExpression loadFreevar(DiagnosticPosition pos, VarSymbol v) {
1363:                return access(v, make.at(pos).Ident(v), null, false);
1364:            }
1365:
1366:            /** Construct a tree simulating the expression <C.this>.
1367:             *  @param pos           The source code position to be used for the tree.
1368:             *  @param c             The qualifier class.
1369:             */
1370:            JCExpression makeThis(DiagnosticPosition pos, TypeSymbol c) {
1371:                if (currentClass == c) {
1372:                    // in this case, `this' works fine
1373:                    return make.at(pos).This(c.erasure(types));
1374:                } else {
1375:                    // need to go via this$n
1376:                    return makeOuterThis(pos, c);
1377:                }
1378:            }
1379:
1380:            /** Construct a tree that represents the outer instance
1381:             *  <C.this>. Never pick the current `this'.
1382:             *  @param pos           The source code position to be used for the tree.
1383:             *  @param c             The qualifier class.
1384:             */
1385:            JCExpression makeOuterThis(DiagnosticPosition pos, TypeSymbol c) {
1386:                List<VarSymbol> ots = outerThisStack;
1387:                if (ots.isEmpty()) {
1388:                    log.error(pos, "no.encl.instance.of.type.in.scope", c);
1389:                    assert false;
1390:                    return makeNull();
1391:                }
1392:                VarSymbol ot = ots.head;
1393:                JCExpression tree = access(make.at(pos).Ident(ot));
1394:                TypeSymbol otc = ot.type.tsym;
1395:                while (otc != c) {
1396:                    do {
1397:                        ots = ots.tail;
1398:                        if (ots.isEmpty()) {
1399:                            log.error(pos, "no.encl.instance.of.type.in.scope",
1400:                                    c);
1401:                            assert false; // should have been caught in Attr
1402:                            return tree;
1403:                        }
1404:                        ot = ots.head;
1405:                    } while (ot.owner != otc);
1406:                    if (otc.owner.kind != PCK && !otc.hasOuterInstance()) {
1407:                        chk.earlyRefError(pos, c);
1408:                        assert false; // should have been caught in Attr
1409:                        return makeNull();
1410:                    }
1411:                    tree = access(make.at(pos).Select(tree, ot));
1412:                    otc = ot.type.tsym;
1413:                }
1414:                return tree;
1415:            }
1416:
1417:            /** Construct a tree that represents the closest outer instance
1418:             *  <C.this> such that the given symbol is a member of C.
1419:             *  @param pos           The source code position to be used for the tree.
1420:             *  @param sym           The accessed symbol.
1421:             *  @param preciseMatch  should we accept a type that is a subtype of
1422:             *                       sym's owner, even if it doesn't contain sym
1423:             *                       due to hiding, overriding, or non-inheritance
1424:             *                       due to protection?
1425:             */
1426:            JCExpression makeOwnerThis(DiagnosticPosition pos, Symbol sym,
1427:                    boolean preciseMatch) {
1428:                Symbol c = sym.owner;
1429:                if (preciseMatch ? sym.isMemberOf(currentClass, types)
1430:                        : currentClass.isSubClass(sym.owner, types)) {
1431:                    // in this case, `this' works fine
1432:                    return make.at(pos).This(c.erasure(types));
1433:                } else {
1434:                    // need to go via this$n
1435:                    return makeOwnerThisN(pos, sym, preciseMatch);
1436:                }
1437:            }
1438:
1439:            /**
1440:             * Similar to makeOwnerThis but will never pick "this".
1441:             */
1442:            JCExpression makeOwnerThisN(DiagnosticPosition pos, Symbol sym,
1443:                    boolean preciseMatch) {
1444:                Symbol c = sym.owner;
1445:                List<VarSymbol> ots = outerThisStack;
1446:                if (ots.isEmpty()) {
1447:                    log.error(pos, "no.encl.instance.of.type.in.scope", c);
1448:                    assert false;
1449:                    return makeNull();
1450:                }
1451:                VarSymbol ot = ots.head;
1452:                JCExpression tree = access(make.at(pos).Ident(ot));
1453:                TypeSymbol otc = ot.type.tsym;
1454:                while (!(preciseMatch ? sym.isMemberOf(otc, types) : otc
1455:                        .isSubClass(sym.owner, types))) {
1456:                    do {
1457:                        ots = ots.tail;
1458:                        if (ots.isEmpty()) {
1459:                            log.error(pos, "no.encl.instance.of.type.in.scope",
1460:                                    c);
1461:                            assert false;
1462:                            return tree;
1463:                        }
1464:                        ot = ots.head;
1465:                    } while (ot.owner != otc);
1466:                    tree = access(make.at(pos).Select(tree, ot));
1467:                    otc = ot.type.tsym;
1468:                }
1469:                return tree;
1470:            }
1471:
1472:            /** Return tree simulating the assignment <this.name = name>, where
1473:             *  name is the name of a free variable.
1474:             */
1475:            JCStatement initField(int pos, Name name) {
1476:                Scope.Entry e = proxies.lookup(name);
1477:                Symbol rhs = e.sym;
1478:                assert rhs.owner.kind == MTH;
1479:                Symbol lhs = e.next().sym;
1480:                assert rhs.owner.owner == lhs.owner;
1481:                make.at(pos);
1482:                return make.Exec(make.Assign(
1483:                        make.Select(make.This(lhs.owner.erasure(types)), lhs),
1484:                        make.Ident(rhs)).setType(lhs.erasure(types)));
1485:            }
1486:
1487:            /** Return tree simulating the assignment <this.this$n = this$n>.
1488:             */
1489:            JCStatement initOuterThis(int pos) {
1490:                VarSymbol rhs = outerThisStack.head;
1491:                assert rhs.owner.kind == MTH;
1492:                VarSymbol lhs = outerThisStack.tail.head;
1493:                assert rhs.owner.owner == lhs.owner;
1494:                make.at(pos);
1495:                return make.Exec(make.Assign(
1496:                        make.Select(make.This(lhs.owner.erasure(types)), lhs),
1497:                        make.Ident(rhs)).setType(lhs.erasure(types)));
1498:            }
1499:
1500:            /**************************************************************************
1501:             * Code for .class
1502:             *************************************************************************/
1503:
1504:            /** Return the symbol of a class to contain a cache of
1505:             *  compiler-generated statics such as class$ and the
1506:             *  $assertionsDisabled flag.  We create an anonymous nested class
1507:             *  (unless one already exists) and return its symbol.  However,
1508:             *  for backward compatibility in 1.4 and earlier we use the
1509:             *  top-level class itself.
1510:             */
1511:            private ClassSymbol outerCacheClass() {
1512:                ClassSymbol clazz = outermostClassDef.sym;
1513:                if ((clazz.flags() & INTERFACE) == 0
1514:                        && !target.useInnerCacheClass())
1515:                    return clazz;
1516:                Scope s = clazz.members();
1517:                for (Scope.Entry e = s.elems; e != null; e = e.sibling)
1518:                    if (e.sym.kind == TYP && e.sym.name == names.empty
1519:                            && (e.sym.flags() & INTERFACE) == 0)
1520:                        return (ClassSymbol) e.sym;
1521:                return makeEmptyClass(STATIC | SYNTHETIC, clazz);
1522:            }
1523:
1524:            /** Return symbol for "class$" method. If there is no method definition
1525:             *  for class$, construct one as follows:
1526:             *
1527:             *    class class$(String x0) {
1528:             *      try {
1529:             *        return Class.forName(x0);
1530:             *      } catch (ClassNotFoundException x1) {
1531:             *        throw new NoClassDefFoundError(x1.getMessage());
1532:             *      }
1533:             *    }
1534:             */
1535:            private MethodSymbol classDollarSym(DiagnosticPosition pos) {
1536:                ClassSymbol outerCacheClass = outerCacheClass();
1537:                MethodSymbol classDollarSym = (MethodSymbol) lookupSynthetic(
1538:                        classDollar, outerCacheClass.members());
1539:                if (classDollarSym == null) {
1540:                    classDollarSym = new MethodSymbol(STATIC | SYNTHETIC,
1541:                            classDollar, new MethodType(List
1542:                                    .of(syms.stringType), types
1543:                                    .erasure(syms.classType),
1544:                                    List.<Type> nil(), syms.methodClass),
1545:                            outerCacheClass);
1546:                    enterSynthetic(pos, classDollarSym, outerCacheClass
1547:                            .members());
1548:
1549:                    JCMethodDecl md = make.MethodDef(classDollarSym, null);
1550:                    try {
1551:                        md.body = classDollarSymBody(pos, md);
1552:                    } catch (CompletionFailure ex) {
1553:                        md.body = make.Block(0, List.<JCStatement> nil());
1554:                        chk.completionError(pos, ex);
1555:                    }
1556:                    JCClassDecl outerCacheClassDef = classDef(outerCacheClass);
1557:                    outerCacheClassDef.defs = outerCacheClassDef.defs
1558:                            .prepend(md);
1559:                }
1560:                return classDollarSym;
1561:            }
1562:
1563:            /** Generate code for class$(String name). */
1564:            JCBlock classDollarSymBody(DiagnosticPosition pos, JCMethodDecl md) {
1565:                MethodSymbol classDollarSym = md.sym;
1566:                ClassSymbol outerCacheClass = (ClassSymbol) classDollarSym.owner;
1567:
1568:                JCBlock returnResult;
1569:
1570:                // in 1.4.2 and above, we use
1571:                // Class.forName(String name, boolean init, ClassLoader loader);
1572:                // which requires we cache the current loader in cl$
1573:                if (target.classLiteralsNoInit()) {
1574:                    // clsym = "private static ClassLoader cl$"
1575:                    VarSymbol clsym = new VarSymbol(STATIC | SYNTHETIC, names
1576:                            .fromString("cl" + target.syntheticNameChar()),
1577:                            syms.classLoaderType, outerCacheClass);
1578:                    enterSynthetic(pos, clsym, outerCacheClass.members());
1579:
1580:                    // emit "private static ClassLoader cl$;"
1581:                    JCVariableDecl cldef = make.VarDef(clsym, null);
1582:                    JCClassDecl outerCacheClassDef = classDef(outerCacheClass);
1583:                    outerCacheClassDef.defs = outerCacheClassDef.defs
1584:                            .prepend(cldef);
1585:
1586:                    // newcache := "new cache$1[0]"
1587:                    JCNewArray newcache = make.NewArray(make
1588:                            .Type(outerCacheClass.type), List
1589:                            .<JCExpression> of(make.Literal(INT, 0).setType(
1590:                                    syms.intType)), null);
1591:                    newcache.type = new ArrayType(types
1592:                            .erasure(outerCacheClass.type), syms.arrayClass);
1593:
1594:                    // forNameSym := java.lang.Class.forName(
1595:                    //     String s,boolean init,ClassLoader loader)
1596:                    Symbol forNameSym = lookupMethod(make_pos, names.forName,
1597:                            types.erasure(syms.classType), List.of(
1598:                                    syms.stringType, syms.booleanType,
1599:                                    syms.classLoaderType));
1600:                    // clvalue := "(cl$ == null) ?
1601:                    // $newcache.getClass().getComponentType().getClassLoader() : cl$"
1602:                    JCExpression clvalue = make
1603:                            .Conditional(
1604:                                    makeBinary(JCTree.EQ, make.Ident(clsym),
1605:                                            makeNull()),
1606:                                    make.Assign(
1607:                                            make.Ident(clsym),
1608:                                            makeCall(makeCall(makeCall(
1609:                                                    newcache, names.getClass,
1610:                                                    List.<JCExpression> nil()),
1611:                                                    names.getComponentType,
1612:                                                    List.<JCExpression> nil()),
1613:                                                    names.getClassLoader,
1614:                                                    List.<JCExpression> nil()))
1615:                                            .setType(syms.classLoaderType),
1616:                                    make.Ident(clsym)).setType(
1617:                                    syms.classLoaderType);
1618:
1619:                    // returnResult := "{ return Class.forName(param1, false, cl$); }"
1620:                    List<JCExpression> args = List.of(make
1621:                            .Ident(md.params.head.sym), makeLit(
1622:                            syms.booleanType, 0), clvalue);
1623:                    returnResult = make.Block(0, List.<JCStatement> of(make
1624:                            .Call(make. // return
1625:                                    App(make.Ident(forNameSym), args))));
1626:                } else {
1627:                    // forNameSym := java.lang.Class.forName(String s)
1628:                    Symbol forNameSym = lookupMethod(make_pos, names.forName,
1629:                            types.erasure(syms.classType), List
1630:                                    .of(syms.stringType));
1631:                    // returnResult := "{ return Class.forName(param1); }"
1632:                    returnResult = make.Block(0, List.of(make.Call(make. // return
1633:                            App(make.QualIdent(forNameSym), List
1634:                                    .<JCExpression> of(make
1635:                                            .Ident(md.params.head.sym))))));
1636:                }
1637:
1638:                // catchParam := ClassNotFoundException e1
1639:                VarSymbol catchParam = new VarSymbol(0, make.paramName(1),
1640:                        syms.classNotFoundExceptionType, classDollarSym);
1641:
1642:                JCStatement rethrow;
1643:                if (target.hasInitCause()) {
1644:                    // rethrow = "throw new NoClassDefFoundError().initCause(e);
1645:                    JCTree throwExpr = makeCall(makeNewClass(
1646:                            syms.noClassDefFoundErrorType, List
1647:                                    .<JCExpression> nil()), names.initCause,
1648:                            List.<JCExpression> of(make.Ident(catchParam)));
1649:                    rethrow = make.Throw(throwExpr);
1650:                } else {
1651:                    // getMessageSym := ClassNotFoundException.getMessage()
1652:                    Symbol getMessageSym = lookupMethod(make_pos,
1653:                            names.getMessage, syms.classNotFoundExceptionType,
1654:                            List.<Type> nil());
1655:                    // rethrow = "throw new NoClassDefFoundError(e.getMessage());"
1656:                    rethrow = make.Throw(makeNewClass(
1657:                            syms.noClassDefFoundErrorType, List
1658:                                    .<JCExpression> of(make.App(make.Select(
1659:                                            make.Ident(catchParam),
1660:                                            getMessageSym), List
1661:                                            .<JCExpression> nil()))));
1662:                }
1663:
1664:                // rethrowStmt := "( $rethrow )"
1665:                JCBlock rethrowStmt = make.Block(0, List.of(rethrow));
1666:
1667:                // catchBlock := "catch ($catchParam) $rethrowStmt"
1668:                JCCatch catchBlock = make.Catch(make.VarDef(catchParam, null),
1669:                        rethrowStmt);
1670:
1671:                // tryCatch := "try $returnResult $catchBlock"
1672:                JCStatement tryCatch = make.Try(returnResult, List
1673:                        .of(catchBlock), null);
1674:
1675:                return make.Block(0, List.of(tryCatch));
1676:            }
1677:
1678:            // where
1679:            /** Create an attributed tree of the form left.name(). */
1680:            private JCMethodInvocation makeCall(JCExpression left, Name name,
1681:                    List<JCExpression> args) {
1682:                assert left.type != null;
1683:                Symbol funcsym = lookupMethod(make_pos, name, left.type,
1684:                        TreeInfo.types(args));
1685:                return make.App(make.Select(left, funcsym), args);
1686:            }
1687:
1688:            /** The Name Of The variable to cache T.class values.
1689:             *  @param sig      The signature of type T.
1690:             */
1691:            private Name cacheName(String sig) {
1692:                StringBuffer buf = new StringBuffer();
1693:                if (sig.startsWith("[")) {
1694:                    buf = buf.append("array");
1695:                    while (sig.startsWith("[")) {
1696:                        buf = buf.append(target.syntheticNameChar());
1697:                        sig = sig.substring(1);
1698:                    }
1699:                    if (sig.startsWith("L")) {
1700:                        sig = sig.substring(0, sig.length() - 1);
1701:                    }
1702:                } else {
1703:                    buf = buf.append("class" + target.syntheticNameChar());
1704:                }
1705:                buf = buf.append(sig.replace('.', target.syntheticNameChar()));
1706:                return names.fromString(buf.toString());
1707:            }
1708:
1709:            /** The variable symbol that caches T.class values.
1710:             *  If none exists yet, create a definition.
1711:             *  @param sig      The signature of type T.
1712:             *  @param pos	The position to report diagnostics, if any.
1713:             */
1714:            private VarSymbol cacheSym(DiagnosticPosition pos, String sig) {
1715:                ClassSymbol outerCacheClass = outerCacheClass();
1716:                Name cname = cacheName(sig);
1717:                VarSymbol cacheSym = (VarSymbol) lookupSynthetic(cname,
1718:                        outerCacheClass.members());
1719:                if (cacheSym == null) {
1720:                    cacheSym = new VarSymbol(STATIC | SYNTHETIC, cname, types
1721:                            .erasure(syms.classType), outerCacheClass);
1722:                    enterSynthetic(pos, cacheSym, outerCacheClass.members());
1723:
1724:                    JCVariableDecl cacheDef = make.VarDef(cacheSym, null);
1725:                    JCClassDecl outerCacheClassDef = classDef(outerCacheClass);
1726:                    outerCacheClassDef.defs = outerCacheClassDef.defs
1727:                            .prepend(cacheDef);
1728:                }
1729:                return cacheSym;
1730:            }
1731:
1732:            /** The tree simulating a T.class expression.
1733:             *  @param clazz      The tree identifying type T.
1734:             */
1735:            private JCExpression classOf(JCTree clazz) {
1736:                return classOfType(clazz.type, clazz.pos());
1737:            }
1738:
1739:            private JCExpression classOfType(Type type, DiagnosticPosition pos) {
1740:                switch (type.tag) {
1741:                case BYTE:
1742:                case SHORT:
1743:                case CHAR:
1744:                case INT:
1745:                case LONG:
1746:                case FLOAT:
1747:                case DOUBLE:
1748:                case BOOLEAN:
1749:                case VOID:
1750:                    // replace with <BoxedClass>.TYPE
1751:                    ClassSymbol c = types.boxedClass(type);
1752:                    Symbol typeSym = rs.access(rs.findIdentInType(attrEnv,
1753:                            c.type, names.TYPE, VAR), pos, c.type, names.TYPE,
1754:                            true);
1755:                    if (typeSym.kind == VAR)
1756:                        ((VarSymbol) typeSym).getConstValue(); // ensure initializer is evaluated
1757:                    return make.QualIdent(typeSym);
1758:                case CLASS:
1759:                case ARRAY:
1760:                    if (target.hasClassLiterals()) {
1761:                        VarSymbol sym = new VarSymbol(STATIC | PUBLIC | FINAL,
1762:                                names._class, syms.classType, type.tsym);
1763:                        return make_at(pos).Select(make.Type(type), sym);
1764:                    }
1765:                    // replace with <cache == null ? cache = class$(tsig) : cache>
1766:                    // where
1767:                    //  - <tsig>  is the type signature of T,
1768:                    //  - <cache> is the cache variable for tsig.
1769:                    String sig = writer.xClassName(type).toString().replace(
1770:                            '/', '.');
1771:                    Symbol cs = cacheSym(pos, sig);
1772:                    return make_at(pos)
1773:                            .Conditional(
1774:                                    makeBinary(JCTree.EQ, make.Ident(cs),
1775:                                            makeNull()),
1776:                                    make
1777:                                            .Assign(
1778:                                                    make.Ident(cs),
1779:                                                    make
1780:                                                            .App(
1781:                                                                    make
1782:                                                                            .Ident(classDollarSym(pos)),
1783:                                                                    List
1784:                                                                            .<JCExpression> of(make
1785:                                                                                    .Literal(
1786:                                                                                            CLASS,
1787:                                                                                            sig)
1788:                                                                                    .setType(
1789:                                                                                            syms.stringType))))
1790:                                            .setType(
1791:                                                    types
1792:                                                            .erasure(syms.classType)),
1793:                                    make.Ident(cs)).setType(
1794:                                    types.erasure(syms.classType));
1795:                default:
1796:                    throw new AssertionError();
1797:                }
1798:            }
1799:
1800:            /**************************************************************************
1801:             * Code for enabling/disabling assertions.
1802:             *************************************************************************/
1803:
1804:            // This code is not particularly robust if the user has
1805:            // previously declared a member named '$assertionsDisabled'.
1806:            // The same faulty idiom also appears in the translation of
1807:            // class literals above.  We should report an error if a
1808:            // previous declaration is not synthetic.
1809:            private JCExpression assertFlagTest(DiagnosticPosition pos) {
1810:                // Outermost class may be either true class or an interface.
1811:                ClassSymbol outermostClass = outermostClassDef.sym;
1812:
1813:                // note that this is a class, as an interface can't contain a statement.
1814:                ClassSymbol container = currentClass;
1815:
1816:                VarSymbol assertDisabledSym = (VarSymbol) lookupSynthetic(
1817:                        dollarAssertionsDisabled, container.members());
1818:                if (assertDisabledSym == null) {
1819:                    assertDisabledSym = new VarSymbol(STATIC | FINAL
1820:                            | SYNTHETIC, dollarAssertionsDisabled,
1821:                            syms.booleanType, container);
1822:                    enterSynthetic(pos, assertDisabledSym, container.members());
1823:                    Symbol desiredAssertionStatusSym = lookupMethod(pos,
1824:                            names.desiredAssertionStatus, types
1825:                                    .erasure(syms.classType), List.<Type> nil());
1826:                    JCClassDecl containerDef = classDef(container);
1827:                    make_at(containerDef.pos());
1828:                    JCExpression notStatus = makeUnary(JCTree.NOT, make
1829:                            .App(make.Select(classOfType(types
1830:                                    .erasure(outermostClass.type), containerDef
1831:                                    .pos()), desiredAssertionStatusSym)));
1832:                    JCVariableDecl assertDisabledDef = make.VarDef(
1833:                            assertDisabledSym, notStatus);
1834:                    containerDef.defs = containerDef.defs
1835:                            .prepend(assertDisabledDef);
1836:                }
1837:                make_at(pos);
1838:                return makeUnary(JCTree.NOT, make.Ident(assertDisabledSym));
1839:            }
1840:
1841:            /**************************************************************************
1842:             * Building blocks for let expressions
1843:             *************************************************************************/
1844:
1845:            interface TreeBuilder {
1846:                JCTree build(JCTree arg);
1847:            }
1848:
1849:            /** Construct an expression using the builder, with the given rval
1850:             *  expression as an argument to the builder.  However, the rval
1851:             *  expression must be computed only once, even if used multiple
1852:             *  times in the result of the builder.  We do that by
1853:             *  constructing a "let" expression that saves the rvalue into a
1854:             *  temporary variable and then uses the temporary variable in
1855:             *  place of the expression built by the builder.  The complete
1856:             *  resulting expression is of the form
1857:             *  <pre>
1858:             *    (let <b>TYPE</b> <b>TEMP</b> = <b>RVAL</b>;
1859:             *     in (<b>BUILDER</b>(<b>TEMP</b>)))
1860:             *  </pre>
1861:             *  where <code><b>TEMP</b></code> is a newly declared variable
1862:             *  in the let expression.
1863:             */
1864:            JCTree abstractRval(JCTree rval, Type type, TreeBuilder builder) {
1865:                rval = TreeInfo.skipParens(rval);
1866:                switch (rval.getTag()) {
1867:                case JCTree.LITERAL:
1868:                    return builder.build(rval);
1869:                case JCTree.IDENT:
1870:                    JCIdent id = (JCIdent) rval;
1871:                    if ((id.sym.flags() & FINAL) != 0
1872:                            && id.sym.owner.kind == MTH)
1873:                        return builder.build(rval);
1874:                }
1875:                VarSymbol var = new VarSymbol(FINAL | SYNTHETIC, Name
1876:                        .fromString(names, target.syntheticNameChar() + ""
1877:                                + rval.hashCode()), type, currentMethodSym);
1878:                JCVariableDecl def = make.VarDef(var, (JCExpression) rval); // XXX cast
1879:                JCTree built = builder.build(make.Ident(var));
1880:                JCTree res = make.LetExpr(def, built);
1881:                res.type = built.type;
1882:                return res;
1883:            }
1884:
1885:            // same as above, with the type of the temporary variable computed
1886:            JCTree abstractRval(JCTree rval, TreeBuilder builder) {
1887:                return abstractRval(rval, rval.type, builder);
1888:            }
1889:
1890:            // same as above, but for an expression that may be used as either
1891:            // an rvalue or an lvalue.  This requires special handling for
1892:            // Select expressions, where we place the left-hand-side of the
1893:            // select in a temporary, and for Indexed expressions, where we
1894:            // place both the indexed expression and the index value in temps.
1895:            JCTree abstractLval(JCTree lval, final TreeBuilder builder) {
1896:                lval = TreeInfo.skipParens(lval);
1897:                switch (lval.getTag()) {
1898:                case JCTree.IDENT:
1899:                    return builder.build(lval);
1900:                case JCTree.SELECT: {
1901:                    final JCFieldAccess s = (JCFieldAccess) lval;
1902:                    JCTree selected = TreeInfo.skipParens(s.selected);
1903:                    Symbol lid = TreeInfo.symbol(s.selected);
1904:                    if (lid != null && lid.kind == TYP)
1905:                        return builder.build(lval);
1906:                    return abstractRval(s.selected, new TreeBuilder() {
1907:                        public JCTree build(final JCTree selected) {
1908:                            return builder.build(make.Select(
1909:                                    (JCExpression) selected, s.sym));
1910:                        }
1911:                    });
1912:                }
1913:                case JCTree.INDEXED: {
1914:                    final JCArrayAccess i = (JCArrayAccess) lval;
1915:                    return abstractRval(i.indexed, new TreeBuilder() {
1916:                        public JCTree build(final JCTree indexed) {
1917:                            return abstractRval(i.index, syms.intType,
1918:                                    new TreeBuilder() {
1919:                                        public JCTree build(final JCTree index) {
1920:                                            JCTree newLval = make.Indexed(
1921:                                                    (JCExpression) indexed,
1922:                                                    (JCExpression) index);
1923:                                            newLval.setType(i.type);
1924:                                            return builder.build(newLval);
1925:                                        }
1926:                                    });
1927:                        }
1928:                    });
1929:                }
1930:                }
1931:                throw new AssertionError(lval);
1932:            }
1933:
1934:            // evaluate and discard the first expression, then evaluate the second.
1935:            JCTree makeComma(final JCTree expr1, final JCTree expr2) {
1936:                return abstractRval(expr1, new TreeBuilder() {
1937:                    public JCTree build(final JCTree discarded) {
1938:                        return expr2;
1939:                    }
1940:                });
1941:            }
1942:
1943:            /**************************************************************************
1944:             * Translation methods
1945:             *************************************************************************/
1946:
1947:            /** Visitor argument: enclosing operator node.
1948:             */
1949:            private JCExpression enclOp;
1950:
1951:            /** Visitor method: Translate a single node.
1952:             *  Attach the source position from the old tree to its replacement tree.
1953:             */
1954:            public <T extends JCTree> T translate(T tree) {
1955:                if (tree == null) {
1956:                    return null;
1957:                } else {
1958:                    make_at(tree.pos());
1959:                    T result = super .translate(tree);
1960:                    if (endPositions != null && result != tree) {
1961:                        Integer endPos = endPositions.remove(tree);
1962:                        if (endPos != null)
1963:                            endPositions.put(result, endPos);
1964:                    }
1965:                    return result;
1966:                }
1967:            }
1968:
1969:            /** Visitor method: Translate a single node, boxing or unboxing if needed.
1970:             */
1971:            public <T extends JCTree> T translate(T tree, Type type) {
1972:                return (tree == null) ? null : boxIfNeeded(translate(tree),
1973:                        type);
1974:            }
1975:
1976:            /** Visitor method: Translate tree.
1977:             */
1978:            public <T extends JCTree> T translate(T tree, JCExpression enclOp) {
1979:                JCExpression prevEnclOp = this .enclOp;
1980:                this .enclOp = enclOp;
1981:                T res = translate(tree);
1982:                this .enclOp = prevEnclOp;
1983:                return res;
1984:            }
1985:
1986:            /** Visitor method: Translate list of trees.
1987:             */
1988:            public <T extends JCTree> List<T> translate(List<T> trees,
1989:                    JCExpression enclOp) {
1990:                JCExpression prevEnclOp = this .enclOp;
1991:                this .enclOp = enclOp;
1992:                List<T> res = translate(trees);
1993:                this .enclOp = prevEnclOp;
1994:                return res;
1995:            }
1996:
1997:            /** Visitor method: Translate list of trees.
1998:             */
1999:            public <T extends JCTree> List<T> translate(List<T> trees, Type type) {
2000:                if (trees == null)
2001:                    return null;
2002:                for (List<T> l = trees; l.nonEmpty(); l = l.tail)
2003:                    l.head = translate(l.head, type);
2004:                return trees;
2005:            }
2006:
2007:            public void visitTopLevel(JCCompilationUnit tree) {
2008:                if (tree.packageAnnotations.nonEmpty()) {
2009:                    Name name = names.package_info;
2010:                    long flags = Flags.SYNTHETIC | Flags.ABSTRACT
2011:                            | Flags.INTERFACE;
2012:                    JCClassDecl packageAnnotationsClass = make.ClassDef(make
2013:                            .Modifiers(flags, tree.packageAnnotations), name,
2014:                            List.<JCTypeParameter> nil(), null, List
2015:                                    .<JCExpression> nil(), List.<JCTree> nil());
2016:                    ClassSymbol c = reader.enterClass(name, tree.packge);
2017:                    c.flatname = names.fromString(tree.packge + "." + name);
2018:                    c.sourcefile = tree.sourcefile;
2019:                    c.completer = null;
2020:                    c.members_field = new Scope(c);
2021:                    c.flags_field = flags;
2022:                    c.attributes_field = tree.packge.attributes_field;
2023:                    tree.packge.attributes_field = List.nil();
2024:                    ClassType ctype = (ClassType) c.type;
2025:                    ctype.super type_field = syms.objectType;
2026:                    ctype.interfaces_field = List.nil();
2027:                    packageAnnotationsClass.sym = c;
2028:
2029:                    translated.append(packageAnnotationsClass);
2030:                }
2031:            }
2032:
2033:            public void visitClassDef(JCClassDecl tree) {
2034:                ClassSymbol currentClassPrev = currentClass;
2035:                MethodSymbol currentMethodSymPrev = currentMethodSym;
2036:                currentClass = tree.sym;
2037:                currentMethodSym = null;
2038:                classdefs.put(currentClass, tree);
2039:
2040:                proxies = proxies.dup(currentClass);
2041:                List<VarSymbol> prevOuterThisStack = outerThisStack;
2042:
2043:                // If this is an enum definition
2044:                if ((tree.mods.flags & ENUM) != 0
2045:                        && (types.super type(currentClass.type).tsym.flags() & ENUM) == 0)
2046:                    visitEnumDef(tree);
2047:
2048:                // If this is a nested class, define a this$n field for
2049:                // it and add to proxies.
2050:                JCVariableDecl otdef = null;
2051:                if (currentClass.hasOuterInstance())
2052:                    otdef = outerThisDef(tree.pos, currentClass);
2053:
2054:                // If this is a local class, define proxies for all its free variables.
2055:                List<JCVariableDecl> fvdefs = freevarDefs(tree.pos,
2056:                        freevars(currentClass), currentClass);
2057:
2058:                // Recursively translate superclass, interfaces.
2059:                tree.extending = translate(tree.extending);
2060:                tree.implementing = translate(tree.implementing);
2061:
2062:                // Recursively translate members, taking into account that new members
2063:                // might be created during the translation and prepended to the member
2064:                // list `tree.defs'.
2065:                List<JCTree> seen = List.nil();
2066:                while (tree.defs != seen) {
2067:                    List<JCTree> unseen = tree.defs;
2068:                    for (List<JCTree> l = unseen; l.nonEmpty() && l != seen; l = l.tail) {
2069:                        JCTree outermostMemberDefPrev = outermostMemberDef;
2070:                        if (outermostMemberDefPrev == null)
2071:                            outermostMemberDef = l.head;
2072:                        l.head = translate(l.head);
2073:                        outermostMemberDef = outermostMemberDefPrev;
2074:                    }
2075:                    seen = unseen;
2076:                }
2077:
2078:                // Convert a protected modifier to public, mask static modifier.
2079:                if ((tree.mods.flags & PROTECTED) != 0)
2080:                    tree.mods.flags |= PUBLIC;
2081:                tree.mods.flags &= ClassFlags;
2082:
2083:                // Convert name to flat representation, replacing '.' by '$'.
2084:                tree.name = Convert.shortName(currentClass.flatName());
2085:
2086:                // Add this$n and free variables proxy definitions to class.
2087:                for (List<JCVariableDecl> l = fvdefs; l.nonEmpty(); l = l.tail) {
2088:                    tree.defs = tree.defs.prepend(l.head);
2089:                    enterSynthetic(tree.pos(), l.head.sym, currentClass
2090:                            .members());
2091:                }
2092:                if (currentClass.hasOuterInstance()) {
2093:                    tree.defs = tree.defs.prepend(otdef);
2094:                    enterSynthetic(tree.pos(), otdef.sym, currentClass
2095:                            .members());
2096:                }
2097:
2098:                proxies = proxies.leave();
2099:                outerThisStack = prevOuterThisStack;
2100:
2101:                // Append translated tree to `translated' queue.
2102:                translated.append(tree);
2103:
2104:                currentClass = currentClassPrev;
2105:                currentMethodSym = currentMethodSymPrev;
2106:
2107:                // Return empty block {} as a placeholder for an inner class.
2108:                result = make_at(tree.pos()).Block(0, List.<JCStatement> nil());
2109:            }
2110:
2111:            /** Translate an enum class. */
2112:            private void visitEnumDef(JCClassDecl tree) {
2113:                make_at(tree.pos());
2114:
2115:                // add the supertype, if needed
2116:                if (tree.extending == null)
2117:                    tree.extending = make.Type(types.super type(tree.type));
2118:
2119:                // classOfType adds a cache field to tree.defs unless
2120:                // target.hasClassLiterals().
2121:                JCExpression e_class = classOfType(tree.sym.type, tree.pos())
2122:                        .setType(types.erasure(syms.classType));
2123:
2124:                // process each enumeration constant, adding implicit constructor parameters
2125:                int nextOrdinal = 0;
2126:                ListBuffer<JCExpression> values = new ListBuffer<JCExpression>();
2127:                ListBuffer<JCTree> enumDefs = new ListBuffer<JCTree>();
2128:                ListBuffer<JCTree> otherDefs = new ListBuffer<JCTree>();
2129:                for (List<JCTree> defs = tree.defs; defs.nonEmpty(); defs = defs.tail) {
2130:                    if (defs.head.getTag() == JCTree.VARDEF
2131:                            && (((JCVariableDecl) defs.head).mods.flags & ENUM) != 0) {
2132:                        JCVariableDecl var = (JCVariableDecl) defs.head;
2133:                        visitEnumConstantDef(var, nextOrdinal++);
2134:                        values.append(make.QualIdent(var.sym));
2135:                        enumDefs.append(var);
2136:                    } else {
2137:                        otherDefs.append(defs.head);
2138:                    }
2139:                }
2140:
2141:                // private static final T[] #VALUES = { a, b, c };
2142:                Name valuesName = names.fromString(target.syntheticNameChar()
2143:                        + "VALUES");
2144:                while (tree.sym.members().lookup(valuesName).scope != null)
2145:                    // avoid name clash
2146:                    valuesName = names.fromString(valuesName + ""
2147:                            + target.syntheticNameChar());
2148:                Type arrayType = new ArrayType(types.erasure(tree.type),
2149:                        syms.arrayClass);
2150:                VarSymbol valuesVar = new VarSymbol(PRIVATE | FINAL | STATIC
2151:                        | SYNTHETIC, valuesName, arrayType, tree.type.tsym);
2152:                JCNewArray newArray = make.NewArray(make.Type(types
2153:                        .erasure(tree.type)), List.<JCExpression> nil(), values
2154:                        .toList());
2155:                newArray.type = arrayType;
2156:                enumDefs.append(make.VarDef(valuesVar, newArray));
2157:                tree.sym.members().enter(valuesVar);
2158:
2159:                Symbol valuesSym = lookupMethod(tree.pos(), names.values,
2160:                        tree.type, List.<Type> nil());
2161:                JCTypeCast valuesResult = make.TypeCast(valuesSym.type
2162:                        .getReturnType(), make.App(make.Select(make
2163:                        .Ident(valuesVar), syms.arrayCloneMethod)));
2164:                JCMethodDecl valuesDef = make.MethodDef(
2165:                        (MethodSymbol) valuesSym, make.Block(0, List
2166:                                .<JCStatement> nil().prepend(
2167:                                        make.Return(valuesResult))));
2168:                enumDefs.append(valuesDef);
2169:
2170:                /** The template for the following code is:
2171:                 *
2172:                 *     public static E valueOf(String name) {
2173:                 *         return (E)Enum.valueOf(E.class, name);
2174:                 *     }
2175:                 *
2176:                 *  where E is tree.sym
2177:                 */
2178:                MethodSymbol valueOfSym = lookupMethod(tree.pos(),
2179:                        names.valueOf, tree.sym.type, List.of(syms.stringType));
2180:                assert (valueOfSym.flags() & STATIC) != 0;
2181:                VarSymbol nameArgSym = valueOfSym.params.head;
2182:                JCIdent nameVal = make.Ident(nameArgSym);
2183:                JCStatement enum_ValueOf = make.Return(make.TypeCast(
2184:                        tree.sym.type, makeCall(make.Ident(syms.enumSym),
2185:                                names.valueOf, List.of(e_class, nameVal))));
2186:                JCMethodDecl valueOf = make.MethodDef(valueOfSym, make.Block(0,
2187:                        List.of(enum_ValueOf)));
2188:                nameVal.sym = valueOf.params.head.sym;
2189:                if (debugLower)
2190:                    System.err.println(tree.sym + ".valueOf = " + valueOf);
2191:                enumDefs.append(valueOf);
2192:
2193:                enumDefs.appendList(otherDefs.toList());
2194:                tree.defs = enumDefs.toList();
2195:
2196:                // Add the necessary members for the EnumCompatibleMode
2197:                if (target.compilerBootstrap(tree.sym)) {
2198:                    addEnumCompatibleMembers(tree);
2199:                }
2200:            }
2201:
2202:            /** Translate an enumeration constant and its initializer. */
2203:            private void visitEnumConstantDef(JCVariableDecl var, int ordinal) {
2204:                JCNewClass varDef = (JCNewClass) var.init;
2205:                varDef.args = varDef.args.prepend(
2206:                        makeLit(syms.intType, ordinal)).prepend(
2207:                        makeLit(syms.stringType, var.name.toString()));
2208:            }
2209:
2210:            public void visitMethodDef(JCMethodDecl tree) {
2211:                if (tree.name == names.init
2212:                        && (currentClass.flags_field & ENUM) != 0) {
2213:                    // Add "String $enum$name, int $enum$ordinal" to the beginning of the
2214:                    // argument list for each constructor of an enum.
2215:                    JCVariableDecl nameParam = make_at(tree.pos()).Param(
2216:                            names.fromString(target.syntheticNameChar()
2217:                                    + "enum" + target.syntheticNameChar()
2218:                                    + "name"), syms.stringType, tree.sym);
2219:                    nameParam.mods.flags |= SYNTHETIC;
2220:                    nameParam.sym.flags_field |= SYNTHETIC;
2221:
2222:                    JCVariableDecl ordParam = make.Param(names
2223:                            .fromString(target.syntheticNameChar() + "enum"
2224:                                    + target.syntheticNameChar() + "ordinal"),
2225:                            syms.intType, tree.sym);
2226:                    ordParam.mods.flags |= SYNTHETIC;
2227:                    ordParam.sym.flags_field |= SYNTHETIC;
2228:
2229:                    tree.params = tree.params.prepend(ordParam).prepend(
2230:                            nameParam);
2231:
2232:                    MethodSymbol m = tree.sym;
2233:                    Type olderasure = m.erasure(types);
2234:                    m.erasure_field = new MethodType(olderasure
2235:                            .getParameterTypes().prepend(syms.intType).prepend(
2236:                                    syms.stringType), olderasure
2237:                            .getReturnType(), olderasure.getThrownTypes(),
2238:                            syms.methodClass);
2239:
2240:                    if (target.compilerBootstrap(m.owner)) {
2241:                        // Initialize synthetic name field
2242:                        Symbol nameVarSym = lookupSynthetic(names
2243:                                .fromString("$name"), tree.sym.owner.members());
2244:                        JCIdent nameIdent = make.Ident(nameParam.sym);
2245:                        JCIdent id1 = make.Ident(nameVarSym);
2246:                        JCAssign newAssign = make.Assign(id1, nameIdent);
2247:                        newAssign.type = id1.type;
2248:                        JCExpressionStatement nameAssign = make.Exec(newAssign);
2249:                        nameAssign.type = id1.type;
2250:                        tree.body.stats = tree.body.stats.prepend(nameAssign);
2251:
2252:                        // Initialize synthetic ordinal field
2253:                        Symbol ordinalVarSym = lookupSynthetic(names
2254:                                .fromString("$ordinal"), tree.sym.owner
2255:                                .members());
2256:                        JCIdent ordIdent = make.Ident(ordParam.sym);
2257:                        id1 = make.Ident(ordinalVarSym);
2258:                        newAssign = make.Assign(id1, ordIdent);
2259:                        newAssign.type = id1.type;
2260:                        JCExpressionStatement ordinalAssign = make
2261:                                .Exec(newAssign);
2262:                        ordinalAssign.type = id1.type;
2263:                        tree.body.stats = tree.body.stats
2264:                                .prepend(ordinalAssign);
2265:                    }
2266:                }
2267:
2268:                JCMethodDecl prevMethodDef = currentMethodDef;
2269:                MethodSymbol prevMethodSym = currentMethodSym;
2270:                try {
2271:                    currentMethodDef = tree;
2272:                    currentMethodSym = tree.sym;
2273:                    visitMethodDefInternal(tree);
2274:                } finally {
2275:                    currentMethodDef = prevMethodDef;
2276:                    currentMethodSym = prevMethodSym;
2277:                }
2278:            }
2279:
2280:            //where
2281:            private void visitMethodDefInternal(JCMethodDecl tree) {
2282:                if (tree.name == names.init
2283:                        && (currentClass.isInner() || (currentClass.owner.kind & (VAR | MTH)) != 0)) {
2284:                    // We are seeing a constructor of an inner class.
2285:                    MethodSymbol m = tree.sym;
2286:
2287:                    // Push a new proxy scope for constructor parameters.
2288:                    // and create definitions for any this$n and proxy parameters.
2289:                    proxies = proxies.dup(m);
2290:                    List<VarSymbol> prevOuterThisStack = outerThisStack;
2291:                    List<VarSymbol> fvs = freevars(currentClass);
2292:                    JCVariableDecl otdef = null;
2293:                    if (currentClass.hasOuterInstance())
2294:                        otdef = outerThisDef(tree.pos, m);
2295:                    List<JCVariableDecl> fvdefs = freevarDefs(tree.pos, fvs, m);
2296:
2297:                    // Recursively translate result type, parameters and thrown list.
2298:                    tree.restype = translate(tree.restype);
2299:                    tree.params = translateVarDefs(tree.params);
2300:                    tree.thrown = translate(tree.thrown);
2301:
2302:                    // when compiling stubs, don't process body
2303:                    if (tree.body == null) {
2304:                        result = tree;
2305:                        return;
2306:                    }
2307:
2308:                    // Add this$n (if needed) in front of and free variables behind
2309:                    // constructor parameter list.
2310:                    tree.params = tree.params.appendList(fvdefs);
2311:                    if (currentClass.hasOuterInstance())
2312:                        tree.params = tree.params.prepend(otdef);
2313:
2314:                    // If this is an initial constructor, i.e., it does not start with
2315:                    // this(...), insert initializers for this$n and proxies
2316:                    // before (pre-1.4, after) the call to superclass constructor.
2317:                    JCStatement selfCall = translate(tree.body.stats.head);
2318:
2319:                    List<JCStatement> added = List.nil();
2320:                    if (fvs.nonEmpty()) {
2321:                        List<Type> addedargtypes = List.nil();
2322:                        for (List<VarSymbol> l = fvs; l.nonEmpty(); l = l.tail) {
2323:                            if (TreeInfo.isInitialConstructor(tree))
2324:                                added = added.prepend(initField(tree.body.pos,
2325:                                        proxyName(l.head.name)));
2326:                            addedargtypes = addedargtypes.prepend(l.head
2327:                                    .erasure(types));
2328:                        }
2329:                        Type olderasure = m.erasure(types);
2330:                        m.erasure_field = new MethodType(olderasure
2331:                                .getParameterTypes().appendList(addedargtypes),
2332:                                olderasure.getReturnType(), olderasure
2333:                                        .getThrownTypes(), syms.methodClass);
2334:                    }
2335:                    if (currentClass.hasOuterInstance()
2336:                            && TreeInfo.isInitialConstructor(tree)) {
2337:                        added = added.prepend(initOuterThis(tree.body.pos));
2338:                    }
2339:
2340:                    // pop local variables from proxy stack
2341:                    proxies = proxies.leave();
2342:
2343:                    // recursively translate following local statements and
2344:                    // combine with this- or super-call
2345:                    List<JCStatement> stats = translate(tree.body.stats.tail);
2346:                    if (target.initializeFieldsBeforeSuper())
2347:                        tree.body.stats = stats.prepend(selfCall).prependList(
2348:                                added);
2349:                    else
2350:                        tree.body.stats = stats.prependList(added).prepend(
2351:                                selfCall);
2352:
2353:                    outerThisStack = prevOuterThisStack;
2354:                } else {
2355:                    super .visitMethodDef(tree);
2356:                }
2357:                result = tree;
2358:            }
2359:
2360:            public void visitTypeCast(JCTypeCast tree) {
2361:                tree.clazz = translate(tree.clazz);
2362:                if (tree.type.isPrimitive() != tree.expr.type.isPrimitive())
2363:                    tree.expr = translate(tree.expr, tree.type);
2364:                else
2365:                    tree.expr = translate(tree.expr);
2366:                result = tree;
2367:            }
2368:
2369:            public void visitNewClass(JCNewClass tree) {
2370:                ClassSymbol c = (ClassSymbol) tree.constructor.owner;
2371:
2372:                // Box arguments, if necessary
2373:                boolean isEnum = (tree.constructor.owner.flags() & ENUM) != 0;
2374:                List<Type> argTypes = tree.constructor.type.getParameterTypes();
2375:                if (isEnum)
2376:                    argTypes = argTypes.prepend(syms.intType).prepend(
2377:                            syms.stringType);
2378:                tree.args = boxArgs(argTypes, tree.args, tree.varargsElement);
2379:                tree.varargsElement = null;
2380:
2381:                // If created class is local, add free variables after
2382:                // explicit constructor arguments.
2383:                if ((c.owner.kind & (VAR | MTH)) != 0) {
2384:                    tree.args = tree.args.appendList(loadFreevars(tree.pos(),
2385:                            freevars(c)));
2386:                }
2387:
2388:                // If an access constructor is used, append null as a last argument.
2389:                Symbol constructor = accessConstructor(tree.pos(),
2390:                        tree.constructor);
2391:                if (constructor != tree.constructor) {
2392:                    tree.args = tree.args.append(makeNull());
2393:                    tree.constructor = constructor;
2394:                }
2395:
2396:                // If created class has an outer instance, and new is qualified, pass
2397:                // qualifier as first argument. If new is not qualified, pass the
2398:                // correct outer instance as first argument.
2399:                if (c.hasOuterInstance()) {
2400:                    JCExpression this Arg;
2401:                    if (tree.encl != null) {
2402:                        this Arg = attr.makeNullCheck(translate(tree.encl));
2403:                        this Arg.type = tree.encl.type;
2404:                    } else if ((c.owner.kind & (MTH | VAR)) != 0) {
2405:                        // local class
2406:                        this Arg = makeThis(tree.pos(), c.type
2407:                                .getEnclosingType().tsym);
2408:                    } else {
2409:                        // nested class
2410:                        this Arg = makeOwnerThis(tree.pos(), c, false);
2411:                    }
2412:                    tree.args = tree.args.prepend(this Arg);
2413:                }
2414:                tree.encl = null;
2415:
2416:                // If we have an anonymous class, create its flat version, rather
2417:                // than the class or interface following new.
2418:                if (tree.def != null) {
2419:                    translate(tree.def);
2420:                    tree.clazz = access(make_at(tree.clazz.pos()).Ident(
2421:                            tree.def.sym));
2422:                    tree.def = null;
2423:                } else {
2424:                    tree.clazz = access(c, tree.clazz, enclOp, false);
2425:                }
2426:                result = tree;
2427:            }
2428:
2429:            // Simplify conditionals with known constant controlling expressions.
2430:            // This allows us to avoid generating supporting declarations for
2431:            // the dead code, which will not be eliminated during code generation.
2432:            // Note that Flow.isFalse and Flow.isTrue only return true
2433:            // for constant expressions in the sense of JLS 15.27, which
2434:            // are guaranteed to have no side-effects.  More agressive
2435:            // constant propagation would require that we take care to
2436:            // preserve possible side-effects in the condition expression.
2437:
2438:            /** Visitor method for conditional expressions.
2439:             */
2440:            public void visitConditional(JCConditional tree) {
2441:                JCTree cond = tree.cond = translate(tree.cond, syms.booleanType);
2442:                if (cond.type.isTrue()) {
2443:                    result = convert(translate(tree.truepart, tree.type),
2444:                            tree.type);
2445:                } else if (cond.type.isFalse()) {
2446:                    result = convert(translate(tree.falsepart, tree.type),
2447:                            tree.type);
2448:                } else {
2449:                    // Condition is not a compile-time constant.
2450:                    tree.truepart = translate(tree.truepart, tree.type);
2451:                    tree.falsepart = translate(tree.falsepart, tree.type);
2452:                    result = tree;
2453:                }
2454:            }
2455:
2456:            //where
2457:            private JCTree convert(JCTree tree, Type pt) {
2458:                if (tree.type == pt)
2459:                    return tree;
2460:                JCTree result = make_at(tree.pos()).TypeCast(make.Type(pt),
2461:                        (JCExpression) tree);
2462:                result.type = (tree.type.constValue() != null) ? cfolder
2463:                        .coerce(tree.type, pt) : pt;
2464:                return result;
2465:            }
2466:
2467:            /** Visitor method for if statements.
2468:             */
2469:            public void visitIf(JCIf tree) {
2470:                JCTree cond = tree.cond = translate(tree.cond, syms.booleanType);
2471:                if (cond.type.isTrue()) {
2472:                    result = translate(tree.thenpart);
2473:                } else if (cond.type.isFalse()) {
2474:                    if (tree.elsepart != null) {
2475:                        result = translate(tree.elsepart);
2476:                    } else {
2477:                        result = make.Skip();
2478:                    }
2479:                } else {
2480:                    // Condition is not a compile-time constant.
2481:                    tree.thenpart = translate(tree.thenpart);
2482:                    tree.elsepart = translate(tree.elsepart);
2483:                    result = tree;
2484:                }
2485:            }
2486:
2487:            /** Visitor method for assert statements. Translate them away.
2488:             */
2489:            public void visitAssert(JCAssert tree) {
2490:                DiagnosticPosition detailPos = (tree.detail == null) ? tree
2491:                        .pos() : tree.detail.pos();
2492:                tree.cond = translate(tree.cond, syms.booleanType);
2493:                if (!tree.cond.type.isTrue()) {
2494:                    JCExpression cond = assertFlagTest(tree.pos());
2495:                    List<JCExpression> exnArgs = (tree.detail == null) ? List
2496:                            .<JCExpression> nil() : List
2497:                            .of(translate(tree.detail));
2498:                    if (!tree.cond.type.isFalse()) {
2499:                        cond = makeBinary(JCTree.AND, cond, makeUnary(
2500:                                JCTree.NOT, tree.cond));
2501:                    }
2502:                    result = make.If(cond, make_at(detailPos).Throw(
2503:                            makeNewClass(syms.assertionErrorType, exnArgs)),
2504:                            null);
2505:                } else {
2506:                    result = make.Skip();
2507:                }
2508:            }
2509:
2510:            public void visitApply(JCMethodInvocation tree) {
2511:                Symbol meth = TreeInfo.symbol(tree.meth);
2512:                List<Type> argtypes = meth.type.getParameterTypes();
2513:                if (allowEnums && meth.name == names.init
2514:                        && meth.owner == syms.enumSym)
2515:                    argtypes = argtypes.tail.tail;
2516:                tree.args = boxArgs(argtypes, tree.args, tree.varargsElement);
2517:                tree.varargsElement = null;
2518:                Name methName = TreeInfo.name(tree.meth);
2519:                if (meth.name == names.init) {
2520:                    // We are seeing a this(...) or super(...) constructor call.
2521:                    // If an access constructor is used, append null as a last argument.
2522:                    Symbol constructor = accessConstructor(tree.pos(), meth);
2523:                    if (constructor != meth) {
2524:                        tree.args = tree.args.append(makeNull());
2525:                        TreeInfo.setSymbol(tree.meth, constructor);
2526:                    }
2527:
2528:                    // If we are calling a constructor of a local class, add
2529:                    // free variables after explicit constructor arguments.
2530:                    ClassSymbol c = (ClassSymbol) constructor.owner;
2531:                    if ((c.owner.kind & (VAR | MTH)) != 0) {
2532:                        tree.args = tree.args.appendList(loadFreevars(tree
2533:                                .pos(), freevars(c)));
2534:                    }
2535:
2536:                    // If we are calling a constructor of an enum class, pass
2537:                    // along the name and ordinal arguments
2538:                    if ((c.flags_field & ENUM) != 0
2539:                            || c.getQualifiedName() == names.java_lang_Enum) {
2540:                        List<JCVariableDecl> params = currentMethodDef.params;
2541:                        if (currentMethodSym.owner.hasOuterInstance())
2542:                            params = params.tail; // drop this$n
2543:                        tree.args = tree.args
2544:                                .prepend(
2545:                                        make_at(tree.pos()).Ident(
2546:                                                params.tail.head.sym)) // ordinal
2547:                                .prepend(make.Ident(params.head.sym)); // name
2548:                    }
2549:
2550:                    // If we are calling a constructor of a class with an outer
2551:                    // instance, and the call
2552:                    // is qualified, pass qualifier as first argument in front of
2553:                    // the explicit constructor arguments. If the call
2554:                    // is not qualified, pass the correct outer instance as
2555:                    // first argument.
2556:                    if (c.hasOuterInstance()) {
2557:                        JCExpression this Arg;
2558:                        if (tree.meth.getTag() == JCTree.SELECT) {
2559:                            this Arg = attr
2560:                                    .makeNullCheck(translate(((JCFieldAccess) tree.meth).selected));
2561:                            tree.meth = make.Ident(constructor);
2562:                            ((JCIdent) tree.meth).name = methName;
2563:                        } else if ((c.owner.kind & (MTH | VAR)) != 0
2564:                                || methName == names._this ) {
2565:                            // local class or this() call
2566:                            this Arg = makeThis(tree.meth.pos(), c.type
2567:                                    .getEnclosingType().tsym);
2568:                        } else {
2569:                            // super() call of nested class
2570:                            this Arg = makeOwnerThis(tree.meth.pos(), c, false);
2571:                        }
2572:                        tree.args = tree.args.prepend(this Arg);
2573:                    }
2574:                } else {
2575:                    // We are seeing a normal method invocation; translate this as usual.
2576:                    tree.meth = translate(tree.meth);
2577:
2578:                    // If the translated method itself is an Apply tree, we are
2579:                    // seeing an access method invocation. In this case, append
2580:                    // the method arguments to the arguments of the access method.
2581:                    if (tree.meth.getTag() == JCTree.APPLY) {
2582:                        JCMethodInvocation app = (JCMethodInvocation) tree.meth;
2583:                        app.args = tree.args.prependList(app.args);
2584:                        result = app;
2585:                        return;
2586:                    }
2587:                }
2588:                result = tree;
2589:            }
2590:
2591:            List<JCExpression> boxArgs(List<Type> parameters,
2592:                    List<JCExpression> _args, Type varargsElement) {
2593:                List<JCExpression> args = _args;
2594:                if (parameters.isEmpty())
2595:                    return args;
2596:                boolean anyChanges = false;
2597:                ListBuffer<JCExpression> result = new ListBuffer<JCExpression>();
2598:                while (parameters.tail.nonEmpty()) {
2599:                    JCExpression arg = translate(args.head, parameters.head);
2600:                    anyChanges |= (arg != args.head);
2601:                    result.append(arg);
2602:                    args = args.tail;
2603:                    parameters = parameters.tail;
2604:                }
2605:                Type parameter = parameters.head;
2606:                if (varargsElement != null) {
2607:                    anyChanges = true;
2608:                    ListBuffer<JCExpression> elems = new ListBuffer<JCExpression>();
2609:                    while (args.nonEmpty()) {
2610:                        JCExpression arg = translate(args.head, varargsElement);
2611:                        elems.append(arg);
2612:                        args = args.tail;
2613:                    }
2614:                    JCNewArray boxedArgs = make.NewArray(make
2615:                            .Type(varargsElement), List.<JCExpression> nil(),
2616:                            elems.toList());
2617:                    boxedArgs.type = new ArrayType(varargsElement,
2618:                            syms.arrayClass);
2619:                    result.append(boxedArgs);
2620:                } else {
2621:                    if (args.length() != 1)
2622:                        throw new AssertionError(args);
2623:                    JCExpression arg = translate(args.head, parameter);
2624:                    anyChanges |= (arg != args.head);
2625:                    result.append(arg);
2626:                    if (!anyChanges)
2627:                        return _args;
2628:                }
2629:                return result.toList();
2630:            }
2631:
2632:            /** Expand a boxing or unboxing conversion if needed. */
2633:            @SuppressWarnings("unchecked")
2634:            // XXX unchecked
2635:            <T extends JCTree> T boxIfNeeded(T tree, Type type) {
2636:                boolean havePrimitive = tree.type.isPrimitive();
2637:                if (havePrimitive == type.isPrimitive())
2638:                    return tree;
2639:                if (havePrimitive) {
2640:                    Type unboxedTarget = types.unboxedType(type);
2641:                    if (unboxedTarget.tag != NONE) {
2642:                        if (!types.isSubtype(tree.type, unboxedTarget))
2643:                            tree.type = unboxedTarget; // e.g. Character c = 89;
2644:                        return (T) boxPrimitive((JCExpression) tree, type);
2645:                    } else {
2646:                        tree = (T) boxPrimitive((JCExpression) tree);
2647:                    }
2648:                } else {
2649:                    tree = (T) unbox((JCExpression) tree, type);
2650:                }
2651:                return tree;
2652:            }
2653:
2654:            /** Box up a single primitive expression. */
2655:            JCExpression boxPrimitive(JCExpression tree) {
2656:                return boxPrimitive(tree, types.boxedClass(tree.type).type);
2657:            }
2658:
2659:            /** Box up a single primitive expression. */
2660:            JCExpression boxPrimitive(JCExpression tree, Type box) {
2661:                make_at(tree.pos());
2662:                if (target.boxWithConstructors()) {
2663:                    Symbol ctor = lookupConstructor(tree.pos(), box, List
2664:                            .<Type> nil().prepend(tree.type));
2665:                    return make.Create(ctor, List.of(tree));
2666:                } else {
2667:                    Symbol valueOfSym = lookupMethod(tree.pos(), names.valueOf,
2668:                            box, List.<Type> nil().prepend(tree.type));
2669:                    return make.App(make.QualIdent(valueOfSym), List.of(tree));
2670:                }
2671:            }
2672:
2673:            /** Unbox an object to a primitive value. */
2674:            JCExpression unbox(JCExpression tree, Type primitive) {
2675:                Type unboxedType = types.unboxedType(tree.type);
2676:                // note: the "primitive" parameter is not used.  There muse be
2677:                // a conversion from unboxedType to primitive.
2678:                make_at(tree.pos());
2679:                Symbol valueSym = lookupMethod(tree.pos(),
2680:                        unboxedType.tsym.name.append(names.Value), // x.intValue()
2681:                        tree.type, List.<Type> nil());
2682:                return make.App(make.Select(tree, valueSym));
2683:            }
2684:
2685:            /** Visitor method for parenthesized expressions.
2686:             *  If the subexpression has changed, omit the parens.
2687:             */
2688:            public void visitParens(JCParens tree) {
2689:                JCTree expr = translate(tree.expr);
2690:                result = ((expr == tree.expr) ? tree : expr);
2691:            }
2692:
2693:            public void visitIndexed(JCArrayAccess tree) {
2694:                tree.indexed = translate(tree.indexed);
2695:                tree.index = translate(tree.index, syms.intType);
2696:                result = tree;
2697:            }
2698:
2699:            public void visitAssign(JCAssign tree) {
2700:                tree.lhs = translate(tree.lhs, tree);
2701:                tree.rhs = translate(tree.rhs, tree.lhs.type);
2702:
2703:                // If translated left hand side is an Apply, we are
2704:                // seeing an access method invocation. In this case, append
2705:                // right hand side as last argument of the access method.
2706:                if (tree.lhs.getTag() == JCTree.APPLY) {
2707:                    JCMethodInvocation app = (JCMethodInvocation) tree.lhs;
2708:                    app.args = List.of(tree.rhs).prependList(app.args);
2709:                    result = app;
2710:                } else {
2711:                    result = tree;
2712:                }
2713:            }
2714:
2715:            public void visitAssignop(final JCAssignOp tree) {
2716:                if (!tree.lhs.type.isPrimitive()
2717:                        && tree.operator.type.getReturnType().isPrimitive()) {
2718:                    // boxing required; need to rewrite as x = (unbox typeof x)(x op y);
2719:                    // or if x == (typeof x)z then z = (unbox typeof x)((typeof x)z op y)
2720:                    // (but without recomputing x)
2721:                    JCTree arg = (tree.lhs.getTag() == JCTree.TYPECAST) ? ((JCTypeCast) tree.lhs).expr
2722:                            : tree.lhs;
2723:                    JCTree newTree = abstractLval(arg, new TreeBuilder() {
2724:                        public JCTree build(final JCTree lhs) {
2725:                            int newTag = tree.getTag() - JCTree.ASGOffset;
2726:                            // Erasure (TransTypes) can change the type of
2727:                            // tree.lhs.  However, we can still get the
2728:                            // unerased type of tree.lhs as it is stored
2729:                            // in tree.type in Attr.
2730:                            Symbol newOperator = rs.resolveBinaryOperator(tree
2731:                                    .pos(), newTag, attrEnv, tree.type,
2732:                                    tree.rhs.type);
2733:                            JCExpression expr = (JCExpression) lhs;
2734:                            if (expr.type != tree.type)
2735:                                expr = make.TypeCast(tree.type, expr);
2736:                            JCBinary opResult = make.Binary(newTag, expr,
2737:                                    tree.rhs);
2738:                            opResult.operator = newOperator;
2739:                            opResult.type = newOperator.type.getReturnType();
2740:                            JCTypeCast newRhs = make.TypeCast(types
2741:                                    .unboxedType(tree.type), opResult);
2742:                            return make.Assign((JCExpression) lhs, newRhs)
2743:                                    .setType(tree.type);
2744:                        }
2745:                    });
2746:                    result = translate(newTree);
2747:                    return;
2748:                }
2749:                tree.lhs = translate(tree.lhs, tree);
2750:                tree.rhs = translate(tree.rhs, tree.operator.type
2751:                        .getParameterTypes().tail.head);
2752:
2753:                // If translated left hand side is an Apply, we are
2754:                // seeing an access method invocation. In this case, append
2755:                // right hand side as last argument of the access method.
2756:                if (tree.lhs.getTag() == JCTree.APPLY) {
2757:                    JCMethodInvocation app = (JCMethodInvocation) tree.lhs;
2758:                    // if operation is a += on strings,
2759:                    // make sure to convert argument to string
2760:                    JCExpression rhs = (((OperatorSymbol) tree.operator).opcode == string_add) ? makeString(tree.rhs)
2761:                            : tree.rhs;
2762:                    app.args = List.of(rhs).prependList(app.args);
2763:                    result = app;
2764:                } else {
2765:                    result = tree;
2766:                }
2767:            }
2768:
2769:            /** Lower a tree of the form e++ or e-- where e is an object type */
2770:            JCTree lowerBoxedPostop(final JCUnary tree) {
2771:                // translate to tmp1=lval(e); tmp2=tmp1; tmp1 OP 1; tmp2
2772:                // or
2773:                // translate to tmp1=lval(e); tmp2=tmp1; (typeof tree)tmp1 OP 1; tmp2
2774:                // where OP is += or -=
2775:                final boolean cast = tree.arg.getTag() == JCTree.TYPECAST;
2776:                final JCExpression arg = cast ? ((JCTypeCast) tree.arg).expr
2777:                        : tree.arg;
2778:                return abstractLval(arg, new TreeBuilder() {
2779:                    public JCTree build(final JCTree tmp1) {
2780:                        return abstractRval(tmp1, tree.arg.type,
2781:                                new TreeBuilder() {
2782:                                    public JCTree build(final JCTree tmp2) {
2783:                                        int opcode = (tree.getTag() == JCTree.POSTINC) ? JCTree.PLUS_ASG
2784:                                                : JCTree.MINUS_ASG;
2785:                                        JCTree lhs = cast ? make.TypeCast(
2786:                                                tree.arg.type,
2787:                                                (JCExpression) tmp1) : tmp1;
2788:                                        JCTree update = makeAssignop(opcode,
2789:                                                lhs, make.Literal(1));
2790:                                        return makeComma(update, tmp2);
2791:                                    }
2792:                                });
2793:                    }
2794:                });
2795:            }
2796:
2797:            public void visitUnary(JCUnary tree) {
2798:                boolean isUpdateOperator = JCTree.PREINC <= tree.getTag()
2799:                        && tree.getTag() <= JCTree.POSTDEC;
2800:                if (isUpdateOperator && !tree.arg.type.isPrimitive()) {
2801:                    switch (tree.getTag()) {
2802:                    case JCTree.PREINC: // ++ e
2803:                        // translate to e += 1
2804:                    case JCTree.PREDEC: // -- e
2805:                        // translate to e -= 1
2806:                    {
2807:                        int opcode = (tree.getTag() == JCTree.PREINC) ? JCTree.PLUS_ASG
2808:                                : JCTree.MINUS_ASG;
2809:                        JCAssignOp newTree = makeAssignop(opcode, tree.arg,
2810:                                make.Literal(1));
2811:                        result = translate(newTree, tree.type);
2812:                        return;
2813:                    }
2814:                    case JCTree.POSTINC: // e ++
2815:                    case JCTree.POSTDEC: // e --
2816:                    {
2817:                        result = translate(lowerBoxedPostop(tree), tree.type);
2818:                        return;
2819:                    }
2820:                    }
2821:                    throw new AssertionError(tree);
2822:                }
2823:
2824:                tree.arg = boxIfNeeded(translate(tree.arg, tree), tree.type);
2825:
2826:                if (tree.getTag() == JCTree.NOT
2827:                        && tree.arg.type.constValue() != null) {
2828:                    tree.type = cfolder.fold1(bool_not, tree.arg.type);
2829:                }
2830:
2831:                // If translated left hand side is an Apply, we are
2832:                // seeing an access method invocation. In this case, return
2833:                // that access method invokation as result.
2834:                if (isUpdateOperator && tree.arg.getTag() == JCTree.APPLY) {
2835:                    result = tree.arg;
2836:                } else {
2837:                    result = tree;
2838:                }
2839:            }
2840:
2841:            public void visitBinary(JCBinary tree) {
2842:                List<Type> formals = tree.operator.type.getParameterTypes();
2843:                JCTree lhs = tree.lhs = translate(tree.lhs, formals.head);
2844:                switch (tree.getTag()) {
2845:                case JCTree.OR:
2846:                    if (lhs.type.isTrue()) {
2847:                        result = lhs;
2848:                        return;
2849:                    }
2850:                    if (lhs.type.isFalse()) {
2851:                        result = translate(tree.rhs, formals.tail.head);
2852:                        return;
2853:                    }
2854:                    break;
2855:                case JCTree.AND:
2856:                    if (lhs.type.isFalse()) {
2857:                        result = lhs;
2858:                        return;
2859:                    }
2860:                    if (lhs.type.isTrue()) {
2861:                        result = translate(tree.rhs, formals.tail.head);
2862:                        return;
2863:                    }
2864:                    break;
2865:                }
2866:                tree.rhs = translate(tree.rhs, formals.tail.head);
2867:                result = tree;
2868:            }
2869:
2870:            public void visitIdent(JCIdent tree) {
2871:                result = access(tree.sym, tree, enclOp, false);
2872:            }
2873:
2874:            /** Translate away the foreach loop.  */
2875:            public void visitForeachLoop(JCEnhancedForLoop tree) {
2876:                if (types.elemtype(tree.expr.type) == null)
2877:                    visitIterableForeachLoop(tree);
2878:                else
2879:                    visitArrayForeachLoop(tree);
2880:            }
2881:
2882:            // where
2883:            /**
2884:             * A statment of the form
2885:             *
2886:             * <pre>
2887:             *     for ( T v : arrayexpr ) stmt;
2888:             * </pre>
2889:             *
2890:             * (where arrayexpr is of an array type) gets translated to
2891:             *
2892:             * <pre>
2893:             *     for ( { arraytype #arr = arrayexpr;
2894:             *             int #len = array.length;
2895:             *             int #i = 0; };
2896:             *           #i < #len; i$++ ) {
2897:             *         T v = arr$[#i];
2898:             *         stmt;
2899:             *     }
2900:             * </pre>
2901:             *
2902:             * where #arr, #len, and #i are freshly named synthetic local variables.
2903:             */
2904:            private void visitArrayForeachLoop(JCEnhancedForLoop tree) {
2905:                make_at(tree.expr.pos());
2906:                VarSymbol arraycache = new VarSymbol(0, names.fromString("arr"
2907:                        + target.syntheticNameChar()), tree.expr.type,
2908:                        currentMethodSym);
2909:                JCStatement arraycachedef = make.VarDef(arraycache, tree.expr);
2910:                VarSymbol lencache = new VarSymbol(0, names.fromString("len"
2911:                        + target.syntheticNameChar()), syms.intType,
2912:                        currentMethodSym);
2913:                JCStatement lencachedef = make.VarDef(lencache, make.Select(
2914:                        make.Ident(arraycache), syms.lengthVar));
2915:                VarSymbol index = new VarSymbol(0, names.fromString("i"
2916:                        + target.syntheticNameChar()), syms.intType,
2917:                        currentMethodSym);
2918:
2919:                JCVariableDecl indexdef = make.VarDef(index, make.Literal(INT,
2920:                        0));
2921:                indexdef.init.type = indexdef.type = syms.intType.constType(0);
2922:
2923:                List<JCStatement> loopinit = List.of(arraycachedef,
2924:                        lencachedef, indexdef);
2925:                JCBinary cond = makeBinary(JCTree.LT, make.Ident(index), make
2926:                        .Ident(lencache));
2927:
2928:                JCExpressionStatement step = make.Exec(makeUnary(JCTree.PREINC,
2929:                        make.Ident(index)));
2930:
2931:                Type elemtype = types.elemtype(tree.expr.type);
2932:                JCStatement loopvarinit = make.VarDef(tree.var.sym, make
2933:                        .Indexed(make.Ident(arraycache), make.Ident(index))
2934:                        .setType(elemtype));
2935:                JCBlock body = make.Block(0, List.of(loopvarinit, tree.body));
2936:
2937:                result = translate(make.ForLoop(loopinit, cond, List.of(step),
2938:                        body));
2939:                patchTargets(body, tree, result);
2940:            }
2941:
2942:            /** Patch up break and continue targets. */
2943:            private void patchTargets(JCTree body, final JCTree src,
2944:                    final JCTree dest) {
2945:                class Patcher extends TreeScanner {
2946:                    public void visitBreak(JCBreak tree) {
2947:                        if (tree.target == src)
2948:                            tree.target = dest;
2949:                    }
2950:
2951:                    public void visitContinue(JCContinue tree) {
2952:                        if (tree.target == src)
2953:                            tree.target = dest;
2954:                    }
2955:
2956:                    public void visitClassDef(JCClassDecl tree) {
2957:                    }
2958:                }
2959:                new Patcher().scan(body);
2960:            }
2961:
2962:            /**
2963:             * A statement of the form
2964:             *
2965:             * <pre>
2966:             *     for ( T v : coll ) stmt ;
2967:             * </pre>
2968:             *
2969:             * (where coll implements Iterable<? extends T>) gets translated to
2970:             *
2971:             * <pre>
2972:             *     for ( Iterator<? extends T> #i = coll.iterator(); #i.hasNext(); ) {
2973:             *         T v = (T) #i.next();
2974:             *         stmt;
2975:             *     }
2976:             * </pre>
2977:             *
2978:             * where #i is a freshly named synthetic local variable.
2979:             */
2980:            private void visitIterableForeachLoop(JCEnhancedForLoop tree) {
2981:                make_at(tree.expr.pos());
2982:                Type iteratorTarget = syms.objectType;
2983:                Type iterableType = types.asSuper(types
2984:                        .upperBound(tree.expr.type), syms.iterableType.tsym);
2985:                if (iterableType.getTypeArguments().nonEmpty())
2986:                    iteratorTarget = types.erasure(iterableType
2987:                            .getTypeArguments().head);
2988:                Type eType = tree.expr.type;
2989:                tree.expr.type = types.erasure(eType);
2990:                if (eType.tag == TYPEVAR && eType.getUpperBound().isCompound())
2991:                    tree.expr = make.TypeCast(types.erasure(iterableType),
2992:                            tree.expr);
2993:                Symbol iterator = lookupMethod(tree.expr.pos(), names.iterator,
2994:                        types.erasure(syms.iterableType), List.<Type> nil());
2995:                VarSymbol itvar = new VarSymbol(0, names.fromString("i"
2996:                        + target.syntheticNameChar()), types
2997:                        .erasure(iterator.type.getReturnType()),
2998:                        currentMethodSym);
2999:                JCStatement init = make.VarDef(itvar, make.App(make.Select(
3000:                        tree.expr, iterator)));
3001:                Symbol hasNext = lookupMethod(tree.expr.pos(), names.hasNext,
3002:                        itvar.type, List.<Type> nil());
3003:                JCMethodInvocation cond = make.App(make.Select(make
3004:                        .Ident(itvar), hasNext));
3005:                Symbol next = lookupMethod(tree.expr.pos(), names.next,
3006:                        itvar.type, List.<Type> nil());
3007:                JCExpression vardefinit = make.App(make.Select(make
3008:                        .Ident(itvar), next));
3009:                if (iteratorTarget != syms.objectType)
3010:                    vardefinit = make.TypeCast(iteratorTarget, vardefinit);
3011:                JCVariableDecl indexDef = make.VarDef(tree.var.sym, vardefinit);
3012:                JCBlock body = make.Block(0, List.of(indexDef, tree.body));
3013:                result = translate(make.ForLoop(List.of(init), cond, List
3014:                        .<JCExpressionStatement> nil(), body));
3015:                patchTargets(body, tree, result);
3016:            }
3017:
3018:            public void visitVarDef(JCVariableDecl tree) {
3019:                MethodSymbol oldMethodSym = currentMethodSym;
3020:                tree.mods = translate(tree.mods);
3021:                tree.vartype = translate(tree.vartype);
3022:                if (currentMethodSym == null) {
3023:                    // A class or instance field initializer.
3024:                    currentMethodSym = new MethodSymbol(
3025:                            (tree.mods.flags & STATIC) | BLOCK, names.empty,
3026:                            null, currentClass);
3027:                }
3028:                if (tree.init != null)
3029:                    tree.init = translate(tree.init, tree.type);
3030:                result = tree;
3031:                currentMethodSym = oldMethodSym;
3032:            }
3033:
3034:            public void visitBlock(JCBlock tree) {
3035:                MethodSymbol oldMethodSym = currentMethodSym;
3036:                if (currentMethodSym == null) {
3037:                    // Block is a static or instance initializer.
3038:                    currentMethodSym = new MethodSymbol(tree.flags | BLOCK,
3039:                            names.empty, null, currentClass);
3040:                }
3041:                super .visitBlock(tree);
3042:                currentMethodSym = oldMethodSym;
3043:            }
3044:
3045:            public void visitDoLoop(JCDoWhileLoop tree) {
3046:                tree.body = translate(tree.body);
3047:                tree.cond = translate(tree.cond, syms.booleanType);
3048:                result = tree;
3049:            }
3050:
3051:            public void visitWhileLoop(JCWhileLoop tree) {
3052:                tree.cond = translate(tree.cond, syms.booleanType);
3053:                tree.body = translate(tree.body);
3054:                result = tree;
3055:            }
3056:
3057:            public void visitForLoop(JCForLoop tree) {
3058:                tree.init = translate(tree.init);
3059:                if (tree.cond != null)
3060:                    tree.cond = translate(tree.cond, syms.booleanType);
3061:                tree.step = translate(tree.step);
3062:                tree.body = translate(tree.body);
3063:                result = tree;
3064:            }
3065:
3066:            public void visitReturn(JCReturn tree) {
3067:                if (tree.expr != null)
3068:                    tree.expr = translate(tree.expr, types
3069:                            .erasure(currentMethodDef.restype.type));
3070:                result = tree;
3071:            }
3072:
3073:            public void visitSwitch(JCSwitch tree) {
3074:                Type selsuper  = types.super type(tree.selector.type);
3075:                boolean enumSwitch = selsuper  != null
3076:                        && (tree.selector.type.tsym.flags() & ENUM) != 0;
3077:                Type target = enumSwitch ? tree.selector.type : syms.intType;
3078:                tree.selector = translate(tree.selector, target);
3079:                tree.cases = translateCases(tree.cases);
3080:                if (enumSwitch) {
3081:                    result = visitEnumSwitch(tree);
3082:                    patchTargets(result, tree, result);
3083:                } else {
3084:                    result = tree;
3085:                }
3086:            }
3087:
3088:            public JCTree visitEnumSwitch(JCSwitch tree) {
3089:                TypeSymbol enumSym = tree.selector.type.tsym;
3090:                EnumMapping map = mapForEnum(tree.pos(), enumSym);
3091:                make_at(tree.pos());
3092:                Symbol ordinalMethod = lookupMethod(tree.pos(), names.ordinal,
3093:                        tree.selector.type, List.<Type> nil());
3094:                JCArrayAccess selector = make.Indexed(map.mapVar, make.App(make
3095:                        .Select(tree.selector, ordinalMethod)));
3096:                ListBuffer<JCCase> cases = new ListBuffer<JCCase>();
3097:                for (JCCase c : tree.cases) {
3098:                    if (c.pat != null) {
3099:                        VarSymbol label = (VarSymbol) TreeInfo.symbol(c.pat);
3100:                        JCLiteral pat = map.forConstant(label);
3101:                        cases.append(make.Case(pat, c.stats));
3102:                    } else {
3103:                        cases.append(c);
3104:                    }
3105:                }
3106:                return make.Switch(selector, cases.toList());
3107:            }
3108:
3109:            public void visitNewArray(JCNewArray tree) {
3110:                tree.elemtype = translate(tree.elemtype);
3111:                for (List<JCExpression> t = tree.dims; t.tail != null; t = t.tail)
3112:                    if (t.head != null)
3113:                        t.head = translate(t.head, syms.intType);
3114:                tree.elems = translate(tree.elems, types.elemtype(tree.type));
3115:                result = tree;
3116:            }
3117:
3118:            public void visitSelect(JCFieldAccess tree) {
3119:                // need to special case-access of the form C.super.x
3120:                // these will always need an access method.
3121:                boolean qualifiedSuperAccess = tree.selected.getTag() == JCTree.SELECT
3122:                        && TreeInfo.name(tree.selected) == names._super ;
3123:                tree.selected = translate(tree.selected);
3124:                if (tree.name == names._class)
3125:                    result = classOf(tree.selected);
3126:                else if (tree.name == names._this  || tree.name == names._super )
3127:                    result = makeThis(tree.pos(), tree.selected.type.tsym);
3128:                else
3129:                    result = access(tree.sym, tree, enclOp,
3130:                            qualifiedSuperAccess);
3131:            }
3132:
3133:            public void visitLetExpr(LetExpr tree) {
3134:                tree.defs = translateVarDefs(tree.defs);
3135:                tree.expr = translate(tree.expr, tree.type);
3136:                result = tree;
3137:            }
3138:
3139:            // There ought to be nothing to rewrite here;
3140:            // we don't generate code.
3141:            public void visitAnnotation(JCAnnotation tree) {
3142:                result = tree;
3143:            }
3144:
3145:            /**************************************************************************
3146:             * main method
3147:             *************************************************************************/
3148:
3149:            /** Translate a toplevel class and return a list consisting of
3150:             *  the translated class and translated versions of all inner classes.
3151:             *  @param env   The attribution environment current at the class definition.
3152:             *               We need this for resolving some additional symbols.
3153:             *  @param cdef  The tree representing the class definition.
3154:             */
3155:            public List<JCTree> translateTopLevelClass(Env<AttrContext> env,
3156:                    JCTree cdef, TreeMaker make) {
3157:                ListBuffer<JCTree> translated = null;
3158:                try {
3159:                    attrEnv = env;
3160:                    this .make = make;
3161:                    endPositions = env.toplevel.endPositions;
3162:                    currentClass = null;
3163:                    currentMethodDef = null;
3164:                    outermostClassDef = (cdef.getTag() == JCTree.CLASSDEF) ? (JCClassDecl) cdef
3165:                            : null;
3166:                    outermostMemberDef = null;
3167:                    this .translated = new ListBuffer<JCTree>();
3168:                    classdefs = new HashMap<ClassSymbol, JCClassDecl>();
3169:                    actualSymbols = new HashMap<Symbol, Symbol>();
3170:                    freevarCache = new HashMap<ClassSymbol, List<VarSymbol>>();
3171:                    proxies = new Scope(syms.noSymbol);
3172:                    outerThisStack = List.nil();
3173:                    accessNums = new HashMap<Symbol, Integer>();
3174:                    accessSyms = new HashMap<Symbol, MethodSymbol[]>();
3175:                    accessConstrs = new HashMap<Symbol, MethodSymbol>();
3176:                    accessed = new ListBuffer<Symbol>();
3177:                    translate(cdef, (JCExpression) null);
3178:                    for (List<Symbol> l = accessed.toList(); l.nonEmpty(); l = l.tail)
3179:                        makeAccessible(l.head);
3180:                    for (EnumMapping map : enumSwitchMap.values())
3181:                        map.translate();
3182:                    translated = this .translated;
3183:                } finally {
3184:                    // note that recursive invocations of this method fail hard
3185:                    attrEnv = null;
3186:                    this .make = null;
3187:                    endPositions = null;
3188:                    currentClass = null;
3189:                    currentMethodDef = null;
3190:                    outermostClassDef = null;
3191:                    outermostMemberDef = null;
3192:                    this .translated = null;
3193:                    classdefs = null;
3194:                    actualSymbols = null;
3195:                    freevarCache = null;
3196:                    proxies = null;
3197:                    outerThisStack = null;
3198:                    accessNums = null;
3199:                    accessSyms = null;
3200:                    accessConstrs = null;
3201:                    accessed = null;
3202:                    enumSwitchMap.clear();
3203:                }
3204:                return translated.toList();
3205:            }
3206:
3207:            //////////////////////////////////////////////////////////////
3208:            // The following contributed by Borland for bootstrapping purposes
3209:            //////////////////////////////////////////////////////////////
3210:            private void addEnumCompatibleMembers(JCClassDecl cdef) {
3211:                make_at(null);
3212:
3213:                // Add the special enum fields
3214:                VarSymbol ordinalFieldSym = addEnumOrdinalField(cdef);
3215:                VarSymbol nameFieldSym = addEnumNameField(cdef);
3216:
3217:                // Add the accessor methods for name and ordinal
3218:                MethodSymbol ordinalMethodSym = addEnumFieldOrdinalMethod(cdef,
3219:                        ordinalFieldSym);
3220:                MethodSymbol nameMethodSym = addEnumFieldNameMethod(cdef,
3221:                        nameFieldSym);
3222:
3223:                // Add the toString method
3224:                addEnumToString(cdef, nameFieldSym);
3225:
3226:                // Add the compareTo method
3227:                addEnumCompareTo(cdef, ordinalFieldSym);
3228:            }
3229:
3230:            private VarSymbol addEnumOrdinalField(JCClassDecl cdef) {
3231:                VarSymbol ordinal = new VarSymbol(PRIVATE | FINAL | SYNTHETIC,
3232:                        names.fromString("$ordinal"), syms.intType, cdef.sym);
3233:                cdef.sym.members().enter(ordinal);
3234:                cdef.defs = cdef.defs.prepend(make.VarDef(ordinal, null));
3235:                return ordinal;
3236:            }
3237:
3238:            private VarSymbol addEnumNameField(JCClassDecl cdef) {
3239:                VarSymbol name = new VarSymbol(PRIVATE | FINAL | SYNTHETIC,
3240:                        names.fromString("$name"), syms.stringType, cdef.sym);
3241:                cdef.sym.members().enter(name);
3242:                cdef.defs = cdef.defs.prepend(make.VarDef(name, null));
3243:                return name;
3244:            }
3245:
3246:            private MethodSymbol addEnumFieldOrdinalMethod(JCClassDecl cdef,
3247:                    VarSymbol ordinalSymbol) {
3248:                // Add the accessor methods for ordinal
3249:                Symbol ordinalSym = lookupMethod(cdef.pos(), names.ordinal,
3250:                        cdef.type, List.<Type> nil());
3251:
3252:                assert (ordinalSym != null);
3253:                assert (ordinalSym instanceof  MethodSymbol);
3254:
3255:                JCStatement ret = make.Return(make.Ident(ordinalSymbol));
3256:                cdef.defs = cdef.defs.append(make
3257:                        .MethodDef((MethodSymbol) ordinalSym, make.Block(0L,
3258:                                List.of(ret))));
3259:
3260:                return (MethodSymbol) ordinalSym;
3261:            }
3262:
3263:            private MethodSymbol addEnumFieldNameMethod(JCClassDecl cdef,
3264:                    VarSymbol nameSymbol) {
3265:                // Add the accessor methods for name
3266:                Symbol nameSym = lookupMethod(cdef.pos(), names._name,
3267:                        cdef.type, List.<Type> nil());
3268:
3269:                assert (nameSym != null);
3270:                assert (nameSym instanceof  MethodSymbol);
3271:
3272:                JCStatement ret = make.Return(make.Ident(nameSymbol));
3273:
3274:                cdef.defs = cdef.defs.append(make.MethodDef(
3275:                        (MethodSymbol) nameSym, make.Block(0L, List.of(ret))));
3276:
3277:                return (MethodSymbol) nameSym;
3278:            }
3279:
3280:            private MethodSymbol addEnumToString(JCClassDecl cdef,
3281:                    VarSymbol nameSymbol) {
3282:                Symbol toStringSym = lookupMethod(cdef.pos(), names.toString,
3283:                        cdef.type, List.<Type> nil());
3284:
3285:                JCTree toStringDecl = null;
3286:                if (toStringSym != null)
3287:                    toStringDecl = TreeInfo.declarationFor(toStringSym, cdef);
3288:
3289:                if (toStringDecl != null)
3290:                    return (MethodSymbol) toStringSym;
3291:
3292:                JCStatement ret = make.Return(make.Ident(nameSymbol));
3293:
3294:                JCTree resTypeTree = make.Type(syms.stringType);
3295:
3296:                MethodType toStringType = new MethodType(List.<Type> nil(),
3297:                        syms.stringType, List.<Type> nil(), cdef.sym);
3298:                toStringSym = new MethodSymbol(PUBLIC, names.toString,
3299:                        toStringType, cdef.type.tsym);
3300:                toStringDecl = make.MethodDef((MethodSymbol) toStringSym, make
3301:                        .Block(0L, List.of(ret)));
3302:
3303:                cdef.defs = cdef.defs.prepend(toStringDecl);
3304:                cdef.sym.members().enter(toStringSym);
3305:
3306:                return (MethodSymbol) toStringSym;
3307:            }
3308:
3309:            private MethodSymbol addEnumCompareTo(JCClassDecl cdef,
3310:                    VarSymbol ordinalSymbol) {
3311:                Symbol compareToSym = lookupMethod(cdef.pos(), names.compareTo,
3312:                        cdef.type, List.of(cdef.sym.type));
3313:
3314:                assert (compareToSym != null);
3315:                assert (compareToSym instanceof  MethodSymbol);
3316:
3317:                JCMethodDecl compareToDecl = (JCMethodDecl) TreeInfo
3318:                        .declarationFor(compareToSym, cdef);
3319:
3320:                ListBuffer<JCStatement> blockStatements = new ListBuffer<JCStatement>();
3321:
3322:                JCModifiers mod1 = make.Modifiers(0L);
3323:                Name oName = Name.fromString(names, "o");
3324:                JCVariableDecl par1 = make
3325:                        .Param(oName, cdef.type, compareToSym);
3326:
3327:                JCIdent paramId1 = make.Ident(names.java_lang_Object);
3328:                paramId1.type = cdef.type;
3329:                paramId1.sym = par1.sym;
3330:
3331:                ((MethodSymbol) compareToSym).params = List.of(par1.sym);
3332:
3333:                JCIdent par1UsageId = make.Ident(par1.sym);
3334:                JCIdent castTargetIdent = make.Ident(cdef.sym);
3335:                JCTypeCast cast = make.TypeCast(castTargetIdent, par1UsageId);
3336:                cast.setType(castTargetIdent.type);
3337:
3338:                Name otherName = Name.fromString(names, "other");
3339:
3340:                VarSymbol otherVarSym = new VarSymbol(mod1.flags, otherName,
3341:                        cdef.type, compareToSym);
3342:                JCVariableDecl otherVar = make.VarDef(otherVarSym, cast);
3343:                blockStatements.append(otherVar);
3344:
3345:                JCIdent id1 = make.Ident(ordinalSymbol);
3346:
3347:                JCIdent fLocUsageId = make.Ident(otherVarSym);
3348:                JCExpression sel = make.Select(fLocUsageId, ordinalSymbol);
3349:                JCBinary bin = makeBinary(JCTree.MINUS, id1, sel);
3350:                JCReturn ret = make.Return(bin);
3351:                blockStatements.append(ret);
3352:                JCMethodDecl compareToMethod = make.MethodDef(
3353:                        (MethodSymbol) compareToSym, make.Block(0L,
3354:                                blockStatements.toList()));
3355:                compareToMethod.params = List.of(par1);
3356:                cdef.defs = cdef.defs.append(compareToMethod);
3357:
3358:                return (MethodSymbol) compareToSym;
3359:            }
3360:            //////////////////////////////////////////////////////////////
3361:            // The above contributed by Borland for bootstrapping purposes
3362:            //////////////////////////////////////////////////////////////
3363:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.