more bug fixes
[IRC.git] / Robust / src / IR / TypeUtil.java
index 4bdc79e648b3dd369aeb8cb2c1aa86c9eaef69a0..c52679db1a76ef66acfd18b2134be71ff1d5dae9 100644 (file)
@@ -1,5 +1,7 @@
 package IR;
 import java.util.*;
+
+import IR.Flat.FlatNode;
 import IR.Tree.*;
 import java.io.File;
 import Main.Main;
@@ -10,10 +12,14 @@ public class TypeUtil {
   public static final String StartupClass="StartupObject";
   public static final String TagClass="TagDescriptor";
   public static final String ThreadClass="Thread";
+  public static final String TaskClass="Task";
   State state;
   Hashtable supertable;
   Hashtable subclasstable;
   BuildIR bir;
+  
+  // for interfaces
+  Hashtable<ClassDescriptor, Set<ClassDescriptor>> superIFtbl;
 
   public TypeUtil(State state, BuildIR bir) {
     this.state=state;
@@ -28,7 +34,7 @@ public class TypeUtil {
       if (f.exists()) {
        try {
          ParseNode pn=Main.readSourceFile(state, f.getCanonicalPath());
-         bir.buildtree(pn, todo);
+         bir.buildtree(pn, todo,f.getCanonicalPath());
          return;
        } catch (Exception e) {
          throw new Error(e);
@@ -51,6 +57,8 @@ public class TypeUtil {
       //have to find class
       addNewClass(classname, todo);
       cd=(ClassDescriptor)state.getClassSymbolTable().get(classname);
+      cd.setClassLibrary();
+      
       System.out.println("Build class:"+cd);
       todo.add(cd);
     }
@@ -61,11 +69,23 @@ public class TypeUtil {
        supertable.put(cd,cd_super);
       }
     }
+    if (!superIFtbl.containsKey(cd)) {
+      // add inherited interfaces
+      superIFtbl.put(cd,new HashSet());
+      HashSet hs=(HashSet)superIFtbl.get(cd);
+      Vector<String> superifv = cd.getSuperInterface();
+      for(int i = 0; i < superifv.size(); i++) {
+        String superif = superifv.elementAt(i);
+        ClassDescriptor if_super = getClass(superif, todo);
+        hs.add(if_super);
+      }
+    }
     return cd;
   }
 
   private void createTables() {
     supertable=new Hashtable();
+    superIFtbl = new Hashtable<ClassDescriptor,Set<ClassDescriptor>>();
   }
 
   public ClassDescriptor getMainClass() {
@@ -83,6 +103,33 @@ public class TypeUtil {
     throw new Error("Can't find Thread.run");
   }
 
+  public MethodDescriptor getStaticStart() {
+    ClassDescriptor cd=getClass(TypeUtil.ThreadClass);
+    for(Iterator methodit=cd.getMethodTable().getSet("staticStart").iterator(); methodit.hasNext();) {
+      MethodDescriptor md=(MethodDescriptor) methodit.next();
+      if (md.numParameters()!=1||!md.getModifiers().isStatic()||!md.getParamType(0).isClass()||md.getParamType(0).getClassDesc()!=cd)
+       continue;
+      return md;
+    }
+    throw new Error("Can't find Thread.run");
+  }
+  
+  public MethodDescriptor getExecute() {
+    ClassDescriptor cd = getClass(TypeUtil.TaskClass);
+
+    if(cd == null && state.DSMTASK)
+      throw new Error("Task.java is not included");
+
+    for(Iterator methodit = cd.getMethodTable().getSet("execute").iterator(); methodit.hasNext();) {
+      MethodDescriptor md = (MethodDescriptor) methodit.next();
+      if (md.numParameters()!=0 || md.getModifiers().isStatic())
+        continue;
+      return md;
+    }
+    throw new Error("Can't find Task.execute");
+  }
+
+
   public MethodDescriptor getMain() {
     ClassDescriptor cd=getMainClass();
     Set mainset=cd.getMethodTable().getSet("main");
@@ -114,8 +161,15 @@ public class TypeUtil {
     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.getParamType(i), md1.getParamType(i))) {
+        if(((!md1.getParamType(i).isArray() && 
+            (md1.getParamType(i).isInt() || md1.getParamType(i).isLong() || md1.getParamType(i).isDouble() || md1.getParamType(i).isFloat()))
+            && md2.getParamType(i).isClass() && md2.getParamType(i).getClassDesc().getSymbol().equals("Object"))) {
+          // primitive parameters vs Object
+        } else {
+          return false;
+        }
+      }
     }
     if (md1.getReturnType()==null||md2.getReturnType()==null) {
        if (md1.getReturnType()!=md2.getReturnType())
@@ -163,18 +217,64 @@ NextMethod:
 
   public void createFullTable() {
     subclasstable=new Hashtable();
+    HashSet tovisit=new HashSet();
+    HashSet visited=new HashSet();
 
     Iterator classit=state.getClassSymbolTable().getDescriptorsIterator();
     while(classit.hasNext()) {
+      tovisit.clear();
+      visited.clear();
       ClassDescriptor cd=(ClassDescriptor)classit.next();
       ClassDescriptor tmp=cd.getSuperDesc();
+      
+      // check cd's interface ancestors
+      {
+       Iterator it_sifs = cd.getSuperInterfaces();
+       while(it_sifs.hasNext()) {
+         ClassDescriptor cdt = (ClassDescriptor)it_sifs.next();
+         if(!tovisit.contains(cdt)){
+           tovisit.add(cdt);
+         }
+       }
+      }
 
       while(tmp!=null) {
-       if (!subclasstable.containsKey(tmp))
-         subclasstable.put(tmp,new HashSet());
-       HashSet hs=(HashSet)subclasstable.get(tmp);
-       hs.add(cd);
-       tmp=tmp.getSuperDesc();
+        if (!subclasstable.containsKey(tmp))
+          subclasstable.put(tmp,new HashSet());
+        HashSet hs=(HashSet)subclasstable.get(tmp);
+        hs.add(cd);
+       // check tmp's interface ancestors
+       Iterator it_sifs = tmp.getSuperInterfaces();
+       while(it_sifs.hasNext()) {
+         ClassDescriptor cdt = (ClassDescriptor)it_sifs.next();
+         if(!tovisit.contains(cdt)){
+           tovisit.add(cdt);
+         }
+       }
+       
+        tmp=tmp.getSuperDesc();
+      }
+      
+      while(!tovisit.isEmpty()) {
+       ClassDescriptor sif = (ClassDescriptor)tovisit.iterator().next();
+       tovisit.remove(sif);
+        
+       if(!visited.contains(sif)) {
+         if(!this.subclasstable.containsKey(sif)) {
+           this.subclasstable.put(sif, new HashSet());
+         }
+         HashSet hs = (HashSet)this.subclasstable.get(sif);
+         hs.add(cd);
+          
+         Iterator it_sifs = sif.getSuperInterfaces();
+         while(it_sifs.hasNext()) {
+           ClassDescriptor siftmp = (ClassDescriptor)it_sifs.next();
+           if(!tovisit.contains(siftmp)){
+             tovisit.add(siftmp);
+           }
+         }
+         visited.add(sif);
+       }
       }
     }
   }
@@ -186,6 +286,10 @@ NextMethod:
   public ClassDescriptor getSuper(ClassDescriptor cd) {
     return (ClassDescriptor)supertable.get(cd);
   }
+  
+  public Set<ClassDescriptor> getSuperIFs(ClassDescriptor cd) {
+    return superIFtbl.get(cd);
+  }
 
   public boolean isCastable(TypeDescriptor original, TypeDescriptor casttype) {
     if (original.isChar()&&
@@ -232,6 +336,10 @@ NextMethod:
           &&(possiblesuper.getArrayCount()<cd2.getArrayCount()))
        return true;
 
+      //Allow arraytype=null statements
+      if (possiblesuper.isArray()&&cd2.isNull())
+       return true;
+
       return false;
     }
 
@@ -259,8 +367,14 @@ NextMethod:
                          possiblesuper.isFloat()||possiblesuper.isDouble()))
        return true;
       if (cd2.isInt()&&(possiblesuper.isInt()||possiblesuper.isLong()||
-                        possiblesuper.isFloat()||possiblesuper.isDouble()))
+                        possiblesuper.isFloat()||possiblesuper.isDouble()
+                        ||possiblesuper.isEnum()))
        return true;
