X-Git-Url: http://demsky.eecs.uci.edu/git/?a=blobdiff_plain;f=Robust%2Fsrc%2FIR%2FClassDescriptor.java;h=43923d0cff3830e103b83e33840300a2232723a0;hb=bd6155026f555257a526a2e0440b2c9f60eb018f;hp=aae2e558d54fcbeed71d68d1fa709a05df9d19bc;hpb=76ce6dc60427aafd95e53c2188223072fac5f9a3;p=IRC.git diff --git a/Robust/src/IR/ClassDescriptor.java b/Robust/src/IR/ClassDescriptor.java index aae2e558..43923d0c 100644 --- a/Robust/src/IR/ClassDescriptor.java +++ b/Robust/src/IR/ClassDescriptor.java @@ -1,113 +1,462 @@ package IR; import java.util.*; import IR.Tree.*; -import IR.SymbolTable; -import IR.FieldDescriptor; -import IR.MethodDescriptor; -import IR.NameDescriptor; +import Util.Lattice; public class ClassDescriptor extends Descriptor { - public ClassDescriptor(String classname) { - super(classname); - this.classname=classname; - superclass=null; - fields=new SymbolTable(); - methods=new SymbolTable(); - classid=UIDCount++; - } - private static int UIDCount=0; - private final int classid; - String classname; - String superclass; - ClassDescriptor superdesc; + 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; + Modifiers modifiers; - SymbolTable fields; - SymbolTable methods; + SymbolTable fields; + Vector fieldvec; + SymbolTable flags; + SymbolTable methods; + boolean inline=false; + - public int getId() { - return classid; - } - - public Iterator getMethods() { - return methods.getDescriptorsIterator(); - } + ChainHashMap mandatoryImports; + ChainHashMap multiImports; + + int numstaticblocks = 0; + int numstaticfields = 0; + + // for interfaces + Vector 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 enumConstantTbl; + int enumconstantid = 0; + + String sourceFileName; - public Iterator getFields() { - return fields.getDescriptorsIterator(); + public ClassDescriptor(String classname, boolean isInterface) { + this("", classname, isInterface); + } + + 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(); + if(isInterface) { + this.classid = -2; + this.interfaceid = -1; + } else { + classid=UIDCount++; } - - public SymbolTable getFieldTable() { - return fields; + this.packagename=packagename; + superinterfaces = new Vector(); + superIFdesc = new SymbolTable(); + this.innerdescs = new SymbolTable(); + this.enumdescs = new SymbolTable(); + } + + public int getId() { + if(this.isInterface()) { + return this.interfaceid; } + return classid; + } + + public Iterator getMethods() { + return methods.getDescriptorsIterator(); + } + + public Iterator getFields() { + return fields.getDescriptorsIterator(); + } + + public Iterator getFlags() { + 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 SymbolTable getMethodTable() { - return methods; + public String getPackage() { + return packagename; + } + + public SymbolTable getFlagTable() { + return flags; + } + + public SymbolTable getMethodTable() { + return methods; + } + + public SymbolTable getSuperInterfaceTable() { + return this.superIFdesc; + } + + public String getSafeDescriptor() { + return "L"+safename.replace(".","___________"); + } + + public String getSafeSymbol() { + return safename.replace(".","___________").replace("$","___DOLLAR___"); + } + + public String printTree(State state) { + int indent; + 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; - public String getSafeDescriptor() { - return "L"+safename.replace('.','/'); + for(Iterator it=getFlags(); it.hasNext(); ) { + FlagDescriptor fd=(FlagDescriptor)it.next(); + st+=TreeNode.printSpace(indent)+fd.toString()+"\n"; + printcr=true; } + if (printcr) + st+="\n"; + + printcr=false; - public String printTree(State state) { - int indent; - String st=modifiers.toString()+"class "+classname; - if (superclass!=null) - st+="extends "+superclass.toString(); - st+=" {\n"; - indent=TreeNode.INDENT; - boolean printcr=false; - - 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=getMethods();it.hasNext();) { - MethodDescriptor md=(MethodDescriptor)it.next(); - st+=TreeNode.printSpace(indent)+md.toString()+" "; - BlockNode bn=state.getMethodBody(md); - st+=bn.printNode(indent)+"\n\n"; - } - st+="}\n"; - return st; + for(Iterator it=getFields(); it.hasNext(); ) { + FieldDescriptor fd=(FieldDescriptor)it.next(); + st+=TreeNode.printSpace(indent)+fd.toString()+"\n"; + printcr=true; } + if (printcr) + st+="\n"; - public void addField(FieldDescriptor fd) { - if (fields.contains(fd.getSymbol())) - throw new Error(fd.getSymbol()+" already defined"); - fields.add(fd); + for(Iterator it=this.getInnerClasses(); it.hasNext(); ) { + ClassDescriptor icd=(ClassDescriptor)it.next(); + st+=icd.printTree(state)+"\n"; + printcr=true; } + if (printcr) + st+="\n"; - public void addMethod(MethodDescriptor md) { - methods.add(md); + 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; } - - public void setModifiers(Modifiers modifiers) { - this.modifiers=modifiers; + 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); + st+=bn.printNode(indent)+"\n\n"; } + st+="}\n"; + return st; + } - public void setName(String name) { - classname=name; + 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"); + hasFlags=true; + flags.add(fd); + } - public void setSuper(String superclass) { - this.superclass=superclass; + public boolean hasFlags() { + return hasFlags||getSuperDesc()!=null&&getSuperDesc().hasFlags(); + } + + public void addField(FieldDescriptor fd) { + 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) { + methods.add(md); + } + + public void setModifiers(Modifiers modifiers) { + this.modifiers=modifiers; + } + + public void setInline() { + this.inline=true; + } + + public boolean getInline() { + return inline; + } + + public void setSuper(String superclass) { + this.superclass=superclass; + } - public ClassDescriptor getSuperDesc() { - return superdesc; + public ClassDescriptor getSuperDesc() { + return superdesc; + } + + public void setSuperDesc(ClassDescriptor scd) { + this.superdesc=scd; + } + + public String getSuper() { + return superclass; + } + + public void addSuperInterface(String superif) { + this.superinterfaces.addElement(superif); + } + + public Vector 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(); + } + if(this.enumConstantTbl.containsKey(econstant)) { + return; + } else { + this.enumConstantTbl.put(econstant, this.enumconstantid++); } + return; + } - public void setSuper(ClassDescriptor scd) { - this.superdesc=scd; + public int getEnumConstant(String econstant) { + if(this.enumConstantTbl.containsKey(econstant)) { + return this.enumConstantTbl.get(econstant).intValue(); + } else { + return -1; } + } + + public HashMap 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; + } - public String getSuper() { - return superclass; + //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; } + } }