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 isCastable(TypeDescriptor original, TypeDescriptor casttype) {
63         if (original.isChar()&&
64             (casttype.isByte()||
65              casttype.isShort()))
66             return true;
67
68         if (casttype.isChar()&&
69             (original.isByte()||
70              original.isShort()||
71              original.isInt()||
72              original.isLong()||
73              original.isFloat()||
74              original.isDouble()))
75             return true;
76             
77         return false;
78     }
79
80     public boolean isSuperorType(TypeDescriptor possiblesuper, TypeDescriptor cd2) {
81         //Matching type are always okay
82         if (possiblesuper.equals(cd2))
83             return true;
84
85         //Handle arrays
86         if (cd2.isArray()||possiblesuper.isArray()) {
87             // Object is super class of all arrays
88             if (possiblesuper.getSymbol().equals(ObjectClass)&&!possiblesuper.isArray())
89                 return true;
90
91             // If we have the same dimensionality of arrays & both are classes, we can default to the normal test
92             if (cd2.isClass()&&possiblesuper.isClass()
93                 &&(possiblesuper.getArrayCount()==cd2.getArrayCount())&&
94                 isSuperorType(possiblesuper.getClassDesc(), cd2.getClassDesc()))
95                 return true;
96
97             // Object is superclass of all array classes
98             if (possiblesuper.getSymbol().equals(ObjectClass)&&cd2.isClass()
99                 &&(possiblesuper.getArrayCount()<cd2.getArrayCount()))
100                 return true;
101
102             return false;
103         }
104
105         if (possiblesuper.isClass()&&
106              cd2.isClass())
107             return isSuperorType(possiblesuper.getClassDesc(), cd2.getClassDesc());
108         else if (possiblesuper.isClass()&&
109                  cd2.isNull())
110             return true;
111         else if (possiblesuper.isNull())
112             throw new Error(); //not sure when this case would occur
113         else if (possiblesuper.isPrimitive()&&
114                  cd2.isPrimitive()) {
115             ///Primitive widenings from 5.1.2
116             if (cd2.isByte()&&(possiblesuper.isByte()||possiblesuper.isShort()||
117                                possiblesuper.isInt()||possiblesuper.isLong()||
118                                possiblesuper.isFloat()||possiblesuper.isDouble()))
119                 return true;
120             if (cd2.isShort()&&(possiblesuper.isShort()||
121                                 possiblesuper.isInt()||possiblesuper.isLong()||
122                                 possiblesuper.isFloat()||possiblesuper.isDouble()))
123                 return true;
124             if (cd2.isChar()&&(possiblesuper.isChar()||
125                                possiblesuper.isInt()||possiblesuper.isLong()||
126                                possiblesuper.isFloat()||possiblesuper.isDouble()))
127                 return true;
128             if (cd2.isInt()&&(possiblesuper.isInt()||possiblesuper.isLong()||
129                               possiblesuper.isFloat()||possiblesuper.isDouble()))
130                 return true;
131             if (cd2.isLong()&&(possiblesuper.isLong()||
132                                possiblesuper.isFloat()||possiblesuper.isDouble()))
133                 return true;
134             if (cd2.isFloat()&&(possiblesuper.isFloat()||possiblesuper.isDouble()))
135                 return true;
136             if (cd2.isDouble()&&possiblesuper.isDouble())
137                 
138                 return true;
139             if (cd2.isBoolean()&&possiblesuper.isBoolean())
140                 return true;
141             
142             return false;
143         } else if (possiblesuper.isPrimitive()&&(!possiblesuper.isArray())&&
144                    (cd2.isArray()||cd2.isPtr()))
145             return false;
146         else if (cd2.isPrimitive()&&(!cd2.isArray())&&
147                  (possiblesuper.isArray()||possiblesuper.isPtr()))
148             return false;
149         else
150             throw new Error();
151     }
152
153     
154     public boolean isSuperorType(ClassDescriptor possiblesuper, ClassDescriptor cd2) {
155         if (possiblesuper==cd2)
156             return true;
157         else
158             return isSuper(possiblesuper, cd2);
159     }
160
161     private boolean isSuper(ClassDescriptor possiblesuper, ClassDescriptor cd2) {
162         while(cd2!=null) {
163             cd2=getSuper(cd2);
164             if (cd2==possiblesuper)
165                 return true;
166         }
167         return false;
168     }
169 }