4 import IR.Flat.FlatNode;
9 public class TypeUtil {
10 public static String StringClass;
11 public static String ObjectClass;
12 public static String StartupClass;
13 public static String TagClass;
14 public static String ThreadClass;
15 public static String TaskClass;
18 Hashtable subclasstable;
22 Hashtable<ClassDescriptor, Set<ClassDescriptor>> superIFtbl;
24 public TypeUtil(State state, BuildIR bir) {
28 StringClass="java.lang.String";
29 ObjectClass="java.lang.Object";
30 StartupClass="StartupObject";
31 TagClass="TagDescriptor";
32 ThreadClass="java.lang.Thread";
37 StartupClass="StartupObject";
38 TagClass="TagDescriptor";
45 public void addNewClass(String cl, Set todo) {
46 //search through the default locations for the file.
47 for (int i = 0; i < state.classpath.size(); i++) {
48 String path = (String) state.classpath.get(i);
49 File f = new File(path, cl.replace('.', '/') + ".java");
52 ParseNode pn = Main.readSourceFile(state, f.getCanonicalPath());
53 bir.buildtree(pn, todo, f.getCanonicalPath());
55 } catch (Exception e) {
60 throw new Error("Couldn't find class " + cl);
65 public ClassDescriptor getClass(String classname) {
66 ClassDescriptor cd=(ClassDescriptor)state.getClassSymbolTable().get(classname);
70 public ClassDescriptor getClass(String classname, HashSet todo) {
71 ClassDescriptor cd=(ClassDescriptor)state.getClassSymbolTable().get(classname);
74 addNewClass(classname, todo);
75 cd=(ClassDescriptor)state.getClassSymbolTable().get(classname);
77 System.out.println("Build class:"+cd);
80 if (!supertable.containsKey(cd)) {
81 String superc=cd.getSuper();
83 ClassDescriptor cd_super=getClass(superc, todo);
84 supertable.put(cd,cd_super);
87 if (!superIFtbl.containsKey(cd)) {
88 // add inherited interfaces
89 superIFtbl.put(cd,new HashSet());
90 HashSet hs=(HashSet)superIFtbl.get(cd);
91 Vector<String> superifv = cd.getSuperInterface();
92 for(int i = 0; i < superifv.size(); i++) {
93 String superif = superifv.elementAt(i);
94 ClassDescriptor if_super = getClass(superif, todo);
101 private void createTables() {
102 supertable=new Hashtable();
103 superIFtbl = new Hashtable<ClassDescriptor,Set<ClassDescriptor>>();
106 public ClassDescriptor getMainClass() {
107 return getClass(state.main);
110 public MethodDescriptor getRun() {
111 ClassDescriptor cd=getClass(TypeUtil.ThreadClass);
112 for(Iterator methodit=cd.getMethodTable().getSet("run").iterator(); methodit.hasNext();) {
113 MethodDescriptor md=(MethodDescriptor) methodit.next();
114 if (md.numParameters()!=0||md.getModifiers().isStatic())
118 throw new Error("Can't find Thread.run");
121 public MethodDescriptor getStaticStart() {
122 ClassDescriptor cd=getClass(TypeUtil.ThreadClass);
123 for(Iterator methodit=cd.getMethodTable().getSet("staticStart").iterator(); methodit.hasNext();) {
124 MethodDescriptor md=(MethodDescriptor) methodit.next();
125 if (md.numParameters()!=1||!md.getModifiers().isStatic()||!md.getParamType(0).isClass()||md.getParamType(0).getClassDesc()!=cd)
129 throw new Error("Can't find Thread.run");
132 public MethodDescriptor getExecute() {
133 ClassDescriptor cd = getClass(TypeUtil.TaskClass);
135 if(cd == null && state.DSMTASK)
136 throw new Error("Task.java is not included");
138 for(Iterator methodit = cd.getMethodTable().getSet("execute").iterator(); methodit.hasNext();) {
139 MethodDescriptor md = (MethodDescriptor) methodit.next();
140 if (md.numParameters()!=0 || md.getModifiers().isStatic())
144 throw new Error("Can't find Task.execute");
148 public MethodDescriptor getMain() {
149 ClassDescriptor cd=getMainClass();
150 Set mainset=cd.getMethodTable().getSet("main");
152 for(Iterator mainit=mainset.iterator(); mainit.hasNext();) {
153 MethodDescriptor md=(MethodDescriptor)mainit.next();
154 if (md.numParameters()!=1)
156 Descriptor pd=md.getParameter(0);
157 TypeDescriptor tpd=(pd instanceof TagVarDescriptor) ? ((TagVarDescriptor)pd).getType() : ((VarDescriptor)pd)
159 if (tpd.getArrayCount()!=1)
161 if (!tpd.getSymbol().equals(StringClass))
163 if (!md.getModifiers().isStatic())
164 throw new Error("Error: Non static main");
167 throw new Error(cd+" has no main");
170 /** Check to see if md1 is more specific than md2... Informally
171 if md2 could always be called given the arguments passed into
174 public boolean isMoreSpecific(MethodDescriptor md1, MethodDescriptor md2) {
175 /* Checks if md1 is more specific than md2 */
176 if (md1.numParameters()!=md2.numParameters())
178 for(int i=0; i<md1.numParameters(); i++) {
179 if (!this.isSuperorType(md2.getParamType(i), md1.getParamType(i))) {
180 if(((!md1.getParamType(i).isArray() &&
181 (md1.getParamType(i).isInt() || md1.getParamType(i).isLong() || md1.getParamType(i).isDouble() || md1.getParamType(i).isFloat()))
182 && md2.getParamType(i).isClass() && md2.getParamType(i).getClassDesc().getSymbol().equals("Object"))) {
183 // primitive parameters vs Object
189 if (md1.getReturnType()==null||md2.getReturnType()==null) {
190 if (md1.getReturnType()!=md2.getReturnType())
193 if (!this.isSuperorType(md2.getReturnType(), md1.getReturnType()))
196 if (!this.isSuperorType(md2.getClassDesc(), md1.getClassDesc()))
202 public MethodDescriptor getMethod(ClassDescriptor cd, String name, TypeDescriptor[] types) {
203 Set methoddescriptorset=cd.getMethodTable().getSet(name);
204 MethodDescriptor bestmd=null;
206 for(Iterator methodit=methoddescriptorset.iterator(); methodit.hasNext();) {
207 MethodDescriptor currmd=(MethodDescriptor)methodit.next();
208 /* Need correct number of parameters */
209 if (types.length!=currmd.numParameters())
211 for(int i=0; i<types.length; i++) {
212 if (!this.isSuperorType(currmd.getParamType(i),types[i]))
215 /* Method okay so far */
219 if (isMoreSpecific(currmd,bestmd)) {
221 } else if (!isMoreSpecific(bestmd, currmd))
222 throw new Error("No method is most specific");
224 /* Is this more specific than bestmd */
228 throw new Error("Could find: "+name + " in "+cd);
233 public void createFullTable() {
234 subclasstable=new Hashtable();
235 HashSet tovisit=new HashSet();
236 HashSet visited=new HashSet();
238 Iterator classit=state.getClassSymbolTable().getDescriptorsIterator();
239 while(classit.hasNext()) {
242 ClassDescriptor cd=(ClassDescriptor)classit.next();
243 ClassDescriptor tmp=cd.getSuperDesc();
245 // check cd's interface ancestors
247 Iterator it_sifs = cd.getSuperInterfaces();
248 while(it_sifs.hasNext()) {
249 ClassDescriptor cdt = (ClassDescriptor)it_sifs.next();
250 if(!tovisit.contains(cdt)){
257 if (!subclasstable.containsKey(tmp))
258 subclasstable.put(tmp,new HashSet());
259 HashSet hs=(HashSet)subclasstable.get(tmp);
261 // check tmp's interface ancestors
262 Iterator it_sifs = tmp.getSuperInterfaces();
263 while(it_sifs.hasNext()) {
264 ClassDescriptor cdt = (ClassDescriptor)it_sifs.next();
265 if(!tovisit.contains(cdt)){
270 tmp=tmp.getSuperDesc();
273 while(!tovisit.isEmpty()) {
274 ClassDescriptor sif = (ClassDescriptor)tovisit.iterator().next();
277 if(!visited.contains(sif)) {
278 if(!this.subclasstable.containsKey(sif)) {
279 this.subclasstable.put(sif, new HashSet());
281 HashSet hs = (HashSet)this.subclasstable.get(sif);
284 Iterator it_sifs = sif.getSuperInterfaces();
285 while(it_sifs.hasNext()) {
286 ClassDescriptor siftmp = (ClassDescriptor)it_sifs.next();
287 if(!tovisit.contains(siftmp)){
297 public Set getSubClasses(ClassDescriptor cd) {
298 return (Set)subclasstable.get(cd);
301 public ClassDescriptor getSuper(ClassDescriptor cd) {
302 return (ClassDescriptor)supertable.get(cd);
305 public Set<ClassDescriptor> getSuperIFs(ClassDescriptor cd) {
306 return superIFtbl.get(cd);
309 public boolean isCastable(TypeDescriptor original, TypeDescriptor casttype) {
310 if (original.isChar()&&
315 if (casttype.isChar()&&
321 original.isDouble()))
327 public boolean isSuperorType(TypeDescriptor possiblesuper, TypeDescriptor cd2) {
328 if (possiblesuper.isOffset() || cd2.isOffset()) return true;
329 //Matching type are always okay
330 if (possiblesuper.equals(cd2))
333 if ((possiblesuper.isTag() && !cd2.isTag())||
334 (!possiblesuper.isTag() && cd2.isTag()))
338 if (cd2.isArray()||possiblesuper.isArray()) {
339 // Object is super class of all arrays
340 if (possiblesuper.getSymbol().equals(ObjectClass)&&!possiblesuper.isArray())
343 // If we have the same dimensionality of arrays & both are classes, we can default to the normal test
344 if (cd2.isClass()&&possiblesuper.isClass()
345 &&(possiblesuper.getArrayCount()==cd2.getArrayCount())&&
346 isSuperorType(possiblesuper.getClassDesc(), cd2.getClassDesc()))
349 // Object is superclass of all array classes
350 if (possiblesuper.getSymbol().equals(ObjectClass)&&cd2.isClass()
351 &&(possiblesuper.getArrayCount()<cd2.getArrayCount()))
354 //Allow arraytype=null statements
355 if (possiblesuper.isArray()&&cd2.isNull())
361 if (possiblesuper.isClass()&&
363 return isSuperorType(possiblesuper.getClassDesc(), cd2.getClassDesc());
364 else if (possiblesuper.isClass()&&
367 else if (possiblesuper.isNull())
368 throw new Error(); //not sure when this case would occur
369 else if (possiblesuper.isPrimitive()&&
371 ///Primitive widenings from 5.1.2
372 if (cd2.isByte()&&(possiblesuper.isByte()||possiblesuper.isShort()||
373 possiblesuper.isInt()||possiblesuper.isLong()||
374 possiblesuper.isFloat()||possiblesuper.isDouble()))
376 if (cd2.isShort()&&(possiblesuper.isShort()||
377 possiblesuper.isInt()||possiblesuper.isLong()||
378 possiblesuper.isFloat()||possiblesuper.isDouble()))
380 if (cd2.isChar()&&(possiblesuper.isChar()||
381 possiblesuper.isInt()||possiblesuper.isLong()||
382 possiblesuper.isFloat()||possiblesuper.isDouble()))
384 if (cd2.isInt()&&(possiblesuper.isInt()||possiblesuper.isLong()||
385 possiblesuper.isFloat()||possiblesuper.isDouble()
386 ||possiblesuper.isEnum()))
388 if (cd2.isEnum()&&(possiblesuper.isInt()||possiblesuper.isLong()||
389 possiblesuper.isFloat()||possiblesuper.isDouble()))
391 if(cd2.isEnum()&&possiblesuper.isEnum()&&cd2.class_desc.equals(possiblesuper.class_desc))
393 if (cd2.isLong()&&(possiblesuper.isLong()||
394 possiblesuper.isFloat()||possiblesuper.isDouble()))
396 if (cd2.isFloat()&&(possiblesuper.isFloat()||possiblesuper.isDouble()))
398 if (cd2.isDouble()&&possiblesuper.isDouble())
401 if (cd2.isBoolean()&&possiblesuper.isBoolean())
405 } else if (possiblesuper.isPrimitive()&&(!possiblesuper.isArray())&&
408 else if (cd2.isPrimitive()&&(!cd2.isArray())&&
409 possiblesuper.isPtr())
412 throw new Error("Case not handled:"+possiblesuper+" "+cd2);
415 public TypeDescriptor mostSpecific(TypeDescriptor td1, TypeDescriptor td2) {
416 if( isSuperorType( td1, td2 ) ) {
419 if( isSuperorType( td2, td1 ) ) {
422 throw new Error( td1+" and "+td2+" have no superclass relationship" );
425 public TypeDescriptor mostSpecific(TypeDescriptor td1, TypeDescriptor td2, TypeDescriptor td3) {
426 return mostSpecific( td1, mostSpecific( td2, td3 ) );
429 public boolean isSuperorType(ClassDescriptor possiblesuper, ClassDescriptor cd2) {
430 if (possiblesuper==cd2)
433 return isSuper(possiblesuper, cd2);
436 private boolean isSuper(ClassDescriptor possiblesuper, ClassDescriptor cd2) {
437 HashSet tovisit=new HashSet();
438 HashSet visited=new HashSet();
441 // check cd2's interface ancestors
442 Iterator<ClassDescriptor> it_sifs = getSuperIFs(cd2).iterator();
443 while(it_sifs.hasNext()) {
444 ClassDescriptor cd = it_sifs.next();
445 if(cd == possiblesuper) {
447 } else if(!tovisit.contains(cd)){
455 if (cd2==possiblesuper)
458 // check cd2's interface ancestors
460 Iterator it_sifs = getSuperIFs(cd2).iterator();
461 while(it_sifs.hasNext()) {
462 ClassDescriptor cd = (ClassDescriptor)it_sifs.next();
463 if(cd == possiblesuper) {
465 } else if(!tovisit.contains(cd)){
472 while(!tovisit.isEmpty()) {
473 ClassDescriptor cd = (ClassDescriptor)tovisit.iterator().next();
476 if(!visited.contains(cd)) {
477 Iterator it_sifs = getSuperIFs(cd).iterator();
478 while(it_sifs.hasNext()) {
479 ClassDescriptor cdt = (ClassDescriptor)it_sifs.next();
480 if(cdt == possiblesuper) {
482 } else if(!tovisit.contains(cdt)){