4 import IR.Flat.FlatNode;
9 public class TypeUtil {
10 public static final String StringClass="String";
11 public static final String ObjectClass="Object";
12 public static final String StartupClass="StartupObject";
13 public static final String TagClass="TagDescriptor";
14 public static final String ThreadClass="Thread";
15 public static final String TaskClass="Task";
18 Hashtable subclasstable;
24 public TypeUtil(State state, BuildIR bir) {
30 public void addNewClass(String cl, Set todo) {
31 for(int i=0;i<state.classpath.size();i++) {
32 String path=(String)state.classpath.get(i);
33 File f=new File(path, cl+".java");
36 ParseNode pn=Main.readSourceFile(state, f.getCanonicalPath());
37 bir.buildtree(pn, todo);
39 } catch (Exception e) {
44 throw new Error("Couldn't find class "+cl);
49 public ClassDescriptor getClass(String classname) {
50 ClassDescriptor cd=(ClassDescriptor)state.getClassSymbolTable().get(classname);
54 public ClassDescriptor getClass(String classname, HashSet todo) {
55 ClassDescriptor cd=(ClassDescriptor)state.getClassSymbolTable().get(classname);
58 addNewClass(classname, todo);
59 cd=(ClassDescriptor)state.getClassSymbolTable().get(classname);
61 System.out.println("Build class:"+cd);
64 if (!supertable.containsKey(cd)) {
65 String superc=cd.getSuper();
67 ClassDescriptor cd_super=getClass(superc, todo);
68 supertable.put(cd,cd_super);
71 if (!this.superIFtbl.containsKey(cd)) {
72 // add inherited interfaces
73 superIFtbl.put(cd,new HashSet());
74 HashSet hs=(HashSet)superIFtbl.get(cd);
75 Vector<String> superifv = cd.getSuperInterface();
76 for(int i = 0; i < superifv.size(); i++) {
77 String superif = superifv.elementAt(i);
78 ClassDescriptor if_super = getClass(superif, todo);
85 private void createTables() {
86 supertable=new Hashtable();
87 superIFtbl = new Hashtable();
90 public ClassDescriptor getMainClass() {
91 return getClass(state.main);
94 public MethodDescriptor getRun() {
95 ClassDescriptor cd=getClass(TypeUtil.ThreadClass);
96 for(Iterator methodit=cd.getMethodTable().getSet("run").iterator(); methodit.hasNext();) {
97 MethodDescriptor md=(MethodDescriptor) methodit.next();
98 if (md.numParameters()!=0||md.getModifiers().isStatic())
102 throw new Error("Can't find Thread.run");
105 public MethodDescriptor getExecute() {
106 ClassDescriptor cd = getClass(TypeUtil.TaskClass);
108 if(cd == null && state.DSMTASK)
109 throw new Error("Task.java is not included");
111 for(Iterator methodit = cd.getMethodTable().getSet("execute").iterator(); methodit.hasNext();) {
112 MethodDescriptor md = (MethodDescriptor) methodit.next();
113 if (md.numParameters()!=0 || md.getModifiers().isStatic())
117 throw new Error("Can't find Task.execute");
121 public MethodDescriptor getMain() {
122 ClassDescriptor cd=getMainClass();
123 Set mainset=cd.getMethodTable().getSet("main");
124 for(Iterator mainit=mainset.iterator(); mainit.hasNext();) {
125 MethodDescriptor md=(MethodDescriptor)mainit.next();
126 if (md.numParameters()!=1)
128 Descriptor pd=md.getParameter(0);
129 TypeDescriptor tpd=(pd instanceof TagVarDescriptor) ? ((TagVarDescriptor)pd).getType() : ((VarDescriptor)pd)
131 if (tpd.getArrayCount()!=1)
133 if (!tpd.getSymbol().equals("String"))
136 if (!md.getModifiers().isStatic())
137 throw new Error("Error: Non static main");
140 throw new Error(cd+" has no main");
143 /** Check to see if md1 is more specific than md2... Informally
144 if md2 could always be called given the arguments passed into
147 public boolean isMoreSpecific(MethodDescriptor md1, MethodDescriptor md2) {
148 /* Checks if md1 is more specific than md2 */
149 if (md1.numParameters()!=md2.numParameters())
151 for(int i=0; i<md1.numParameters(); i++) {
152 if (!this.isSuperorType(md2.getParamType(i), md1.getParamType(i)))
155 if (md1.getReturnType()==null||md2.getReturnType()==null) {
156 if (md1.getReturnType()!=md2.getReturnType())
159 if (!this.isSuperorType(md2.getReturnType(), md1.getReturnType()))
162 if (!this.isSuperorType(md2.getClassDesc(), md1.getClassDesc()))
168 public MethodDescriptor getMethod(ClassDescriptor cd, String name, TypeDescriptor[] types) {
169 Set methoddescriptorset=cd.getMethodTable().getSet(name);
170 MethodDescriptor bestmd=null;
172 for(Iterator methodit=methoddescriptorset.iterator(); methodit.hasNext();) {
173 MethodDescriptor currmd=(MethodDescriptor)methodit.next();
174 /* Need correct number of parameters */
175 if (types.length!=currmd.numParameters())
177 for(int i=0; i<types.length; i++) {
178 if (!this.isSuperorType(currmd.getParamType(i),types[i]))
181 /* Method okay so far */
185 if (isMoreSpecific(currmd,bestmd)) {
187 } else if (!isMoreSpecific(bestmd, currmd))
188 throw new Error("No method is most specific");
190 /* Is this more specific than bestmd */
194 throw new Error("Could find: "+name + " in "+cd);
199 public void createFullTable() {
200 subclasstable=new Hashtable();
201 //subIFclasstable = new Hashtable();
202 HashSet tovisit=new HashSet();
203 HashSet visited=new HashSet();
205 Iterator classit=state.getClassSymbolTable().getDescriptorsIterator();
206 while(classit.hasNext()) {
207 ClassDescriptor cd=(ClassDescriptor)classit.next();
208 ClassDescriptor tmp=cd.getSuperDesc();
211 // TODO add version for normal Java later
212 // check tmp's interface ancestors
213 Iterator it_sifs = cd.getSuperInterfaces();
214 while(it_sifs.hasNext()) {
215 ClassDescriptor cdt = (ClassDescriptor)it_sifs.next();
216 if(!tovisit.contains(cdt)){
223 if (!subclasstable.containsKey(tmp))
224 subclasstable.put(tmp,new HashSet());
225 HashSet hs=(HashSet)subclasstable.get(tmp);
228 // TODO add version for normal Java later
229 // check tmp's interface ancestors
230 Iterator it_sifs = tmp.getSuperInterfaces();
231 while(it_sifs.hasNext()) {
232 ClassDescriptor cdt = (ClassDescriptor)it_sifs.next();
233 if(!tovisit.contains(cdt)){
238 tmp=tmp.getSuperDesc();
242 // TODO add version for normal Java later
243 while(!tovisit.isEmpty()) {
244 ClassDescriptor sif = (ClassDescriptor)tovisit.iterator().next();
247 if(!visited.contains(sif)) {
248 if(!this.subclasstable.containsKey(sif)) {
249 this.subclasstable.put(sif, new HashSet());
251 HashSet hs = (HashSet)this.subclasstable/*subIFclasstable*/.get(sif);
254 Iterator it_sifs = sif.getSuperInterfaces();
255 while(it_sifs.hasNext()) {
256 ClassDescriptor siftmp = (ClassDescriptor)it_sifs.next();
257 if(!tovisit.contains(siftmp)){
268 public Set getSubClasses(ClassDescriptor cd) {
269 return (Set)subclasstable.get(cd);
272 public ClassDescriptor getSuper(ClassDescriptor cd) {
273 return (ClassDescriptor)supertable.get(cd);
276 public Set getSuperIFs(ClassDescriptor cd) {
277 return (Set)this.superIFtbl.get(cd);
280 public boolean isCastable(TypeDescriptor original, TypeDescriptor casttype) {
281 if (original.isChar()&&
286 if (casttype.isChar()&&
292 original.isDouble()))
298 public boolean isSuperorType(TypeDescriptor possiblesuper, TypeDescriptor cd2) {
300 if(possiblesuper.isClass() && possiblesuper.class_desc.isEnum() && cd2.isInt()) {
304 if (possiblesuper.isOffset() || cd2.isOffset()) return true;
305 //Matching type are always okay
306 if (possiblesuper.equals(cd2))
309 if ((possiblesuper.isTag() && !cd2.isTag())||
310 (!possiblesuper.isTag() && cd2.isTag()))
314 if (cd2.isArray()||possiblesuper.isArray()) {
315 // Object is super class of all arrays
316 if (possiblesuper.getSymbol().equals(ObjectClass)&&!possiblesuper.isArray())
319 // If we have the same dimensionality of arrays & both are classes, we can default to the normal test
320 if (cd2.isClass()&&possiblesuper.isClass()
321 &&(possiblesuper.getArrayCount()==cd2.getArrayCount())&&
322 isSuperorType(possiblesuper.getClassDesc(), cd2.getClassDesc()))
325 // Object is superclass of all array classes
326 if (possiblesuper.getSymbol().equals(ObjectClass)&&cd2.isClass()
327 &&(possiblesuper.getArrayCount()<cd2.getArrayCount()))
330 //Allow arraytype=null statements
331 if (possiblesuper.isArray()&&cd2.isNull())
337 if (possiblesuper.isClass()&&
339 return isSuperorType(possiblesuper.getClassDesc(), cd2.getClassDesc());
340 else if (possiblesuper.isClass()&&
343 else if (possiblesuper.isNull())
344 throw new Error(); //not sure when this case would occur
345 else if (possiblesuper.isPrimitive()&&
347 ///Primitive widenings from 5.1.2
348 if (cd2.isByte()&&(possiblesuper.isByte()||possiblesuper.isShort()||
349 possiblesuper.isInt()||possiblesuper.isLong()||
350 possiblesuper.isFloat()||possiblesuper.isDouble()))
352 if (cd2.isShort()&&(possiblesuper.isShort()||
353 possiblesuper.isInt()||possiblesuper.isLong()||
354 possiblesuper.isFloat()||possiblesuper.isDouble()))
356 if (cd2.isChar()&&(possiblesuper.isChar()||
357 possiblesuper.isInt()||possiblesuper.isLong()||
358 possiblesuper.isFloat()||possiblesuper.isDouble()))
360 if (cd2.isInt()&&(possiblesuper.isInt()||possiblesuper.isLong()||
361 possiblesuper.isFloat()||possiblesuper.isDouble()))
363 if (cd2.isLong()&&(possiblesuper.isLong()||
364 possiblesuper.isFloat()||possiblesuper.isDouble()))
366 if (cd2.isFloat()&&(possiblesuper.isFloat()||possiblesuper.isDouble()))
368 if (cd2.isDouble()&&possiblesuper.isDouble())
371 if (cd2.isBoolean()&&possiblesuper.isBoolean())
375 } else if (possiblesuper.isPrimitive()&&(!possiblesuper.isArray())&&
378 else if (cd2.isPrimitive()&&(!cd2.isArray())&&
379 possiblesuper.isPtr())
382 throw new Error("Case not handled:"+possiblesuper+" "+cd2);
385 public TypeDescriptor mostSpecific(TypeDescriptor td1, TypeDescriptor td2) {
386 if( isSuperorType( td1, td2 ) ) {
389 if( isSuperorType( td2, td1 ) ) {
392 throw new Error( td1+" and "+td2+" have no superclass relationship" );
395 public TypeDescriptor mostSpecific(TypeDescriptor td1, TypeDescriptor td2, TypeDescriptor td3) {
396 return mostSpecific( td1, mostSpecific( td2, td3 ) );
399 public boolean isSuperorType(ClassDescriptor possiblesuper, ClassDescriptor cd2) {
400 if (possiblesuper==cd2)
403 return isSuper(possiblesuper, cd2);
406 private boolean isSuper(ClassDescriptor possiblesuper, ClassDescriptor cd2) {
407 HashSet tovisit=new HashSet();
408 HashSet visited=new HashSet();
411 // TODO add version for normal Java later
412 // check cd2's interface ancestors
413 Iterator it_sifs = getSuperIFs(cd2).iterator();
414 while(it_sifs.hasNext()) {
415 ClassDescriptor cd = (ClassDescriptor)it_sifs.next();
416 if(cd == possiblesuper) {
418 } else if(!tovisit.contains(cd)){
426 if (cd2==possiblesuper)
430 // TODO add version for normal Java later
431 // check cd2's interface ancestors
433 Iterator it_sifs = getSuperIFs(cd2).iterator();
434 while(it_sifs.hasNext()) {
435 ClassDescriptor cd = (ClassDescriptor)it_sifs.next();
436 if(cd == possiblesuper) {
438 } else if(!tovisit.contains(cd)){
447 // TODO add version for normal Java later
448 while(!tovisit.isEmpty()) {
449 ClassDescriptor cd = (ClassDescriptor)tovisit.iterator().next();
452 if(!visited.contains(cd)) {
453 Iterator it_sifs = getSuperIFs(cd).iterator();
454 while(it_sifs.hasNext()) {
455 ClassDescriptor cdt = (ClassDescriptor)it_sifs.next();
456 if(cdt == possiblesuper) {
458 } else if(!tovisit.contains(cdt)){