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