7 public class TypeUtil {
8 public static final String StringClass="String";
9 public static final String ObjectClass="Object";
10 public static final String StartupClass="StartupObject";
11 public static final String TagClass="TagDescriptor";
12 public static final String ThreadClass="Thread";
15 Hashtable subclasstable;
18 public TypeUtil(State state, BuildIR bir) {
24 public void addNewClass(String cl) {
25 if (state.discclass.contains(cl))
27 for(int i=0;i<state.classpath.size();i++) {
28 String path=(String)state.classpath.get(i);
29 File f=new File(path, cl+".java");
32 ParseNode pn=Main.readSourceFile(state, f.getCanonicalPath());
34 state.discclass.add(cl);
36 } catch (Exception e) {
41 throw new Error("Couldn't find class "+cl);
46 public ClassDescriptor getClass(String classname) {
47 ClassDescriptor cd=(ClassDescriptor)state.getClassSymbolTable().get(classname);
51 public ClassDescriptor getClass(String classname, HashSet todo) {
52 ClassDescriptor cd=(ClassDescriptor)state.getClassSymbolTable().get(classname);
55 addNewClass(classname);
56 cd=(ClassDescriptor)state.getClassSymbolTable().get(classname);
57 System.out.println("Build class:"+cd);
60 if (!supertable.containsKey(cd)) {
61 String superc=cd.getSuper();
63 ClassDescriptor cd_super=getClass(superc, todo);
64 supertable.put(cd,cd_super);
70 private void createTables() {
71 supertable=new Hashtable();
74 public ClassDescriptor getMainClass() {
75 return getClass(state.main);
78 public MethodDescriptor getRun() {
79 ClassDescriptor cd=getClass(TypeUtil.ThreadClass);
80 for(Iterator methodit=cd.getMethodTable().getSet("run").iterator(); methodit.hasNext();) {
81 MethodDescriptor md=(MethodDescriptor) methodit.next();
82 if (md.numParameters()!=0||md.getModifiers().isStatic())
86 throw new Error("Can't find Thread.run");
89 public MethodDescriptor getMain() {
90 ClassDescriptor cd=getMainClass();
91 Set mainset=cd.getMethodTable().getSet("main");
92 for(Iterator mainit=mainset.iterator(); mainit.hasNext();) {
93 MethodDescriptor md=(MethodDescriptor)mainit.next();
94 if (md.numParameters()!=1)
96 Descriptor pd=md.getParameter(0);
97 TypeDescriptor tpd=(pd instanceof TagVarDescriptor) ? ((TagVarDescriptor)pd).getType() : ((VarDescriptor)pd)
99 if (tpd.getArrayCount()!=1)
101 if (!tpd.getSymbol().equals("String"))
104 if (!md.getModifiers().isStatic())
105 throw new Error("Error: Non static main");
108 throw new Error(cd+" has no main");
111 /** Check to see if md1 is more specific than md2... Informally
112 if md2 could always be called given the arguments passed into
115 public boolean isMoreSpecific(MethodDescriptor md1, MethodDescriptor md2) {
116 /* Checks if md1 is more specific than md2 */
117 if (md1.numParameters()!=md2.numParameters())
119 for(int i=0; i<md1.numParameters(); i++) {
120 if (!this.isSuperorType(md2.getParamType(i), md1.getParamType(i)))
123 if (!this.isSuperorType(md2.getReturnType(), md1.getReturnType()))
126 if (!this.isSuperorType(md2.getClassDesc(), md1.getClassDesc()))
132 public MethodDescriptor getMethod(ClassDescriptor cd, String name, TypeDescriptor[] types) {
133 Set methoddescriptorset=cd.getMethodTable().getSet(name);
134 MethodDescriptor bestmd=null;
136 for(Iterator methodit=methoddescriptorset.iterator(); methodit.hasNext();) {
137 MethodDescriptor currmd=(MethodDescriptor)methodit.next();
138 /* Need correct number of parameters */
139 if (types.length!=currmd.numParameters())
141 for(int i=0; i<types.length; i++) {
142 if (!this.isSuperorType(currmd.getParamType(i),types[i]))
145 /* Method okay so far */
149 if (isMoreSpecific(currmd,bestmd)) {
151 } else if (!isMoreSpecific(bestmd, currmd))
152 throw new Error("No method is most specific");
154 /* Is this more specific than bestmd */
158 throw new Error("Could find: "+name + " in "+cd);
163 public void createFullTable() {
164 subclasstable=new Hashtable();
166 Iterator classit=state.getClassSymbolTable().getDescriptorsIterator();
167 while(classit.hasNext()) {
168 ClassDescriptor cd=(ClassDescriptor)classit.next();
169 ClassDescriptor tmp=cd.getSuperDesc();
172 if (!subclasstable.containsKey(tmp))
173 subclasstable.put(tmp,new HashSet());
174 HashSet hs=(HashSet)subclasstable.get(tmp);
176 tmp=tmp.getSuperDesc();
181 public Set getSubClasses(ClassDescriptor cd) {
182 return (Set)subclasstable.get(cd);
185 public ClassDescriptor getSuper(ClassDescriptor cd) {
186 return (ClassDescriptor)supertable.get(cd);
189 public boolean isCastable(TypeDescriptor original, TypeDescriptor casttype) {
190 if (original.isChar()&&
195 if (casttype.isChar()&&
201 original.isDouble()))
207 public boolean isSuperorType(TypeDescriptor possiblesuper, TypeDescriptor cd2) {
208 if (possiblesuper.isOffset() || cd2.isOffset()) return true;
209 //Matching type are always okay
210 if (possiblesuper.equals(cd2))
213 if ((possiblesuper.isTag() && !cd2.isTag())||
214 (!possiblesuper.isTag() && cd2.isTag()))
218 if (cd2.isArray()||possiblesuper.isArray()) {
219 // Object is super class of all arrays
220 if (possiblesuper.getSymbol().equals(ObjectClass)&&!possiblesuper.isArray())
223 // If we have the same dimensionality of arrays & both are classes, we can default to the normal test
224 if (cd2.isClass()&&possiblesuper.isClass()
225 &&(possiblesuper.getArrayCount()==cd2.getArrayCount())&&
226 isSuperorType(possiblesuper.getClassDesc(), cd2.getClassDesc()))
229 // Object is superclass of all array classes
230 if (possiblesuper.getSymbol().equals(ObjectClass)&&cd2.isClass()
231 &&(possiblesuper.getArrayCount()<cd2.getArrayCount()))
237 if (possiblesuper.isClass()&&
239 return isSuperorType(possiblesuper.getClassDesc(), cd2.getClassDesc());
240 else if (possiblesuper.isClass()&&
243 else if (possiblesuper.isNull())
244 throw new Error(); //not sure when this case would occur
245 else if (possiblesuper.isPrimitive()&&
247 ///Primitive widenings from 5.1.2
248 if (cd2.isByte()&&(possiblesuper.isByte()||possiblesuper.isShort()||
249 possiblesuper.isInt()||possiblesuper.isLong()||
250 possiblesuper.isFloat()||possiblesuper.isDouble()))
252 if (cd2.isShort()&&(possiblesuper.isShort()||
253 possiblesuper.isInt()||possiblesuper.isLong()||
254 possiblesuper.isFloat()||possiblesuper.isDouble()))
256 if (cd2.isChar()&&(possiblesuper.isChar()||
257 possiblesuper.isInt()||possiblesuper.isLong()||
258 possiblesuper.isFloat()||possiblesuper.isDouble()))
260 if (cd2.isInt()&&(possiblesuper.isInt()||possiblesuper.isLong()||
261 possiblesuper.isFloat()||possiblesuper.isDouble()))
263 if (cd2.isLong()&&(possiblesuper.isLong()||
264 possiblesuper.isFloat()||possiblesuper.isDouble()))
266 if (cd2.isFloat()&&(possiblesuper.isFloat()||possiblesuper.isDouble()))
268 if (cd2.isDouble()&&possiblesuper.isDouble())
271 if (cd2.isBoolean()&&possiblesuper.isBoolean())
275 } else if (possiblesuper.isPrimitive()&&(!possiblesuper.isArray())&&
278 else if (cd2.isPrimitive()&&(!cd2.isArray())&&
279 possiblesuper.isPtr())
282 throw new Error("Case not handled:"+possiblesuper+" "+cd2);
286 public boolean isSuperorType(ClassDescriptor possiblesuper, ClassDescriptor cd2) {
287 if (possiblesuper==cd2)
290 return isSuper(possiblesuper, cd2);
293 private boolean isSuper(ClassDescriptor possiblesuper, ClassDescriptor cd2) {
296 if (cd2==possiblesuper)