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);
34 throw new Error("Couldn't find class:"+superc);
36 supertable.put(cd,cd_super);
41 public ClassDescriptor getMainClass() {
42 return getClass(state.main);
45 public MethodDescriptor getRun() {
46 ClassDescriptor cd=getClass(TypeUtil.ThreadClass);
47 for(Iterator methodit=cd.getMethodTable().getSet("run").iterator(); methodit.hasNext();) {
48 MethodDescriptor md=(MethodDescriptor) methodit.next();
49 if (md.numParameters()!=0||md.getModifiers().isStatic())
53 throw new Error("Can't find Thread.run");
56 public MethodDescriptor getMain() {
57 ClassDescriptor cd=getMainClass();
58 Set mainset=cd.getMethodTable().getSet("main");
59 for(Iterator mainit=mainset.iterator(); mainit.hasNext();) {
60 MethodDescriptor md=(MethodDescriptor)mainit.next();
61 if (md.numParameters()!=1)
63 Descriptor pd=md.getParameter(0);
64 TypeDescriptor tpd=(pd instanceof TagVarDescriptor) ? ((TagVarDescriptor)pd).getType() : ((VarDescriptor)pd)
66 if (tpd.getArrayCount()!=1)
68 if (!tpd.getSymbol().equals("String"))
71 if (!md.getModifiers().isStatic())
72 throw new Error("Error: Non static main");
75 throw new Error(cd+" has no main");
78 /** Check to see if md1 is more specific than md2... Informally
79 if md2 could always be called given the arguments passed into
82 public boolean isMoreSpecific(MethodDescriptor md1, MethodDescriptor md2) {
83 /* Checks if md1 is more specific than md2 */
84 if (md1.numParameters()!=md2.numParameters())
86 for(int i=0; i<md1.numParameters(); i++) {
87 if (!this.isSuperorType(md2.getParamType(i), md1.getParamType(i)))
90 if (!this.isSuperorType(md2.getReturnType(), md1.getReturnType()))
93 if (!this.isSuperorType(md2.getClassDesc(), md1.getClassDesc()))
99 public MethodDescriptor getMethod(ClassDescriptor cd, String name, TypeDescriptor[] types) {
100 Set methoddescriptorset=cd.getMethodTable().getSet(name);
101 MethodDescriptor bestmd=null;
103 for(Iterator methodit=methoddescriptorset.iterator(); methodit.hasNext();) {
104 MethodDescriptor currmd=(MethodDescriptor)methodit.next();
105 /* Need correct number of parameters */
106 if (types.length!=currmd.numParameters())
108 for(int i=0; i<types.length; i++) {
109 if (!this.isSuperorType(currmd.getParamType(i),types[i]))
112 /* Method okay so far */
116 if (isMoreSpecific(currmd,bestmd)) {
118 } else if (!isMoreSpecific(bestmd, currmd))
119 throw new Error("No method is most specific");
121 /* Is this more specific than bestmd */
125 throw new Error("Could find: "+name + " in "+cd);
130 public void createFullTable() {
131 subclasstable=new Hashtable();
133 Iterator classit=state.getClassSymbolTable().getDescriptorsIterator();
134 while(classit.hasNext()) {
135 ClassDescriptor cd=(ClassDescriptor)classit.next();
136 ClassDescriptor tmp=cd.getSuperDesc();
139 if (!subclasstable.containsKey(tmp))
140 subclasstable.put(tmp,new HashSet());
141 HashSet hs=(HashSet)subclasstable.get(tmp);
143 tmp=tmp.getSuperDesc();
148 public Set getSubClasses(ClassDescriptor cd) {
149 return (Set)subclasstable.get(cd);
152 public ClassDescriptor getSuper(ClassDescriptor cd) {
153 return (ClassDescriptor)supertable.get(cd);
156 public boolean isCastable(TypeDescriptor original, TypeDescriptor casttype) {
157 if (original.isChar()&&
162 if (casttype.isChar()&&
168 original.isDouble()))
174 public boolean isSuperorType(TypeDescriptor possiblesuper, TypeDescriptor cd2) {
175 //Matching type are always okay
176 if (possiblesuper.equals(cd2))
179 if ((possiblesuper.isTag() && !cd2.isTag())||
180 (!possiblesuper.isTag() && cd2.isTag()))
184 if (cd2.isArray()||possiblesuper.isArray()) {
185 // Object is super class of all arrays
186 if (possiblesuper.getSymbol().equals(ObjectClass)&&!possiblesuper.isArray())
189 // If we have the same dimensionality of arrays & both are classes, we can default to the normal test
190 if (cd2.isClass()&&possiblesuper.isClass()
191 &&(possiblesuper.getArrayCount()==cd2.getArrayCount())&&
192 isSuperorType(possiblesuper.getClassDesc(), cd2.getClassDesc()))
195 // Object is superclass of all array classes
196 if (possiblesuper.getSymbol().equals(ObjectClass)&&cd2.isClass()
197 &&(possiblesuper.getArrayCount()<cd2.getArrayCount()))
203 if (possiblesuper.isClass()&&
205 return isSuperorType(possiblesuper.getClassDesc(), cd2.getClassDesc());
206 else if (possiblesuper.isClass()&&
209 else if (possiblesuper.isNull())
210 throw new Error(); //not sure when this case would occur
211 else if (possiblesuper.isPrimitive()&&
213 ///Primitive widenings from 5.1.2
214 if (cd2.isByte()&&(possiblesuper.isByte()||possiblesuper.isShort()||
215 possiblesuper.isInt()||possiblesuper.isLong()||
216 possiblesuper.isFloat()||possiblesuper.isDouble()))
218 if (cd2.isShort()&&(possiblesuper.isShort()||
219 possiblesuper.isInt()||possiblesuper.isLong()||
220 possiblesuper.isFloat()||possiblesuper.isDouble()))
222 if (cd2.isChar()&&(possiblesuper.isChar()||
223 possiblesuper.isInt()||possiblesuper.isLong()||
224 possiblesuper.isFloat()||possiblesuper.isDouble()))
226 if (cd2.isInt()&&(possiblesuper.isInt()||possiblesuper.isLong()||
227 possiblesuper.isFloat()||possiblesuper.isDouble()))
229 if (cd2.isLong()&&(possiblesuper.isLong()||
230 possiblesuper.isFloat()||possiblesuper.isDouble()))
232 if (cd2.isFloat()&&(possiblesuper.isFloat()||possiblesuper.isDouble()))
234 if (cd2.isDouble()&&possiblesuper.isDouble())
237 if (cd2.isBoolean()&&possiblesuper.isBoolean())
241 } else if (possiblesuper.isPrimitive()&&(!possiblesuper.isArray())&&
244 else if (cd2.isPrimitive()&&(!cd2.isArray())&&
245 possiblesuper.isPtr())
248 throw new Error("Case not handled:"+possiblesuper+" "+cd2);
252 public boolean isSuperorType(ClassDescriptor possiblesuper, ClassDescriptor cd2) {
253 if (possiblesuper==cd2)
256 return isSuper(possiblesuper, cd2);
259 private boolean isSuper(ClassDescriptor possiblesuper, ClassDescriptor cd2) {
262 if (cd2==possiblesuper)