001 // $Id: TypeSig.java,v 1.34 2006/08/09 10:41:22 rgrig Exp $
002 /* Copyright 2000, 2001, Compaq Computer Corporation */
003
004 package javafe.tc;
005
006 import java.util.Hashtable;
007
008 import javafe.ast.*;
009 import javafe.util.*;
010
011 /**
012
013 A <code>TypeSig</code> is a proxy and adaptor for <a
014 href="javafe.ast.TypeDecl.html"><code>TypeDecl</code></a>.<p>
015
016 They are proxies because, during name resolution, <a
017 href="javafe.ast.TypeName.html"><code>TypeName</code></a> objects are
018 resolved to point to <code>TypeSig</code> objects rather than directly
019 to <code>TypeDecl</code> objects. This gives us the flexibility of
020 deferring parsing of a type declaration until we know we need detailed
021 information about it.<p>
022
023 They are adaptors because they provide extra functionality not provided
024 by <code>TypeDecl</code> objects. In particular, they provide lookup
025 methods that allow clients to find particular members of a type
026 declaration (including inherited members), and resolve methods that
027 perform name resolution inside the implementation of a type
028 declaration.<p>
029
030 <i>What about the fact that we are a subtype of <code>Type</code>?</i>
031
032
033 <h3> Interning </h3>
034
035 <code>TypeSig</code> objects are meant to be "interned"; that is, for
036 each <i>canonical</i> <code>TypeDecl</code>, we want there to be exactly
037 one associated <code>TypeSig</code> object. The first
038 <code>TypeDecl</code> loaded by the system for a given typename is
039 considered to be the canonical <code>TypeDecl</code> for that typename;
040 all other <code>TypeDecl</code>s for that typename are considered
041 non-canonical.<p>
042
043 To achieve this interning, clients of the <code>javafe.tc</code> package
044 should not directly create <code>TypeSig</code> objects; rather, they
045 should rely on <code>javafe.tc</code> to create <code>TypeSig</code>
046 objects for them. Similarly, clients of the <code>javafe.tc</code>
047 package should rely on <code>javafe.tc</code> to do the parsing
048 necessary to create instances of <code>TypeDecl</code>. Not only will
049 the <code>javafe.tc</code> package intern <code>TypeSig</code> objects,
050 it will also ensure that, for <code>TypeSig s</code> and <code>TypeDecl
051 d,</code><ul>
052
053 <li> <code>s.getTypeDecl()</code> is always a canonical <code>TypeDecl</code>
054
055 <li> <code>s.getTypeDecl().sig == s</code>
056
057 <li> if <code>d</code> is canonical then <code>d.sig.getTypeDecl()==d</code>
058
059 <li> if <code>d</code> is not canonical then <code>d.sig</code> is the
060 <code>TypeSig</code> associated with <code>d</code>'s typename.</ul>
061
062 <i>What is the interface for clients within the <code>javafe.tc</code>
063 package?</i><p>
064
065
066
067 <h3> Staging the processing of type declarations </h3><p>
068
069 Resolving the names in a type declaration and checking its static
070 semantics usually involves looking at other declarations to which it
071 refers. Finding, reading, and processing referred-to types makes
072 resolution and checking fairly complicated. As a result, we have
073 decomposed it into smaller steps. Type declarations move through a
074 number of states as the resolution and checking process proceeds. In
075 addition to making the overall processing of type declarations
076 conceptually more manageable, this decomposition has two other
077 benefits:<ul>
078
079
080 <li> <i>Handling cycles</i>. As mentioned above, processing one type may
081 involve processing types to which it refers. However, two types may
082 refer to each other, making it impossible to process any one of them
083 "first." Decomposing the processing into stages helps us handle such
084 cycles.
085
086 <li> <i>Improving performance</i>. Processing one type declaration does
087 not require fully processing the declarations to which it refers. How
088 much processing is required of a referred-to type depends on the manner
089 in which it is referred (e.g., the superclass of a class requires more
090 processing than a type referred to by another type referred to by the
091 class). Decomposing processing into stages allows us to be lazy in
092 processing referred-to types; that is, it allows us to process them only
093 to the extent that is necessary and no further.</ul>
094
095
096 The rest of this section details the states through which a
097 <code>TypeSig</code> object moves during its lifetime. Most clients of
098 the <code>javafe.tc</code> package do not need to know about these
099 details. However, clients interested in extending the processing done
100 by the <code>javafe.tc</code> package may need to add other states as
101 well. Also, this documentation gives an overview of the
102 <code>javafe.tc</code> package for those interested in understanding its
103 implementation.<p>
104
105 <code>TypeSig</code>s start in the <i><code>TypeSig</code> created</i>
106 state then move sequentially through the following four states:
107 <i>parsed</i>, <i>supertype links resolved</i>, <i>prepped</i>, and
108 <i>checked</i>. Each following state represents additional processing
109 completed on top of the processing required for the previous state. A
110 description of these states in reverse order follows. Included are the
111 properties that hold in each state; these properties are "additive":
112 properties of states later in the list are also properties of states
113 earlier in the list.<ul>
114
115 <li> <i>Checked.</i> Type declarations in this state have been fully
116 disambiguated, resolved and checked (see <a
117 href="javafe.tc.TypeCheck.html"> <code>TypeCheck</code> </a> for the
118 definitions of disambiguation, resolution, and checking).
119 Transitioning to this state can trigger parsing and/or preparation of
120 types referenced (<i>where?</i>) either explicitly or implicitly.
121 Implicitly referenced types are types used but not explicitly
122 mentioned in a <code>TypeName</code> node (<i>huh?</i>); for example,
123 the type of the result of <code>foo</code> in the expression
124 "<code>bar(x.foo())</code>" is implicitly referenced by this
125 expression.<p>
126
127
128 <li> <i>Prepped.</i> When checking a type declaration, we need to look
129 up members of other type declarations it uses. Before looking up
130 members of these referred-to declarations, it is useful to do some work
131 on them first, such as building internal tables. <code>TypeSig</code>s
132 in the prepped state have had such work done on their declarations,
133 preparing them for having their members queried. As a convenience, the
134 methods of <code>TypeSig</code> that lookup the members of a type
135 declaration, such as <A href="#lookupField(javafe.ast.Identifier,
136 javafe.tc.TypeSig)"> <code>lookupField</code></A> and <A
137 href="#lookupMethod(javafe.ast.Identifier, javafe.ast.Type[],
138 javafe.tc.TypeSig)"> <code>lookupMethod</code></a>, automatically
139 transition the declaration (<i><code>TypeSig</code></i>?) to the prepped
140 state if it isn't there already.<p>
141
142 When preparing the declaration associated with a <code>TypeSig</code>,
143 it is also useful to report certain errors in it, such as two fields
144 with the same name. This way, when checking a class, the user will also
145 see a report of errors in the interfaces (but not the implementations)
146 of the classes used by the class being checked.<p>
147
148 The prepped state is <i>supertype transitive</i>: a state <i>X</i> is
149 supertype transitive if a <code>TypeSig</code> can only be in state
150 <i>X</i> if all its supertypes are at least in state <i>X</i>. Note
151 that there is no requirement that <i>X</i>'s type members be in any
152 particular state.<p>
153
154
155 <li> <i>Supertype links resolved.</i> When preparing or checking a type
156 declaration, we may need to ask if one type referred to by the
157 declaration is a supertype of another. To perform this query, we need
158 to resolve supertype links. After parsing, the supertypes of a type
159 declaration are represented as <code>TypeName</code>s, which are
160 symbolic references. Resolution of a <code>TypeName</code> object
161 involves pointing its <code>sig</code> field to the <code>TypeSig</code>
162 object for the type declaration to which the <code>TypeName</code>
163 symbolically refers. Resolving the supertype links of type declarations
164 separately from preparing them allows us to perform supertype checks
165 during the preparation process.<p>
166
167 As a convenience, the <code>isSubtypeOf</code> method of
168 <code>TypeSig</code>, which performs the supertype test, automatically
169 resolves supertype links if they have not been resolved already.<p>
170
171 Like the prepped state, the "supertype links resolved" state is
172 supertype transitive.<p>
173
174
175 <li> <i>Parsed</i>. Although many <code>TypeSig</code>s come into
176 existence when their type declarations are parsed, some of them can be
177 created earlier. Thus, we can distinguish <code>TypeSig</code>s that
178 have been parsed from those that have not. However, it is difficult for
179 a client outside <code>javafe.tc</code> to know whether or not a
180 <code>TypeSig</code> has been parsed. This is because, if a client
181 calls <a href="#getTypeDecl()"> <code>getTypeDecl</code></a> on a
182 <code>TypeSig</code> that has not been parsed, it will be parsed
183 automatically.<p>
184
185
186 <li> <i><code>TypeSig</code> created</i>. This is the initial state
187 of <code>TypeSig</code> objects that come into existence before their
188 corresponding declarations have been parsed. Again, it is it is
189 difficult for a client outside <code>javafe.tc</code> to to distinguish
190 between this state and the parsed state.</ul>
191
192
193
194
195 <h3> More internal details </h3>
196
197 <p> This section contains a few more details about the implementation
198 for those who wish to understand it.
199
200 <p> Inside the <code>javafe.tc</code> package, creation of
201 <code>TypeSig</code> and <code>TypeDecl</code> objects is managed by
202 the <a href="javafe.tc.OutsideEnv.html"> <code>OutsideEnv</code>
203 </a> class. Methods of this class take the fully-qualified name of
204 an "package-member type" -- that is, a type declaration not nested
205 inside another declaration -- and return the <code>TypeSig</code>
206 instance associated with the type declaration denoted by that name.
207 <code>OutsideEnv</code> also coordinates the parsing of type
208 declarations, ensuring that only one <code>TypeDecl</code> is
209 created for a type declaration, and ensuring that
210 <code>TypeSig</code> objects point to the appropriate
211 <code>TypeDecl</code> objects.
212
213 <p> The <code>OutsideEnv</code> uses direct instances of
214 <code>TypeSig</CODE> for nested types only. It uses a special subclass
215 of <code>TypeSig</code>, <code>TopTypeSig</code>, for externally
216 nameable types (what the Java spec calls "top-level types"). This
217 subclass has fields giving the types external name. A further subclass
218 of <code>TopTypeSig</code>, <code>OutsideTypeSig</code>, handles outside
219 types. Alone among <code>TypeSigs</code>, <code>OutsideTypeSig</code>s
220 have the the ability to load their <code>TypeDecl</code> objects lazily.
221 All other <code>TypeSig</code> classes must have their
222 <code>TypeDecl</code> provided at creation time. However, this is an
223 implementation issue only: clients outside of <code>javafe.tc</code>
224 should not assume the existence of these subclasses.
225
226 <p> Transitioning a <code>TypeSig</code> from one state to another may
227 require parsing and processing of other types such as supertypes or the
228 types found in method signatures. For example, checking that the
229 <code>throws</code> clause of a method override is legal may involve
230 checking a subtype relationship, which requires that types involved be
231 supertype-link resolved. We call transitions that arise in the process
232 of another transitions "secondary transitions." The code that
233 implements transitions does not have to explicitly invoke secondary
234 transitions; rather, they are performed by calling methods like
235 <code>lookupField</code> or <code>isSubtypeOf</code>, whose
236 implementations <em>do</em> invoke transitions if they are needed. For
237 example, the method that implements the preparation transition does not
238 directly call the method that implements supertype link resolution, but
239 it <em>does</em> call <code>isSubtypeOf</code>, which in turn does
240 directly call the supertype link resolution method. Thus, secondary
241 transitions are largely transparent to the code implementing each
242 transition, with one exception. The code implementing the transition to
243 one state can<em>not</em> invoke methods that automatically transition
244 types to a higher state. For example, the code implementing supertype
245 link resolution cannot call <code>lookupField</code>. This discipline
246 helps us avoid looping.
247
248
249 @see OutsideEnv
250 @see TypeCheck
251 @see TypeDecl
252 @see TypeName
253
254 */
255 public class TypeSig extends Type
256 {
257 /***************************************************
258 * *
259 * Basic TypeSig instance variables: *
260 * *
261 **************************************************/
262
263 /**
264 * The name of the package we belong to. Always non-null.
265 */
266 //@ invariant \nonnullelements(packageName);
267 public /*public readonly non_null */ String[] packageName;
268
269 /**
270 * Our enclosing type or null iff we are a package-member type.
271 */
272 public /*public readonly*/ TypeSig enclosingType;
273
274 /**
275 * Our simple name or null if we are an anonymous type.
276 */
277 public /*public readonly*/ String simpleName;
278
279 /**
280 * Are we a direct member of a package or a type? <p>
281 *
282 * (Otherwise, we are a block-level type or an anonymous type.) <p>
283 */
284 public /*public readonly*/ boolean member;
285
286
287 /**
288 * Our enclosing Env; may be null for member types because of
289 * laziness. Use TypeSig.getEnclosingEnv() to obtain an always
290 * non-null version of this.
291 */
292 protected /*subclass-only*/ Env enclosingEnv;
293
294 /**
295 * Our TypeDecl; may be null only for package-member type
296 * because of laziness. Use getTypeDecl() to obtain an always
297 * non-null version of this. <p>
298 *
299 * This variable should be set only using setDecl. <p>
300 */
301 //@ invariant state >= PARSED ==> myTypeDecl != null;
302 //@ invariant state < PARSED ==> myTypeDecl == null;
303 /*@spec_public*/ protected TypeDecl myTypeDecl;
304
305 /**
306 * The CompilationUnit we belong to; null iff myTypeDecl is null
307 * because of laziness. Use getCompilationUnit() to obtain an
308 * always non-null version of this.
309 */
310 //@ invariant (myTypeDecl==null) == (CU==null);
311 protected CompilationUnit CU;
312
313
314
315 /*
316 * Enforce the various invariants about what kind of type we represent
317 * and the nullness of our basic instance variables.
318 *
319 *
320 * You can tell what kind of type we are as follows:
321 *
322 * package-member type if enclosingType==null
323 * type-member type if enclosingType != null && member
324 * block level type if simpleName != null && !member
325 * anonymous type if simpleName==null
326 */
327 //@ invariant (enclosingType==null) ==> member; // package-member
328 //@ invariant (simpleName==null) ==> !member; // anonymous
329 //@ invariant !member ==> enclosingEnv != null;
330 //@ invariant (enclosingType != null) ==> myTypeDecl != null;
331
332
333 /***************************************************
334 * *
335 * Associating TypeSigs and TypeDecls: *
336 * *
337 **************************************************/
338
339 /**
340 * Decorates <code>TypeDecl</code> nodes to point to
341 * <code>TypeSig</code> objects.
342 */
343 //@ invariant sigDecoration.decorationType == \type(TypeSig);
344 public static final ASTDecoration sigDecoration
345 = new ASTDecoration("sigDecoration");
346
347
348 /**
349 * The myTypeDecl field maps TypeSigs to TypeDecls. The
350 * getSig(TypeDecl) function provides the reverse mapping. <p>
351 *
352 * Precondition: d has already been associated with a TypeSig. <p>
353 */
354 //@ ensures \result != null;
355 public static TypeSig getSig(/*@ non_null @*/ TypeDecl d) {
356 TypeSig r = (TypeSig)sigDecoration.get(d);
357 if (r == null) Assert.notNull(r, //@ nowarn Pre;
358 "getSig called on a TypeDecl (" + d.id + ") not associated with a TypeSig");
359 return r;
360 }
361
362
363 /**
364 * Protected routine used to associate a TypeSig with a TypeDecl. <p>
365 *
366 * It automatically creates TypeSigs for any (indirect) members
367 * of decl and associates them properly. <p>
368 *
369 * CU must be the CompilationUnit that decl belongs to.<p>
370 */
371 //@ ensures this.myTypeDecl != null;
372 protected void setDecl(/*@ non_null @*/ TypeDecl decl,
373 /*@ non_null @*/ CompilationUnit CU) {
374 this.myTypeDecl = decl;
375 this.CU = CU;
376 state = PARSED;
377 sigDecoration.set(decl, this);
378
379 // Create TypeSigs for any TypeDecl members of us:
380 for (int i = 0; i < decl.elems.size(); i++) {
381 TypeDeclElem member = decl.elems.elementAt(i);
382 if (!(member instanceof TypeDecl))
383 continue;
384
385 TypeDecl subDecl = (TypeDecl)member;
386 TypeSig subSig = Types.makeTypeSig(
387 packageName, subDecl.id.toString(),
388 this, subDecl, CU);
389 // (The TypeSig constructor will call subSig.setDecl(subDecl, CU))
390 }
391 }
392
393 /***************************************************
394 * *
395 * Creation: *
396 * *
397 **************************************************/
398
399 /**
400 * Create a TypeSig that represents a non-member type. <p>
401 *
402 * We represent a block-level type if simpleName is non-null,
403 * and an anonymous type otherwise. <p>
404 */
405 //@ requires !(enclosingEnv instanceof EnvForCU);
406 protected TypeSig(String simpleName,
407 /*@ non_null @*/ Env enclosingEnv,
408 /*@ non_null @*/ TypeDecl decl) {
409 super(); //@ nowarn Pre; // can't do set before super()
410
411 member = false;
412
413 this.simpleName = simpleName;
414 this.enclosingEnv = enclosingEnv;
415
416 this.enclosingType = enclosingEnv.getEnclosingClass();
417 //@ assume this.enclosingType != this;
418 Assert.notNull(this.enclosingType);
419
420 // We inherit our packageName and CompilationUnit from our
421 // enclosing type:
422 this.packageName = this.enclosingType.packageName;
423 this.CU = this.enclosingType.getCompilationUnit();
424
425 setDecl(decl, this.CU); //@ nowarn Invariant; // helper function
426 }
427
428
429 /**
430 * Create a TypeSig that represents a member type. <p>
431 *
432 * This constructor is designed to be private to TypeSig;
433 * It is protected to support the Types inst pattern, but
434 * clients should use
435 * OutsideEnv.lookup[Deffered] and getSig to get TypeSig's
436 * representing member types. <p>
437 *
438 * We represent a package-member type if enclosingType is
439 * non-null, and a type-member type otherwise. <p>
440 *
441 * Note: packageName should never be modified by the caller after
442 * this call.<p>
443 *
444 * CU must be the CompilationUnit that decl belongs to.<p>
445 */
446 //@ requires \nonnullelements(packageName);
447 //@ requires (enclosingType != null) ==> (decl != null);
448 //@ requires (decl==null) == (CU==null);
449 protected TypeSig(/*@non_null*/ String[] packageName,
450 /*@ non_null @*/ String simpleName,
451 TypeSig enclosingType,
452 TypeDecl decl, CompilationUnit CU) {
453 super(); //@ nowarn Pre; // can't do set before super
454
455 member = true;
456
457 this.packageName = packageName;
458 this.simpleName = simpleName;
459 this.enclosingType = enclosingType;
460
461 this.enclosingEnv = null; // be lazy...
462 if (decl != null)
463 setDecl(decl, CU); //@ nowarn Invariant; // helper function
464 }
465
466
467 /**
468 * Create a TypeSig that represents an internal-use-only
469 * package-member type. Such types do not have external names
470 * and should be avoided if at all possible since they are
471 * kludges. <p>
472 *
473 * This constructor should only be used by
474 * PrepTypeDeclaration.getRootInterface().<p>
475 *
476 * Note: packageName should never be modified by the caller after
477 * this call.<p>
478 *
479 * CU must be the CompilationUnit that decl belongs to.<p>
480 */
481 //@ requires \nonnullelements(packageName);
482 protected TypeSig(/*@non_null*/ String[] packageName,
483 /*@ non_null @*/ String simpleName,
484 /*@ non_null @*/ TypeDecl decl,
485 /*@ non_null @*/ CompilationUnit CU) {
486 this(packageName, simpleName, null, decl, CU);
487 }
488
489
490
491 // //@ requires \nonnullelements(packageName);
492 // //@ requires (enclosingType != null) ==> (decl != null);
493 // //@ requires (decl==null) == (CU==null);
494 // //@ ensures \result != null;
495 // UNUSED
496 // private static TypeSig make(String[] packageName,
497 // /*@ non_null @*/ String simpleName,
498 // TypeSig enclosingType,
499 // TypeDecl decl,
500 // CompilationUnit CU) {
501 // TypeSig t = Types.makeTypeSig(packageName,
502 // simpleName,
503 // enclosingType,
504 // decl,
505 // CU);
506 // return t;
507 // }
508
509 /***************************************************
510 * *
511 * Interning by External Name for package-members: *
512 * *
513 **************************************************/
514
515 /*
516 * We maintain a mapping from fully-qualified names to
517 * package-member types so that OutsideEnv never creates 2
518 * TypeSigs with the same external name.
519 *
520 * This map is complete in the sense that all created
521 * package-member types are in its range.
522 *
523 * These functions are intended for use *only* by OutsideEnv!
524 */
525
526
527 /**
528 * The map from fully-qualified external names of package-member
529 * types to the TypeSigs representing them. <p>
530 *
531 * Invariant: map's range includes all existing package-member
532 * TypeSigs; map sends getKey(P,T) to the unique package-member
533 * TypeSig with external name P.T.<p>
534 *
535 * The domain type of map is String and its range type is (non-null)
536 * TypeSigs.<p>
537 */
538 // Old specs from original full JML spec files. Must be
539 // rewritten for current java.util.Hashtable specs.
540 //- invariant map.keyType == \type(String);
541 //- invariant map.elementType == \type(TypeSig);
542 //@ spec_public
543 private static final Hashtable map = new Hashtable(101);
544
545 public static final void clear() {
546 map.clear();
547 }
548
549 /**
550 * Compute the key for map for fully-qualified type P.T.
551 */
552 //@ requires \nonnullelements(P);
553 //@ ensures \result != null;
554 private static String getKey(/*@non_null*/ String[] P, /*@ non_null @*/ String T) {
555 String key = "";
556
557 for (int i=0; i<P.length; i++)
558 key += "."+P[i];
559 key += "."+T;
560
561 return key;
562 }
563
564
565 /**
566 * If a TypeSig representing the package-member type named P.T
567 * has been created, return it; otherwise, return null. <p>
568 *
569 * This function should only be called by OutsideEnv. <p>
570 */
571 //@ requires \nonnullelements(P);
572 static public TypeSig lookup(/*@non_null*/ String[] P, /*@ non_null @*/ String T) {
573 return (TypeSig)map.get(getKey(P,T));
574 }
575
576 // FIXME - the type lookup ends up parsing a qualified name into
577 // pieces and then reassembling them through getKey into a
578 // qualified name. This could be improved by providing a
579 // direct lookup from a fully qualified name
580
581 /**
582 * If a TypeSig representing the package-member type named P.T
583 * has been created, return it; otherwise, create such a TypeSig
584 * then return it. <p>
585 *
586 * This function should only be called by OutsideEnv. <p>
587 */
588 //@ requires \nonnullelements(P);
589 //@ ensures \result != null;
590 static /*package*/ TypeSig get(/*@non_null*/ String[] P, /*@ non_null @*/ String T) {
591 String key = getKey(P,T);
592 TypeSig result = (TypeSig)map.get(key);
593 if (result != null)
594 return result;
595
596 result = Types.makeTypeSig(P, T, (TypeSig)null, (TypeDecl)null,
597 (CompilationUnit)null);
598 map.put(key, result);
599 return result;
600 }
601
602 /***************************************************
603 * *
604 * Lazy loading of TypeDecls: *
605 * *
606 **************************************************/
607
608 /**
609 * Get the non-null TypeDecl we are associated with. <p>
610 *
611 * (Under the covers, for package-member types, this method may
612 * cause <code>OutsideEnv</code> to parse the
613 * <code>TypeDecl</code> in question, but this should be
614 * transparent to most clients.) <p>
615 */
616 //@ ensures \result != null;
617 //@ ensures state>=PARSED;
618 public TypeDecl getTypeDecl() {
619 if (myTypeDecl==null)
620 preload();
621
622 return myTypeDecl;
623 }
624
625 /**
626 * Get the non-null CompilationUnit we are associated with. <p>
627 *
628 * (Under the covers, for package-member types, this method may
629 * cause <code>OutsideEnv</code> to parse the type in question,
630 * but this should be transparent to most clients.) <p>
631 */
632 //@ ensures \result != null;
633 public CompilationUnit getCompilationUnit() {
634 if (myTypeDecl==null)
635 preload();
636
637 return CU;
638 }
639
640
641 /**
642 * Ensure that we have loaded our TypeDecl, invoking OutsideEnv
643 * if needed to load a TypeDecl into us via load below. We abort
644 * via an assertion failure if OutsideEnv fails to load us.
645 */
646 //@ ensures myTypeDecl != null;
647 private void preload() {
648 if (myTypeDecl != null)
649 return;
650
651 /*
652 * This call should always call our load method (below) with a
653 * TypeDecl.
654 */
655 OutsideEnv.load(this);
656 Assert.notNull(myTypeDecl);
657 }
658
659
660 /*
661 * The below functions are provided for use by OutsideEnv in
662 * loading us.
663 */
664
665
666 /**
667 * Is our TypeDecl already loaded?
668 */
669 //@ ensures !member ==> \result;
670 //@ ensures \result == (myTypeDecl != null);
671 public boolean isPreloaded() {
672 return myTypeDecl != null;
673 }
674
675
676 /**
677 * Load the non-null TypeDecl decl as our TypeDecl.
678 * This method is used by OutsideEnv to install a TypeDecl in us once
679 * it has been loaded.<p>
680 *
681 * If we have already been loaded with a different TypeDecl, then
682 * an appropriate fatal error results. <p>
683 *
684 * Note: This method should *only* be called by OutsideEnv.load.<p>
685 *
686 * CU must be the CompilationUnit that decl belongs to.<p>
687 */
688 //@ ensures myTypeDecl != null;
689 /*package*/ void load(/*@ non_null @*/ TypeDecl decl,
690 /*@ non_null @*/ CompilationUnit CU) {
691 // If no (potential) duplication, just install decl and return:
692 if (myTypeDecl==null) {
693 setDecl(decl, CU);
694 return;
695 }
696
697 if (myTypeDecl==decl && this.CU==CU)
698 return;
699
700 ErrorSet.fatal(decl.loc, "type " + this.getExternalName()
701 + " already defined at "
702 + Location.toString(myTypeDecl.loc));
703 }
704
705 /***************************************************
706 * *
707 * Name accessor functions: *
708 * *
709 **************************************************/
710
711 /**
712 * Return our package name as a human-readable string
713 * suitable for display. If we are in the unnamed package,
714 * the constant THE_UNNAMED_PACKAGE is returned.
715 */
716 //@ ensures \result != null;
717 public String getPackageName() {
718 if (packageName.length == 0)
719 return THE_UNNAMED_PACKAGE;
720
721 StringBuffer P = new StringBuffer(5*packageName.length);
722 for (int i = 0; i < packageName.length; i++) {
723 if (i != 0)
724 P.append('.');
725 P.append(packageName[i]);
726 }
727
728 return P.toString();
729 }
730
731 public final static String THE_UNNAMED_PACKAGE = "<the unnamed package>";
732
733
734 /**
735 * Return our exact type name, omitting the package name, as a
736 * human-readable string suitable for display.
737 */
738 //@ ensures \result != null;
739 public String getTypeName() {
740 if (enclosingType==null) {
741 // package-member type:
742 return simpleName;
743 }
744
745 String parent = enclosingType.getTypeName();
746 if (member)
747 return parent+"$"+simpleName;
748 if (simpleName != null)
749 return parent+"$"
750 +Location.toLineNumber(getTypeDecl().getStartLoc())+"$"
751 +simpleName;
752 else
753 return parent+"$"
754 +Location.toLineNumber(getTypeDecl().getStartLoc())+"$"
755 +"<anonymous>";
756 }
757
758
759 /**
760 * Return our exact fully-qualified external name as a
761 * human-readable string suitable for display. The package name is
762 * omitted if it is the unnamed package.
763 */
764 //@ ensures \result != null;
765 public String getExternalName() {
766 String P = getPackageName();
767 if (P==THE_UNNAMED_PACKAGE)
768 return getTypeName();
769 else
770 return P+"."+getTypeName();
771 }
772
773
774 /**
775 * Returns a String that represents the value of this Object.
776 */
777 public /*@non_null*/ String toString() {
778 return getExternalName();
779 }
780
781 /***************************************************
782 * *
783 * ASTNode functions: *
784 * *
785 **************************************************/
786
787 public int childCount() {
788 return 0;
789 }
790
791 public Object childAt(int i) {
792 throw new IndexOutOfBoundsException();
793 } //@ nowarn Exception;
794
795 public int getTag() {
796 return TagConstants.TYPESIG;
797 }
798
799 public void accept(Visitor v) {
800 // v does not have a special visitor method for TypeSig
801 // so just use the one for Type
802 v.visitType( this );
803 }
804
805
806 public Object accept(VisitorArgResult v, Object o) {
807 return v.visitType( this,o );
808 }
809
810 /*
811 // We don't promise any meaningful locations...
812 //@ invariant !syntax;
813 {
814 // Deal with can't handle non-injective fields & invariants problem:
815 //@ assume (\forall MethodDecl m; m.returnType != this);
816 //@ assume (\forall GenericVarDecl g; g.type != this);
817 //@ set syntax = false;
818 }
819 */
820
821 //@ public represents startLoc <- getTypeDecl().getStartLoc();
822 public int getStartLoc() {
823 return getTypeDecl().getStartLoc();
824 }
825
826 //@ also public normal_behavior
827 //@ ensures \result == getTypeDecl().getEndLoc();
828 public int getEndLoc() {
829 return getTypeDecl().getEndLoc();
830 }
831
832 /***************************************************
833 * *
834 * Looking up type members: *
835 * *
836 **************************************************/
837
838 /**
839 * Do we have a type member named id (including inherited type
840 * members)? <p>
841 *
842 * If we have exactly one such type member, then return it. If
843 * we have no such type member, return null. If we have more
844 * than one such type member, then if loc != Location.NULL then a
845 * fatal error is reported at that location via ErrorSet else one
846 * of the relevant type members is returned.<p>
847 *
848 * If caller is null, this routine does not check that the
849 * resulting type (if any) is accessible. If caller is not
850 * null, then the resulting type is checked to be accessible
851 * from the caller. <p>
852 */
853 public TypeSig lookupType(TypeSig caller,
854 /*@ non_null @*/ Identifier id, int loc) {
855 // Look locally first:
856 TypeSig result = lookupLocalType(caller,id);
857 if (result != null)
858 return result;
859
860 /*
861 * Then try our superclass (if any):
862 */
863 resolveSupertypeLinks();
864 TypeSig s = superClass();
865 if (s != null) {
866 result = s.lookupType(caller,id,loc);
867 }
868
869 /*
870 * and our superinterfaces, checking for duplicates:
871 */
872 TypeDecl decl = getTypeDecl();
873 for (int i=0; i<decl.superInterfaces.size(); i++ ) {
874 TypeName superInterfaceName = decl.superInterfaces.elementAt(i);
875 TypeSig newResult = getSig(superInterfaceName).lookupType(caller,id, loc);
876 if (newResult==null)
877 continue;
878
879 if (result==null || result==newResult)
880 result = newResult;
881 else {
882 if (loc != Location.NULL)
883 ErrorSet.fatal(loc, "Reference to type member `"
884 + id.toString()
885 + "' of type " + toString()
886 + " is ambiguous; it may refer to type "
887 + result.toString()
888 + " or to type "
889 + newResult.toString()
890 + ".");
891 else
892 return result;
893 }
894 }
895
896 return result;
897 }
898
899
900 /**
901 * Do we have a type member named id (*not* including inherited
902 * type members)? If so, return it; otherwise, return null. <p>
903 *
904 * If caller is null, then this routine does not check that the
905 * resulting type (if any) is actually accessable. If caller is
906 * non_null, then the resulting type is checked that it is
907 * accessible from the caller.<p>
908 */
909
910 public TypeSig lookupLocalType(TypeSig caller, Identifier id) {
911 TypeDeclElemVec elems = getTypeDecl().elems;
912 for (int i=0; i<elems.size(); i++) {
913 TypeDeclElem e = elems.elementAt(i);
914 if (e instanceof TypeDecl && ((TypeDecl)e).id==id) {
915 TypeDecl td = (TypeDecl)e;
916 TypeSig t = getSig(td);
917 if (caller == null) return t;
918 TypeSig c = caller;
919 do {
920 if (TypeCheck.inst.canAccess(c, this, td.modifiers,
921 td.pmodifiers) ) {
922 return t;
923 }
924 c = c.enclosingType;
925 } while (c != null);
926 }
927 }
928 return null;
929 }
930
931 /***************************************************
932 * *
933 * Environments: *
934 * *
935 **************************************************/
936
937 /**
938 * Return our enclosing environment.
939 */
940 //@ ensures \result != null;
941 public Env getEnclosingEnv() {
942 if (enclosingEnv != null)
943 return enclosingEnv;
944
945 if (enclosingType==null)
946 enclosingEnv = new EnvForCU(getCompilationUnit());
947 else
948 enclosingEnv = enclosingType.getEnv(isStatic());
949
950 return enclosingEnv;
951 }
952
953
954 /**
955 * Return an environment for use in checking code inside us. <p>
956 *
957 * Our instance members are considered accessible iff
958 * staticContext is false.
959 */
960 //@ ensures \result != null;
961 public EnvForTypeSig getEnv(boolean staticContext) {
962 return new EnvForTypeSig(getEnclosingEnv(), this, staticContext);
963 }
964
965 /***************************************************
966 * *
967 * Misc: *
968 * *
969 **************************************************/
970
971 /**
972 * Are we (possibly implicitly) static? <p>
973 *
974 * This differs from using Modifiers.isStatic because it does not
975 * rely on Prep'ing having added the static modifier where
976 * implicit so we can be used by Prep itself.
977 */
978 public boolean isStatic() {
979 if (Modifiers.isStatic(getTypeDecl().modifiers))
980 return true;
981
982 // interfaces are implicitly static:
983 if (getTypeDecl() instanceof InterfaceDecl)
984 return true;
985
986 // interface members are implicitly static:
987 if (enclosingType != null &&
988 enclosingType.getTypeDecl() instanceof InterfaceDecl)
989 return true;
990
991 return false;
992 }
993
994
995 /**
996 * Are we a top-level type? <p>
997 *
998 * True iff either we are a package-level type or a static member
999 * of a top-level type. <p>
1000 *
1001 * Note: This may be called during any state; it may bump
1002 * TypeSigs to the Parsed state. <p>
1003 */
1004 //@ ensures enclosingType==null ==> \result;
1005 public boolean isTopLevelType() {
1006 if (enclosingType==null)
1007 return true;
1008
1009 if (!isStatic())
1010 return false;
1011
1012 return enclosingType.isTopLevelType();
1013 }
1014
1015 //************************************************************
1016 //************************************************************
1017 //************************************************************
1018 //************************************************************
1019 //************************************************************
1020
1021 /***************************************************
1022 * *
1023 * TypeSig states and transition functions: *
1024 * *
1025 **************************************************/
1026
1027 /*
1028 * The states that a TypeSig can be in. The variable state (below)
1029 * holds our current state, which must be one of the following
1030 * values:
1031 */
1032 public final static int CREATED = 1;
1033 public final static int PARSED = 2;
1034 public final static int RESOLVINGLINKS = 3; // used by SLResolution
1035 public final static int LINKSRESOLVED = 4;
1036 public final static int PREPPED = 5;
1037 public final static int CHECKED = 6;
1038
1039 /**
1040 * The current state of <code>this</code>. Must be one of
1041 * <code>CREATED</code>, <code>PARSED</code>,
1042 * <code>LINKSRESOLVED</code>, <code>PREPPED</code>, or
1043 * <code>CHECKED</code>. In most circumstances, this field
1044 * should not be written to; rather, methods of
1045 * <code>TypeSig</code> should be called to effect changes to it.
1046 * This field must never be decreased after creation time.
1047 */
1048 public int state = CREATED;
1049
1050
1051 /*
1052 * Note: The transition to PARSED from CREATED is performed
1053 * automatically by setDecl.
1054 */
1055
1056 /**
1057 * Transition <code>this</code> to the supertype links resolved
1058 * state. <p>
1059 *
1060 * See the TypeSig type comments for details of what this involves.<p>
1061 *
1062 * A fatal error may be reported if we cannot resolve a supertype
1063 * name, or detect a cycle in the type hierarchy.<p>
1064 */
1065 //@ modifies state;
1066 //@ ensures state >= TypeSig.LINKSRESOLVED;
1067 public void resolveSupertypeLinks() {
1068 if (state<LINKSRESOLVED)
1069 SLResolution.transition(this);
1070 }
1071
1072 /**
1073 * Transition <code>this</code> to the "prepped" state. <p>
1074 *
1075 * A prepped declaration has all of the <code>TypeName</code>
1076 * nodes defining the types of its members resolved. For a field
1077 * declaration, this means resolving the <code>type</code> field;
1078 * For a routine declaration, this means resolving
1079 * <code>TypeName</code>s that occur in the <code>args</code>,
1080 * <code>raises</code>, and <code>returnType</code> fields.<p>
1081 *
1082 * See the TypeSig type comments for more details of what this
1083 * involves.<p>
1084 */
1085 //@ modifies state;
1086 //@ ensures state >= PREPPED;
1087 public void prep() {
1088 if (state >= TypeSig.PREPPED)
1089 return;
1090
1091 if (Info.on) Info.out("[prepping-slinks " + this + "]");
1092 resolveSupertypeLinks();
1093 if (Info.on) Info.out("[prepping " + this + "]");
1094 PrepTypeDeclaration.inst.prepTypeSignature(this);
1095 if (Info.on) Info.out("[prepping-complete " + this + "]");
1096
1097 state = TypeSig.PREPPED;
1098 }
1099
1100 /**
1101 * Transition <code>this</code> to the "checked" state. <p>
1102 *
1103 * See the TypeSig type comments for details of what this involves.<p>
1104 *
1105 * A fatal error may be reported if we cannot resolve a supertype
1106 * name, or detect a cycle in the type hierarchy.<p>
1107 */
1108 //@ modifies state;
1109 //@ ensures state >= CHECKED;
1110 public void typecheck() {
1111 if (this.state >= TypeSig.CHECKED)
1112 return;
1113 if (this.state < TypeSig.PREPPED)
1114 prep();
1115
1116 typecheckSuperTypes();
1117 long start = 0;
1118 if (Info.on) start = javafe.Tool.currentTime();
1119 if (Info.on) Info.out("[typechecking " + this + "]");
1120 TypeCheck.inst.makeFlowInsensitiveChecks().checkTypeDeclaration(this);
1121 if (Info.on) Info.out("[typechecking-end " + this + " " + javafe.Tool.timeUsed(start) + "]");
1122 // TODO: @review kiniry 31 Aug - Why is this commented out?
1123 // FlowSensitiveChecks.checkTypeDeclaration(this);
1124 this.state = TypeSig.CHECKED;
1125 }
1126
1127 /**
1128 * Typecheck the superclass of the current classtype being typecheck and
1129 * typecheck all interfaces that the current classtype implements.
1130 */
1131 public void typecheckSuperTypes() {
1132 TypeSig t = superClass();
1133 // If we are typechecking an inner class whose parent is the enclosing
1134 // environment, then do not try to typecheck the parent as that is what we
1135 // are doing at this moment!
1136 if ((t != null) && getEnclosingEnv().getEnclosingClass() != enclosingType)
1137 t.typecheck();
1138 TypeDecl decl = getTypeDecl();
1139 for (int i=0; i<decl.superInterfaces.size(); i++ ) {
1140 TypeName superInterfaceName = decl.superInterfaces.elementAt(i);
1141 TypeSig ts = getSig(superInterfaceName);
1142 ts.typecheck();
1143 }
1144 }
1145
1146 /***************************************************
1147 * *
1148 * Looking up fields, methods, and constructors: *
1149 * *
1150 **************************************************/
1151
1152 //// Fields and methods associated with preparation of a TypeSig
1153
1154 /** After preparation, this field contains all field members of
1155 the <code>TypeDecl</code> associated with <code>this</code>,
1156 including inherited ones. */
1157
1158 // "invariant" fields.<each element>.hasParent
1159 //@ invariant state >= PREPPED ==> fields != null;
1160 //@ spec_public
1161 protected FieldDeclVec fields;
1162
1163 // Note: 'fields' contains all visible fields
1164 // 'hiddenfields' contains all the others (e.g. hidden or not accessible)
1165 //@ invariant state >= PREPPED ==> hiddenfields != null;
1166 protected FieldDeclVec hiddenfields;
1167
1168 /** After preparation, this field contains all method members of
1169 the <code>TypeDecl</code> associated with <code>this</code>,
1170 including inherited ones. */
1171
1172 // "invariant" methods.<each element>.hasParent
1173 //@ invariant state >= PREPPED ==> methods != null;
1174 //@ spec_public
1175 protected MethodDeclVec methods;
1176
1177 /** Returns all fields of the type declaration associated with
1178 <code>this</code>, including inherited ones. (If
1179 <code>this</code> has not been prepped yet, this method will prep
1180 it (possibly triggering parsing and/or processing of other
1181 types).) If allFields is true, then all declared fields, including
1182 hidden and inaccessible fields, are returned; if allFields is false,
1183 then only visible fields are returned. */
1184
1185 // "ensures" <result elements>.hasParent
1186 //@ ensures \result != null;
1187 public FieldDeclVec getFields(boolean allFields) {
1188 prep();
1189 Assert.notNull( fields );
1190 if (!allFields) return fields;
1191 FieldDeclVec v = fields.copy();
1192 v.append(hiddenfields);
1193 return v;
1194 }
1195
1196 public FieldDeclVec getFieldsRaw() { return fields; }
1197
1198 public FieldDeclVec getHiddenFields() { return hiddenfields; }
1199
1200 /** Similar to <code>getFields</code>, except for methods. */
1201
1202 // "ensures" <result elements>.hasParent
1203 //@ ensures \result != null;
1204 public MethodDeclVec getMethods() {
1205 prep();
1206 Assert.notNull( methods );
1207 return methods;
1208 }
1209
1210
1211 /** TBW */
1212
1213 //@ requires \nonnullelements(args) && caller != null;
1214 //@ ensures \result != null;
1215 public ConstructorDecl lookupConstructor(Type[] args, TypeSig caller)
1216 throws LookupException
1217 {
1218 prep();
1219
1220 // Holds the most specific, applicable, accessible constructor found so far
1221 ConstructorDecl mostSpecific = null;
1222 boolean somethingFound = false;
1223 TypeDecl decl = getTypeDecl();
1224
1225 search:
1226 for(int i = 0; i < decl.elems.size(); i++) {
1227 TypeDeclElem elem = decl.elems.elementAt(i);
1228 if (elem instanceof ConstructorDecl) {
1229 ConstructorDecl md = (ConstructorDecl)elem;
1230 if (md.args.size() == args.length
1231 && TypeCheck.inst.canAccess(caller, this, md.modifiers,
1232 md.pmodifiers) ) {
1233 // accessible, same name and number of args
1234
1235 somethingFound = true;
1236 for(int j = 0; j < args.length; j++)
1237 if (! Types.isInvocationConvertable(args[j],
1238 md.args.elementAt(j).type))
1239 continue search;
1240 // accessible and applicable
1241
1242 if (mostSpecific == null ||
1243 Types.routineMoreSpecific(md, mostSpecific))
1244 mostSpecific = md;
1245 else if (! Types.routineMoreSpecific(mostSpecific, md))
1246 throw new LookupException( LookupException.AMBIGUOUS );
1247 }
1248 }
1249 }
1250
1251 if (mostSpecific != null)
1252 return mostSpecific;
1253 else if (somethingFound)
1254 throw new LookupException( LookupException.BADTYPECOMBO );
1255 else
1256 throw new LookupException( LookupException.NOTFOUND );
1257 }
1258
1259 /** TBW */
1260
1261 //@ ensures \result != null;
1262 //@ ensures \result.id == id;
1263 public FieldDecl lookupField(Identifier id, /*@ non_null */ TypeSig caller)
1264 throws LookupException
1265 {
1266 FieldDeclVec fields = getFields(false);
1267 FieldDecl r = null;
1268 for(int i=0; i<fields.size(); i++ ) {
1269 FieldDecl fd = fields.elementAt(i);
1270 if (fd.id == id)
1271 if (r == null) r = fd;
1272 else throw new LookupException( LookupException.AMBIGUOUS );
1273 }
1274
1275 if (r == null)
1276 throw new LookupException( LookupException.NOTFOUND );
1277 else if (! TypeCheck.inst.canAccess(caller, this, r.modifiers,
1278 r.pmodifiers))
1279 throw new LookupException( LookupException.NOTACCESSIBLE );
1280 else return r;
1281 }
1282
1283
1284 /** TBW */
1285
1286 public boolean hasField(Identifier id) {
1287 FieldDeclVec fields = getFields(false);
1288 for(int i=0; i<fields.size(); i++)
1289 if (fields.elementAt(i).id == id) return true;
1290 return false;
1291 }
1292
1293 public MethodDecl hasMethod(Identifier id, Type[] args) {
1294 try {
1295 return lookupMethod(id,args,this);
1296 } catch (LookupException e) {
1297 return null;
1298 }
1299 }
1300
1301 /** TBW */
1302
1303 //@ requires \nonnullelements(args) && caller != null;
1304 //@ ensures \result != null;
1305 //@ ensures \result.id == id;
1306 public MethodDecl lookupMethod(Identifier id, Type[] args, TypeSig caller)
1307 throws LookupException
1308 {
1309 MethodDeclVec methods = getMethods();
1310
1311 // Holds the most specific, applicable, accessible method found so far
1312 MethodDecl mostSpecific = null;
1313 boolean somethingFound = false;
1314
1315 search:
1316 for(int i = 0; i < methods.size(); i++) {
1317 MethodDecl md = methods.elementAt(i);
1318 if (md.id == id
1319 && md.args.size() == args.length
1320 && TypeCheck.inst.canAccess(caller, this, md.modifiers,
1321 md.pmodifiers)) {
1322 // accessible, same name and number of args
1323
1324 somethingFound = true;
1325 for(int j=0; j<args.length; j++) {
1326 // FIXME - the argument (particularly the second) might be just a
1327 // Typename - ought to resolve it once and for all, instead of doing so
1328 // each time the following method is called.
1329 if(! Types.isInvocationConvertable(args[j],
1330 md.args.elementAt(j).type)) {
1331 continue search;
1332 }
1333 }
1334 // accessible and applicable
1335
1336 if (mostSpecific == null
1337 || Types.routineMoreSpecific(md, mostSpecific))
1338 mostSpecific = md;
1339 else if (! Types.routineMoreSpecific(mostSpecific, md))
1340 throw new LookupException( LookupException.AMBIGUOUS );
1341 }
1342 }
1343
1344 if (mostSpecific != null)
1345 return mostSpecific;
1346 else if (somethingFound)
1347 throw new LookupException( LookupException.BADTYPECOMBO );
1348 else
1349 throw new LookupException( LookupException.NOTFOUND );
1350 }
1351
1352 //************************************************************
1353 //************************************************************
1354 //************************************************************
1355 //************************************************************
1356 //************************************************************
1357
1358
1359 /**
1360 * Gets the TypeSig recorded by <code>setSig</code>, or null.
1361 */
1362 public static TypeSig getRawSig(/*@ non_null @*/ TypeName n) {
1363 TypeSig r = (TypeSig)sigDecoration.get(n);
1364 return r;
1365 }
1366
1367 /**
1368 * Gets the TypeSig recorded by <code>setSig</code>.
1369 *
1370 * Precondition: n has been resolved.
1371 */
1372 //@ ensures \result != null;
1373 public static TypeSig getSig(/*@ non_null @*/ TypeName n) {
1374 TypeSig r = (TypeSig)sigDecoration.get(n);
1375 if (r==null) {
1376 ErrorSet.error(n.getStartLoc(),
1377 "Internal error: getSig called on a TypeName ("
1378 + n + ") that has not been resolved!");
1379 System.out.flush();
1380 Assert.precondition( //@ nowarn Pre; // punt on catching this
1381 "See previous error message");
1382 }
1383
1384 return r;
1385 }
1386
1387 public static void setSig(/*@ non_null @*/ TypeName n,
1388 /*@ non_null @*/ TypeSig sig) {
1389 sigDecoration.set(n, sig);
1390 }
1391
1392 public final boolean isSubtypeOf(TypeSig s2) {
1393 if (state < TypeSig.LINKSRESOLVED)
1394 resolveSupertypeLinks();
1395
1396 TypeSig jlo = Types.javaLangObject();
1397
1398 if (this == s2 || s2 == jlo)
1399 return true;
1400 if (this == jlo)
1401 return false;
1402
1403 TypeDecl d = getTypeDecl();
1404 if (d.getTag() == TagConstants.CLASSDECL &&
1405 ((ClassDecl)d).superClass != null) {
1406 TypeSig s1 = getSig(((ClassDecl)d).superClass);
1407 if (s1 == s2)
1408 return true;
1409 if (s1.isSubtypeOf(s2))
1410 return true;
1411 }
1412
1413 for(int i = 0; i < d.superInterfaces.size(); i++) {
1414 TypeSig s1 = getSig(d.superInterfaces.elementAt(i));
1415 if (s1 == s2)
1416 return true;
1417 if (s1.isSubtypeOf(s2))
1418 return true;
1419 }
1420
1421 return false;
1422 }
1423
1424 //// Helper functions
1425
1426 //@ requires s != null;
1427 public final boolean inSamePackageAs(TypeSig s) {
1428 String[] p1 = this.packageName;
1429 String[] p2 = s.packageName;
1430 if (p1.length != p2.length) return false;
1431 for(int i = 0; i < p1.length; i++)
1432 if (! p1[i].equals(p2[i])) return false;
1433 return true;
1434 }
1435
1436 /** Check invariants of a TypeSig, raising an exception if
1437 they don't hold. */
1438
1439 public void check() {
1440 Assert.notFalse(state != RESOLVINGLINKS); //@ nowarn Pre;
1441
1442 if (state >= CREATED) {
1443 if (state == CREATED)
1444 Assert.notFalse(myTypeDecl == null);
1445 }
1446
1447 if (state >= PARSED) {
1448 Assert.notNull(myTypeDecl);
1449 Assert.notFalse(this == getSig(myTypeDecl)); //@ nowarn Pre;
1450 }
1451 }
1452
1453 /** Check invariants of a TypeSig, raising an exception if
1454 they don't hold. */
1455
1456 public void deepCheck() {
1457 Info.out("[checking deep invariants on " + this + "]");
1458 check();
1459 if (state >= PARSED) {
1460 myTypeDecl.check();
1461 CheckInvariants.checkTypeDeclOfSig(this);
1462 }
1463 }
1464
1465 private TypeSig superClass = null;
1466
1467 // Probably should use this only after super types have been resolved.
1468 public TypeSig superClass() {
1469 if (superClass != null) return superClass;
1470 TypeDecl decl = getTypeDecl();
1471 if (decl instanceof ClassDecl) {
1472 TypeName n = ((ClassDecl)decl).superClass;
1473 if (n != null) {
1474 superClass = getSig(n);
1475 }
1476 }
1477 return superClass;
1478 }
1479
1480 /* This class returns a Collection containing all of the super interfaces
1481 of the receiver TypeSig. No interface is repeated.
1482 */
1483 public java.util.Collection superInterfaces() {
1484 TypeSig t = this;
1485 java.util.ArrayList result = new java.util.ArrayList();
1486 int j = 0;
1487 while (true) {
1488 TypeNameVec tv = t.getTypeDecl().superInterfaces;
1489 for (int i = 0; i<tv.size(); ++i) {
1490 TypeName tt = tv.elementAt(i);
1491 TypeSig tts = getSig(tt);
1492 if (!result.contains(tts)) result.add(tts);
1493 }
1494 if (j >= result.size()) break;
1495 t = (TypeSig)result.get(j++);
1496 }
1497 return result;
1498 }
1499
1500 } // end of class TypeSig
1501
1502 /*
1503 * Local Variables:
1504 * Mode: Java
1505 * fill-column: 85
1506 * End:
1507 */