KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > aspectj > compiler > base > ast > Type


1 /* -*- Mode: Java; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
2  *
3  * This file is part of the compiler and core tools for the AspectJ(tm)
4  * programming language; see http://aspectj.org
5  *
6  * The contents of this file are subject to the Mozilla Public License
7  * Version 1.1 (the "License"); you may not use this file except in
8  * compliance with the License. You may obtain a copy of the License at
9  * either http://www.mozilla.org/MPL/ or http://aspectj.org/MPL/.
10  *
11  * Software distributed under the License is distributed on an "AS IS" basis,
12  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
13  * for the specific language governing rights and limitations under the
14  * License.
15  *
16  * The Original Code is AspectJ.
17  *
18  * The Initial Developer of the Original Code is Xerox Corporation. Portions
19  * created by Xerox Corporation are Copyright (C) 1999-2002 Xerox Corporation.
20  * All Rights Reserved.
21  *
22  * Contributor(s):
23  */

24
25 package org.aspectj.compiler.base.ast;
26
27 import org.aspectj.compiler.base.*;
28 import java.util.*;
29
30 //ASPECT use introduction from crosscuts package
31
import org.aspectj.compiler.crosscuts.ast.*;
32
33 import org.aspectj.compiler.base.bcg.CodeBuilder;
34 import org.aspectj.compiler.base.bcg.Label;
35
36 /**
37  * A single instance of this class will exist for each type in the world
38  * This class provides 6 kinds of methods
39  * 1. methods for comparing types for assignability, subtyping, ...
40  * 2. methods for looking up methods, fields, and other decs in types
41  * 3. methods to determine if a type is of a certain kind (isAspect, isClass, ...)
42  * 4. methods for producing reasonable string representations of types
43  * 5. generally static methods for manipulating sets of Types
44  * 6. a few special purpose methods that need more thought
45  */

