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