+      if (cd2.isEnum()&&(possiblesuper.isInt()||possiblesuper.isLong()||
+                         possiblesuper.isFloat()||possiblesuper.isDouble()))
+        return true;
+      if(cd2.isEnum()&&possiblesuper.isEnum()&&cd2.class_desc.equals(possiblesuper.class_desc))
+        return true;
       if (cd2.isLong()&&(possiblesuper.isLong()||
                          possiblesuper.isFloat()||possiblesuper.isDouble()))
        return true;
@@ -283,6 +397,19 @@ NextMethod:
       throw new Error("Case not handled:"+possiblesuper+" "+cd2);
   }
 
+  public TypeDescriptor mostSpecific(TypeDescriptor td1, TypeDescriptor td2) {
+    if( isSuperorType( td1, td2 ) ) {
+      return td2;
+    }
+    if( isSuperorType( td2, td1 ) ) {
+      return td1;
+    }
+    throw new Error( td1+" and "+td2+" have no superclass relationship" );
+  }
+
+  public TypeDescriptor mostSpecific(TypeDescriptor td1, TypeDescriptor td2, TypeDescriptor td3) {
+    return mostSpecific( td1, mostSpecific( td2, td3 ) );
+  }
 
   public boolean isSuperorType(ClassDescriptor possiblesuper, ClassDescriptor cd2) {
     if (possiblesuper==cd2)
@@ -292,10 +419,57 @@ NextMethod:
   }
 
   private boolean isSuper(ClassDescriptor possiblesuper, ClassDescriptor cd2) {
+    HashSet tovisit=new HashSet();
+    HashSet visited=new HashSet();
+    
+    {
+      // check cd2's interface ancestors
+      Iterator<ClassDescriptor> it_sifs = getSuperIFs(cd2).iterator();
+      while(it_sifs.hasNext()) {
+       ClassDescriptor cd = it_sifs.next();
+       if(cd == possiblesuper) {
+         return true;
+       } else if(!tovisit.contains(cd)){
+         tovisit.add(cd);
+       }
+      }
+    }
+
     while(cd2!=null) {
       cd2=getSuper(cd2);
       if (cd2==possiblesuper)
        return true;
+      
+      // check cd2's interface ancestors
+      if(cd2 != null) {
+       Iterator it_sifs = getSuperIFs(cd2).iterator();
+       while(it_sifs.hasNext()) {
+         ClassDescriptor cd = (ClassDescriptor)it_sifs.next();
+         if(cd == possiblesuper) {
+           return true;
+         } else if(!tovisit.contains(cd)){
+           tovisit.add(cd);
+         }
+       }
+      }
+    }
+    
+    while(!tovisit.isEmpty()) {
+      ClassDescriptor cd = (ClassDescriptor)tovisit.iterator().next();
+      tovisit.remove(cd);
+      
+      if(!visited.contains(cd)) {
+       Iterator it_sifs = getSuperIFs(cd).iterator();
+       while(it_sifs.hasNext()) {
+         ClassDescriptor cdt = (ClassDescriptor)it_sifs.next();
+         if(cdt == possiblesuper) {
+           return true;
+         } else if(!tovisit.contains(cdt)){
+           tovisit.add(cdt);
+         }
+       }
+       visited.add(cd);
+      }
     }
     return false;
   }