4 public class TypeUtil {
5 public static final String StringClass="String";
6 public static final String ObjectClass="Object";
7 public static final String StartupClass="StartupObject";
8 public static final String TagClass="TagDescriptor";
9 public static final String ThreadClass="Thread";
12 Hashtable subclasstable;
14 public TypeUtil(State state) {
19 public ClassDescriptor getClass(String classname) {
20 ClassDescriptor cd=(ClassDescriptor)state.getClassSymbolTable().get(classname);
24 private void createTables() {
25 supertable=new Hashtable();
27 Iterator classit=state.getClassSymbolTable().getDescriptorsIterator();
28 while(classit.hasNext()) {
29 ClassDescriptor cd=(ClassDescriptor)classit.next();
30 String superc=cd.getSuper();
32 ClassDescriptor cd_super=getClass(superc);
33 supertable.put(cd,cd_super);
38 public ClassDescriptor getMainClass() {
39 return getClass(state.main);
42 public MethodDescriptor getRun() {
43 ClassDescriptor cd=getClass(TypeUtil.ThreadClass);
44 for(Iterator methodit=cd.getMethodTable().getSet("run").iterator();methodit.hasNext();) {
45 MethodDescriptor md=(MethodDescriptor) methodit.next();
46 if (md.numParameters()!=0||md.getModifiers().isStatic())
50 throw new Error("Can't find Thread.run");
53 public MethodDescriptor getMain() {
54 ClassDescriptor cd=getMainClass();
55 Set mainset=cd.getMethodTable().getSet("main");
56 for(Iterator mainit=mainset.iterator();mainit.hasNext();) {
57 MethodDescriptor md=(MethodDescriptor)mainit.next();
58 if (md.numParameters()!=1)
60 Descriptor pd=md.getParameter(0);
61 TypeDescriptor tpd=(pd instanceof TagVarDescriptor)?((TagVarDescriptor)pd).getType():((VarDescriptor)pd)
63 if (tpd.getArrayCount()!=1)
65 if (!tpd.getSymbol().equals("String"))
68 if (!md.getModifiers().isStatic())
69 throw new Error("Error: Non static main");
72 throw new Error(cd+" has no main");
75 public void createFullTable() {
76 subclasstable=new Hashtable();
78 Iterator classit=state.getClassSymbolTable().getDescriptorsIterator();
79 while(classit.hasNext()) {
80 ClassDescriptor cd=(ClassDescriptor)classit.next();
81 ClassDescriptor tmp=cd.getSuperDesc();
84 if (!subclasstable.containsKey(tmp))
85 subclasstable.put(tmp,new HashSet());
86 HashSet hs=(HashSet)subclasstable.get(tmp);
88 tmp=tmp.getSuperDesc();
93 public Set getSubClasses(ClassDescriptor cd) {
94 return (Set)subclasstable.get(cd);
97 public ClassDescriptor getSuper(ClassDescriptor cd) {
98 return (ClassDescriptor)supertable.get(cd);
101 public boolean isCastable(TypeDescriptor original, TypeDescriptor casttype) {
102 if (original.isChar()&&
107 if (casttype.isChar()&&
113 original.isDouble()))
119 public boolean isSuperorType(TypeDescriptor possiblesuper, TypeDescriptor cd2) {
120 //Matching type are always okay
121 if (possiblesuper.equals(cd2))
124 if ((possiblesuper.isTag() && !cd2.isTag())||
125 (!possiblesuper.isTag() && cd2.isTag()))
129 if (cd2.isArray()||possiblesuper.isArray()) {
130 // Object is super class of all arrays
131 if (possiblesuper.getSymbol().equals(ObjectClass)&&!possiblesuper.isArray())
134 // If we have the same dimensionality of arrays & both are classes, we can default to the normal test
135 if (cd2.isClass()&&possiblesuper.isClass()
136 &&(possiblesuper.getArrayCount()==cd2.getArrayCount())&&
137 isSuperorType(possiblesuper.getClassDesc(), cd2.getClassDesc()))
140 // Object is superclass of all array classes
141 if (possiblesuper.getSymbol().equals(ObjectClass)&&cd2.isClass()
142 &&(possiblesuper.getArrayCount()<cd2.getArrayCount()))
148 if (possiblesuper.isClass()&&
150 return isSuperorType(possiblesuper.getClassDesc(), cd2.getClassDesc());
151 else if (possiblesuper.isClass()&&
154 else if (possiblesuper.isNull())
155 throw new Error(); //not sure when this case would occur
156 else if (possiblesuper.isPrimitive()&&
158 ///Primitive widenings from 5.1.2
159 if (cd2.isByte()&&(possiblesuper.isByte()||possiblesuper.isShort()||
160 possiblesuper.isInt()||possiblesuper.isLong()||
161 possiblesuper.isFloat()||possiblesuper.isDouble()))
163 if (cd2.isShort()&&(possiblesuper.isShort()||
164 possiblesuper.isInt()||possiblesuper.isLong()||
165 possiblesuper.isFloat()||possiblesuper.isDouble()))
167 if (cd2.isChar()&&(possiblesuper.isChar()||
168 possiblesuper.isInt()||possiblesuper.isLong()||
169 possiblesuper.isFloat()||possiblesuper.isDouble()))
171 if (cd2.isInt()&&(possiblesuper.isInt()||possiblesuper.isLong()||
172 possiblesuper.isFloat()||possiblesuper.isDouble()))
174 if (cd2.isLong()&&(possiblesuper.isLong()||
175 possiblesuper.isFloat()||possiblesuper.isDouble()))
177 if (cd2.isFloat()&&(possiblesuper.isFloat()||possiblesuper.isDouble()))
179 if (cd2.isDouble()&&possiblesuper.isDouble())
182 if (cd2.isBoolean()&&possiblesuper.isBoolean())
186 } else if (possiblesuper.isPrimitive()&&(!possiblesuper.isArray())&&
187 (cd2.isArray()||cd2.isPtr()))
189 else if (cd2.isPrimitive()&&(!cd2.isArray())&&
190 (possiblesuper.isArray()||possiblesuper.isPtr()))
193 throw new Error("Case not handled:"+possiblesuper+" "+cd2);
197 public boolean isSuperorType(ClassDescriptor possiblesuper, ClassDescriptor cd2) {
198 if (possiblesuper==cd2)
201 return isSuper(possiblesuper, cd2);
204 private boolean isSuper(ClassDescriptor possiblesuper, ClassDescriptor cd2) {
207 if (cd2==possiblesuper)