get rid of the stream parsing that occurs in the Layer III decoder. BitStream.readFra...
[IRC.git] / Robust / src / IR / ClassDescriptor.java
1 package IR;
2 import java.util.*;
3 import IR.Tree.*;
4 import Util.Lattice;
5
6 public class ClassDescriptor extends Descriptor {
7   private static int UIDCount=1; // start from 1 instead of 0 for multicore gc
8   private final int classid;
9   String superclass;
10   ClassDescriptor superdesc;
11   boolean hasFlags=false;
12   String packagename;
13   String classname;
14
15   Modifiers modifiers;
16
17   SymbolTable fields;
18   Vector fieldvec;
19   SymbolTable flags;
20   SymbolTable methods;
21   boolean inline=false;
22   
23
24   ChainHashMap mandatoryImports;
25   ChainHashMap multiImports;
26
27   int numstaticblocks = 0;
28   int numstaticfields = 0;
29
30   // for interfaces
31   Vector<String> superinterfaces;
32   SymbolTable superIFdesc;
33   private int interfaceid;
34
35   // for inner classes
36   boolean isInnerClass=false;
37
38   // inner classes/enum can have these
39   String surroundingclass=null;
40   ClassDescriptor surroudingdesc=null;
41   SymbolTable innerdescs;
42
43   // for enum type
44   boolean isEnum = false;
45   SymbolTable enumdescs;
46   HashMap<String, Integer> enumConstantTbl;
47   int enumconstantid = 0;
48
49   String sourceFileName;
50
51   public ClassDescriptor(String classname, boolean isInterface) {
52     this("", classname, isInterface);
53   }
54
55   public ClassDescriptor(String packagename, String classname, boolean isInterface) {
56     //make the name canonical by class file path (i.e. package)
57     super(packagename!=null?packagename+"."+classname:classname);
58     this.classname=classname;
59     superclass=null;
60     flags=new SymbolTable();
61     fields=new SymbolTable();
62     fieldvec=new Vector();
63     methods=new SymbolTable();
64     if(isInterface) {
65       this.classid = -2;
66       this.interfaceid = -1;
67     } else {
68       classid=UIDCount++;
69     }
70     this.packagename=packagename;
71     superinterfaces = new Vector<String>();
72     superIFdesc = new SymbolTable();
73     this.innerdescs = new SymbolTable();
74     this.enumdescs = new SymbolTable();
75   }
76
77   public int getId() {
78     if(this.isInterface()) {
79       return this.interfaceid;
80     }
81     return classid;
82   }
83
84   public Iterator getMethods() {
85     return methods.getDescriptorsIterator();
86   }
87
88   public Iterator getFields() {
89     return fields.getDescriptorsIterator();
90   }
91
92   public Iterator getFlags() {
93     return flags.getDescriptorsIterator();
94   }
95
96   public Iterator getSuperInterfaces() {
97     return this.superIFdesc.getDescriptorsIterator();
98   }
99
100   public SymbolTable getFieldTable() {
101     return fields;
102   }
103
104   public Vector getFieldVec() {
105     return fieldvec;
106   }
107
108   public String getClassName() {
109     return classname;
110   }
111
112   public String getPackage() {
113     return packagename;
114   }
115
116   public SymbolTable getFlagTable() {
117     return flags;
118   }
119
120   public SymbolTable getMethodTable() {
121     return methods;
122   }
123
124   public SymbolTable getSuperInterfaceTable() {
125     return this.superIFdesc;
126   }
127
128   public String getSafeDescriptor() {
129     return "L"+safename.replace(".","___________");
130   }
131
132   public String getSafeSymbol() {
133     return safename.replace(".","___________").replace("$","___DOLLAR___");
134   }
135
136   public String printTree(State state) {
137     int indent;
138     String st=modifiers.toString()+"class "+getSymbol();
139     if (superclass!=null)
140       st+="extends "+superclass.toString();
141     if(this.superinterfaces != null) {
142       st += "implements ";
143       boolean needcomma = false;
144       for(int i = 0; i < this.superinterfaces.size(); i++) {
145         if(needcomma) {
146           st += ", ";
147         }
148         st += this.superinterfaces.elementAt(i);
149         needcomma = true;
150       }
151     }
152     st+=" {\n";
153     indent=TreeNode.INDENT;
154     boolean printcr=false;
155
156     for(Iterator it=getFlags(); it.hasNext(); ) {
157       FlagDescriptor fd=(FlagDescriptor)it.next();
158       st+=TreeNode.printSpace(indent)+fd.toString()+"\n";
159       printcr=true;
160     }
161     if (printcr)
162       st+="\n";
163
164     printcr=false;
165
166     for(Iterator it=getFields(); it.hasNext(); ) {
167       FieldDescriptor fd=(FieldDescriptor)it.next();
168       st+=TreeNode.printSpace(indent)+fd.toString()+"\n";
169       printcr=true;
170     }
171     if (printcr)
172       st+="\n";
173
174     for(Iterator it=this.getInnerClasses(); it.hasNext(); ) {
175       ClassDescriptor icd=(ClassDescriptor)it.next();
176       st+=icd.printTree(state)+"\n";
177       printcr=true;
178     }
179     if (printcr)
180       st+="\n";
181
182     for(Iterator it=this.getEnum(); it.hasNext(); ) {
183       ClassDescriptor icd = (ClassDescriptor)it.next();
184       st += icd.getModifier().toString() + " enum " + icd.getSymbol() + " {\n  ";
185       Set keys = icd.getEnumConstantTbl().keySet();
186       String[] econstants = new String[keys.size()];
187       Iterator it_keys = keys.iterator();
188       while(it_keys.hasNext()) {
189         String key = (String)it_keys.next();
190         econstants[icd.getEnumConstant(key)] = key;
191       }
192       for(int i = 0; i < econstants.length; i++) {
193         st += econstants[i];
194         if(i < econstants.length-1) {
195           st += ", ";
196         }
197       }
198       st+="\n}\n";
199       printcr=true;
200     }
201     if (printcr)
202       st+="\n";
203
204     for(Iterator it=getMethods(); it.hasNext(); ) {
205       MethodDescriptor md=(MethodDescriptor)it.next();
206       st+=TreeNode.printSpace(indent)+md.toString()+" ";
207       BlockNode bn=state.getMethodBody(md);
208       st+=bn.printNode(indent)+"\n\n";
209     }
210     st+="}\n";
211     return st;
212   }
213
214   public MethodDescriptor getCalledMethod(MethodDescriptor md) {
215     ClassDescriptor cn=this;
216     while(true) {
217       if (cn==null) {
218         // TODO: the original code returned "null" if no super class
219         // ever defines the method.  Is there a situation where this is
220         // fine and the client should take other actions?  If not, we should
221         // change this warning to an error.
222         System.out.println("ClassDescriptor.java: WARNING "+md+
223                            " did not resolve to an actual method.");
224         return null;
225       }
226       Set possiblematches=cn.getMethodTable().getSetFromSameScope(md.getSymbol());
227       for(Iterator matchit=possiblematches.iterator(); matchit.hasNext(); ) {
228         MethodDescriptor matchmd=(MethodDescriptor)matchit.next();
229
230         if (md.matches(matchmd)) {
231           return matchmd;
232         }
233       }
234
235       //Not found...walk one level up
236       cn=cn.getSuperDesc();
237     }
238   }
239
240   public void addFlag(FlagDescriptor fd) {
241     if (flags.contains(fd.getSymbol()))
242       throw new Error(fd.getSymbol()+" already defined");
243     hasFlags=true;
244     flags.add(fd);
245   }
246
247   public boolean hasFlags() {
248     return hasFlags||getSuperDesc()!=null&&getSuperDesc().hasFlags();
249   }
250
251   public void addField(FieldDescriptor fd) {
252     if (fields.contains(fd.getSymbol()))
253       throw new Error(fd.getSymbol()+" already defined");
254     fields.add(fd);
255     fieldvec.add(fd);
256     if(fd.isStatic()) {
257       this.incStaticFields();
258     }
259     fd.setClassDescriptor(this);
260   }
261
262   public void addMethod(MethodDescriptor md) {
263     methods.add(md);
264   }
265
266   public void setModifiers(Modifiers modifiers) {
267     this.modifiers=modifiers;
268   }
269
270   public void setInline() {
271     this.inline=true;
272   }
273
274   public boolean getInline() {
275     return inline;
276   }
277
278   public void setSuper(String superclass) {
279     this.superclass=superclass;
280   }
281
282   public ClassDescriptor getSuperDesc() {
283     return superdesc;
284   }
285
286   public void setSuperDesc(ClassDescriptor scd) {
287     this.superdesc=scd;
288   }
289
290   public String getSuper() {
291     return superclass;
292   }
293
294   public void addSuperInterface(String superif) {
295     this.superinterfaces.addElement(superif);
296   }
297
298   public Vector<String> getSuperInterface() {
299     return this.superinterfaces;
300   }
301
302   public void addSuperInterfaces(ClassDescriptor sif) {
303     this.superIFdesc.add(sif);
304   }
305
306   public void incStaticBlocks() {
307     this.numstaticblocks++;
308   }
309
310   public int getNumStaticBlocks() {
311     return this.numstaticblocks;
312   }
313
314   public void incStaticFields() {
315     this.numstaticfields++;
316   }
317
318   public int getNumStaticFields() {
319     return this.numstaticfields;
320   }
321
322   public boolean isAbstract() {
323     return this.modifiers.isAbstract();
324   }
325
326   public boolean isInterface() {
327     return (this.classid == -2);
328   }
329
330   public void setInterfaceId(int id) {
331     this.interfaceid = id;
332   }
333
334   public boolean isStatic() {
335     return this.modifiers.isStatic();
336   }
337
338   public void setAsInnerClass() {
339     this.isInnerClass = true;
340   }
341
342   public boolean isInnerClass() {
343     return this.isInnerClass;
344   }
345
346   public void setSurroundingClass(String sclass) {
347     this.surroundingclass=sclass;
348   }
349
350   public String getSurrounding() {
351     return this.surroundingclass;
352   }
353
354   public ClassDescriptor getSurroundingDesc() {
355     return this.surroudingdesc;
356   }
357
358   public void setSurrounding(ClassDescriptor scd) {
359     this.surroudingdesc=scd;
360   }
361
362   public void addInnerClass(ClassDescriptor icd) {
363     this.innerdescs.add(icd);
364   }
365
366   public Iterator getInnerClasses() {
367     return this.innerdescs.getDescriptorsIterator();
368   }
369
370   public SymbolTable getInnerClassTable() {
371     return this.innerdescs;
372   }
373
374   public void setAsEnum() {
375     this.isEnum = true;
376   }
377
378   public boolean isEnum() {
379     return this.isEnum;
380   }
381
382   public void addEnum(ClassDescriptor icd) {
383     this.enumdescs.add(icd);
384   }
385
386   public Iterator getEnum() {
387     return this.enumdescs.getDescriptorsIterator();
388   }
389
390   public SymbolTable getEnumTable() {
391     return this.enumdescs;
392   }
393
394   public void addEnumConstant(String econstant) {
395     if(this.enumConstantTbl == null) {
396       this.enumConstantTbl = new HashMap<String, Integer>();
397     }
398     if(this.enumConstantTbl.containsKey(econstant)) {
399       return;
400     } else {
401       this.enumConstantTbl.put(econstant, this.enumconstantid++);
402     }
403     return;
404   }
405
406   public int getEnumConstant(String econstant) {
407     if(this.enumConstantTbl.containsKey(econstant)) {
408       return this.enumConstantTbl.get(econstant).intValue();
409     } else {
410       return -1;
411     }
412   }
413
414   public HashMap<String, Integer> getEnumConstantTbl() {
415     return this.enumConstantTbl;
416   }
417
418   public Modifiers getModifier() {
419     return this.modifiers;
420   }
421
422   public void setSourceFileName(String sourceFileName) {
423     this.sourceFileName=sourceFileName;
424   }
425
426   public void setImports(ChainHashMap singleImports, ChainHashMap multiImports) {
427     this.mandatoryImports = singleImports;
428     this.multiImports = multiImports;
429   }
430
431   public String getSourceFileName() {
432     return this.sourceFileName;
433   }
434
435   public ChainHashMap getSingleImportMappings() {
436     return this.mandatoryImports;
437   }
438   
439   public ChainHashMap getMultiImportMappings() {
440     return this.multiImports;
441   }
442
443   //Returns the full name/path of another class referenced from this class via imports.
444   public String getCanonicalImportMapName(String otherClassname) {
445     if(mandatoryImports.containsKey(otherClassname)) {
446       return (String) mandatoryImports.get(otherClassname);
447     } else if(multiImports.containsKey(otherClassname)) {
448       //Test for error
449       Object o = multiImports.get(otherClassname);
450       if(o instanceof Error) {
451         throw new Error("Class " + otherClassname + " is ambiguous. Cause: more than 1 package import contain the same class.");
452       } else {
453         //At this point, if we found a unique class
454         //we can treat it as a single, mandatory import.
455         mandatoryImports.put(otherClassname, o);
456         return (String) o;
457       }
458     } else {
459       return otherClassname;
460     }
461   }
462 }