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