Checkins
[IRC.git] / Robust / src / IR / TypeUtil.java
1 package IR;
2 import java.util.*;
3
4 public class TypeUtil {
5     public static final String StringClass="String";
6     public static final String ObjectClass="Object";
7     State state;
8     Hashtable supertable;
9     Hashtable subclasstable;
10
11     public TypeUtil(State state) {
12         this.state=state;
13         createTables();
14     }
15
16     public ClassDescriptor getClass(String classname) {
17         ClassDescriptor cd=(ClassDescriptor)state.getClassSymbolTable().get(classname);
18         return cd;
19     }
20
21     private void createTables() {
22         supertable=new Hashtable();
23
24         Iterator classit=state.getClassSymbolTable().getDescriptorsIterator();
25         while(classit.hasNext()) {
26             ClassDescriptor cd=(ClassDescriptor)classit.next();
27             String superc=cd.getSuper();
28             if (superc!=null) {
29                 ClassDescriptor cd_super=getClass(superc);
30                 supertable.put(cd,cd_super);
31             }
32         }
33     }
34
35     public void createFullTable() {
36         subclasstable=new Hashtable();
37     
38         Iterator classit=state.getClassSymbolTable().getDescriptorsIterator();
39         while(classit.hasNext()) {
40             ClassDescriptor cd=(ClassDescriptor)classit.next();
41             ClassDescriptor tmp=cd.getSuperDesc();
42             
43             while(tmp!=null) {
44                 if (!subclasstable.containsKey(tmp))
45                     subclasstable.put(tmp,new HashSet());
46                 HashSet hs=(HashSet)subclasstable.get(tmp);
47                 hs.add(cd);
48                 tmp=tmp.getSuperDesc();
49             }
50         }
51     }
52
53     public Set getSubClasses(ClassDescriptor cd) {
54         return (Set)subclasstable.get(cd);
55     }
56
57     public ClassDescriptor getSuper(ClassDescriptor cd) {
58         return (ClassDescriptor)supertable.get(cd);
59     }
60
61     public boolean isSuperorType(TypeDescriptor possiblesuper, TypeDescriptor cd2) {
62         //Matching type are always okay
63         if (possiblesuper.equals(cd2))
64             return true;
65
66         //Handle arrays
67         if (cd2.isArray()||possiblesuper.isArray()) {
68             // Object is super class of all arrays
69             if (possiblesuper.getSymbol().equals(ObjectClass)&&!possiblesuper.isArray())
70                 return true;
71
72             // If we have the same dimensionality of arrays & both are classes, we can default to the normal test
73             if (cd2.isClass()&&possiblesuper.isClass()
74                 &&(possiblesuper.getArrayCount()==cd2.getArrayCount())&&
75                 isSuperorType(possiblesuper.getClassDesc(), cd2.getClassDesc()))
76                 return true;
77
78             // Object is superclass of all array classes
79             if (possiblesuper.getSymbol().equals(ObjectClass)&&cd2.isClass()
80                 &&(possiblesuper.getArrayCount()<cd2.getArrayCount()))
81                 return true;
82
83             return false;
84         }
85
86         if (possiblesuper.isClass()&&
87              cd2.isClass())
88             return isSuperorType(possiblesuper.getClassDesc(), cd2.getClassDesc());
89         else if (possiblesuper.isClass()&&
90                  cd2.isNull())
91             return true;
92         else if (possiblesuper.isNull())
93             throw new Error(); //not sure when this case would occur
94         else if (possiblesuper.isPrimitive()&&
95                  cd2.isPrimitive()) {
96             ///Primitive widenings from 5.1.2
97             if (cd2.isByte()&&(possiblesuper.isByte()||possiblesuper.isShort()||
98                                possiblesuper.isInt()||possiblesuper.isLong()||
99                                possiblesuper.isFloat()||possiblesuper.isDouble()))
100                 return true;
101             if (cd2.isShort()&&(possiblesuper.isShort()||
102                                 possiblesuper.isInt()||possiblesuper.isLong()||
103                                 possiblesuper.isFloat()||possiblesuper.isDouble()))
104                 return true;
105             if (cd2.isChar()&&(possiblesuper.isChar()||
106                                possiblesuper.isInt()||possiblesuper.isLong()||
107                                possiblesuper.isFloat()||possiblesuper.isDouble()))
108                 return true;
109             if (cd2.isInt()&&(possiblesuper.isInt()||possiblesuper.isLong()||
110                               possiblesuper.isFloat()||possiblesuper.isDouble()))
111                 return true;
112             if (cd2.isLong()&&(possiblesuper.isLong()||
113                                possiblesuper.isFloat()||possiblesuper.isDouble()))
114                 return true;
115             if (cd2.isFloat()&&(possiblesuper.isFloat()||possiblesuper.isDouble()))
116                 return true;
117             if (cd2.isDouble()&&possiblesuper.isDouble())
118                 
119                 return true;
120             if (cd2.isBoolean()&&possiblesuper.isBoolean())
121                 return true;
122             
123             return false;
124         } else throw new Error();
125     }
126
127
128     private boolean isSuperorType(ClassDescriptor possiblesuper, ClassDescriptor cd2) {
129         if (possiblesuper==cd2)
130             return true;
131         else
132             return isSuper(possiblesuper, cd2);
133     }
134
135     private boolean isSuper(ClassDescriptor possiblesuper, ClassDescriptor cd2) {
136         while(cd2!=null) {
137             cd2=getSuper(cd2);
138             if (cd2==possiblesuper)
139                 return true;
140         }
141         return false;
142     }
143 }