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