4 import IR.Flat.FlatNode;
9 public class TypeUtil {
10 public static String StringClass;
11 public static String StringClassValueField;
12 public static String ObjectClass;
13 public static String StartupClass;
14 public static String TagClass;
15 public static String ThreadClass;
16 public static String TaskClass;
19 Hashtable subclasstable;
23 Hashtable<ClassDescriptor, Set<ClassDescriptor>> superIFtbl;
25 public TypeUtil(State state, BuildIR bir) {
29 StringClass="java.lang.String";
30 StringClassValueField="value";
31 ObjectClass="java.lang.Object";
32 StartupClass="StartupObject";
33 TagClass="TagDescriptor";
34 ThreadClass="java.lang.Thread";
38 StringClassValueField="value";
40 StartupClass="StartupObject";
41 TagClass="TagDescriptor";
48 public void addNewClass(String cl, Set todo) {
49 //search through the default locations for the file.
51 // do not consider package or import when compiling MGC version
52 cl = (cl.lastIndexOf('.')==-1)?cl:cl.substring(cl.lastIndexOf('.')+1);
54 for (int i = 0; i < state.classpath.size(); i++) {
55 String path = (String) state.classpath.get(i);
56 File f = new File(path, cl.replace('.', '/') + ".java");
59 ParseNode pn = Main.readSourceFile(state, f.getCanonicalPath());
60 bir.buildtree(pn, todo, f.getCanonicalPath());
62 } catch (Exception e) {
71 public ClassDescriptor getClass(String classname) {
72 String cl = classname;
74 // do not consider package or import when compiling MGC version
75 cl = (cl.lastIndexOf('.')==-1)?cl:cl.substring(cl.lastIndexOf('.')+1);
77 ClassDescriptor cd=(ClassDescriptor)state.getClassSymbolTable().get(cl);
81 public ClassDescriptor getClass(ClassDescriptor context, String classnameIn, HashSet todo) {
84 int dotindex=classnameIn.indexOf('.',fileindex);
88 //get entire class name
89 dotindex=classnameIn.length();
92 String classnamestr = classnameIn.substring(0, dotindex);
93 String remainder = classnameIn.substring(dotindex, classnameIn.length());
96 classnamestr = context.getCanonicalImportMapName(classnamestr);
98 ClassDescriptor cd=helperGetClass(classnamestr, remainder, todo);
103 } while(fileindex!=0);
104 throw new Error("Cannot find class: "+classnameIn);
107 private ClassDescriptor helperGetClass(String classname, String remainder, HashSet todo) {
108 String cl = classname;
110 // do not consider package or import when compiling MGC version
111 cl = (cl.lastIndexOf('.')==-1)?cl:cl.substring(cl.lastIndexOf('.')+1);
114 ClassDescriptor cd=(ClassDescriptor)state.getClassSymbolTable().get(cl);
117 addNewClass(cl, todo);
118 String cl2=cl+remainder.replace('.','$');
119 cd=(ClassDescriptor)state.getClassSymbolTable().get(cl2);
122 System.out.println("Build class:"+cd);
125 String cl2=cl+remainder.replace('.','$');
126 cd=(ClassDescriptor)state.getClassSymbolTable().get(cl2);
130 if (!supertable.containsKey(cd)) {
131 String superc=cd.getSuper();
133 ClassDescriptor cd_super=getClass(cd, superc, todo);
134 supertable.put(cd,cd_super);
137 if (!superIFtbl.containsKey(cd)) {
138 // add inherited interfaces
139 superIFtbl.put(cd,new HashSet());
140 HashSet hs=(HashSet)superIFtbl.get(cd);
141 Vector<String> superifv = cd.getSuperInterface();
142 for(int i = 0; i < superifv.size(); i++) {
143 String superif = superifv.elementAt(i);
144 ClassDescriptor if_super = getClass(cd, superif, todo);
151 private void createTables() {
152 supertable=new Hashtable();
153 superIFtbl = new Hashtable<ClassDescriptor,Set<ClassDescriptor>>();
156 public ClassDescriptor getMainClass() {
157 return getClass(state.main);
160 public MethodDescriptor getRun() {
161 ClassDescriptor cd=getClass(TypeUtil.ThreadClass);
162 for(Iterator methodit=cd.getMethodTable().getSet("run").iterator(); methodit.hasNext(); ) {
163 MethodDescriptor md=(MethodDescriptor) methodit.next();
164 if (md.numParameters()!=0||md.getModifiers().isStatic())
168 throw new Error("Can't find Thread.run");
171 public MethodDescriptor getStaticStart() {
172 ClassDescriptor cd=getClass(TypeUtil.ThreadClass);
173 for(Iterator methodit=cd.getMethodTable().getSet("staticStart").iterator(); methodit.hasNext(); ) {
174 MethodDescriptor md=(MethodDescriptor) methodit.next();
175 if (md.numParameters()!=1||!md.getModifiers().isStatic()||!md.getParamType(0).isClass()||md.getParamType(0).getClassDesc()!=cd)
179 throw new Error("Can't find Thread.run");
182 public MethodDescriptor getExecute() {
183 ClassDescriptor cd = getClass(TypeUtil.TaskClass);
185 if(cd == null && state.DSMTASK)
186 throw new Error("Task.java is not included");
188 for(Iterator methodit = cd.getMethodTable().getSet("execute").iterator(); methodit.hasNext(); ) {
189 MethodDescriptor md = (MethodDescriptor) methodit.next();
190 if (md.numParameters()!=0 || md.getModifiers().isStatic())
194 throw new Error("Can't find Task.execute");
198 public MethodDescriptor getMain() {
199 ClassDescriptor cd=getMainClass();
200 Set mainset=cd.getMethodTable().getSet("main");
202 for(Iterator mainit=mainset.iterator(); mainit.hasNext(); ) {
203 MethodDescriptor md=(MethodDescriptor)mainit.next();
204 if (md.numParameters()!=1)
206 Descriptor pd=md.getParameter(0);
207 TypeDescriptor tpd=(pd instanceof TagVarDescriptor)?((TagVarDescriptor)pd).getType():((VarDescriptor)pd)
209 if (tpd.getArrayCount()!=1)
211 if (!tpd.getSymbol().equals(StringClass))
213 if (!md.getModifiers().isStatic())
214 throw new Error("Error: Non static main");
217 throw new Error(cd+" has no main");
220 /** Check to see if md1 is more specific than md2... Informally
221 if md2 could always be called given the arguments passed into
224 public boolean isMoreSpecific(MethodDescriptor md1, MethodDescriptor md2, boolean checkReturnType) {
225 /* Checks if md1 is more specific than md2 */
226 if (md1.numParameters()!=md2.numParameters())
228 for(int i=0; i<md1.numParameters(); i++) {
229 if (!this.isSuperorType(md2.getParamType(i), md1.getParamType(i))) {
230 if(((!md1.getParamType(i).isArray() &&
231 (md1.getParamType(i).isInt() || md1.getParamType(i).isLong() || md1.getParamType(i).isDouble() || md1.getParamType(i).isFloat()))
232 && md2.getParamType(i).isClass() && md2.getParamType(i).getClassDesc().getSymbol().equals("Object"))) {
233 // primitive parameters vs Object
239 if(checkReturnType) {
240 if (md1.getReturnType()==null||md2.getReturnType()==null) {
241 if (md1.getReturnType()!=md2.getReturnType())
244 if (!this.isSuperorType(md2.getReturnType(), md1.getReturnType()))
248 if (!this.isSuperorType(md2.getClassDesc(), md1.getClassDesc()))
254 public MethodDescriptor getMethod(ClassDescriptor cd, String name, TypeDescriptor[] types) {
255 Set methoddescriptorset=cd.getMethodTable().getSet(name);
256 MethodDescriptor bestmd=null;
258 for(Iterator methodit=methoddescriptorset.iterator(); methodit.hasNext(); ) {
259 MethodDescriptor currmd=(MethodDescriptor)methodit.next();
260 /* Need correct number of parameters */
261 if (types.length!=currmd.numParameters())
263 for(int i=0; i<types.length; i++) {
264 if (!this.isSuperorType(currmd.getParamType(i),types[i]))
267 /* Method okay so far */
271 if (isMoreSpecific(currmd,bestmd, true)) {
273 } else if (!isMoreSpecific(bestmd, currmd, true))
274 throw new Error("No method is most specific");
276 /* Is this more specific than bestmd */
280 throw new Error("Could find: "+name + " in "+cd);
285 public void createFullTable() {
286 subclasstable=new Hashtable();
287 HashSet tovisit=new HashSet();
288 HashSet visited=new HashSet();
290 Iterator classit=state.getClassSymbolTable().getDescriptorsIterator();
291 while(classit.hasNext()) {
294 ClassDescriptor cd=(ClassDescriptor)classit.next();
295 ClassDescriptor tmp=cd.getSuperDesc();
297 // check cd's interface ancestors
299 Iterator it_sifs = cd.getSuperInterfaces();
300 while(it_sifs.hasNext()) {
301 ClassDescriptor cdt = (ClassDescriptor)it_sifs.next();
302 if(!tovisit.contains(cdt)) {
309 if (!subclasstable.containsKey(tmp))
310 subclasstable.put(tmp,new HashSet());
311 HashSet hs=(HashSet)subclasstable.get(tmp);
313 // check tmp's interface ancestors
314 Iterator it_sifs = tmp.getSuperInterfaces();
315 while(it_sifs.hasNext()) {
316 ClassDescriptor cdt = (ClassDescriptor)it_sifs.next();
317 if(!tovisit.contains(cdt)) {
322 tmp=tmp.getSuperDesc();
325 while(!tovisit.isEmpty()) {
326 ClassDescriptor sif = (ClassDescriptor)tovisit.iterator().next();
329 if(!visited.contains(sif)) {
330 if(!this.subclasstable.containsKey(sif)) {
331 this.subclasstable.put(sif, new HashSet());
333 HashSet hs = (HashSet) this.subclasstable.get(sif);
336 Iterator it_sifs = sif.getSuperInterfaces();
337 while(it_sifs.hasNext()) {
338 ClassDescriptor siftmp = (ClassDescriptor)it_sifs.next();
339 if(!tovisit.contains(siftmp)) {
349 public Set getSubClasses(ClassDescriptor cd) {
350 return (Set)subclasstable.get(cd);
353 public ClassDescriptor getSuper(ClassDescriptor cd) {
354 return (ClassDescriptor)supertable.get(cd);
357 public Set<ClassDescriptor> getSuperIFs(ClassDescriptor cd) {
358 return superIFtbl.get(cd);
361 public boolean isCastable(TypeDescriptor original, TypeDescriptor casttype) {
362 if (original.isChar()&&
367 if (casttype.isChar()&&
373 original.isDouble()))
379 public boolean isSuperorType(TypeDescriptor possiblesuper, TypeDescriptor cd2) {
380 if (possiblesuper.isOffset() || cd2.isOffset()) return true;
381 //Matching type are always okay
382 if (possiblesuper.equals(cd2))
385 if ((possiblesuper.isTag() && !cd2.isTag())||
386 (!possiblesuper.isTag() && cd2.isTag()))
390 if (cd2.isArray()||possiblesuper.isArray()) {
391 // Object is super class of all arrays
392 if (possiblesuper.getSymbol().equals(ObjectClass)&&!possiblesuper.isArray())
395 // If we have the same dimensionality of arrays & both are classes, we can default to the normal test
396 if (cd2.isClass()&&possiblesuper.isClass()
397 &&(possiblesuper.getArrayCount()==cd2.getArrayCount())&&
398 isSuperorType(possiblesuper.getClassDesc(), cd2.getClassDesc()))
401 // Object is superclass of all array classes
402 if (possiblesuper.getSymbol().equals(ObjectClass)&&cd2.isClass()
403 &&(possiblesuper.getArrayCount()<cd2.getArrayCount()))
406 //Allow arraytype=null statements
407 if (possiblesuper.isArray()&&cd2.isNull())
413 // Object is superclass of interfaces
414 if(possiblesuper.getSymbol().equals(ObjectClass)&&cd2.isClass()&&cd2.getClassDesc().isInterface())
417 if (possiblesuper.isClass()&&
419 return isSuperorType(possiblesuper.getClassDesc(), cd2.getClassDesc());
420 else if (possiblesuper.isClass()&&
423 else if (possiblesuper.isNull())
424 throw new Error(); //not sure when this case would occur
425 else if (possiblesuper.isPrimitive()&&
427 ///Primitive widenings from 5.1.2
428 if (cd2.isByte()&&(possiblesuper.isByte()||possiblesuper.isShort()||
429 possiblesuper.isInt()||possiblesuper.isLong()||
430 possiblesuper.isFloat()||possiblesuper.isDouble()))
432 if (cd2.isShort()&&(possiblesuper.isShort()||
433 possiblesuper.isInt()||possiblesuper.isLong()||
434 possiblesuper.isFloat()||possiblesuper.isDouble()))
436 if (cd2.isChar()&&(possiblesuper.isChar()||
437 possiblesuper.isInt()||possiblesuper.isLong()||
438 possiblesuper.isFloat()||possiblesuper.isDouble()))
440 if (cd2.isInt()&&(possiblesuper.isInt()||possiblesuper.isLong()||
441 possiblesuper.isFloat()||possiblesuper.isDouble()
442 ||possiblesuper.isEnum()))
444 if (cd2.isEnum()&&(possiblesuper.isInt()||possiblesuper.isLong()||
445 possiblesuper.isFloat()||possiblesuper.isDouble()))
447 if(cd2.isEnum()&&possiblesuper.isEnum()&&cd2.class_desc.equals(possiblesuper.class_desc))
449 if (cd2.isLong()&&(possiblesuper.isLong()||
450 possiblesuper.isFloat()||possiblesuper.isDouble()))
452 if (cd2.isFloat()&&(possiblesuper.isFloat()||possiblesuper.isDouble()))
454 if (cd2.isDouble()&&possiblesuper.isDouble())
457 if (cd2.isBoolean()&&possiblesuper.isBoolean())
461 } else if (possiblesuper.isPrimitive()&&(!possiblesuper.isArray())&&
464 else if (cd2.isPrimitive()&&(!cd2.isArray())&&
465 possiblesuper.isPtr())
468 throw new Error("Case not handled:"+possiblesuper+" "+cd2);
471 public TypeDescriptor mostSpecific(TypeDescriptor td1, TypeDescriptor td2) {
472 if( isSuperorType(td1, td2) ) {
475 if( isSuperorType(td2, td1) ) {
478 throw new Error(td1+" and "+td2+" have no superclass relationship");
481 public TypeDescriptor mostSpecific(TypeDescriptor td1, TypeDescriptor td2, TypeDescriptor td3) {
482 return mostSpecific(td1, mostSpecific(td2, td3) );
485 public boolean isSuperorType(ClassDescriptor possiblesuper, ClassDescriptor cd2) {
486 if (possiblesuper==cd2)
489 return isSuper(possiblesuper, cd2);
492 private boolean isSuper(ClassDescriptor possiblesuper, ClassDescriptor cd2) {
493 HashSet tovisit=new HashSet();
494 HashSet visited=new HashSet();
497 // check cd2's interface ancestors
498 Iterator<ClassDescriptor> it_sifs = getSuperIFs(cd2).iterator();
499 while(it_sifs.hasNext()) {
500 ClassDescriptor cd = it_sifs.next();
501 if(cd == possiblesuper) {
503 } else if(!tovisit.contains(cd)) {
511 if (cd2==possiblesuper)
514 // check cd2's interface ancestors
516 Iterator it_sifs = getSuperIFs(cd2).iterator();
517 while(it_sifs.hasNext()) {
518 ClassDescriptor cd = (ClassDescriptor)it_sifs.next();
519 if(cd == possiblesuper) {
521 } else if(!tovisit.contains(cd)) {
528 while(!tovisit.isEmpty()) {
529 ClassDescriptor cd = (ClassDescriptor)tovisit.iterator().next();
532 if(!visited.contains(cd)) {
533 Iterator it_sifs = getSuperIFs(cd).iterator();
534 while(it_sifs.hasNext()) {
535 ClassDescriptor cdt = (ClassDescriptor)it_sifs.next();
536 if(cdt == possiblesuper) {
538 } else if(!tovisit.contains(cdt)) {