start of new file
[IRC.git] / Robust / src / IR / TypeUtil.java
index 600ec9b937b2becdafc093674d1e51ec5df1e5fe..92e4e5861b45b6483e7a1dedf14b70ef882ff5df 100644 (file)
@@ -3,8 +3,13 @@ import java.util.*;
 
 public class TypeUtil {
     public static final String StringClass="String";
+    public static final String ObjectClass="Object";
+    public static final String StartupClass="StartupObject";
+    public static final String TagClass="TagDescriptor";
+    public static final String ThreadClass="Thread";
     State state;
     Hashtable supertable;
+    Hashtable subclasstable;
 
     public TypeUtil(State state) {
        this.state=state;
@@ -18,22 +23,183 @@ public class TypeUtil {
 
     private void createTables() {
        supertable=new Hashtable();
+
        Iterator classit=state.getClassSymbolTable().getDescriptorsIterator();
        while(classit.hasNext()) {
            ClassDescriptor cd=(ClassDescriptor)classit.next();
            String superc=cd.getSuper();
            if (superc!=null) {
                ClassDescriptor cd_super=getClass(superc);
+               if (cd_super==null) {
+                   throw new Error("Couldn't find class:"+superc);
+               }
                supertable.put(cd,cd_super);
            }
        }
     }
 
+    public ClassDescriptor getMainClass() {
+       return getClass(state.main);
+    }
+
+    public MethodDescriptor getRun() {
+       ClassDescriptor cd=getClass(TypeUtil.ThreadClass);
+       for(Iterator methodit=cd.getMethodTable().getSet("run").iterator();methodit.hasNext();) {
+           MethodDescriptor md=(MethodDescriptor) methodit.next();
+           if (md.numParameters()!=0||md.getModifiers().isStatic())
+               continue;
+           return md;
+       }
+       throw new Error("Can't find Thread.run");
+    }
+
+    public MethodDescriptor getMain() {
+       ClassDescriptor cd=getMainClass();
+       Set mainset=cd.getMethodTable().getSet("main");
+       for(Iterator mainit=mainset.iterator();mainit.hasNext();) {
+           MethodDescriptor md=(MethodDescriptor)mainit.next();
+           if (md.numParameters()!=1)
+               continue;
+           Descriptor pd=md.getParameter(0);
+           TypeDescriptor tpd=(pd instanceof TagVarDescriptor)?((TagVarDescriptor)pd).getType():((VarDescriptor)pd)
+               .getType();
+           if (tpd.getArrayCount()!=1)
+               continue;
+           if (!tpd.getSymbol().equals("String"))
+               continue;
+           
+           if (!md.getModifiers().isStatic())
+               throw new Error("Error: Non static main");
+           return md;
+       }
+       throw new Error(cd+" has no main");
+    }
+
+    /** Check to see if md1 is more specific than md2...  Informally
+       if md2 could always be called given the arguments passed into
+       md1 */
+
+    public boolean isMoreSpecific(MethodDescriptor md1, MethodDescriptor md2) {
+       /* Checks if md1 is more specific than md2 */
+       if (md1.numParameters()!=md2.numParameters())
+           throw new Error();
+       for(int i=0;i<md1.numParameters();i++) {
+           if (!this.isSuperorType(md2.getParamType(i), md1.getParamType(i)))
+               return false;
+       }
+       if (!this.isSuperorType(md2.getReturnType(), md1.getReturnType()))
+               return false;
+
+       if (!this.isSuperorType(md2.getClassDesc(), md1.getClassDesc()))
+               return false;
+
+       return true;
+    }
+
+    public MethodDescriptor getMethod(ClassDescriptor cd, String name, TypeDescriptor[] types) {
+       Set methoddescriptorset=cd.getMethodTable().getSet(name);
+        MethodDescriptor bestmd=null;
+        NextMethod:
+        for(Iterator methodit=methoddescriptorset.iterator();methodit.hasNext();) {
+            MethodDescriptor currmd=(MethodDescriptor)methodit.next();
+            /* Need correct number of parameters */
+            if (types.length!=currmd.numParameters())
+                continue;
+            for(int i=0;i<types.length;i++) {
+                if (!this.isSuperorType(currmd.getParamType(i),types[i]))
+                    continue NextMethod;
+            }
+            /* Method okay so far */
+            if (bestmd==null)
+                bestmd=currmd;
+            else {
+                if (isMoreSpecific(currmd,bestmd)) {
+                    bestmd=currmd;
+                } else if (!isMoreSpecific(bestmd, currmd))
+                    throw new Error("No method is most specific");
+                
+                /* Is this more specific than bestmd */
+            }
+        }
+       if (bestmd==null)
+           throw new Error("Could find: "+name + " in "+cd);
+
+       return bestmd;
+    }
+
+    public void createFullTable() {
+       subclasstable=new Hashtable();
+    
+       Iterator classit=state.getClassSymbolTable().getDescriptorsIterator();
+       while(classit.hasNext()) {
+           ClassDescriptor cd=(ClassDescriptor)classit.next();
+           ClassDescriptor tmp=cd.getSuperDesc();
+           
+           while(tmp!=null) {
+               if (!subclasstable.containsKey(tmp))
+                   subclasstable.put(tmp,new HashSet());
+               HashSet hs=(HashSet)subclasstable.get(tmp);
+               hs.add(cd);
+               tmp=tmp.getSuperDesc();
+           }
+       }
+    }
+
+    public Set getSubClasses(ClassDescriptor cd) {
+       return (Set)subclasstable.get(cd);
+    }
+
     public ClassDescriptor getSuper(ClassDescriptor cd) {
        return (ClassDescriptor)supertable.get(cd);
     }
 
+    public boolean isCastable(TypeDescriptor original, TypeDescriptor casttype) {
+       if (original.isChar()&&
+           (casttype.isByte()||
+            casttype.isShort()))
+           return true;
+
+       if (casttype.isChar()&&
+           (original.isByte()||
+            original.isShort()||
+            original.isInt()||
+            original.isLong()||
+            original.isFloat()||
+            original.isDouble()))
+           return true;
+           
+       return false;
+    }
+
     public boolean isSuperorType(TypeDescriptor possiblesuper, TypeDescriptor cd2) {
+       //Matching type are always okay
+       if (possiblesuper.equals(cd2))
+           return true;
+
+       if ((possiblesuper.isTag() && !cd2.isTag())||
+           (!possiblesuper.isTag() && cd2.isTag()))
+           return false;
+
+       //Handle arrays
+       if (cd2.isArray()||possiblesuper.isArray()) {
+           // Object is super class of all arrays
+           if (possiblesuper.getSymbol().equals(ObjectClass)&&!possiblesuper.isArray())
+               return true;
+
+           // If we have the same dimensionality of arrays & both are classes, we can default to the normal test
+           if (cd2.isClass()&&possiblesuper.isClass()
+               &&(possiblesuper.getArrayCount()==cd2.getArrayCount())&&
+               isSuperorType(possiblesuper.getClassDesc(), cd2.getClassDesc()))
+               return true;
+
+           // Object is superclass of all array classes
+           if (possiblesuper.getSymbol().equals(ObjectClass)&&cd2.isClass()
+               &&(possiblesuper.getArrayCount()<cd2.getArrayCount()))
+               return true;
+
+           return false;
+       }
+
        if (possiblesuper.isClass()&&
             cd2.isClass())
            return isSuperorType(possiblesuper.getClassDesc(), cd2.getClassDesc());
@@ -72,10 +238,17 @@ public class TypeUtil {
                return true;
            
            return false;
-       } else throw new Error();
+       } else if (possiblesuper.isPrimitive()&&(!possiblesuper.isArray())&&
+                  cd2.isPtr())
+           return false;
+       else if (cd2.isPrimitive()&&(!cd2.isArray())&&
+                possiblesuper.isPtr())
+           return false;
+       else
+           throw new Error("Case not handled:"+possiblesuper+" "+cd2);
     }
 
-
+    
     public boolean isSuperorType(ClassDescriptor possiblesuper, ClassDescriptor cd2) {
        if (possiblesuper==cd2)
            return true;
@@ -83,7 +256,7 @@ public class TypeUtil {
            return isSuper(possiblesuper, cd2);
     }
 
-    public boolean isSuper(ClassDescriptor possiblesuper, ClassDescriptor cd2) {
+    private boolean isSuper(ClassDescriptor possiblesuper, ClassDescriptor cd2) {
        while(cd2!=null) {
            cd2=getSuper(cd2);
            if (cd2==possiblesuper)