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";
13 public static final String TaskClass="Task";
16 Hashtable subclasstable;
19 public TypeUtil(State state, BuildIR bir) {
25 public void addNewClass(String cl, Set todo) {
26 for(int i=0;i<state.classpath.size();i++) {
27 String path=(String)state.classpath.get(i);
28 File f=new File(path, cl+".java");
31 ParseNode pn=Main.readSourceFile(state, f.getCanonicalPath());
32 bir.buildtree(pn, todo);
34 } catch (Exception e) {
39 throw new Error("Couldn't find class "+cl);
44 public ClassDescriptor getClass(String classname) {
45 ClassDescriptor cd=(ClassDescriptor)state.getClassSymbolTable().get(classname);
49 public ClassDescriptor getClass(String classname, HashSet todo) {
50 ClassDescriptor cd=(ClassDescriptor)state.getClassSymbolTable().get(classname);
53 addNewClass(classname, todo);
54 cd=(ClassDescriptor)state.getClassSymbolTable().get(classname);
56 System.out.println("Build class:"+cd);
59 if (!supertable.containsKey(cd)) {
60 String superc=cd.getSuper();
62 ClassDescriptor cd_super=getClass(superc, todo);
63 supertable.put(cd,cd_super);
69 private void createTables() {
70 supertable=new Hashtable();
73 public ClassDescriptor getMainClass() {
74 return getClass(state.main);
77 public MethodDescriptor getRun() {
78 ClassDescriptor cd=getClass(TypeUtil.ThreadClass);
79 for(Iterator methodit=cd.getMethodTable().getSet("run").iterator(); methodit.hasNext();) {
80 MethodDescriptor md=(MethodDescriptor) methodit.next();
81 if (md.numParameters()!=0||md.getModifiers().isStatic())
85 throw new Error("Can't find Thread.run");
88 public MethodDescriptor getExecute() {
89 ClassDescriptor cd = getClass(TypeUtil.TaskClass);
91 if(cd == null && state.DSMTASK)
92 throw new Error("Task.java is not included");
94 for(Iterator methodit = cd.getMethodTable().getSet("execute").iterator(); methodit.hasNext();) {
95 MethodDescriptor md = (MethodDescriptor) methodit.next();
96 if (md.numParameters()!=0 || md.getModifiers().isStatic())
100 throw new Error("Can't find Task.execute");
104 public MethodDescriptor getMain() {
105 ClassDescriptor cd=getMainClass();
106 Set mainset=cd.getMethodTable().getSet("main");
107 for(Iterator mainit=mainset.iterator(); mainit.hasNext();) {
108 MethodDescriptor md=(MethodDescriptor)mainit.next();
109 if (md.numParameters()!=1)
111 Descriptor pd=md.getParameter(0);
112 TypeDescriptor tpd=(pd instanceof TagVarDescriptor) ? ((TagVarDescriptor)pd).getType() : ((VarDescriptor)pd)
114 if (tpd.getArrayCount()!=1)
116 if (!tpd.getSymbol().equals("String"))
119 if (!md.getModifiers().isStatic())
120 throw new Error("Error: Non static main");
123 throw new Error(cd+" has no main");
126 /** Check to see if md1 is more specific than md2... Informally
127 if md2 could always be called given the arguments passed into
130 public boolean isMoreSpecific(MethodDescriptor md1, MethodDescriptor md2) {
131 /* Checks if md1 is more specific than md2 */
132 if (md1.numParameters()!=md2.numParameters())
134 for(int i=0; i<md1.numParameters(); i++) {
135 if (!this.isSuperorType(md2.getParamType(i), md1.getParamType(i)))
138 if (md1.getReturnType()==null||md2.getReturnType()==null) {
139 if (md1.getReturnType()!=md2.getReturnType())
142 if (!this.isSuperorType(md2.getReturnType(), md1.getReturnType()))
145 if (!this.isSuperorType(md2.getClassDesc(), md1.getClassDesc()))
151 public MethodDescriptor getMethod(ClassDescriptor cd, String name, TypeDescriptor[] types) {
152 Set methoddescriptorset=cd.getMethodTable().getSet(name);
153 MethodDescriptor bestmd=null;
155 for(Iterator methodit=methoddescriptorset.iterator(); methodit.hasNext();) {
156 MethodDescriptor currmd=(MethodDescriptor)methodit.next();
157 /* Need correct number of parameters */
158 if (types.length!=currmd.numParameters())
160 for(int i=0; i<types.length; i++) {
161 if (!this.isSuperorType(currmd.getParamType(i),types[i]))
164 /* Method okay so far */
168 if (isMoreSpecific(currmd,bestmd)) {
170 } else if (!isMoreSpecific(bestmd, currmd))
171 throw new Error("No method is most specific");
173 /* Is this more specific than bestmd */
177 throw new Error("Could find: "+name + " in "+cd);
182 public void createFullTable() {
183 subclasstable=new Hashtable();
185 Iterator classit=state.getClassSymbolTable().getDescriptorsIterator();
186 while(classit.hasNext()) {
187 ClassDescriptor cd=(ClassDescriptor)classit.next();
188 ClassDescriptor tmp=cd.getSuperDesc();
191 if (!subclasstable.containsKey(tmp))
192 subclasstable.put(tmp,new HashSet());
193 HashSet hs=(HashSet)subclasstable.get(tmp);
195 tmp=tmp.getSuperDesc();
200 public Set getSubClasses(ClassDescriptor cd) {
201 return (Set)subclasstable.get(cd);
204 public ClassDescriptor getSuper(ClassDescriptor cd) {
205 return (ClassDescriptor)supertable.get(cd);
208 public boolean isCastable(TypeDescriptor original, TypeDescriptor casttype) {
209 if (original.isChar()&&
214 if (casttype.isChar()&&
220 original.isDouble()))
226 public boolean isSuperorType(TypeDescriptor possiblesuper, TypeDescriptor cd2) {
227 if (possiblesuper.isOffset() || cd2.isOffset()) return true;
228 //Matching type are always okay
229 if (possiblesuper.equals(cd2))
232 if ((possiblesuper.isTag() && !cd2.isTag())||
233 (!possiblesuper.isTag() && cd2.isTag()))
237 if (cd2.isArray()||possiblesuper.isArray()) {
238 // Object is super class of all arrays
239 if (possiblesuper.getSymbol().equals(ObjectClass)&&!possiblesuper.isArray())
242 // If we have the same dimensionality of arrays & both are classes, we can default to the normal test
243 if (cd2.isClass()&&possiblesuper.isClass()
244 &&(possiblesuper.getArrayCount()==cd2.getArrayCount())&&
245 isSuperorType(possiblesuper.getClassDesc(), cd2.getClassDesc()))
248 // Object is superclass of all array classes
249 if (possiblesuper.getSymbol().equals(ObjectClass)&&cd2.isClass()
250 &&(possiblesuper.getArrayCount()<cd2.getArrayCount()))
253 //Allow arraytype=null statements
254 if (possiblesuper.isArray()&&cd2.isNull())
260 if (possiblesuper.isClass()&&
262 return isSuperorType(possiblesuper.getClassDesc(), cd2.getClassDesc());
263 else if (possiblesuper.isClass()&&
266 else if (possiblesuper.isNull())
267 throw new Error(); //not sure when this case would occur
268 else if (possiblesuper.isPrimitive()&&
270 ///Primitive widenings from 5.1.2
271 if (cd2.isByte()&&(possiblesuper.isByte()||possiblesuper.isShort()||
272 possiblesuper.isInt()||possiblesuper.isLong()||
273 possiblesuper.isFloat()||possiblesuper.isDouble()))
275 if (cd2.isShort()&&(possiblesuper.isShort()||
276 possiblesuper.isInt()||possiblesuper.isLong()||
277 possiblesuper.isFloat()||possiblesuper.isDouble()))
279 if (cd2.isChar()&&(possiblesuper.isChar()||
280 possiblesuper.isInt()||possiblesuper.isLong()||
281 possiblesuper.isFloat()||possiblesuper.isDouble()))
283 if (cd2.isInt()&&(possiblesuper.isInt()||possiblesuper.isLong()||
284 possiblesuper.isFloat()||possiblesuper.isDouble()))
286 if (cd2.isLong()&&(possiblesuper.isLong()||
287 possiblesuper.isFloat()||possiblesuper.isDouble()))
289 if (cd2.isFloat()&&(possiblesuper.isFloat()||possiblesuper.isDouble()))
291 if (cd2.isDouble()&&possiblesuper.isDouble())
294 if (cd2.isBoolean()&&possiblesuper.isBoolean())
298 } else if (possiblesuper.isPrimitive()&&(!possiblesuper.isArray())&&
301 else if (cd2.isPrimitive()&&(!cd2.isArray())&&
302 possiblesuper.isPtr())
305 throw new Error("Case not handled:"+possiblesuper+" "+cd2);
308 public TypeDescriptor mostSpecific(TypeDescriptor td1, TypeDescriptor td2) {
309 if( isSuperorType( td1, td2 ) ) {
312 if( isSuperorType( td2, td1 ) ) {
315 throw new Error( td1+" and "+td2+" have no superclass relationship" );
318 public TypeDescriptor mostSpecific(TypeDescriptor td1, TypeDescriptor td2, TypeDescriptor td3) {
319 return mostSpecific( td1, mostSpecific( td2, td3 ) );
322 public boolean isSuperorType(ClassDescriptor possiblesuper, ClassDescriptor cd2) {
323 if (possiblesuper==cd2)
326 return isSuper(possiblesuper, cd2);
329 private boolean isSuper(ClassDescriptor possiblesuper, ClassDescriptor cd2) {
333 if (cd2==possiblesuper)