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) {
67 throw new Error("Couldn't find class " + cl);
72 public ClassDescriptor getClass(String classname) {
73 String cl = classname;
75 // do not consider package or import when compiling MGC version
76 cl = (cl.lastIndexOf('.')==-1)?cl:cl.substring(cl.lastIndexOf('.')+1);
78 ClassDescriptor cd=(ClassDescriptor)state.getClassSymbolTable().get(cl);
82 public ClassDescriptor getClass(String classname, HashSet todo) {
83 String cl = classname;
85 // do not consider package or import when compiling MGC version
86 cl = (cl.lastIndexOf('.')==-1)?cl:cl.substring(cl.lastIndexOf('.')+1);
88 ClassDescriptor cd=(ClassDescriptor)state.getClassSymbolTable().get(cl);
91 addNewClass(cl, todo);
92 cd=(ClassDescriptor)state.getClassSymbolTable().get(cl);
94 System.out.println("Build class:"+cd);
97 if (!supertable.containsKey(cd)) {
98 String superc=cd.getSuper();
100 ClassDescriptor cd_super=getClass(superc, todo);
101 supertable.put(cd,cd_super);
104 if (!superIFtbl.containsKey(cd)) {
105 // add inherited interfaces
106 superIFtbl.put(cd,new HashSet());
107 HashSet hs=(HashSet)superIFtbl.get(cd);
108 Vector<String> superifv = cd.getSuperInterface();
109 for(int i = 0; i < superifv.size(); i++) {
110 String superif = superifv.elementAt(i);
111 ClassDescriptor if_super = getClass(superif, todo);
118 private void createTables() {
119 supertable=new Hashtable();
120 superIFtbl = new Hashtable<ClassDescriptor,Set<ClassDescriptor>>();
123 public ClassDescriptor getMainClass() {
124 return getClass(state.main);
127 public MethodDescriptor getRun() {
128 ClassDescriptor cd=getClass(TypeUtil.ThreadClass);
129 for(Iterator methodit=cd.getMethodTable().getSet("run").iterator(); methodit.hasNext(); ) {
130 MethodDescriptor md=(MethodDescriptor) methodit.next();
131 if (md.numParameters()!=0||md.getModifiers().isStatic())
135 throw new Error("Can't find Thread.run");
138 public MethodDescriptor getStaticStart() {
139 ClassDescriptor cd=getClass(TypeUtil.ThreadClass);
140 for(Iterator methodit=cd.getMethodTable().getSet("staticStart").iterator(); methodit.hasNext(); ) {
141 MethodDescriptor md=(MethodDescriptor) methodit.next();
142 if (md.numParameters()!=1||!md.getModifiers().isStatic()||!md.getParamType(0).isClass()||md.getParamType(0).getClassDesc()!=cd)
146 throw new Error("Can't find Thread.run");
149 public MethodDescriptor getExecute() {
150 ClassDescriptor cd = getClass(TypeUtil.TaskClass);
152 if(cd == null && state.DSMTASK)
153 throw new Error("Task.java is not included");
155 for(Iterator methodit = cd.getMethodTable().getSet("execute").iterator(); methodit.hasNext(); ) {
156 MethodDescriptor md = (MethodDescriptor) methodit.next();
157 if (md.numParameters()!=0 || md.getModifiers().isStatic())
161 throw new Error("Can't find Task.execute");
165 public MethodDescriptor getMain() {
166 ClassDescriptor cd=getMainClass();
167 Set mainset=cd.getMethodTable().getSet("main");
169 for(Iterator mainit=mainset.iterator(); mainit.hasNext(); ) {
170 MethodDescriptor md=(MethodDescriptor)mainit.next();
171 if (md.numParameters()!=1)
173 Descriptor pd=md.getParameter(0);
174 TypeDescriptor tpd=(pd instanceof TagVarDescriptor)?((TagVarDescriptor)pd).getType():((VarDescriptor)pd)
176 if (tpd.getArrayCount()!=1)
178 if (!tpd.getSymbol().equals(StringClass))
180 if (!md.getModifiers().isStatic())
181 throw new Error("Error: Non static main");
184 throw new Error(cd+" has no main");
187 /** Check to see if md1 is more specific than md2... Informally
188 if md2 could always be called given the arguments passed into
191 public boolean isMoreSpecific(MethodDescriptor md1, MethodDescriptor md2) {
192 /* Checks if md1 is more specific than md2 */
193 if (md1.numParameters()!=md2.numParameters())
195 for(int i=0; i<md1.numParameters(); i++) {
196 if (!this.isSuperorType(md2.getParamType(i), md1.getParamType(i))) {
197 if(((!md1.getParamType(i).isArray() &&
198 (md1.getParamType(i).isInt() || md1.getParamType(i).isLong() || md1.getParamType(i).isDouble() || md1.getParamType(i).isFloat()))
199 && md2.getParamType(i).isClass() && md2.getParamType(i).getClassDesc().getSymbol().equals("Object"))) {
200 // primitive parameters vs Object
206 if (md1.getReturnType()==null||md2.getReturnType()==null) {
207 if (md1.getReturnType()!=md2.getReturnType())
210 if (!this.isSuperorType(md2.getReturnType(), md1.getReturnType()))
213 if (!this.isSuperorType(md2.getClassDesc(), md1.getClassDesc()))
219 public MethodDescriptor getMethod(ClassDescriptor cd, String name, TypeDescriptor[] types) {
220 Set methoddescriptorset=cd.getMethodTable().getSet(name);
221 MethodDescriptor bestmd=null;
223 for(Iterator methodit=methoddescriptorset.iterator(); methodit.hasNext(); ) {
224 MethodDescriptor currmd=(MethodDescriptor)methodit.next();
225 /* Need correct number of parameters */
226 if (types.length!=currmd.numParameters())
228 for(int i=0; i<types.length; i++) {
229 if (!this.isSuperorType(currmd.getParamType(i),types[i]))
232 /* Method okay so far */
236 if (isMoreSpecific(currmd,bestmd)) {
238 } else if (!isMoreSpecific(bestmd, currmd))
239 throw new Error("No method is most specific");
241 /* Is this more specific than bestmd */
245 throw new Error("Could find: "+name + " in "+cd);
250 public void createFullTable() {
251 subclasstable=new Hashtable();
252 HashSet tovisit=new HashSet();
253 HashSet visited=new HashSet();
255 Iterator classit=state.getClassSymbolTable().getDescriptorsIterator();
256 while(classit.hasNext()) {
259 ClassDescriptor cd=(ClassDescriptor)classit.next();
260 ClassDescriptor tmp=cd.getSuperDesc();
262 // check cd's interface ancestors
264 Iterator it_sifs = cd.getSuperInterfaces();
265 while(it_sifs.hasNext()) {
266 ClassDescriptor cdt = (ClassDescriptor)it_sifs.next();
267 if(!tovisit.contains(cdt)) {
274 if (!subclasstable.containsKey(tmp))
275 subclasstable.put(tmp,new HashSet());
276 HashSet hs=(HashSet)subclasstable.get(tmp);
278 // check tmp's interface ancestors
279 Iterator it_sifs = tmp.getSuperInterfaces();
280 while(it_sifs.hasNext()) {
281 ClassDescriptor cdt = (ClassDescriptor)it_sifs.next();
282 if(!tovisit.contains(cdt)) {
287 tmp=tmp.getSuperDesc();
290 while(!tovisit.isEmpty()) {
291 ClassDescriptor sif = (ClassDescriptor)tovisit.iterator().next();
294 if(!visited.contains(sif)) {
295 if(!this.subclasstable.containsKey(sif)) {
296 this.subclasstable.put(sif, new HashSet());
298 HashSet hs = (HashSet) this.subclasstable.get(sif);
301 Iterator it_sifs = sif.getSuperInterfaces();
302 while(it_sifs.hasNext()) {
303 ClassDescriptor siftmp = (ClassDescriptor)it_sifs.next();
304 if(!tovisit.contains(siftmp)) {
314 public Set getSubClasses(ClassDescriptor cd) {
315 return (Set)subclasstable.get(cd);
318 public ClassDescriptor getSuper(ClassDescriptor cd) {
319 return (ClassDescriptor)supertable.get(cd);
322 public Set<ClassDescriptor> getSuperIFs(ClassDescriptor cd) {
323 return superIFtbl.get(cd);
326 public boolean isCastable(TypeDescriptor original, TypeDescriptor casttype) {
327 if (original.isChar()&&
332 if (casttype.isChar()&&
338 original.isDouble()))
344 public boolean isSuperorType(TypeDescriptor possiblesuper, TypeDescriptor cd2) {
345 if (possiblesuper.isOffset() || cd2.isOffset()) return true;
346 //Matching type are always okay
347 if (possiblesuper.equals(cd2))
350 if ((possiblesuper.isTag() && !cd2.isTag())||
351 (!possiblesuper.isTag() && cd2.isTag()))
355 if (cd2.isArray()||possiblesuper.isArray()) {
356 // Object is super class of all arrays
357 if (possiblesuper.getSymbol().equals(ObjectClass)&&!possiblesuper.isArray())
360 // If we have the same dimensionality of arrays & both are classes, we can default to the normal test
361 if (cd2.isClass()&&possiblesuper.isClass()
362 &&(possiblesuper.getArrayCount()==cd2.getArrayCount())&&
363 isSuperorType(possiblesuper.getClassDesc(), cd2.getClassDesc()))
366 // Object is superclass of all array classes
367 if (possiblesuper.getSymbol().equals(ObjectClass)&&cd2.isClass()
368 &&(possiblesuper.getArrayCount()<cd2.getArrayCount()))
371 //Allow arraytype=null statements
372 if (possiblesuper.isArray()&&cd2.isNull())
378 if (possiblesuper.isClass()&&
380 return isSuperorType(possiblesuper.getClassDesc(), cd2.getClassDesc());
381 else if (possiblesuper.isClass()&&
384 else if (possiblesuper.isNull())
385 throw new Error(); //not sure when this case would occur
386 else if (possiblesuper.isPrimitive()&&
388 ///Primitive widenings from 5.1.2
389 if (cd2.isByte()&&(possiblesuper.isByte()||possiblesuper.isShort()||
390 possiblesuper.isInt()||possiblesuper.isLong()||
391 possiblesuper.isFloat()||possiblesuper.isDouble()))
393 if (cd2.isShort()&&(possiblesuper.isShort()||
394 possiblesuper.isInt()||possiblesuper.isLong()||
395 possiblesuper.isFloat()||possiblesuper.isDouble()))
397 if (cd2.isChar()&&(possiblesuper.isChar()||
398 possiblesuper.isInt()||possiblesuper.isLong()||
399 possiblesuper.isFloat()||possiblesuper.isDouble()))
401 if (cd2.isInt()&&(possiblesuper.isInt()||possiblesuper.isLong()||
402 possiblesuper.isFloat()||possiblesuper.isDouble()
403 ||possiblesuper.isEnum()))
405 if (cd2.isEnum()&&(possiblesuper.isInt()||possiblesuper.isLong()||
406 possiblesuper.isFloat()||possiblesuper.isDouble()))
408 if(cd2.isEnum()&&possiblesuper.isEnum()&&cd2.class_desc.equals(possiblesuper.class_desc))
410 if (cd2.isLong()&&(possiblesuper.isLong()||
411 possiblesuper.isFloat()||possiblesuper.isDouble()))
413 if (cd2.isFloat()&&(possiblesuper.isFloat()||possiblesuper.isDouble()))
415 if (cd2.isDouble()&&possiblesuper.isDouble())
418 if (cd2.isBoolean()&&possiblesuper.isBoolean())
422 } else if (possiblesuper.isPrimitive()&&(!possiblesuper.isArray())&&
425 else if (cd2.isPrimitive()&&(!cd2.isArray())&&
426 possiblesuper.isPtr())
429 throw new Error("Case not handled:"+possiblesuper+" "+cd2);
432 public TypeDescriptor mostSpecific(TypeDescriptor td1, TypeDescriptor td2) {
433 if( isSuperorType(td1, td2) ) {
436 if( isSuperorType(td2, td1) ) {
439 throw new Error(td1+" and "+td2+" have no superclass relationship");
442 public TypeDescriptor mostSpecific(TypeDescriptor td1, TypeDescriptor td2, TypeDescriptor td3) {
443 return mostSpecific(td1, mostSpecific(td2, td3) );
446 public boolean isSuperorType(ClassDescriptor possiblesuper, ClassDescriptor cd2) {
447 if (possiblesuper==cd2)
450 return isSuper(possiblesuper, cd2);
453 private boolean isSuper(ClassDescriptor possiblesuper, ClassDescriptor cd2) {
454 HashSet tovisit=new HashSet();
455 HashSet visited=new HashSet();
458 // check cd2's interface ancestors
459 Iterator<ClassDescriptor> it_sifs = getSuperIFs(cd2).iterator();
460 while(it_sifs.hasNext()) {
461 ClassDescriptor cd = it_sifs.next();
462 if(cd == possiblesuper) {
464 } else if(!tovisit.contains(cd)) {
472 if (cd2==possiblesuper)
475 // check cd2's interface ancestors
477 Iterator it_sifs = getSuperIFs(cd2).iterator();
478 while(it_sifs.hasNext()) {
479 ClassDescriptor cd = (ClassDescriptor)it_sifs.next();
480 if(cd == possiblesuper) {
482 } else if(!tovisit.contains(cd)) {
489 while(!tovisit.isEmpty()) {
490 ClassDescriptor cd = (ClassDescriptor)tovisit.iterator().next();
493 if(!visited.contains(cd)) {
494 Iterator it_sifs = getSuperIFs(cd).iterator();
495 while(it_sifs.hasNext()) {
496 ClassDescriptor cdt = (ClassDescriptor)it_sifs.next();
497 if(cdt == possiblesuper) {
499 } else if(!tovisit.contains(cdt)) {