KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > polyglot > ext > jl > types > TypeSystem_c


1 package polyglot.ext.jl.types;
2
3 import java.lang.reflect.Modifier JavaDoc;
4 import java.util.*;
5
6 import polyglot.frontend.ExtensionInfo;
7 import polyglot.frontend.Source;
8 import polyglot.main.Report;
9 import polyglot.types.*;
10 import polyglot.types.Package;
11 import polyglot.util.InternalCompilerError;
12 import polyglot.util.Position;
13 import polyglot.util.StringUtil;
14
15 /**
16  * TypeSystem_c
17  *
18  * Overview:
19  * A TypeSystem_c is a universe of types, including all Java types.
20  **/

21 public class TypeSystem_c implements TypeSystem
22 {
23     protected TopLevelResolver systemResolver;
24     protected TableResolver parsedResolver;
25     protected LoadedClassResolver loadedResolver;
26     protected Map flagsForName;
27
28     public TypeSystem_c() {}
29
30     /**
31      * Initializes the type system and its internal constants (which depend on
32      * the resolver).
33      */

34     public void initialize(LoadedClassResolver loadedResolver, ExtensionInfo extInfo)
35                            throws SemanticException {
36
37         if (Report.should_report(Report.types, 1))
38         Report.report(1, "Initializing " + getClass().getName());
39
40         // The parsed class resolver. This resolver contains classes parsed
41
// from source files.
42
this.parsedResolver = new TableResolver();
43
44
45         // The loaded class resolver. This resolver automatically loads types
46
// from class files and from source files not mentioned on the command
47
// line.
48
this.loadedResolver = loadedResolver;
49
50         CompoundResolver compoundResolver =
51             new CompoundResolver(parsedResolver, loadedResolver);
52
53         // The system class resolver. The class resolver contains a map from
54
// class names to ClassTypes. A Job looks up classes first in its
55
// import table and then in the system resolver. The system resolver
56
// first tries to find the class in parsed class resolver.
57
this.systemResolver = new CachingResolver(compoundResolver, extInfo);
58
59         initFlags();
60
61         initTypes();
62     }
63
64     protected void initTypes() throws SemanticException {
65         // FIXME: don't do this when rewriting a type system!
66

67         // Prime the resolver cache so that we don't need to check
68
// later if these are loaded.
69

70         // We cache the most commonly used ones in fields.
71
/* DISABLED CACHING OF COMMON CLASSES; CAUSES PROBLEMS IF
72            COMPILING CORE CLASSES (e.g. java.lang package).
73            TODO: Longer term fix. Maybe a flag to tell if we are compiling
74                  core classes? XXX
75         Object();
76         Class();
77         String();
78         Throwable();
79
80         systemResolver.find("java.lang.Error");
81         systemResolver.find("java.lang.Exception");
82         systemResolver.find("java.lang.RuntimeException");
83         systemResolver.find("java.lang.Cloneable");
84         systemResolver.find("java.io.Serializable");
85         systemResolver.find("java.lang.NullPointerException");
86         systemResolver.find("java.lang.ClassCastException");
87         systemResolver.find("java.lang.ArrayIndexOutOfBoundsException");
88         systemResolver.find("java.lang.ArrayStoreException");
89         systemResolver.find("java.lang.ArithmeticException");
90         */

91     }
92
93     public TopLevelResolver systemResolver() {
94       return systemResolver;
95     }
96
97     public TableResolver parsedResolver() {
98         return parsedResolver;
99     }
100
101     public LoadedClassResolver loadedResolver() {
102         return loadedResolver;
103     }
104
105     public ImportTable importTable(String JavaDoc sourceName, Package JavaDoc pkg) {
106         assert_(pkg);
107         return new ImportTable(this, systemResolver, pkg, sourceName);
108     }
109
110     public ImportTable importTable(Package JavaDoc pkg) {
111         assert_(pkg);
112         return new ImportTable(this, systemResolver, pkg);
113     }
114
115     /**
116      * Returns true if the package named <code>name</code> exists.
117      */

118     public boolean packageExists(String JavaDoc name) {
119         return systemResolver.packageExists(name);
120     }
121
122     protected void assert_(Collection l) {
123         for (Iterator i = l.iterator(); i.hasNext(); ) {
124             TypeObject o = (TypeObject) i.next();
125             assert_(o);
126         }
127     }
128
129     protected void assert_(TypeObject o) {
130         if (o != null && o.typeSystem() != this) {
131             throw new InternalCompilerError("we are " + this + " but " + o +
132                                             " is from " + o.typeSystem());
133         }
134     }
135
136     public String JavaDoc wrapperTypeString(PrimitiveType t) {
137         assert_(t);
138
139     if (t.kind() == PrimitiveType.BOOLEAN) {
140         return "java.lang.Boolean";
141     }
142     if (t.kind() == PrimitiveType.CHAR) {
143         return "java.lang.Character";
144     }
145     if (t.kind() == PrimitiveType.BYTE) {
146         return "java.lang.Byte";
147     }
148     if (t.kind() == PrimitiveType.SHORT) {
149         return "java.lang.Short";
150     }
151     if (t.kind() == PrimitiveType.INT) {
152         return "java.lang.Integer";
153     }
154     if (t.kind() == PrimitiveType.LONG) {
155         return "java.lang.Long";
156     }
157     if (t.kind() == PrimitiveType.FLOAT) {
158         return "java.lang.Float";
159     }
160     if (t.kind() == PrimitiveType.DOUBLE) {
161         return "java.lang.Double";
162     }
163     if (t.kind() == PrimitiveType.VOID) {
164         return "java.lang.Void";
165     }
166
167     throw new InternalCompilerError("Unrecognized primitive type.");
168     }
169
170     public Context createContext() {
171     return new Context_c(this);
172     }
173
174     public Resolver packageContextResolver(Resolver cr, Package JavaDoc p) {
175         assert_(p);
176     return new PackageContextResolver(this, p, cr);
177     }
178
179     public Resolver classContextResolver(ClassType type) {
180         assert_(type);
181     return new ClassContextResolver(this, type);
182     }
183
184     public FieldInstance fieldInstance(Position pos,
185                                    ReferenceType container, Flags flags,
186                        Type type, String JavaDoc name) {
187         assert_(container);
188         assert_(type);
189     return new FieldInstance_c(this, pos, container, flags, type, name);
190     }
191
192     public LocalInstance localInstance(Position pos,
193                                    Flags flags, Type type, String JavaDoc name) {
194         assert_(type);
195     return new LocalInstance_c(this, pos, flags, type, name);
196     }
197
198     public ConstructorInstance defaultConstructor(Position pos,
199                                                   ClassType container) {
200         assert_(container);
201         
202         // access for the default constructor is determined by the
203
// access of the containing class. See the JLS, 2nd Ed., 8.8.7.
204
Flags access = Flags.NONE;
205         if (container.flags().isPrivate()) {
206             access = access.Private();
207         }
208         if (container.flags().isProtected()) {
209             access = access.Protected();
210         }
211         if (container.flags().isPublic()) {
212             access = access.Public();
213         }
214         return constructorInstance(pos, container,
215                                    access, Collections.EMPTY_LIST,
216                                    Collections.EMPTY_LIST);
217     }
218
219     public ConstructorInstance constructorInstance(Position pos,
220                                                ClassType container,
221                            Flags flags, List argTypes,
222                            List excTypes) {
223         assert_(container);
224         assert_(argTypes);
225         assert_(excTypes);
226     return new ConstructorInstance_c(this, pos, container, flags,
227                                      argTypes, excTypes);
228     }
229
230     public InitializerInstance initializerInstance(Position pos,
231                                                ClassType container,
232                            Flags flags) {
233         assert_(container);
234     return new InitializerInstance_c(this, pos, container, flags);
235     }
236
237     public MethodInstance methodInstance(Position pos,
238                                      ReferenceType container, Flags flags,
239                      Type returnType, String JavaDoc name,
240                      List argTypes, List excTypes) {
241
242         assert_(container);
243         assert_(returnType);
244         assert_(argTypes);
245         assert_(excTypes);
246     return new MethodInstance_c(this, pos, container, flags,
247                     returnType, name, argTypes, excTypes);
248     }
249
250     /**
251      * Returns true iff child and ancestor are distinct
252      * reference types, and child descends from ancestor.
253      **/

254     public boolean descendsFrom(Type child, Type ancestor) {
255         assert_(child);
256         assert_(ancestor);
257         return child.descendsFromImpl(ancestor);
258     }
259
260     /**
261      * Requires: all type arguments are canonical. ToType is not a NullType.
262      *
263      * Returns true iff a cast from fromType to toType is valid; in other
264      * words, some non-null members of fromType are also members of toType.
265      **/

266     public boolean isCastValid(Type fromType, Type toType) {
267         assert_(fromType);
268         assert_(toType);
269         return fromType.isCastValidImpl(toType);
270     }
271
272     /**
273      * Requires: all type arguments are canonical.
274      *
275      * Returns true iff an implicit cast from fromType to toType is valid;
276      * in other words, every member of fromType is member of toType.
277      *
278      * Returns true iff child and ancestor are non-primitive
279      * types, and a variable of type child may be legally assigned
280      * to a variable of type ancestor.
281      *
282      */

283     public boolean isImplicitCastValid(Type fromType, Type toType) {
284         assert_(fromType);
285         assert_(toType);
286         return fromType.isImplicitCastValidImpl(toType);
287     }
288
289     /**
290      * Returns true iff type1 and type2 represent the same type object.
291      */

292     public boolean equals(TypeObject type1, TypeObject type2) {
293         assert_(type1);
294         assert_(type2);
295         if (type1 instanceof TypeObject_c) {
296             return ((TypeObject_c)type1).equalsImpl(type2);
297         } else {
298             throw new InternalCompilerError("Unknown implementation of "
299                 + "TypeObject", type1.position());
300         }
301     }
302
303     /**
304      * Returns true if <code>value</code> can be implicitly cast to Primitive
305      * type <code>t</code>.
306      */

307     public boolean numericConversionValid(Type t, Object JavaDoc value) {
308         assert_(t);
309         return t.numericConversionValidImpl(value);
310     }
311
312     /**
313      * Returns true if <code>value</code> can be implicitly cast to Primitive
314      * type <code>t</code>. This method should be removed. It is kept for
315      * backward compatibility.
316      */

317     public boolean numericConversionValid(Type t, long value) {
318         assert_(t);
319         return t.numericConversionValidImpl(value);
320     }
321
322     ////
323
// Functions for one-type checking and resolution.
324
////
325

326     /**
327      * Returns true iff <type> is a canonical (fully qualified) type.
328      */

329     public boolean isCanonical(Type type) {
330         assert_(type);
331     return type.isCanonical();
332     }
333
334     /**
335      * Checks whether the member mi can be accessed from Context "context".
336      */

337     public boolean isAccessible(MemberInstance mi, Context context) {
338         return isAccessible(mi, context.currentClass());
339     }
340
341     /**
342      * Checks whether the member mi can be accessed from code that is
343      * declared in the class contextClass.
344      */

345     protected boolean isAccessible(MemberInstance mi, ClassType contextClass) {
346         assert_(mi);
347
348         ReferenceType target = mi.container();
349     Flags flags = mi.flags();
350
351         if (! target.isClass()) {
352             // public members of non-classes are accessible;
353
// non-public members of non-classes are inaccessible
354
return flags.isPublic();
355         }
356
357         ClassType targetClass = target.toClass();
358
359         if (! classAccessible(targetClass, contextClass)) {
360             return false;
361         }
362
363         if (equals(targetClass, contextClass))
364             return true;
365
366         // If the current class and the target class are both in the
367
// same class body, then protection doesn't matter, i.e.
368
// protected and private members may be accessed. Do this by
369
// working up through contextClass's containers.
370
if (isEnclosed(contextClass, targetClass) || isEnclosed(targetClass, contextClass))
371             return true;
372
373         ClassType ct = contextClass;
374         while (!ct.isTopLevel()) {
375             ct = ct.outer();
376             if (isEnclosed(targetClass, ct))
377                 return true;
378         }
379
380     // protected
381
if (flags.isProtected()) {
382             // If the current class is in a
383
// class body that extends/implements the target class, then
384
// protected members can be accessed. Do this by
385
// working up through contextClass's containers.
386
if (descendsFrom(contextClass, targetClass)) {
387                 return true;
388             }
389
390             ct = contextClass;
391             while (!ct.isTopLevel()) {
392                 ct = ct.outer();
393                 if (descendsFrom(ct, targetClass)) {
394                     return true;
395                 }
396             }
397         }
398
399         return accessibleFromPackage(flags, targetClass.package_(), contextClass.package_());
400     }
401
402     /** True if the class targetClass accessible from the context. */
403     public boolean classAccessible(ClassType targetClass, Context context) {
404         if (context.currentClass() == null) {
405             return classAccessibleFromPackage(targetClass, context.importTable().package_());
406         }
407         else {
408             return classAccessible(targetClass, context.currentClass());
409         }
410     }
411
412     /** True if the class targetClass accessible from the body of class contextClass. */
413     protected boolean classAccessible(ClassType targetClass, ClassType contextClass) {
414         assert_(targetClass);
415
416         if (targetClass.isMember()) {
417             return isAccessible(targetClass, contextClass);
418         }
419
420         // Local and anonymous classes are accessible if they can be named.
421
// This method wouldn't be called if they weren't named.
422
if (! targetClass.isTopLevel()) {
423             return true;
424         }
425
426         // targetClass must be a top-level class
427

428         // same class
429
if (equals(targetClass, contextClass))
430             return true;
431
432         if (isEnclosed(contextClass, targetClass))
433             return true;
434
435         return accessibleFromPackage(targetClass.flags(),
436                                      targetClass.package_(), contextClass.package_());
437     }
438
439     /** True if the class targetClass accessible from the package pkg. */
440     public boolean classAccessibleFromPackage(ClassType targetClass, Package JavaDoc pkg) {
441         assert_(targetClass);
442
443         // Local and anonymous classes are not accessible from the outermost
444
// scope of a compilation unit.
445
if (! targetClass.isTopLevel() && ! targetClass.isMember())
446             return false;
447
448     Flags flags = targetClass.flags();
449
450         if (targetClass.isMember()) {
451             if (! targetClass.container().isClass()) {
452                 // public members of non-classes are accessible
453
return flags.isPublic();
454             }
455
456             if (! classAccessibleFromPackage(targetClass.container().toClass(), pkg)) {
457                 return false;
458             }
459         }
460
461         return accessibleFromPackage(flags, targetClass.package_(), pkg);
462     }
463
464     /**
465      * Return true if a member (in an accessible container) or a
466      * top-level class with access flags <code>flags</code>
467      * in package <code>pkg1</code> is accessible from package
468      * <code>pkg2</code>.
469      */

470     protected boolean accessibleFromPackage(Flags flags, Package JavaDoc pkg1, Package JavaDoc pkg2) {
471         // Check if public.
472
if (flags.isPublic()) {
473             return true;
474         }
475
476         // Check if same package.
477
if (flags.isPackage() || flags.isProtected()) {
478             if (pkg1 == null && pkg2 == null)
479                 return true;
480             if (pkg1 != null && pkg1.equals(pkg2))
481                 return true;
482     }
483
484         // Otherwise private.
485
return false;
486     }
487
488     public boolean isEnclosed(ClassType inner, ClassType outer) {
489         return inner.isEnclosedImpl(outer);
490     }
491
492     public boolean hasEnclosingInstance(ClassType inner, ClassType encl) {
493         return inner.hasEnclosingInstanceImpl(encl);
494     }
495
496     public void checkCycles(ReferenceType goal) throws SemanticException {
497     checkCycles(goal, goal);
498     }
499
500     protected void checkCycles(ReferenceType curr, ReferenceType goal)
501     throws SemanticException {
502
503         assert_(curr);
504         assert_(goal);
505
506     if (curr == null) {
507         return;
508     }
509
510     ReferenceType superType = null;
511
512     if (curr.superType() != null) {
513         superType = curr.superType().toReference();
514     }
515
516     if (goal == superType) {
517         throw new SemanticException("Circular inheritance involving " + goal,
518                                         curr.position());
519     }
520
521     checkCycles(superType, goal);
522
523     for (Iterator i = curr.interfaces().iterator(); i.hasNext(); ) {
524         Type si = (Type) i.next();
525
526         if (si == goal) {
527                 throw new SemanticException("Circular inheritance involving " + goal,
528                                             curr.position());
529         }
530
531         checkCycles(si.toReference(), goal);
532         }
533         if (curr.isClass()) {
534             checkCycles(curr.toClass().outer(), goal);
535         }
536     }
537
538     ////
539
// Various one-type predicates.
540
////
541

542     /**
543      * Returns true iff the type t can be coerced to a String in the given
544      * Context. If a type can be coerced to a String then it can be
545      * concatenated with Strings, e.g. if o is of type T, then the code snippet
546      * "" + o
547      * would be allowed.
548      */

549     public boolean canCoerceToString(Type t, Context c) {
550         // every Object can be coerced to a string, as can any primitive,
551
// except void.
552
return ! t.isVoid();
553     }
554
555     /**
556      * Returns true iff an object of type <type> may be thrown.
557      **/

558     public boolean isThrowable(Type type) {
559         assert_(type);
560         return type.isThrowable();
561     }
562
563     /**
564      * Returns a true iff the type or a supertype is in the list
565      * returned by uncheckedExceptions().
566      */

567     public boolean isUncheckedException(Type type) {
568         assert_(type);
569         return type.isUncheckedException();
570     }
571
572     /**
573      * Returns a list of the Throwable types that need not be declared
574      * in method and constructor signatures.
575      */

576     public Collection uncheckedExceptions() {
577         List l = new ArrayList(2);
578     l.add(Error());
579     l.add(RuntimeException());
580     return l;
581     }
582
583     public boolean isSubtype(Type t1, Type t2) {
584         assert_(t1);
585         assert_(t2);
586         return t1.isSubtypeImpl(t2);
587     }
588
589     ////
590
// Functions for type membership.
591
////
592

593     /**
594      * @deprecated
595      */

596     public FieldInstance findField(ReferenceType container, String JavaDoc name,
597                                Context c) throws SemanticException {
598         ClassType ct = null;
599         if (c != null) ct = c.currentClass();
600         return findField(container, name, ct);
601     }
602     
603     /**
604      * Returns the FieldInstance for the field <code>name</code> defined
605      * in type <code>container</code> or a supertype, and visible from
606      * <code>currClass</code>. If no such field is found, a SemanticException
607      * is thrown. <code>currClass</code> may be null.
608      **/

609     public FieldInstance findField(ReferenceType container, String JavaDoc name,
610                                ClassType currClass) throws SemanticException {
611     Collection fields = findFields(container, name);
612     
613     if (fields.size() == 0) {
614         throw new NoMemberException(NoMemberException.FIELD,
615                     "Field \"" + name +
616                     "\" not found in type \"" +
617                     container + "\".");
618     }
619     
620     Iterator i = fields.iterator();
621     FieldInstance fi = (FieldInstance) i.next();
622     
623     if (i.hasNext()) {
624         FieldInstance fi2 = (FieldInstance) i.next();
625         
626         throw new SemanticException("Field \"" + name +
627                     "\" is ambiguous; it is defined in both " +
628                     fi.container() + " and " +
629                     fi2.container() + ".");
630     }
631     
632     if (currClass != null && ! isAccessible(fi, currClass)) {
633             throw new SemanticException("Cannot access " + fi + ".");
634         }
635     
636         return fi;
637     }
638
639     /**
640      * Returns the FieldInstance for the field <code>name</code> defined
641      * in type <code>container</code> or a supertype. If no such field is
642      * found, a SemanticException is thrown.
643      */

644     public FieldInstance findField(ReferenceType container, String JavaDoc name)
645     throws SemanticException {
646     
647     return findField(container, name, (ClassType) null);
648     }
649         
650     
651     /**
652      * Returns a set of fields named <code>name</code> defined
653      * in type <code>container</code> or a supertype. The list
654      * returned may be empty.
655      */

656     protected Set findFields(ReferenceType container, String JavaDoc name) {
657         assert_(container);
658
659         if (container == null) {
660             throw new InternalCompilerError("Cannot access field \"" + name +
661                 "\" within a null container type.");
662         }
663
664     FieldInstance fi = container.fieldNamed(name);
665     
666     if (fi != null) {
667         return Collections.singleton(fi);
668     }
669
670     Set fields = new HashSet();
671
672     if (container.superType() != null && container.superType().isReference()) {
673         Set superFields = findFields(container.superType().toReference(), name);
674         fields.addAll(superFields);
675     }
676
677     if (container.isClass()) {
678         // Need to check interfaces for static fields.
679
ClassType ct = container.toClass();
680     
681         for (Iterator i = ct.interfaces().iterator(); i.hasNext(); ) {
682         Type it = (Type) i.next();
683         Set superFields = findFields(it.toReference(), name);
684         fields.addAll(superFields);
685         }
686     }
687     
688     return fields;
689     }
690
691     /**
692      * @deprecated
693      */

694     public ClassType findMemberClass(ClassType container, String JavaDoc name,
695                                      Context c) throws SemanticException {
696         return findMemberClass(container, name, c.currentClass());
697     }
698     
699     public ClassType findMemberClass(ClassType container, String JavaDoc name,
700                                      ClassType currClass) throws SemanticException
701     {
702     assert_(container);
703     
704     Set s = findMemberClasses(container, name);
705     
706     if (s.size() == 0) {
707         throw new NoClassException(name, container);
708     }
709     
710     Iterator i = s.iterator();
711     ClassType t = (ClassType) i.next();
712     
713     if (i.hasNext()) {
714         ClassType t2 = (ClassType) i.next();
715         throw new SemanticException("Member type \"" + name +
716                     "\" is ambiguous; it is defined in both " +
717                     t.container() + " and " +
718                     t2.container() + ".");
719     }
720     
721     if (currClass != null && ! isAccessible(t, currClass)) {
722         throw new SemanticException("Cannot access member type \"" + t + "\".");
723     }
724     
725     return t;
726     }
727     
728     public Set findMemberClasses(ClassType container, String JavaDoc name) throws SemanticException {
729     assert_(container);
730     
731     ClassType mt = container.memberClassNamed(name);
732     
733     if (mt != null) {
734         if (! mt.isMember()) {
735         throw new InternalCompilerError("Class " + mt +
736                         " is not a member class, " +
737                         " but is in " + container +
738                         "\'s list of members.");
739         }
740         
741         if (mt.outer() != container) {
742         throw new InternalCompilerError("Class " + mt +
743                         " has outer class " +
744                         mt.outer() +
745                         " but is a member of " +
746                         container);
747         }
748         
749         return Collections.singleton(mt);
750     }
751     
752     Set memberClasses = new HashSet();
753     
754     if (container.superType() != null) {
755         Set s = findMemberClasses(container.superType().toClass(), name);
756         memberClasses.addAll(s);
757     }
758     
759     for (Iterator i = container.interfaces().iterator(); i.hasNext(); ) {
760         Type it = (Type) i.next();
761         
762         Set s = findMemberClasses(it.toClass(), name);
763         memberClasses.addAll(s);
764     }
765     
766     return memberClasses;
767     }
768     
769     public ClassType findMemberClass(ClassType container, String JavaDoc name)
770         throws SemanticException {
771
772     return findMemberClass(container, name, (ClassType) null);
773     }
774     
775     protected static String JavaDoc listToString(List l) {
776     StringBuffer JavaDoc sb = new StringBuffer JavaDoc();
777
778     for (Iterator i = l.iterator(); i.hasNext(); ) {
779         Object JavaDoc o = i.next();
780             sb.append(o.toString());
781
782         if (i.hasNext()) {
783                 sb.append(", ");
784         }
785     }
786
787     return sb.toString();
788     }
789
790     /**
791      * @deprecated
792      */

793     public MethodInstance findMethod(ReferenceType container,
794                                  String JavaDoc name, List argTypes, Context c)
795     throws SemanticException {
796         return findMethod(container, name, argTypes, c.currentClass());
797     }
798
799     /**
800      * Returns the list of methods with the given name defined or inherited
801      * into container, checking if the methods are accessible from the
802      * body of currClass
803      */

804     public boolean hasMethodNamed(ReferenceType container, String JavaDoc name) {
805         assert_(container);
806
807         if (container == null) {
808             throw new InternalCompilerError("Cannot access method \"" + name +
809                 "\" within a null container type.");
810         }
811
812     if (! container.methodsNamed(name).isEmpty()) {
813             return true;
814     }
815
816     if (container.superType() != null && container.superType().isReference()) {
817             if (hasMethodNamed(container.superType().toReference(), name)) {
818                 return true;
819             }
820     }
821
822     if (container.isClass()) {
823         ClassType ct = container.toClass();
824     
825         for (Iterator i = ct.interfaces().iterator(); i.hasNext(); ) {
826         Type it = (Type) i.next();
827                 if (hasMethodNamed(it.toReference(), name)) {
828                     return true;
829                 }
830         }
831     }
832     
833         return false;
834     }
835
836     /**
837      * Requires: all type arguments are canonical.
838      *
839      * Returns the MethodInstance named 'name' defined on 'type' visible in
840      * context. If no such field may be found, returns a fieldmatch
841      * with an error explaining why. Access flags are considered.
842      **/

843     public MethodInstance findMethod(ReferenceType container,
844                                  String JavaDoc name, List argTypes, ClassType currClass)
845     throws SemanticException {
846
847         assert_(container);
848         assert_(argTypes);
849
850     List acceptable = findAcceptableMethods(container, name, argTypes, currClass);
851
852     if (acceptable.size() == 0) {
853         throw new NoMemberException(NoMemberException.METHOD,
854         "No valid method call found for " + name +
855         "(" + listToString(argTypes) + ")" +
856         " in " +
857         container + ".");
858     }
859
860     MethodInstance mi = (MethodInstance)
861         findProcedure(acceptable, container, argTypes, currClass);
862
863     if (mi == null) {
864         throw new SemanticException("Reference to " + name +
865                     " is ambiguous, multiple methods match: "
866                     + acceptable);
867     }
868         
869     return mi;
870     }
871
872     /**
873      * @deprecated
874      */

875     public ConstructorInstance findConstructor(ClassType container,
876                                  List argTypes, Context c)
877     throws SemanticException {
878         return findConstructor(container, argTypes, c.currentClass());
879     }
880
881     public ConstructorInstance findConstructor(ClassType container,
882                            List argTypes, ClassType currClass)
883     throws SemanticException {
884
885         assert_(container);
886         assert_(argTypes);
887
888     List acceptable = findAcceptableConstructors(container, argTypes, currClass);
889
890     if (acceptable.size() == 0) {
891         throw new NoMemberException(NoMemberException.CONSTRUCTOR,
892                                         "No valid constructor found for " +
893                                         container + "(" + listToString(argTypes) + ").");
894     }
895
896     ConstructorInstance ci = (ConstructorInstance)
897         findProcedure(acceptable, container, argTypes, currClass);
898
899     if (ci == null) {
900         throw new NoMemberException(NoMemberException.CONSTRUCTOR,
901         "Reference to " + container + " is ambiguous, multiple " +
902         "constructors match: " + acceptable);
903     }
904
905     return ci;
906     }
907
908     protected ProcedureInstance findProcedure(List acceptable,
909                                           ReferenceType container,
910                           List argTypes,
911                           ClassType currClass)
912     throws SemanticException {
913
914         Collection maximal = findMostSpecificProcedures(acceptable, container,
915                                                         argTypes, currClass);
916
917         if (maximal.size() == 1) {
918             return (ProcedureInstance) maximal.iterator().next();
919         }
920
921         return null;
922     }
923         
924     protected Collection findMostSpecificProcedures(List acceptable,
925                                                     ReferenceType container, List argTypes,
926                                                     ClassType currClass)
927         throws SemanticException {
928
929         assert_(container);
930         assert_(argTypes);
931
932     // now, use JLS 15.11.2.2
933
// First sort from most- to least-specific.
934
MostSpecificComparator msc = new MostSpecificComparator();
935     Collections.sort(acceptable, msc);
936
937         List maximal = new ArrayList(acceptable.size());
938
939     Iterator i = acceptable.iterator();
940
941     ProcedureInstance first = (ProcedureInstance) i.next();
942         maximal.add(first);
943
944     // Now check to make sure that we have a maximal most-specific method.
945
while (i.hasNext()) {
946         ProcedureInstance p = (ProcedureInstance) i.next();
947
948         if (msc.compare(first, p) >= 0) {
949                 maximal.add(p);
950         }
951     }
952
953         if (maximal.size() > 1) {
954             // If exactly one method is not abstract, it is the most specific.
955
List notAbstract = new ArrayList(maximal.size());
956             for (Iterator j = maximal.iterator(); j.hasNext(); ) {
957                 ProcedureInstance p = (ProcedureInstance) j.next();
958                 if (! p.flags().isAbstract()) {
959                     notAbstract.add(p);
960                 }
961             }
962
963             if (notAbstract.size() == 1) {
964                 maximal = notAbstract;
965             }
966             else if (notAbstract.size() == 0) {
967                 // all are abstract; if all signatures match, any will do.
968
Iterator j = maximal.iterator();
969                 first = (ProcedureInstance) j.next();
970                 while (j.hasNext()) {
971                     ProcedureInstance p = (ProcedureInstance) j.next();
972                     if (! first.hasFormals(p.formalTypes())) {
973                         // not all signatures match; must be ambiguous
974
return maximal;
975                     }
976                 }
977
978                 // all signatures match, just take the first
979
maximal = Collections.singletonList(first);
980             }
981         }
982
983         return maximal;
984     }
985
986     /**
987      * Class to handle the comparisons; dispatches to moreSpecific method.
988      */

989     protected class MostSpecificComparator implements Comparator {
990     public int compare(Object JavaDoc o1, Object JavaDoc o2) {
991         ProcedureInstance p1 = (ProcedureInstance) o1;
992         ProcedureInstance p2 = (ProcedureInstance) o2;
993
994         if (moreSpecific(p1, p2)) return -1;
995         if (moreSpecific(p2, p1)) return 1;
996             return 0;
997     }
998     }
999
1000    /**
1001     * Populates the list acceptable with those MethodInstances which are
1002     * Applicable and Accessible as defined by JLS 15.11.2.1
1003     */

1004    protected List findAcceptableMethods(ReferenceType container, String JavaDoc name,
1005                                         List argTypes, ClassType currClass)
1006    throws SemanticException {
1007
1008        assert_(container);
1009        assert_(argTypes);
1010
1011        // The list of acceptable methods. These methods are accessible from
1012
// currClass, the method call is valid, and they are not overridden
1013
// by an unacceptable method (which can occur with protected methods
1014
// only).
1015
List acceptable = new ArrayList();
1016
1017        // A list of unacceptable methods, where the method call is valid, but
1018
// the method is not accessible. This list is needed to make sure that
1019
// the acceptable methods are not overridden by an unacceptable method.
1020
List unacceptable = new ArrayList();
1021        
1022    Set visitedTypes = new HashSet();
1023
1024    LinkedList typeQueue = new LinkedList();
1025    typeQueue.addLast(container);
1026
1027    while (! typeQueue.isEmpty()) {
1028        Type type = (Type) typeQueue.removeFirst();
1029
1030        if (visitedTypes.contains(type)) {
1031        continue;
1032        }
1033
1034        visitedTypes.add(type);
1035
1036            if (Report.should_report(Report.types, 2))
1037        Report.report(2, "Searching type " + type + " for method " +
1038                              name + "(" + listToString(argTypes) + ")");
1039
1040        if (! type.isReference()) {
1041            throw new SemanticException("Cannot call method in " +
1042            " non-reference type " + type + ".");
1043        }
1044        
1045        for (Iterator i = type.toReference().methods().iterator(); i.hasNext(); ) {
1046        MethodInstance mi = (MethodInstance) i.next();
1047
1048        if (Report.should_report(Report.types, 3))
1049            Report.report(3, "Trying " + mi);
1050
1051                if (methodCallValid(mi, name, argTypes)) {
1052                    if (isAccessible(mi, currClass)) {
1053                        if (Report.should_report(Report.types, 3)) {
1054                            Report.report(3, "->acceptable: " + mi + " in "
1055                                          + mi.container());
1056                        }
1057
1058                        acceptable.add(mi);
1059                    }
1060                    else {
1061                        // method call is valid, but the method is
1062
// unacceptable.
1063
unacceptable.add(mi);
1064                    }
1065        }
1066            }
1067            if (type.toReference().superType() != null) {
1068                typeQueue.addLast(type.toReference().superType());
1069            }
1070
1071            typeQueue.addAll(type.toReference().interfaces());
1072        }
1073
1074        // remove any method in acceptable that are overridden by an
1075
// unacceptable
1076
// method.
1077
for (Iterator i = unacceptable.iterator(); i.hasNext();) {
1078            MethodInstance mi = (MethodInstance)i.next();
1079            acceptable.removeAll(mi.overrides());
1080        }
1081
1082        return acceptable;
1083    }
1084
1085    /**
1086     * Populates the list acceptable with those MethodInstances which are
1087     * Applicable and Accessible as defined by JLS 15.11.2.1
1088     */

1089    protected List findAcceptableConstructors(ClassType container,
1090                                              List argTypes,
1091                                              ClassType currClass)
1092        throws SemanticException
1093    {
1094        assert_(container);
1095        assert_(argTypes);
1096
1097    List acceptable = new ArrayList();
1098
1099    if (Report.should_report(Report.types, 2))
1100        Report.report(2, "Searching type " + container +
1101                          " for constructor " + container + "(" +
1102                          listToString(argTypes) + ")");
1103
1104    for (Iterator i = container.constructors().iterator(); i.hasNext(); ) {
1105        ConstructorInstance ci = (ConstructorInstance) i.next();
1106
1107        if (Report.should_report(Report.types, 3))
1108        Report.report(3, "Trying " + ci);
1109
1110        if (callValid(ci, argTypes) && isAccessible(ci, currClass)) {
1111        if (Report.should_report(Report.types, 3))
1112            Report.report(3, "->acceptable: " + ci);
1113        acceptable.add(ci);
1114        }
1115    }
1116
1117    return acceptable;
1118    }
1119
1120    /**
1121     * Returns whether method 1 is <i>more specific</i> than method 2,
1122     * where <i>more specific</i> is defined as JLS 15.11.2.2
1123     */

1124    public boolean moreSpecific(ProcedureInstance p1, ProcedureInstance p2) {
1125        return p1.moreSpecificImpl(p2);
1126    }
1127
1128    /**
1129     * Returns the supertype of type, or null if type has no supertype.
1130     **/

1131    public Type superType(ReferenceType type) {
1132        assert_(type);
1133    return type.superType();
1134    }
1135
1136    /**
1137     * Returns an immutable list of all the interface types which type
1138     * implements.
1139     **/

1140    public List interfaces(ReferenceType type) {
1141        assert_(type);
1142    return type.interfaces();
1143    }
1144
1145    /**
1146     * Requires: all type arguments are canonical.
1147     * Returns the least common ancestor of Type1 and Type2
1148     **/

1149    public Type leastCommonAncestor(Type type1, Type type2)
1150        throws SemanticException
1151    {
1152        assert_(type1);
1153        assert_(type2);
1154
1155    if (equals(type1, type2)) return type1;
1156
1157    if (type1.isNumeric() && type2.isNumeric()) {
1158        if (isImplicitCastValid(type1, type2)) {
1159            return type2;
1160        }
1161
1162        if (isImplicitCastValid(type2, type1)) {
1163            return type1;
1164        }
1165
1166        if (type1.isChar() && type2.isByte() ||
1167            type1.isByte() && type2.isChar()) {
1168        return Int();
1169        }
1170
1171        if (type1.isChar() && type2.isShort() ||
1172            type1.isShort() && type2.isChar()) {
1173        return Int();
1174        }
1175    }
1176
1177    if (type1.isArray() && type2.isArray()) {
1178        return arrayOf(leastCommonAncestor(type1.toArray().base(),
1179                           type2.toArray().base()));
1180    }
1181
1182    if (type1.isReference() && type2.isNull()) return type1;
1183    if (type2.isReference() && type1.isNull()) return type2;
1184
1185    if (type1.isReference() && type2.isReference()) {
1186        // Don't consider interfaces.
1187
if (type1.isClass() && type1.toClass().flags().isInterface()) {
1188            return Object();
1189        }
1190
1191        if (type2.isClass() && type2.toClass().flags().isInterface()) {
1192            return Object();
1193        }
1194
1195        // Check against Object to ensure superType() is not null.
1196
if (equals(type1, Object())) return type1;
1197        if (equals(type2, Object())) return type2;
1198
1199        if (isSubtype(type1, type2)) return type2;
1200        if (isSubtype(type2, type1)) return type1;
1201
1202        // Walk up the hierarchy
1203
Type t1 = leastCommonAncestor(type1.toReference().superType(),
1204                                  type2);
1205        Type t2 = leastCommonAncestor(type2.toReference().superType(),
1206                      type1);
1207
1208        if (equals(t1, t2)) return t1;
1209
1210        return Object();
1211    }
1212
1213    throw new SemanticException(
1214       "No least common ancestor found for types \"" + type1 +
1215       "\" and \"" + type2 + "\".");
1216    }
1217
1218    ////
1219
// Functions for method testing.
1220
////
1221

1222    /**
1223     * Returns true iff <p1> throws fewer exceptions than <p2>.
1224     */

1225    public boolean throwsSubset(ProcedureInstance p1, ProcedureInstance p2) {
1226        assert_(p1);
1227        assert_(p2);
1228        return p1.throwsSubsetImpl(p2);
1229    }
1230
1231    /** Return true if t overrides mi */
1232    public boolean hasFormals(ProcedureInstance pi, List formalTypes) {
1233        assert_(pi);
1234        assert_(formalTypes);
1235        return pi.hasFormalsImpl(formalTypes);
1236    }
1237
1238    /** Return true if t overrides mi */
1239    public boolean hasMethod(ReferenceType t, MethodInstance mi) {
1240        assert_(t);
1241        assert_(mi);
1242        return t.hasMethodImpl(mi);
1243    }
1244
1245    public List overrides(MethodInstance mi) {
1246        return mi.overridesImpl();
1247    }
1248
1249    public List implemented(MethodInstance mi) {
1250    return mi.implementedImpl(mi.container());
1251    }
1252
1253    public boolean canOverride(MethodInstance mi, MethodInstance mj) {
1254        try {
1255            return mi.canOverrideImpl(mj, true);
1256        }
1257        catch (SemanticException e) {
1258            // this is the exception thrown by the canOverrideImpl check.
1259
// It should never be thrown if the quiet argument of
1260
// canOverrideImpl is true.
1261
throw new InternalCompilerError(e);
1262        }
1263    }
1264
1265    public void checkOverride(MethodInstance mi, MethodInstance mj) throws SemanticException {
1266        mi.canOverrideImpl(mj, false);
1267    }
1268
1269    /**
1270     * Returns true iff <m1> is the same method as <m2>
1271     */

1272    public boolean isSameMethod(MethodInstance m1, MethodInstance m2) {
1273        assert_(m1);
1274        assert_(m2);
1275        return m1.isSameMethodImpl(m2);
1276    }
1277
1278    public boolean methodCallValid(MethodInstance prototype,
1279                   String JavaDoc name, List argTypes) {
1280        assert_(prototype);
1281        assert_(argTypes);
1282    return prototype.methodCallValidImpl(name, argTypes);
1283    }
1284
1285    public boolean callValid(ProcedureInstance prototype, List argTypes) {
1286        assert_(prototype);
1287        assert_(argTypes);
1288        return prototype.callValidImpl(argTypes);
1289    }
1290
1291    ////
1292
// Functions which yield particular types.
1293
////
1294
public NullType Null() { return NULL_; }
1295    public PrimitiveType Void() { return VOID_; }
1296    public PrimitiveType Boolean() { return BOOLEAN_; }
1297    public PrimitiveType Char() { return CHAR_; }
1298    public PrimitiveType Byte() { return BYTE_; }
1299    public PrimitiveType Short() { return SHORT_; }
1300    public PrimitiveType Int() { return INT_; }
1301    public PrimitiveType Long() { return LONG_; }
1302    public PrimitiveType Float() { return FLOAT_; }
1303    public PrimitiveType Double() { return DOUBLE_; }
1304
1305    protected ClassType load(String JavaDoc name) {
1306      try {
1307          return (ClassType) typeForName(name);
1308      }
1309      catch (SemanticException e) {
1310          throw new InternalCompilerError("Cannot find class \"" +
1311                                          name + "\"; " + e.getMessage(),
1312                                          e);
1313      }
1314    }
1315    
1316    public Named forName(String JavaDoc name) throws SemanticException {
1317        try {
1318            return systemResolver.find(name);
1319        }
1320        catch (SemanticException e) {
1321            if (! StringUtil.isNameShort(name)) {
1322                String JavaDoc containerName = StringUtil.getPackageComponent(name);
1323                String JavaDoc shortName = StringUtil.getShortNameComponent(name);
1324                
1325                try {
1326                    Named container = forName(containerName);
1327            if (container instanceof ClassType) {
1328            return classContextResolver((ClassType) container).find(shortName);
1329            }
1330                }
1331                catch (SemanticException e2) {
1332                }
1333            }
1334        
1335            // throw the original exception
1336
throw e;
1337        }
1338    }
1339
1340    public Type typeForName(String JavaDoc name) throws SemanticException {
1341    return (Type) forName(name);
1342    }
1343
1344    protected ClassType OBJECT_;
1345    protected ClassType CLASS_;
1346    protected ClassType STRING_;
1347    protected ClassType THROWABLE_;
1348
1349    public ClassType Object() { if (OBJECT_ != null) return OBJECT_;
1350                                 return OBJECT_ = load("java.lang.Object"); }
1351    public ClassType Class() { if (CLASS_ != null) return CLASS_;
1352                                 return CLASS_ = load("java.lang.Class"); }
1353    public ClassType String() { if (STRING_ != null) return STRING_;
1354                                 return STRING_ = load("java.lang.String"); }
1355    public ClassType Throwable() { if (THROWABLE_ != null) return THROWABLE_;
1356                                   return THROWABLE_ = load("java.lang.Throwable"); }
1357    public ClassType Error() { return load("java.lang.Error"); }
1358    public ClassType Exception() { return load("java.lang.Exception"); }
1359    public ClassType RuntimeException() { return load("java.lang.RuntimeException"); }
1360    public ClassType Cloneable() { return load("java.lang.Cloneable"); }
1361    public ClassType Serializable() { return load("java.io.Serializable"); }
1362    public ClassType NullPointerException() { return load("java.lang.NullPointerException"); }
1363    public ClassType ClassCastException() { return load("java.lang.ClassCastException"); }
1364    public ClassType OutOfBoundsException() { return load("java.lang.ArrayIndexOutOfBoundsException"); }
1365    public ClassType ArrayStoreException() { return load("java.lang.ArrayStoreException"); }
1366    public ClassType ArithmeticException() { return load("java.lang.ArithmeticException"); }
1367
1368    protected NullType createNull() {
1369        return new NullType_c(this);
1370    }
1371
1372    protected PrimitiveType createPrimitive(PrimitiveType.Kind kind) {
1373        return new PrimitiveType_c(this, kind);
1374    }
1375
1376    protected final NullType NULL_ = createNull();
1377    protected final PrimitiveType VOID_ = createPrimitive(PrimitiveType.VOID);
1378    protected final PrimitiveType BOOLEAN_ = createPrimitive(PrimitiveType.BOOLEAN);
1379    protected final PrimitiveType CHAR_ = createPrimitive(PrimitiveType.CHAR);
1380    protected final PrimitiveType BYTE_ = createPrimitive(PrimitiveType.BYTE);
1381    protected final PrimitiveType SHORT_ = createPrimitive(PrimitiveType.SHORT);
1382    protected final PrimitiveType INT_ = createPrimitive(PrimitiveType.INT);
1383    protected final PrimitiveType LONG_ = createPrimitive(PrimitiveType.LONG);
1384    protected final PrimitiveType FLOAT_ = createPrimitive(PrimitiveType.FLOAT);
1385    protected final PrimitiveType DOUBLE_ = createPrimitive(PrimitiveType.DOUBLE);
1386
1387    public Object JavaDoc placeHolder(TypeObject o) {
1388        assert_(o);
1389        return placeHolder(o, new HashSet());
1390    }
1391
1392    public Object JavaDoc placeHolder(TypeObject o, Set roots) {
1393        assert_(o);
1394
1395        if (o instanceof ClassType) {
1396            ClassType ct = (ClassType) o;
1397
1398            // This should never happen: anonymous and local types cannot
1399
// appear in signatures.
1400
if (ct.isLocal() || ct.isAnonymous()) {
1401                throw new InternalCompilerError("Cannot serialize " + o + ".");
1402            }
1403
1404            return new PlaceHolder_c(ct);
1405        }
1406
1407    return o;
1408    }
1409
1410    protected UnknownType unknownType = new UnknownType_c(this);
1411    protected UnknownPackage unknownPackage = new UnknownPackage_c(this);
1412    protected UnknownQualifier unknownQualifier = new UnknownQualifier_c(this);
1413
1414    public UnknownType unknownType(Position pos) {
1415    return unknownType;
1416    }
1417
1418    public UnknownPackage unknownPackage(Position pos) {
1419    return unknownPackage;
1420    }
1421
1422    public UnknownQualifier unknownQualifier(Position pos) {
1423    return unknownQualifier;
1424    }
1425
1426    public Package JavaDoc packageForName(Package JavaDoc prefix, String JavaDoc name) throws SemanticException {
1427        return createPackage(prefix, name);
1428    }
1429
1430    public Package JavaDoc packageForName(String JavaDoc name) throws SemanticException {
1431        if (name == null || name.equals("")) {
1432        return null;
1433    }
1434
1435    String JavaDoc s = StringUtil.getShortNameComponent(name);
1436    String JavaDoc p = StringUtil.getPackageComponent(name);
1437
1438    return packageForName(packageForName(p), s);
1439    }
1440
1441    public Package JavaDoc createPackage(Package JavaDoc prefix, String JavaDoc name) {
1442        assert_(prefix);
1443    return new Package_c(this, prefix, name);
1444    }
1445
1446    public Package JavaDoc createPackage(String JavaDoc name) {
1447        if (name == null || name.equals("")) {
1448        return null;
1449    }
1450
1451    String JavaDoc s = StringUtil.getShortNameComponent(name);
1452    String JavaDoc p = StringUtil.getPackageComponent(name);
1453
1454    return createPackage(createPackage(p), s);
1455    }
1456
1457    /**
1458     * Returns a type identical to <type>, but with <dims> more array
1459     * dimensions.
1460     */

1461    public ArrayType arrayOf(Type type) {
1462        assert_(type);
1463        return arrayOf(type.position(), type);
1464    }
1465
1466    public ArrayType arrayOf(Position pos, Type type) {
1467        assert_(type);
1468    return arrayType(pos, type);
1469    }
1470
1471    /**
1472     * Factory method for ArrayTypes.
1473     */

1474    protected ArrayType arrayType(Position pos, Type type) {
1475    return new ArrayType_c(this, pos, type);
1476    }
1477
1478    public ArrayType arrayOf(Type type, int dims) {
1479        return arrayOf(null, type, dims);
1480    }
1481
1482    public ArrayType arrayOf(Position pos, Type type, int dims) {
1483    if (dims > 1) {
1484        return arrayOf(pos, arrayOf(pos, type, dims-1));
1485    }
1486    else if (dims == 1) {
1487        return arrayOf(pos, type);
1488    }
1489    else {
1490        throw new InternalCompilerError(
1491        "Must call arrayOf(type, dims) with dims > 0");
1492    }
1493    }
1494
1495    /**
1496     * Returns a canonical type corresponding to the Java Class object
1497     * theClass. Does not require that <theClass> have a JavaClass
1498     * registered in this typeSystem. Does not register the type in
1499     * this TypeSystem. For use only by JavaClass implementations.
1500     **/

1501    public Type typeForClass(Class JavaDoc clazz) throws SemanticException
1502    {
1503    if (clazz == Void.TYPE) return VOID_;
1504    if (clazz == Boolean.TYPE) return BOOLEAN_;
1505    if (clazz == Byte.TYPE) return BYTE_;
1506    if (clazz == Character.TYPE) return CHAR_;
1507    if (clazz == Short.TYPE) return SHORT_;
1508    if (clazz == Integer.TYPE) return INT_;
1509    if (clazz == Long.TYPE) return LONG_;
1510    if (clazz == Float.TYPE) return FLOAT_;
1511    if (clazz == Double.TYPE) return DOUBLE_;
1512
1513    if (clazz.isArray()) {
1514        return arrayOf(typeForClass(clazz.getComponentType()));
1515    }
1516
1517    return (Type) systemResolver.find(clazz.getName());
1518    }
1519
1520    public Set getTypeEncoderRootSet(Type t) {
1521        // The root set is now just the type itself. Previously it contained
1522
// the member classes tool
1523
return Collections.singleton(t);
1524    }
1525
1526    /**
1527     * Get the transformed class name of a class.
1528     * This utility method returns the "mangled" name of the given class,
1529     * whereby all periods ('.') following the toplevel class name
1530     * are replaced with dollar signs ('$'). If any of the containing
1531     * classes is not a member class or a top level class, then null is
1532     * returned.
1533     */

1534    public String JavaDoc getTransformedClassName(ClassType ct) {
1535        StringBuffer JavaDoc sb = new StringBuffer JavaDoc(ct.fullName().length());
1536        if (!ct.isMember() && !ct.isTopLevel()) {
1537            return null;
1538        }
1539        while (ct.isMember()) {
1540            sb.insert(0, ct.name());
1541            sb.insert(0, '$');
1542            ct = ct.outer();
1543            if (!ct.isMember() && !ct.isTopLevel()) {
1544                return null;
1545            }
1546        }
1547
1548        sb.insert(0, ct.fullName());
1549        return sb.toString();
1550    }
1551
1552    public String JavaDoc translatePackage(Resolver c, Package JavaDoc p) {
1553        return p.translate(c);
1554    }
1555
1556    public String JavaDoc translateArray(Resolver c, ArrayType t) {
1557        return t.translate(c);
1558    }
1559
1560    public String JavaDoc translateClass(Resolver c, ClassType t) {
1561        return t.translate(c);
1562    }
1563
1564    public String JavaDoc translatePrimitive(Resolver c, PrimitiveType t) {
1565        return t.translate(c);
1566    }
1567
1568    public PrimitiveType primitiveForName(String JavaDoc name)
1569    throws SemanticException {
1570
1571    if (name.equals("void")) return Void();
1572    if (name.equals("boolean")) return Boolean();
1573    if (name.equals("char")) return Char();
1574    if (name.equals("byte")) return Byte();
1575    if (name.equals("short")) return Short();
1576    if (name.equals("int")) return Int();
1577    if (name.equals("long")) return Long();
1578    if (name.equals("float")) return Float();
1579    if (name.equals("double")) return Double();
1580
1581    throw new SemanticException("Unrecognized primitive type \"" +
1582        name + "\".");
1583    }
1584
1585    protected LazyClassInitializer defaultClassInit;
1586
1587    public LazyClassInitializer defaultClassInitializer() {
1588        if (defaultClassInit == null) {
1589            defaultClassInit = new LazyClassInitializer_c(this);
1590        }
1591
1592        return defaultClassInit;
1593    }
1594
1595    public final ParsedClassType createClassType() {
1596        return createClassType(defaultClassInitializer(), null);
1597    }
1598    public final ParsedClassType createClassType(Source fromSource) {
1599        return createClassType(defaultClassInitializer(), fromSource);
1600    }
1601
1602    public final ParsedClassType createClassType(LazyClassInitializer init) {
1603        return createClassType(init, null);
1604    }
1605
1606    public ParsedClassType createClassType(LazyClassInitializer init, Source fromSource) {
1607        return new ParsedClassType_c(this, init, fromSource);
1608    }
1609
1610    public List defaultPackageImports() {
1611    List l = new ArrayList(1);
1612    l.add("java.lang");
1613    return l;
1614    }
1615
1616    public PrimitiveType promote(Type t1, Type t2) throws SemanticException {
1617    if (! t1.isNumeric()) {
1618        throw new SemanticException(
1619        "Cannot promote non-numeric type " + t1);
1620    }
1621
1622    if (! t2.isNumeric()) {
1623        throw new SemanticException(
1624        "Cannot promote non-numeric type " + t2);
1625    }
1626
1627    return promoteNumeric(t1.toPrimitive(), t2.toPrimitive());
1628    }
1629
1630    protected PrimitiveType promoteNumeric(PrimitiveType t1, PrimitiveType t2) {
1631    if (t1.isDouble() || t2.isDouble()) {
1632        return Double();
1633    }
1634
1635    if (t1.isFloat() || t2.isFloat()) {
1636        return Float();
1637    }
1638
1639    if (t1.isLong() || t2.isLong()) {
1640        return Long();
1641    }
1642
1643    return Int();
1644    }
1645
1646    public PrimitiveType promote(Type t) throws SemanticException {
1647    if (! t.isNumeric()) {
1648        throw new SemanticException(
1649        "Cannot promote non-numeric type " + t);
1650    }
1651
1652    return promoteNumeric(t.toPrimitive());
1653    }
1654
1655    protected PrimitiveType promoteNumeric(PrimitiveType t) {
1656    if (t.isByte() || t.isShort() || t.isChar()) {
1657        return Int();
1658    }
1659
1660    return t.toPrimitive();
1661    }
1662
1663    /** All possible <i>access</i> flags. */
1664    protected final Flags ACCESS_FLAGS = Public().Protected().Private();
1665
1666    /** All flags allowed for a local variable. */
1667    protected final Flags LOCAL_FLAGS = Final();
1668
1669    /** All flags allowed for a field. */
1670    protected final Flags FIELD_FLAGS = ACCESS_FLAGS.Static().Final()
1671                                        .Transient().Volatile();
1672
1673    /** All flags allowed for a constructor. */
1674    protected final Flags CONSTRUCTOR_FLAGS = ACCESS_FLAGS
1675                                              .Synchronized().Native();
1676
1677    /** All flags allowed for an initializer block. */
1678    protected final Flags INITIALIZER_FLAGS = Static();
1679
1680    /** All flags allowed for a method. */
1681    protected final Flags METHOD_FLAGS = ACCESS_FLAGS.Abstract().Static()
1682                                         .Final().Native()
1683                                         .Synchronized().StrictFP();
1684
1685    /** All flags allowed for a top-level class. */
1686    protected final Flags TOP_LEVEL_CLASS_FLAGS = ACCESS_FLAGS.clear(Private())
1687                                                  .Abstract().Final()
1688                                                  .StrictFP().Interface();
1689
1690    /** All flags allowed for a member class. */
1691    protected final Flags MEMBER_CLASS_FLAGS = ACCESS_FLAGS.Static()
1692                                                  .Abstract().Final()
1693                                                  .StrictFP().Interface();
1694
1695
1696    /** All flags allowed for a local class. */
1697    protected final Flags LOCAL_CLASS_FLAGS = TOP_LEVEL_CLASS_FLAGS
1698                                              .clear(ACCESS_FLAGS);
1699
1700    public void checkMethodFlags(Flags f) throws SemanticException {
1701        if (! f.clear(METHOD_FLAGS).equals(Flags.NONE)) {
1702        throw new SemanticException(
1703        "Cannot declare method with flags " +
1704        f.clear(METHOD_FLAGS) + ".");
1705    }
1706
1707        if (f.isAbstract() && f.isPrivate()) {
1708        throw new SemanticException(
1709        "Cannot declare method that is both abstract and private.");
1710        }
1711
1712        if (f.isAbstract() && f.isStatic()) {
1713        throw new SemanticException(
1714        "Cannot declare method that is both abstract and static.");
1715        }
1716
1717        if (f.isAbstract() && f.isFinal()) {
1718        throw new SemanticException(
1719        "Cannot declare method that is both abstract and final.");
1720        }
1721
1722        if (f.isAbstract() && f.isNative()) {
1723        throw new SemanticException(
1724        "Cannot declare method that is both abstract and native.");
1725        }
1726
1727        if (f.isAbstract() && f.isSynchronized()) {
1728        throw new SemanticException(
1729        "Cannot declare method that is both abstract and synchronized.");
1730        }
1731
1732        if (f.isAbstract() && f.isStrictFP()) {
1733        throw new SemanticException(
1734        "Cannot declare method that is both abstract and strictfp.");
1735        }
1736
1737    checkAccessFlags(f);
1738    }
1739
1740    public void checkLocalFlags(Flags f) throws SemanticException {
1741        if (! f.clear(LOCAL_FLAGS).equals(Flags.NONE)) {
1742        throw new SemanticException(
1743        "Cannot declare local variable with flags " +
1744        f.clear(LOCAL_FLAGS) + ".");
1745    }
1746    }
1747
1748    public void checkFieldFlags(Flags f) throws SemanticException {
1749        if (! f.clear(FIELD_FLAGS).equals(Flags.NONE)) {
1750        throw new SemanticException(
1751        "Cannot declare field with flags " +
1752        f.clear(FIELD_FLAGS) + ".");
1753    }
1754
1755    checkAccessFlags(f);
1756    }
1757
1758    public void checkConstructorFlags(Flags f) throws SemanticException {
1759        if (! f.clear(CONSTRUCTOR_FLAGS).equals(Flags.NONE)) {
1760        throw new SemanticException(
1761        "Cannot declare constructor with flags " +
1762        f.clear(CONSTRUCTOR_FLAGS) + ".");
1763    }
1764
1765    checkAccessFlags(f);
1766    }
1767
1768    public void checkInitializerFlags(Flags f) throws SemanticException {
1769        if (! f.clear(INITIALIZER_FLAGS).equals(Flags.NONE)) {
1770        throw new SemanticException(
1771        "Cannot declare initializer with flags " +
1772        f.clear(INITIALIZER_FLAGS) + ".");
1773    }
1774    }
1775
1776    public void checkTopLevelClassFlags(Flags f) throws SemanticException {
1777        if (! f.clear(TOP_LEVEL_CLASS_FLAGS).equals(Flags.NONE)) {
1778        throw new SemanticException(
1779        "Cannot declare a top-level class with flag(s) " +
1780        f.clear(TOP_LEVEL_CLASS_FLAGS) + ".");
1781    }
1782
1783        if (f.isFinal() && f.isInterface()) {
1784            throw new SemanticException("Cannot declare a final interface.");
1785        }
1786
1787    checkAccessFlags(f);
1788    }
1789
1790    public void checkMemberClassFlags(Flags f) throws SemanticException {
1791        if (! f.clear(MEMBER_CLASS_FLAGS).equals(Flags.NONE)) {
1792        throw new SemanticException(
1793        "Cannot declare a member class with flag(s) " +
1794        f.clear(MEMBER_CLASS_FLAGS) + ".");
1795    }
1796
1797        if (f.isStrictFP() && f.isInterface()) {
1798            throw new SemanticException("Cannot declare a strictfp interface.");
1799        }
1800
1801        if (f.isFinal() && f.isInterface()) {
1802            throw new SemanticException("Cannot declare a final interface.");
1803        }
1804
1805    checkAccessFlags(f);
1806    }
1807
1808    public void checkLocalClassFlags(Flags f) throws SemanticException {
1809        if (f.isInterface()) {
1810            throw new SemanticException("Cannot declare a local interface.");
1811        }
1812
1813        if (! f.clear(LOCAL_CLASS_FLAGS).equals(Flags.NONE)) {
1814        throw new SemanticException(
1815        "Cannot declare a local class with flag(s) " +
1816        f.clear(LOCAL_CLASS_FLAGS) + ".");
1817    }
1818
1819    checkAccessFlags(f);
1820    }
1821
1822    public void checkAccessFlags(Flags f) throws SemanticException {
1823        int count = 0;
1824        if (f.isPublic()) count++;
1825        if (f.isProtected()) count++;
1826        if (f.isPrivate()) count++;
1827
1828    if (count > 1) {
1829        throw new SemanticException(
1830        "Invalid access flags: " + f.retain(ACCESS_FLAGS) + ".");
1831    }
1832    }
1833
1834    /**
1835     * Utility method to gather all the superclasses and interfaces of
1836     * <code>ct</code> that may contain abstract methods that must be
1837     * implemented by <code>ct</code>. The list returned also contains
1838     * <code>ct</code>.
1839     */

1840    protected List abstractSuperInterfaces(ReferenceType rt) {
1841        List superInterfaces = new LinkedList();
1842        superInterfaces.add(rt);
1843
1844        for (Iterator iter = rt.interfaces().iterator(); iter.hasNext(); ) {
1845            ClassType interf = (ClassType)iter.next();
1846            superInterfaces.addAll(abstractSuperInterfaces(interf));
1847        }
1848
1849        if (rt.superType() != null) {
1850            ClassType c = rt.superType().toClass();
1851            if (c.flags().isAbstract()) {
1852                // the superclass is abstract, so it may contain methods
1853
// that must be implemented.
1854
superInterfaces.addAll(abstractSuperInterfaces(c));
1855            }
1856            else {
1857                // the superclass is not abstract, so it must implement
1858
// all abstract methods of any interfaces it implements, and
1859
// any superclasses it may have.
1860
}
1861        }
1862        return superInterfaces;
1863    }
1864
1865    /**
1866     * Assert that <code>ct</code> implements all abstract methods required;
1867     * that is, if it is a concrete class, then it must implement all
1868     * interfaces and abstract methods that it or it's superclasses declare, and if
1869     * it is an abstract class then any methods that it overrides are overridden
1870     * correctly.
1871     */

1872    public void checkClassConformance(ClassType ct) throws SemanticException {
1873        if (ct.flags().isInterface()) {
1874            // don't need to check interfaces
1875
return;
1876        }
1877
1878        // build up a list of superclasses and interfaces that ct
1879
// extends/implements that may contain abstract methods that
1880
// ct must define.
1881
List superInterfaces = abstractSuperInterfaces(ct);
1882
1883        // check each abstract method of the classes and interfaces in
1884
// superInterfaces
1885
for (Iterator i = superInterfaces.iterator(); i.hasNext(); ) {
1886            ReferenceType rt = (ReferenceType)i.next();
1887            for (Iterator j = rt.methods().iterator(); j.hasNext(); ) {
1888                MethodInstance mi = (MethodInstance)j.next();
1889                if (!mi.flags().isAbstract()) {
1890                    // the method isn't abstract, so ct doesn't have to
1891
// implement it.
1892
continue;
1893                }
1894
1895                boolean implFound = false;
1896                ReferenceType curr = ct;
1897                while (curr != null && !implFound) {
1898                    List possible = curr.methods(mi.name(), mi.formalTypes());
1899                    for (Iterator k = possible.iterator(); k.hasNext(); ) {
1900                        MethodInstance mj = (MethodInstance)k.next();
1901                        if (!mj.flags().isAbstract() &&
1902                            ((isAccessible(mi, ct) && isAccessible(mj, ct)) ||
1903                                    isAccessible(mi, mj.container().toClass()))) {
1904                            // The method mj may be a suitable implementation of mi.
1905
// mj is not abstract, and either mj's container
1906
// can access mi (thus mj can really override mi), or
1907
// mi and mj are both accessible from ct (e.g.,
1908
// mi is declared in an interface that ct implements,
1909
// and mj is defined in a superclass of ct).
1910

1911                            // If neither the method instance mj nor the method
1912
// instance mi is declared in the class type ct, then
1913
// we need to check that it has appropriate protections.
1914
if (!equals(ct, mj.container()) && !equals(ct, mi.container())) {
1915                                try {
1916                                    // check that mj can override mi, which
1917
// includes access protection checks.
1918
checkOverride(mj, mi);
1919                                }
1920                                catch (SemanticException e) {
1921                                    // change the position of the semantic
1922
// exception to be the class that we
1923
// are checking.
1924
throw new SemanticException(e.getMessage(),
1925                                        ct.position());
1926                                }
1927                            }
1928                            else {
1929                                // the method implementation mj or mi was
1930
// declared in ct. So other checks will take
1931
// care of access issues
1932
}
1933                            implFound = true;
1934                            break;
1935                        }
1936                    }
1937
1938                    if (curr == mi.container()) {
1939                        // we've reached the definition of the abstract
1940
// method. We don't want to look higher in the
1941
// hierarchy; this is not an optimization, but is
1942
// required for correctness.
1943
break;
1944                    }
1945                    
1946                    curr = curr.superType() == null ?
1947                           null : curr.superType().toReference();
1948                }
1949
1950
1951                // did we find a suitable implementation of the method mi?
1952
if (!implFound && !ct.flags().isAbstract()) {
1953                    throw new SemanticException(ct.fullName() + " should be " +
1954                            "declared abstract; it does not define " +
1955                            mi.signature() + ", which is declared in " +
1956                            rt.toClass().fullName(), ct.position());
1957                }
1958            }
1959        }
1960    }
1961
1962    /**
1963     * Returns t, modified as necessary to make it a legal
1964     * static target.
1965     */

1966    public Type staticTarget(Type t) {
1967        // Nothing needs done in standard Java.
1968
return t;
1969    }
1970
1971    protected void initFlags() {
1972        flagsForName = new HashMap();
1973        flagsForName.put("public", Flags.PUBLIC);
1974        flagsForName.put("private", Flags.PRIVATE);
1975        flagsForName.put("protected", Flags.PROTECTED);
1976        flagsForName.put("static", Flags.STATIC);
1977        flagsForName.put("final", Flags.FINAL);
1978        flagsForName.put("synchronized", Flags.SYNCHRONIZED);
1979        flagsForName.put("transient", Flags.TRANSIENT);
1980        flagsForName.put("native", Flags.NATIVE);
1981        flagsForName.put("interface", Flags.INTERFACE);
1982        flagsForName.put("abstract", Flags.ABSTRACT);
1983        flagsForName.put("volatile", Flags.VOLATILE);
1984        flagsForName.put("strictfp", Flags.STRICTFP);
1985    }
1986
1987    public Flags createNewFlag(String JavaDoc name, Flags after) {
1988        Flags f = Flags.createFlag(name, after);
1989        flagsForName.put(name, f);
1990        return f;
1991    }
1992
1993    public Flags NoFlags() { return Flags.NONE; }
1994    public Flags Public() { return Flags.PUBLIC; }
1995    public Flags Private() { return Flags.PRIVATE; }
1996    public Flags Protected() { return Flags.PROTECTED; }
1997    public Flags Static() { return Flags.STATIC; }
1998    public Flags Final() { return Flags.FINAL; }
1999    public Flags Synchronized() { return Flags.SYNCHRONIZED; }
2000    public Flags Transient() { return Flags.TRANSIENT; }
2001    public Flags Native() { return Flags.NATIVE; }
2002    public Flags Interface() { return Flags.INTERFACE; }
2003    public Flags Abstract() { return Flags.ABSTRACT; }
2004    public Flags Volatile() { return Flags.VOLATILE; }
2005    public Flags StrictFP() { return Flags.STRICTFP; }
2006
2007    public Flags flagsForBits(int bits) {
2008        Flags f = Flags.NONE;
2009
2010        if ((bits & Modifier.PUBLIC) != 0) f = f.Public();
2011        if ((bits & Modifier.PRIVATE) != 0) f = f.Private();
2012        if ((bits & Modifier.PROTECTED) != 0) f = f.Protected();
2013        if ((bits & Modifier.STATIC) != 0) f = f.Static();
2014        if ((bits & Modifier.FINAL) != 0) f = f.Final();
2015        if ((bits & Modifier.SYNCHRONIZED) != 0) f = f.Synchronized();
2016        if ((bits & Modifier.TRANSIENT) != 0) f = f.Transient();
2017        if ((bits & Modifier.NATIVE) != 0) f = f.Native();
2018        if ((bits & Modifier.INTERFACE) != 0) f = f.Interface();
2019        if ((bits & Modifier.ABSTRACT) != 0) f = f.Abstract();
2020        if ((bits & Modifier.VOLATILE) != 0) f = f.Volatile();
2021        if ((bits & Modifier.STRICT) != 0) f = f.StrictFP();
2022
2023        return f;
2024    }
2025
2026    public Flags flagsForName(String JavaDoc name) {
2027        Flags f = (Flags) flagsForName.get(name);
2028        if (f == null) {
2029            throw new InternalCompilerError("No flag named \"" + name + "\".");
2030        }
2031        return f;
2032    }
2033
2034    public String JavaDoc toString() {
2035        return StringUtil.getShortNameComponent(getClass().getName());
2036    }
2037
2038}
2039
Popular Tags