add longer mp3 file for test
[IRC.git] / Robust / src / IR / ClassDescriptor.java
index 26e57df088aae1c7ee1532add838aacc1ee5ae8d..43923d0cff3830e103b83e33840300a2232723a0 100644 (file)
@@ -1,6 +1,7 @@
 package IR;
 import java.util.*;
 import IR.Tree.*;
+import Util.Lattice;
 
 public class ClassDescriptor extends Descriptor {
   private static int UIDCount=1; // start from 1 instead of 0 for multicore gc
@@ -9,6 +10,7 @@ public class ClassDescriptor extends Descriptor {
   ClassDescriptor superdesc;
   boolean hasFlags=false;
   String packagename;
+  String classname;
 
   Modifiers modifiers;
 
@@ -16,42 +18,55 @@ public class ClassDescriptor extends Descriptor {
   Vector fieldvec;
   SymbolTable flags;
   SymbolTable methods;
+  boolean inline=false;
   
+
+  ChainHashMap mandatoryImports;
+  ChainHashMap multiImports;
+
   int numstaticblocks = 0;
   int numstaticfields = 0;
-  
+
   // for interfaces
   Vector<String> superinterfaces;
   SymbolTable superIFdesc;
-  private boolean isInterface;
-  
+  private int interfaceid;
+
   // for inner classes
   boolean isInnerClass=false;
-  
+
   // inner classes/enum can have these
   String surroundingclass=null;
   ClassDescriptor surroudingdesc=null;
   SymbolTable innerdescs;
-  
+
   // for enum type
   boolean isEnum = false;
   SymbolTable enumdescs;
   HashMap<String, Integer> enumConstantTbl;
   int enumconstantid = 0;
 
+  String sourceFileName;
+
   public ClassDescriptor(String classname, boolean isInterface) {
     this("", classname, isInterface);
   }
 
   public ClassDescriptor(String packagename, String classname, boolean isInterface) {
-    super(classname);
+    //make the name canonical by class file path (i.e. package)
+    super(packagename!=null?packagename+"."+classname:classname);
+    this.classname=classname;
     superclass=null;
     flags=new SymbolTable();
     fields=new SymbolTable();
     fieldvec=new Vector();
     methods=new SymbolTable();
-    this.isInterface = isInterface;
-    classid=UIDCount++;
+    if(isInterface) {
+      this.classid = -2;
+      this.interfaceid = -1;
+    } else {
+      classid=UIDCount++;
+    }
     this.packagename=packagename;
     superinterfaces = new Vector<String>();
     superIFdesc = new SymbolTable();
@@ -60,6 +75,9 @@ public class ClassDescriptor extends Descriptor {
   }
 
   public int getId() {
+    if(this.isInterface()) {
+      return this.interfaceid;
+    }
     return classid;
   }
 
@@ -74,7 +92,7 @@ public class ClassDescriptor extends Descriptor {
   public Iterator getFlags() {
     return flags.getDescriptorsIterator();
   }
-  
+
   public Iterator getSuperInterfaces() {
     return this.superIFdesc.getDescriptorsIterator();
   }
@@ -87,6 +105,14 @@ public class ClassDescriptor extends Descriptor {
     return fieldvec;
   }
 
+  public String getClassName() {
+    return classname;
+  }
+
+  public String getPackage() {
+    return packagename;
+  }
+
   public SymbolTable getFlagTable() {
     return flags;
   }
@@ -94,13 +120,17 @@ public class ClassDescriptor extends Descriptor {
   public SymbolTable getMethodTable() {
     return methods;
   }
-  
+
   public SymbolTable getSuperInterfaceTable() {
     return this.superIFdesc;
   }
 
   public String getSafeDescriptor() {
-    return "L"+safename.replace('.','/');
+    return "L"+safename.replace(".","___________");
+  }
+
+  public String getSafeSymbol() {
+    return safename.replace(".","___________").replace("$","___DOLLAR___");
   }
 
   public String printTree(State state) {
@@ -123,7 +153,7 @@ public class ClassDescriptor extends Descriptor {
     indent=TreeNode.INDENT;
     boolean printcr=false;
 
-    for(Iterator it=getFlags(); it.hasNext();) {
+    for(Iterator it=getFlags(); it.hasNext(); ) {
       FlagDescriptor fd=(FlagDescriptor)it.next();
       st+=TreeNode.printSpace(indent)+fd.toString()+"\n";
       printcr=true;
@@ -133,23 +163,23 @@ public class ClassDescriptor extends Descriptor {
 
     printcr=false;
 
-    for(Iterator it=getFields(); it.hasNext();) {
+    for(Iterator it=getFields(); it.hasNext(); ) {
       FieldDescriptor fd=(FieldDescriptor)it.next();
       st+=TreeNode.printSpace(indent)+fd.toString()+"\n";
       printcr=true;
     }
     if (printcr)
       st+="\n";
-    
-    for(Iterator it=this.getInnerClasses(); it.hasNext();) {
+
+    for(Iterator it=this.getInnerClasses(); it.hasNext(); ) {
       ClassDescriptor icd=(ClassDescriptor)it.next();
       st+=icd.printTree(state)+"\n";
       printcr=true;
     }
     if (printcr)
       st+="\n";
-    
-    for(Iterator it=this.getEnum(); it.hasNext();) {
+
+    for(Iterator it=this.getEnum(); it.hasNext(); ) {
       ClassDescriptor icd = (ClassDescriptor)it.next();
       st += icd.getModifier().toString() + " enum " + icd.getSymbol() + " {\n  ";
       Set keys = icd.getEnumConstantTbl().keySet();
@@ -171,7 +201,7 @@ public class ClassDescriptor extends Descriptor {
     if (printcr)
       st+="\n";
 
-    for(Iterator it=getMethods(); it.hasNext();) {
+    for(Iterator it=getMethods(); it.hasNext(); ) {
       MethodDescriptor md=(MethodDescriptor)it.next();
       st+=TreeNode.printSpace(indent)+md.toString()+" ";
       BlockNode bn=state.getMethodBody(md);
@@ -184,18 +214,24 @@ public class ClassDescriptor extends Descriptor {
   public MethodDescriptor getCalledMethod(MethodDescriptor md) {
     ClassDescriptor cn=this;
     while(true) {
-      Iterator methodit=cn.getMethods();
-      //Iterator through methods
-      while(methodit.hasNext()) {
-       Set possiblematches=cn.getMethodTable().getSet(md.getSymbol());
-       boolean foundmatch=false;
-       for(Iterator matchit=possiblematches.iterator(); matchit.hasNext();) {
-         MethodDescriptor matchmd=(MethodDescriptor)matchit.next();
-         if (md.matches(matchmd)) {
-           return matchmd;
-         }
-       }
+      if (cn==null) {
+        // TODO: the original code returned "null" if no super class
+        // ever defines the method.  Is there a situation where this is
+        // fine and the client should take other actions?  If not, we should
+        // change this warning to an error.
+        System.out.println("ClassDescriptor.java: WARNING "+md+
+                           " did not resolve to an actual method.");
+        return null;
+      }
+      Set possiblematches=cn.getMethodTable().getSetFromSameScope(md.getSymbol());
+      for(Iterator matchit=possiblematches.iterator(); matchit.hasNext(); ) {
+        MethodDescriptor matchmd=(MethodDescriptor)matchit.next();
+
+        if (md.matches(matchmd)) {
+          return matchmd;
+        }
       }
+
       //Not found...walk one level up
       cn=cn.getSuperDesc();
     }
@@ -231,6 +267,14 @@ public class ClassDescriptor extends Descriptor {
     this.modifiers=modifiers;
   }
 
+  public void setInline() {
+    this.inline=true;
+  }
+
+  public boolean getInline() {
+    return inline;
+  }
+
   public void setSuper(String superclass) {
     this.superclass=superclass;
   }
@@ -239,62 +283,66 @@ public class ClassDescriptor extends Descriptor {
     return superdesc;
   }
 
-  public void setSuper(ClassDescriptor scd) {
+  public void setSuperDesc(ClassDescriptor scd) {
     this.superdesc=scd;
   }
 
   public String getSuper() {
     return superclass;
   }
-  
+
   public void addSuperInterface(String superif) {
     this.superinterfaces.addElement(superif);
   }
-  
+
   public Vector<String> getSuperInterface() {
     return this.superinterfaces;
   }
-  
+
   public void addSuperInterfaces(ClassDescriptor sif) {
     this.superIFdesc.add(sif);
   }
-  
+
   public void incStaticBlocks() {
     this.numstaticblocks++;
   }
-  
+
   public int getNumStaticBlocks() {
     return this.numstaticblocks;
   }
-  
+
   public void incStaticFields() {
     this.numstaticfields++;
   }
-  
+
   public int getNumStaticFields() {
     return this.numstaticfields;
   }
-  
+
   public boolean isAbstract() {
     return this.modifiers.isAbstract();
   }
-  
+
   public boolean isInterface() {
-    return this.isInterface;
+    return (this.classid == -2);
   }
-  
+
+  public void setInterfaceId(int id) {
+    this.interfaceid = id;
+  }
+
   public boolean isStatic() {
     return this.modifiers.isStatic();
   }
-  
+
   public void setAsInnerClass() {
     this.isInnerClass = true;
   }
-  
+
   public boolean isInnerClass() {
     return this.isInnerClass;
   }
-  
+
   public void setSurroundingClass(String sclass) {
     this.surroundingclass=sclass;
   }
@@ -310,11 +358,11 @@ public class ClassDescriptor extends Descriptor {
   public void setSurrounding(ClassDescriptor scd) {
     this.surroudingdesc=scd;
   }
-  
+
   public void addInnerClass(ClassDescriptor icd) {
     this.innerdescs.add(icd);
   }
-  
+
   public Iterator getInnerClasses() {
     return this.innerdescs.getDescriptorsIterator();
   }
@@ -322,19 +370,19 @@ public class ClassDescriptor extends Descriptor {
   public SymbolTable getInnerClassTable() {
     return this.innerdescs;
   }
-  
+
   public void setAsEnum() {
     this.isEnum = true;
   }
-  
+
   public boolean isEnum() {
     return this.isEnum;
   }
-  
+
   public void addEnum(ClassDescriptor icd) {
     this.enumdescs.add(icd);
   }
-  
+
   public Iterator getEnum() {
     return this.enumdescs.getDescriptorsIterator();
   }
@@ -342,7 +390,7 @@ public class ClassDescriptor extends Descriptor {
   public SymbolTable getEnumTable() {
     return this.enumdescs;
   }
-  
+
   public void addEnumConstant(String econstant) {
     if(this.enumConstantTbl == null) {
       this.enumConstantTbl = new HashMap<String, Integer>();
@@ -354,7 +402,7 @@ public class ClassDescriptor extends Descriptor {
     }
     return;
   }
-  
+
   public int getEnumConstant(String econstant) {
     if(this.enumConstantTbl.containsKey(econstant)) {
       return this.enumConstantTbl.get(econstant).intValue();
@@ -362,12 +410,53 @@ public class ClassDescriptor extends Descriptor {
       return -1;
     }
   }
-  
+
   public HashMap<String, Integer> getEnumConstantTbl() {
     return this.enumConstantTbl;
   }
-  
+
   public Modifiers getModifier() {
     return this.modifiers;
   }
+
+  public void setSourceFileName(String sourceFileName) {
+    this.sourceFileName=sourceFileName;
+  }
+
+  public void setImports(ChainHashMap singleImports, ChainHashMap multiImports) {
+    this.mandatoryImports = singleImports;
+    this.multiImports = multiImports;
+  }
+
+  public String getSourceFileName() {
+    return this.sourceFileName;
+  }
+
+  public ChainHashMap getSingleImportMappings() {
+    return this.mandatoryImports;
+  }
+  
+  public ChainHashMap getMultiImportMappings() {
+    return this.multiImports;
+  }
+
+  //Returns the full name/path of another class referenced from this class via imports.
+  public String getCanonicalImportMapName(String otherClassname) {
+    if(mandatoryImports.containsKey(otherClassname)) {
+      return (String) mandatoryImports.get(otherClassname);
+    } else if(multiImports.containsKey(otherClassname)) {
+      //Test for error
+      Object o = multiImports.get(otherClassname);
+      if(o instanceof Error) {
+        throw new Error("Class " + otherClassname + " is ambiguous. Cause: more than 1 package import contain the same class.");
+      } else {
+        //At this point, if we found a unique class
+        //we can treat it as a single, mandatory import.
+        mandatoryImports.put(otherClassname, o);
+        return (String) o;
+      }
+    } else {
+      return otherClassname;
+    }
+  }
 }