get rid of the stream parsing that occurs in the Layer III decoder. BitStream.readFra...
[IRC.git] / Robust / src / IR / ClassDescriptor.java
index e38a12f6bba121151b9ca3365aa2d362a57b1d42..43923d0cff3830e103b83e33840300a2232723a0 100644 (file)
@@ -1,36 +1,83 @@
 package IR;
 import java.util.*;
 import IR.Tree.*;
+import Util.Lattice;
 
 public class ClassDescriptor extends Descriptor {
-  private static int UIDCount=0;
+  private static int UIDCount=1; // start from 1 instead of 0 for multicore gc
   private final int classid;
   String superclass;
   ClassDescriptor superdesc;
   boolean hasFlags=false;
   String packagename;
+  String classname;
 
   Modifiers modifiers;
 
   SymbolTable fields;
+  Vector fieldvec;
   SymbolTable flags;
   SymbolTable methods;
+  boolean inline=false;
+  
 
-  public ClassDescriptor(String classname) {
-    this("", classname);
+  ChainHashMap mandatoryImports;
+  ChainHashMap multiImports;
+
+  int numstaticblocks = 0;
+  int numstaticfields = 0;
+
+  // for interfaces
+  Vector<String> superinterfaces;
+  SymbolTable superIFdesc;
+  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) {
-    super(classname);
+  public ClassDescriptor(String packagename, String classname, boolean isInterface) {
+    //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();
-    classid=UIDCount++;
+    if(isInterface) {
+      this.classid = -2;
+      this.interfaceid = -1;
+    } else {
+      classid=UIDCount++;
+    }
     this.packagename=packagename;
+    superinterfaces = new Vector<String>();
+    superIFdesc = new SymbolTable();
+    this.innerdescs = new SymbolTable();
+    this.enumdescs = new SymbolTable();
   }
 
   public int getId() {
+    if(this.isInterface()) {
+      return this.interfaceid;
+    }
     return classid;
   }
 
@@ -46,10 +93,26 @@ public class ClassDescriptor extends Descriptor {
     return flags.getDescriptorsIterator();
   }
 
+  public Iterator getSuperInterfaces() {
+    return this.superIFdesc.getDescriptorsIterator();
+  }
+
   public SymbolTable getFieldTable() {
     return fields;
   }
 
+  public Vector getFieldVec() {
+    return fieldvec;
+  }
+
+  public String getClassName() {
+    return classname;
+  }
+
+  public String getPackage() {
+    return packagename;
+  }
+
   public SymbolTable getFlagTable() {
     return flags;
   }
@@ -58,8 +121,16 @@ public class ClassDescriptor extends Descriptor {
     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) {
@@ -67,11 +138,22 @@ public class ClassDescriptor extends Descriptor {
     String st=modifiers.toString()+"class "+getSymbol();
     if (superclass!=null)
       st+="extends "+superclass.toString();
+    if(this.superinterfaces != null) {
+      st += "implements ";
+      boolean needcomma = false;
+      for(int i = 0; i < this.superinterfaces.size(); i++) {
+        if(needcomma) {
+          st += ", ";
+        }
+        st += this.superinterfaces.elementAt(i);
+        needcomma = true;
+      }
+    }
     st+=" {\n";
     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;
@@ -81,7 +163,7 @@ 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;
@@ -89,7 +171,37 @@ public class ClassDescriptor extends Descriptor {
     if (printcr)
       st+="\n";
 
-    for(Iterator it=getMethods(); 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(); ) {
+      ClassDescriptor icd = (ClassDescriptor)it.next();
+      st += icd.getModifier().toString() + " enum " + icd.getSymbol() + " {\n  ";
+      Set keys = icd.getEnumConstantTbl().keySet();
+      String[] econstants = new String[keys.size()];
+      Iterator it_keys = keys.iterator();
+      while(it_keys.hasNext()) {
+        String key = (String)it_keys.next();
+        econstants[icd.getEnumConstant(key)] = key;
+      }
+      for(int i = 0; i < econstants.length; i++) {
+        st += econstants[i];
+        if(i < econstants.length-1) {
+          st += ", ";
+        }
+      }
+      st+="\n}\n";
+      printcr=true;
+    }
+    if (printcr)
+      st+="\n";
+
+    for(Iterator it=getMethods(); it.hasNext(); ) {
       MethodDescriptor md=(MethodDescriptor)it.next();
       st+=TreeNode.printSpace(indent)+md.toString()+" ";
       BlockNode bn=state.getMethodBody(md);
@@ -99,6 +211,32 @@ public class ClassDescriptor extends Descriptor {
     return st;
   }
 
+  public MethodDescriptor getCalledMethod(MethodDescriptor md) {
+    ClassDescriptor cn=this;
+    while(true) {
+      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();
+    }
+  }
+
   public void addFlag(FlagDescriptor fd) {
     if (flags.contains(fd.getSymbol()))
       throw new Error(fd.getSymbol()+" already defined");
@@ -114,6 +252,11 @@ public class ClassDescriptor extends Descriptor {
     if (fields.contains(fd.getSymbol()))
       throw new Error(fd.getSymbol()+" already defined");
     fields.add(fd);
+    fieldvec.add(fd);
+    if(fd.isStatic()) {
+      this.incStaticFields();
+    }
+    fd.setClassDescriptor(this);
   }
 
   public void addMethod(MethodDescriptor md) {
@@ -124,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;
   }
@@ -132,11 +283,180 @@ 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.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;
+  }
+
+  public String getSurrounding() {
+    return this.surroundingclass;
+  }
+
+  public ClassDescriptor getSurroundingDesc() {
+    return this.surroudingdesc;
+  }
+
+  public void setSurrounding(ClassDescriptor scd) {
+    this.surroudingdesc=scd;
+  }
+
+  public void addInnerClass(ClassDescriptor icd) {
+    this.innerdescs.add(icd);
+  }
+
+  public Iterator getInnerClasses() {
+    return this.innerdescs.getDescriptorsIterator();
+  }
+
+  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();
+  }
+
+  public SymbolTable getEnumTable() {
+    return this.enumdescs;
+  }
+
+  public void addEnumConstant(String econstant) {
+    if(this.enumConstantTbl == null) {
+      this.enumConstantTbl = new HashMap<String, Integer>();
+    }
+    if(this.enumConstantTbl.containsKey(econstant)) {
+      return;
+    } else {
+      this.enumConstantTbl.put(econstant, this.enumconstantid++);
+    }
+    return;
+  }
+
+  public int getEnumConstant(String econstant) {
+    if(this.enumConstantTbl.containsKey(econstant)) {
+      return this.enumConstantTbl.get(econstant).intValue();
+    } else {
+      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;
+    }
+  }
 }