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