46 public abstract class Type extends SemanticObject {
47     private ArrayType arrayType = null;
48     public synchronized ArrayType getArrayType() {
49         if (arrayType == null) {
50             arrayType = new ArrayType(getCompiler(), this);
51         }
52         return arrayType;
53     }
54
55     public int getArrayDimCount() { return 0; }
56
57     public Type getBaseComponentType() { return this; }
58
59     // code to handle the type graph
60
// I THINK this is the right place for it...
61
protected final Set directSubTypes = new HashSet();
62     protected final Set directSuperTypes = new HashSet();
63     public void addDirectSuperType(Type superType) {
64         //XXX awful hack for minimal circularity checking
65
if (superType == this) {
66             getCompiler().showError(getTypeDec(), getString() + " tries to extend itself");
67         }
68
69         directSuperTypes.add(superType);
70         superType.directSubTypes.add(this);
71     }
72
73
74     public Type(JavaCompiler compiler) {
75         super(compiler);
76     }
77
78     protected void showNotFoundError(String JavaDoc id, ASTObject fromWhere, String JavaDoc kind) {
79         getCompiler().showError(fromWhere, "no " + kind + "s on " + toShortString());
80     }
81
82     public boolean isEffectivelyStatic() {
83         return true;
84     }
85
86     //XXX should be abstract
87
public void ensureBuiltTypeGraph() {
88     }
89
90     public void ensureFinishedSignature() {
91     }
92
93
94     public void buildTypeGraph() { }
95     public void validateTypeGraph() { }
96     public void finishTypeIntroductions() { ensureBuiltTypeGraph(); }
97     public void finish() { finishTypeIntroductions(); }
98     
99
100     public Collection getDirectSuperTypes() {
101         buildTypeGraph();
102         return directSuperTypes;
103     }
104
105     public Collection getDirectSubTypes() {
106         buildTypeGraph();
107         return directSubTypes;
108     }
109
110     public Type getDeclaringType() {
111         return null;
112     }
113
114     //XXX too dangerous
115
public TypeDec getTypeDec() { return (TypeDec)dec; }
116
117     public PointcutSO getPointcut(String JavaDoc id, ASTObject fromWhere, boolean showError) {
118         if (showError) showNotFoundError(id, fromWhere, "pointcut");
119         return null; //getWorld().POINTCUT_DEC_NOT_FOUND;
120
}
121
122     public Field getField(String JavaDoc id, ASTObject fromWhere, boolean showError) {
123         if (showError) showNotFoundError(id, fromWhere, "field");
124         return null; //getWorld().FIELD_DEC_NOT_FOUND;
125
}
126
127     public Type getInnerType(String JavaDoc id, ASTObject fromWhere, boolean showError) {
128         if (showError) showNotFoundError(id, fromWhere, "inner type");
129         return getTypeManager().TYPE_NOT_FOUND;
130     }
131
132     public Method getMethod(String JavaDoc id, ASTObject fromWhere, Exprs params,
133                                boolean showError)
134     {
135         if (showError) showNotFoundError(id, fromWhere, "method");
136         return null; //getWorld().METHOD_DEC_NOT_FOUND;
137
}
138
139     public Constructor getConstructor(ASTObject fromWhere, Exprs params,
140                                          boolean showError)
141     {
142         if (showError) showNotFoundError(getPrettyString(), fromWhere, "constructor");
143         return null; //getWorld().CONSTRUCTOR_DEC_NOT_FOUND;
144
}
145
146     // currently only used by ReceptionsPointcut
147
public boolean hasMethodNamed(String JavaDoc id) {
148         return false;
149     }
150
151     // only used by CodePattern
152
public SemanticObject findMatchingSemanticObject(SemanticObject o) {
153         return null;
154     }
155
156     //XXX replace with above
157
/**
158      * Will return a declaration in this types signature which matches the signature
159      * of dec.
160      */

161     public Dec findMatchingDec(Dec dec) {
162         SemanticObject o = findMatchingSemanticObject(dec.getCorrespondingSemanticObject());
163         if (o == null) return null;
164         return o.getCorrespondingDec();
165     }
166
167     // currently only used by AdviceWeaver for dealing with synthetic reception points
168
public Collection getInheritedMethods() {
169         return Collections.EMPTY_LIST;
170     }
171
172     // used by StructureViewer
173
public Collection getInheritedMembers() {
174         return Collections.EMPTY_LIST;
175     }
176
177     public boolean isCloneable() { return false; }
178
179     public boolean isInterface() { return false; }
180     public boolean isClass() { return false; }
181     public boolean isAspect() { return false; }
182
183     //??? why isn't this just !isAbstract()???
184
public boolean isConcrete() { return isClass(); }
185     public boolean isAbstract() { return false; }
186
187     public boolean isInnerType() { return false; }
188
189     /** is this the TypeNotFound sentinel? */
190     public boolean isMissing() { return false; }
191
192     public boolean isAnonymous() { return false; }
193
194     public boolean isAssignableFrom(Type other) {
195         return other.isSubtypeOf(this);
196     }
197
198     public boolean isSubtypeOf(Type other) {
199         ensureBuiltTypeGraph();
200         //System.out.println(this.getString() + " subtype? " + other.getString());
201
if (this.isEquivalent(other)) return true;
202
203         for (Iterator i = directSuperTypes.iterator(); i.hasNext(); ) {
204             Type superType = (Type)i.next();
205             // don't return true based on missing super types
206
if (superType.isMissing()) continue;
207             //System.out.println(" supertype: " + superType);
208
if (superType.isSubtypeOf(other)) return true;
209         }
210         return false;
211     }
212
213     public boolean isStrictSubtypeOf(Type other) {
214         return (this != other) && this.isSubtypeOf(other);
215     }
216
217     //XXX these don't handle interfaces correctly at all
218
public abstract boolean isCoercableTo(Type other);
219 // {
220
// return isAssignableFrom(other) || other.isAssignableFrom(this);
221
// }
222

223     //??? what extra do I need to worry about here ???
224
public boolean isMethodConvertableTo(Type other) {
225 // System.out.println(" " + this + " is convertable? " + other + " == " +
226
// other.isAssignableFrom(this));
227
return other.isAssignableFrom(this);
228     }
229
230     public boolean isEquivalent(Type other) {
231         return isAnyType() || other.isAnyType() || this == other;
232     }
233
234     public boolean dominates(Type other) {
235         return this.isStrictSubtypeOf(other);
236     }
237
238     public TypeD makeTypeD() {
239         //XXXthrow new RuntimeException("shouldn't ever call Type.makeTypeD");
240
return new ResolvedTypeD(getAST().getSourceLocation(), this);
241     }
242
243     //XXX all five should be abstract
244
public Expr getClassExpr() {
245         throw new RuntimeException JavaDoc("internal error: no class expr for " + this);
246     }
247     public Expr fromObject(Expr expr) { return null; }
248     public Expr makeObject(Expr expr) { return expr; } //XXX ugly}
249
public Expr getNullExpr() { return null; }
250     public Type getRefType() { return this; }
251
252
253     public Type getOutermostType() {
254         return this;
255     }
256
257     public Type getPrivateCookieType() {
258         return getOutermostType();
259     }
260
261     public Type getPackageCookieType() {
262         return getOutermostType();
263     }
264
265
266     // The next six methods will almost certainly go by the wayside
267
// when the type reorganization is done.
268
public boolean isObject() {
269         if (this == getTypeManager().getObjectType()) return true;
270         return false;
271     }
272
273     public boolean isUncheckedThrowable() {
274         if (this.isSubtypeOf(getTypeManager().getErrorType())) return true;
275         if (this.isSubtypeOf(getTypeManager().getRuntimeExceptionType())) return true;
276         return false;
277     }
278
279     public boolean isVoid() {
280         return this == getTypeManager().voidType;
281     }
282
283     public boolean isReferenceType() {
284         return this instanceof RefType;
285     }
286
287     public boolean isString() {
288         return this == getTypeManager().getStringType();
289     }
290     public final boolean isPrimitive() {
291         return isNumeric() || isBoolean() || isVoid();
292     }
293     public final boolean isNumeric() {
294         return isIntegral() || this == getTypeManager().floatType || this == getTypeManager().doubleType;
295     }
296     public final boolean isIntegral() {
297         return this == getTypeManager().byteType || this == getTypeManager().charType || this == getTypeManager().shortType ||
298                this == getTypeManager().intType || this == getTypeManager().longType;
299     }
300     public final boolean isBoolean() {
301         return this == getTypeManager().booleanType;
302     }
303
304     public boolean isAnyType() {
305         return false;
306     }
307
308
309     public abstract String JavaDoc toShortString();
310     public String JavaDoc getString() { return toShortString(); }
311     public String JavaDoc getPrettyString() { return toShortString(); }
312     public String JavaDoc getId() { return toShortString(); }
313     public String JavaDoc getExtendedId() { return toShortString(); }
314     
315     /**
316      * @return e.g. qualified type name java.util.Map.Entry will be returned as Map.Entry
317      */

318     public String JavaDoc getSourceExtendedId() { return toShortString(); }
319     public String JavaDoc getPackageName() { return null; }
320
321     public Type getOutermostLexicalType() { return this; }
322     public Type getOutermostBytecodeType() { return getOutermostType(); }
323
324     public boolean isAccessible(ASTObject fromWhere, boolean inBytecode) {
325         //System.out.println(this + " : " + getArrayDimCount());
326
if (isPrimitive()) return true;
327         if (getArrayDimCount() > 0) return getBaseComponentType().isAccessible(fromWhere, inBytecode);
328         return super.isAccessible(fromWhere, inBytecode);
329     }
330
331     // utility functions on sets
332
private static boolean anyParentsInSet(Type type, Set set) {
333         for(Iterator iter = set.iterator(); iter.hasNext(); ) {
334             Type testType = (Type)iter.next();
335             if (type.isStrictSubtypeOf(testType)) return true;
336         }
337         return false;
338     }
339
340
341     public static boolean hasMatchingType(Collection c, Type t) {
342         for (Iterator j = c.iterator(); j.hasNext(); ) {
343             Type testType = (Type)j.next();
344             if (t.isSubtypeOf(testType)) return true;
345         }
346         return false;
347     }
348
349     public static Set intersect(Set t1, Set t2) {
350         Set ret = new HashSet();
351         for (Iterator i = t1.iterator(); i.hasNext(); ) {
352             Type t = (Type)i.next();
353             if (hasMatchingType(t2, t)) {
354                 ret.add(t);
355             }
356         }
357         
358         for (Iterator i = t2.iterator(); i.hasNext(); ) {
359             Type t = (Type)i.next();
360             if (hasMatchingType(t1, t)) {
361                 ret.add(t);
362             }
363         }
364         return ret;
365     }
366
367     public static Set filterTopTypes(Set set) {
368         Set topSet = new HashSet();
369         for(Iterator iter = set.iterator(); iter.hasNext(); ) {
370             Type testType = (Type)iter.next();
371             if (!anyParentsInSet(testType, set)) {
372                 topSet.add(testType);
373             }
374         }
375         return topSet;
376     }
377
378     public static Set filterSubTypes(Type type, Set set) {
379         Set topSet = new HashSet();
380         for(Iterator iter = set.iterator(); iter.hasNext(); ) {
381             Type testType = (Type)iter.next();
382             if (testType.isSubtypeOf(type)) {
383                 topSet.add(testType);
384             } else if (type.isSubtypeOf(testType)) {
385                 topSet.add(type);
386             }
387         }
388         return topSet;
389     }
390
391     private void addMySubTypes(Set types) {
392         if (types.contains(this)) return;
393
394         types.add(this);
395
396         for (Iterator i = directSubTypes.iterator(); i.hasNext(); ) {
397             Type addType = (Type)i.next();
398             addType.addMySubTypes(types);
399         }
400     }
401
402
403     public Set getSubTypes() {
404         Set subTypes = new HashSet();
405         addMySubTypes(subTypes);
406         return subTypes;
407     }
408
409
410     public static Set addSubTypes(Set types) {
411         Set newTypes = new HashSet();
412
413         for(Iterator iter = types.iterator(); iter.hasNext(); ) {
414             Type type = (Type)iter.next();
415             newTypes.addAll(type.getSubTypes());
416         }
417         return newTypes;
418     }
419
420
421     private void addMySuperInterfaces(Set types) {
422         if (types.contains(this)) return;
423
424         if (this.isInterface()) types.add(this);
425
426         for (Iterator i = directSuperTypes.iterator(); i.hasNext(); ) {
427             Type addType = (Type)i.next();
428             addType.addMySuperInterfaces(types);
429         }
430     }
431     
432
433     public Set getAllSuperInterfaces() {
434         Set newTypes = new HashSet();
435         addMySuperInterfaces(newTypes);
436         return newTypes;
437     }
438
439     public static Set filterConcreteTypes(Set types) {
440         Set newTypes = new HashSet();
441
442         for(Iterator iter = types.iterator(); iter.hasNext(); ) {
443             Type type = (Type)iter.next();
444             if (type.isConcrete()) newTypes.add(type);
445         }
446         return newTypes;
447     }
448
449     public static Set makeTypeSet(Collection typeDecSet) {
450         HashSet ret = new HashSet();
451         for (Iterator i = typeDecSet.iterator(); i.hasNext(); ) {
452             ret.add( ((TypeDec)i.next()).getType() );
453         }
454         return ret;
455     }
456
457     // ------------------------------
458
// ASPECT: Constant folding
459

460     final LiteralExpr unsupportedFold() {
461         throw new RuntimeException JavaDoc("Unsupported fold on " + this);
462     }
463     abstract LiteralExpr foldCast(LiteralExpr lit);
464
465     abstract LiteralExpr foldPlusOp(LiteralExpr rand);
466     abstract LiteralExpr foldMinusOp(LiteralExpr rand);
467     abstract LiteralExpr foldBitNotOp(LiteralExpr rand);
468     abstract LiteralExpr foldLogNotOp(LiteralExpr rand);
469
470     abstract LiteralExpr foldAddOp(LiteralExpr lit1, LiteralExpr lit2);
471     abstract LiteralExpr foldNumericOp(String JavaDoc op, LiteralExpr lit1, LiteralExpr lit2);
472     abstract LiteralExpr foldBitwiseOp(String JavaDoc op, LiteralExpr lit1, LiteralExpr lit2);
473     abstract LiteralExpr foldShiftOp(String JavaDoc op, LiteralExpr lit1, LiteralExpr lit2);
474     abstract LiteralExpr foldEqualityTestOp(String JavaDoc op, LiteralExpr lit1, LiteralExpr lit2);
475     abstract LiteralExpr foldNumericTestOp(String JavaDoc op, LiteralExpr lit1, LiteralExpr lit2);
476
477     // ------------------------------
478
// ASPECT: code generation
479

480     // type numbers used only for the NEWARRAY instruction.
481
public static final int REF = 0;
482     public static final int VOID = 1;
483     public static final int BOOLEAN = 4;
484     public static final int CHAR = 5;
485     public static final int FLOAT = 6;
486     public static final int DOUBLE = 7;
487     public static final int BYTE = 8;
488     public static final int SHORT = 9;
489     public static final int INT = 10;
490     public static final int LONG = 11;
491
492     public int getTypeIndex() { return REF; }
493
494     // only overridden in ArrayType
495
void emitMultiNewarray(CodeBuilder cb, int filledDims) {
496         throw new RuntimeException JavaDoc("Unsupported emit on " + this);
497     }
498
499     // things overridden based on slot count (i.e., in DoubleType, LongType, VoidType)
500
void emitPop(CodeBuilder cb) { cb.emitPOP(); }
501     void emitDup(CodeBuilder cb) { cb.emitDUP(); }
502     void emitDupX1(CodeBuilder cb) { cb.emitDUP_X1(); }
503     void emitDupX2(CodeBuilder cb) { cb.emitDUP_X2(); }
504
505     // general type-based emitters
506
final void unsupportedEmit() {
507         throw new RuntimeException JavaDoc("Unsupported emit on " + this);
508     }
509     abstract void emitAload(CodeBuilder cb);
510     abstract void emitAstore(CodeBuilder cb);
511     abstract void emitInstanceof(CodeBuilder cb);
512     abstract void emitBitNot(CodeBuilder cb);
513     abstract void emitLogNot(CodeBuilder cb);
514     abstract void emitNewarray(CodeBuilder cb);
515     abstract void emitZero(CodeBuilder cb);
516     abstract void emitOne(CodeBuilder cb);
517     abstract void emitMinusOne(CodeBuilder cb);
518     abstract void emitAdd(CodeBuilder cb);
519     abstract void emitNeg(CodeBuilder cb);
520
521     abstract void emitNumericOp(CodeBuilder cb, String JavaDoc op);
522     abstract void emitBitwiseOp(CodeBuilder cb, String JavaDoc op);
523     abstract void emitShiftOp(CodeBuilder cb, String JavaDoc op);
524
525     abstract void emitCast(CodeBuilder cb, Type castTo);
526
527     public abstract void emitLoad(CodeBuilder cb, int loc);
528     public abstract void emitStore(CodeBuilder cb, int loc);
529     public abstract void emitReturn(CodeBuilder cb);
530
531     abstract void emitEqualityCompare(CodeBuilder cb, String JavaDoc op, Label t, Label f);
532     abstract void emitNumericCompare(CodeBuilder cb, String JavaDoc op, Label t, Label f);
533
534     // ------------------------------
535
// "fast" opcode handling
536

537     boolean hasFastEqualityTestOp() { return false; }
538     void emitFastEqualityTestOp(CodeBuilder cb, EqualityTestOpExpr e,
539                                 Label t, Label f) {
540         throw new RuntimeException JavaDoc("no fast equality op available");
541     }
542
543
544     boolean hasFastNumericTestOp() { return false; }
545     void emitFastNumericTestOp(CodeBuilder cb, NumericTestOpExpr e,
546                                Label t, Label f) {
547         throw new RuntimeException JavaDoc("no fast numeric op available");
548     }
549
550     boolean hasFastIncOp(Expr lhs, int rhs) { return false; }
551     void emitFastIncOp(CodeBuilder cb, Expr lhs, int rhs) {
552         throw new RuntimeException JavaDoc("no fast inc op available");
553     }
554
555     // ------------------------------
556
// ASPECT: Virtual machine internal names
557

558     /** The internal name is the name internal to the VM. Notably,
559         this uses / rather than . as a package separator. This is
560         only really defined on {@link NameType} and {@link ArrayType}. */

561     public String JavaDoc getInternalName() {
562         throw new RuntimeException JavaDoc("No internal name for " + this);
563     }
564
565     /** What is the JVM external name for this type? Strangely
566         enough, this is the same as getString() for primitive and
567         name-types, but is the same as getDescriptor() with '.'s
568         instead of '/'s for array types. Extremely wacky, and
569         currently only used in desugaring {@link ClassExpr}
570         expressions.
571     */

572
573     // XXX important: this must generate the post-inner-munged name
574
public String JavaDoc getExternalName() { // overridden in ArrayType and NameType
575
return getString();
576     }
577     
578
579     public List/*String*/ getNamePieces() {
580         String JavaDoc s = getString();
581         List ret = new ArrayList();
582         int lastDot = 0;
583         while (true) {
584             int nextDot = s.indexOf('.', lastDot);
585             if (nextDot == -1) break;
586             ret.add(s.substring(lastDot, nextDot));
587             lastDot = nextDot+1;
588         }
589         ret.add(s.substring(lastDot));
590         return ret;
591     }
592
593     /** The descriptor for this type, as used by classfiles. Note that
594         {@link FieldDec} and {@link MethodDec} objects also have
595         descriptors, which are built up out of type descriptors. */

596     public abstract String JavaDoc getDescriptor();
597
598     /** The number of slots for elements of this type. This is always
599         one, but is overridden for two in {@link LongType} and {@link
600         DoubleType}, and zero in {@link VoidType}. */

601     public int getSlotCount() { return 1; }
602
603 }
604
Popular Tags