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) {
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 (md1.getReturnType()==null||md2.getReturnType()==null) {
240 if (md1.getReturnType()!=md2.getReturnType())
243 if (!this.isSuperorType(md2.getReturnType(), md1.getReturnType()))
246 if (!this.isSuperorType(md2.getClassDesc(), md1.getClassDesc()))
252 public MethodDescriptor getMethod(ClassDescriptor cd, String name, TypeDescriptor[] types) {
253 Set methoddescriptorset=cd.getMethodTable().getSet(name);
254 MethodDescriptor bestmd=null;
256 for(Iterator methodit=methoddescriptorset.iterator(); methodit.hasNext(); ) {
257 MethodDescriptor currmd=(MethodDescriptor)methodit.next();
258 /* Need correct number of parameters */
259 if (types.length!=currmd.numParameters())
261 for(int i=0; i<types.length; i++) {
262 if (!this.isSuperorType(currmd.getParamType(i),types[i]))
265 /* Method okay so far */
269 if (isMoreSpecific(currmd,bestmd)) {
271 } else if (!isMoreSpecific(bestmd, currmd))
272 throw new Error("No method is most specific");
274 /* Is this more specific than bestmd */
278 throw new Error("Could find: "+name + " in "+cd);
283 public void createFullTable() {
284 subclasstable=new Hashtable();
285 HashSet tovisit=new HashSet();
286 HashSet visited=new HashSet();
288 Iterator classit=state.getClassSymbolTable().getDescriptorsIterator();
289 while(classit.hasNext()) {
292 ClassDescriptor cd=(ClassDescriptor)classit.next();
293 ClassDescriptor tmp=cd.getSuperDesc();
295 // check cd's interface ancestors
297 Iterator it_sifs = cd.getSuperInterfaces();
298 while(it_sifs.hasNext()) {
299 ClassDescriptor cdt = (ClassDescriptor)it_sifs.next();
300 if(!tovisit.contains(cdt)) {
307 if (!subclasstable.containsKey(tmp))
308 subclasstable.put(tmp,new HashSet());
309 HashSet hs=(HashSet)subclasstable.get(tmp);
311 // check tmp's interface ancestors
312 Iterator it_sifs = tmp.getSuperInterfaces();
313 while(it_sifs.hasNext()) {
314 ClassDescriptor cdt = (ClassDescriptor)it_sifs.next();
315 if(!tovisit.contains(cdt)) {
320 tmp=tmp.getSuperDesc();
323 while(!tovisit.isEmpty()) {
324 ClassDescriptor sif = (ClassDescriptor)tovisit.iterator().next();
327 if(!visited.contains(sif)) {
328 if(!this.subclasstable.containsKey(sif)) {
329 this.subclasstable.put(sif, new HashSet());
331 HashSet hs = (HashSet) this.subclasstable.get(sif);
334 Iterator it_sifs = sif.getSuperInterfaces();
335 while(it_sifs.hasNext()) {
336 ClassDescriptor siftmp = (ClassDescriptor)it_sifs.next();
337 if(!tovisit.contains(siftmp)) {
347 public Set getSubClasses(ClassDescriptor cd) {
348 return (Set)subclasstable.get(cd);
351 public ClassDescriptor getSuper(ClassDescriptor cd) {
352 return (ClassDescriptor)supertable.get(cd);
355 public Set<ClassDescriptor> getSuperIFs(ClassDescriptor cd) {
356 return superIFtbl.get(cd);
359 public boolean isCastable(TypeDescriptor original, TypeDescriptor casttype) {
360 if (original.isChar()&&
365 if (casttype.isChar()&&
371 original.isDouble()))
377 public boolean isSuperorType(TypeDescriptor possiblesuper, TypeDescriptor cd2) {
378 if (possiblesuper.isOffset() || cd2.isOffset()) return true;
379 //Matching type are always okay
380 if (possiblesuper.equals(cd2))
383 if ((possiblesuper.isTag() && !cd2.isTag())||
384 (!possiblesuper.isTag() && cd2.isTag()))
388 if (cd2.isArray()||possiblesuper.isArray()) {
389 // Object is super class of all arrays
390 if (possiblesuper.getSymbol().equals(ObjectClass)&&!possiblesuper.isArray())
393 // If we have the same dimensionality of arrays & both are classes, we can default to the normal test
394 if (cd2.isClass()&&possiblesuper.isClass()
395 &&(possiblesuper.getArrayCount()==cd2.getArrayCount())&&
396 isSuperorType(possiblesuper.getClassDesc(), cd2.getClassDesc()))
399 // Object is superclass of all array classes
400 if (possiblesuper.getSymbol().equals(ObjectClass)&&cd2.isClass()
401 &&(possiblesuper.getArrayCount()<cd2.getArrayCount()))
404 //Allow arraytype=null statements
405 if (possiblesuper.isArray()&&cd2.isNull())
411 // Object is superclass of interfaces
412 if(possiblesuper.getSymbol().equals(ObjectClass)&&cd2.isClass()&&cd2.getClassDesc().isInterface())
415 if (possiblesuper.isClass()&&
417 return isSuperorType(possiblesuper.getClassDesc(), cd2.getClassDesc());
418 else if (possiblesuper.isClass()&&
421 else if (possiblesuper.isNull())
422 throw new Error(); //not sure when this case would occur
423 else if (possiblesuper.isPrimitive()&&
425 ///Primitive widenings from 5.1.2
426 if (cd2.isByte()&&(possiblesuper.isByte()||possiblesuper.isShort()||
427 possiblesuper.isInt()||possiblesuper.isLong()||
428 possiblesuper.isFloat()||possiblesuper.isDouble()))
430 if (cd2.isShort()&&(possiblesuper.isShort()||
431 possiblesuper.isInt()||possiblesuper.isLong()||
432 possiblesuper.isFloat()||possiblesuper.isDouble()))
434 if (cd2.isChar()&&(possiblesuper.isChar()||
435 possiblesuper.isInt()||possiblesuper.isLong()||
436 possiblesuper.isFloat()||possiblesuper.isDouble()))
438 if (cd2.isInt()&&(possiblesuper.isInt()||possiblesuper.isLong()||
439 possiblesuper.isFloat()||possiblesuper.isDouble()
440 ||possiblesuper.isEnum()))
442 if (cd2.isEnum()&&(possiblesuper.isInt()||possiblesuper.isLong()||
443 possiblesuper.isFloat()||possiblesuper.isDouble()))
445 if(cd2.isEnum()&&possiblesuper.isEnum()&&cd2.class_desc.equals(possiblesuper.class_desc))
447 if (cd2.isLong()&&(possiblesuper.isLong()||
448 possiblesuper.isFloat()||possiblesuper.isDouble()))
450 if (cd2.isFloat()&&(possiblesuper.isFloat()||possiblesuper.isDouble()))
452 if (cd2.isDouble()&&possiblesuper.isDouble())
455 if (cd2.isBoolean()&&possiblesuper.isBoolean())
459 } else if (possiblesuper.isPrimitive()&&(!possiblesuper.isArray())&&
462 else if (cd2.isPrimitive()&&(!cd2.isArray())&&
463 possiblesuper.isPtr())
466 throw new Error("Case not handled:"+possiblesuper+" "+cd2);
469 public TypeDescriptor mostSpecific(TypeDescriptor td1, TypeDescriptor td2) {
470 if( isSuperorType(td1, td2) ) {
473 if( isSuperorType(td2, td1) ) {
476 throw new Error(td1+" and "+td2+" have no superclass relationship");
479 public TypeDescriptor mostSpecific(TypeDescriptor td1, TypeDescriptor td2, TypeDescriptor td3) {
480 return mostSpecific(td1, mostSpecific(td2, td3) );
483 public boolean isSuperorType(ClassDescriptor possiblesuper, ClassDescriptor cd2) {
484 if (possiblesuper==cd2)
487 return isSuper(possiblesuper, cd2);
490 private boolean isSuper(ClassDescriptor possiblesuper, ClassDescriptor cd2) {
491 HashSet tovisit=new HashSet();
492 HashSet visited=new HashSet();
495 // check cd2's interface ancestors
496 Iterator<ClassDescriptor> it_sifs = getSuperIFs(cd2).iterator();
497 while(it_sifs.hasNext()) {
498 ClassDescriptor cd = it_sifs.next();
499 if(cd == possiblesuper) {
501 } else if(!tovisit.contains(cd)) {
509 if (cd2==possiblesuper)
512 // check cd2's interface ancestors
514 Iterator it_sifs = getSuperIFs(cd2).iterator();
515 while(it_sifs.hasNext()) {
516 ClassDescriptor cd = (ClassDescriptor)it_sifs.next();
517 if(cd == possiblesuper) {
519 } else if(!tovisit.contains(cd)) {
526 while(!tovisit.isEmpty()) {
527 ClassDescriptor cd = (ClassDescriptor)tovisit.iterator().next();
530 if(!visited.contains(cd)) {
531 Iterator it_sifs = getSuperIFs(cd).iterator();
532 while(it_sifs.hasNext()) {
533 ClassDescriptor cdt = (ClassDescriptor)it_sifs.next();
534 if(cdt == possiblesuper) {
536 } else if(!tovisit.contains(cdt)) {