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";
11 Hashtable subclasstable;
13 public TypeUtil(State state) {
18 public ClassDescriptor getClass(String classname) {
19 ClassDescriptor cd=(ClassDescriptor)state.getClassSymbolTable().get(classname);
23 private void createTables() {
24 supertable=new Hashtable();
26 Iterator classit=state.getClassSymbolTable().getDescriptorsIterator();
27 while(classit.hasNext()) {
28 ClassDescriptor cd=(ClassDescriptor)classit.next();
29 String superc=cd.getSuper();
31 ClassDescriptor cd_super=getClass(superc);
32 supertable.put(cd,cd_super);
37 public ClassDescriptor getMainClass() {
38 return getClass(state.main);
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)
48 Descriptor pd=md.getParameter(0);
49 TypeDescriptor tpd=(pd instanceof TagVarDescriptor)?((TagVarDescriptor)pd).getType():((VarDescriptor)pd)
51 if (tpd.getArrayCount()!=1)
53 if (!tpd.getSymbol().equals("String"))
56 if (!md.getModifiers().isStatic())
57 throw new Error("Error: Non static main");
60 throw new Error(cd+" has no main");
63 public void createFullTable() {
64 subclasstable=new Hashtable();
66 Iterator classit=state.getClassSymbolTable().getDescriptorsIterator();
67 while(classit.hasNext()) {
68 ClassDescriptor cd=(ClassDescriptor)classit.next();
69 ClassDescriptor tmp=cd.getSuperDesc();
72 if (!subclasstable.containsKey(tmp))
73 subclasstable.put(tmp,new HashSet());
74 HashSet hs=(HashSet)subclasstable.get(tmp);
76 tmp=tmp.getSuperDesc();
81 public Set getSubClasses(ClassDescriptor cd) {
82 return (Set)subclasstable.get(cd);
85 public ClassDescriptor getSuper(ClassDescriptor cd) {
86 return (ClassDescriptor)supertable.get(cd);
89 public boolean isCastable(TypeDescriptor original, TypeDescriptor casttype) {
90 if (original.isChar()&&
95 if (casttype.isChar()&&
101 original.isDouble()))
107 public boolean isSuperorType(TypeDescriptor possiblesuper, TypeDescriptor cd2) {
108 //Matching type are always okay
109 if (possiblesuper.equals(cd2))
112 if ((possiblesuper.isTag() && !cd2.isTag())||
113 (!possiblesuper.isTag() && cd2.isTag()))
117 if (cd2.isArray()||possiblesuper.isArray()) {
118 // Object is super class of all arrays
119 if (possiblesuper.getSymbol().equals(ObjectClass)&&!possiblesuper.isArray())
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()))
128 // Object is superclass of all array classes
129 if (possiblesuper.getSymbol().equals(ObjectClass)&&cd2.isClass()
130 &&(possiblesuper.getArrayCount()<cd2.getArrayCount()))
136 if (possiblesuper.isClass()&&
138 return isSuperorType(possiblesuper.getClassDesc(), cd2.getClassDesc());
139 else if (possiblesuper.isClass()&&
142 else if (possiblesuper.isNull())
143 throw new Error(); //not sure when this case would occur
144 else if (possiblesuper.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()))
151 if (cd2.isShort()&&(possiblesuper.isShort()||
152 possiblesuper.isInt()||possiblesuper.isLong()||
153 possiblesuper.isFloat()||possiblesuper.isDouble()))
155 if (cd2.isChar()&&(possiblesuper.isChar()||
156 possiblesuper.isInt()||possiblesuper.isLong()||
157 possiblesuper.isFloat()||possiblesuper.isDouble()))
159 if (cd2.isInt()&&(possiblesuper.isInt()||possiblesuper.isLong()||
160 possiblesuper.isFloat()||possiblesuper.isDouble()))
162 if (cd2.isLong()&&(possiblesuper.isLong()||
163 possiblesuper.isFloat()||possiblesuper.isDouble()))
165 if (cd2.isFloat()&&(possiblesuper.isFloat()||possiblesuper.isDouble()))
167 if (cd2.isDouble()&&possiblesuper.isDouble())
170 if (cd2.isBoolean()&&possiblesuper.isBoolean())
174 } else if (possiblesuper.isPrimitive()&&(!possiblesuper.isArray())&&
175 (cd2.isArray()||cd2.isPtr()))
177 else if (cd2.isPrimitive()&&(!cd2.isArray())&&
178 (possiblesuper.isArray()||possiblesuper.isPtr()))
181 throw new Error("Case not handled:"+possiblesuper+" "+cd2);
185 public boolean isSuperorType(ClassDescriptor possiblesuper, ClassDescriptor cd2) {
186 if (possiblesuper==cd2)
189 return isSuper(possiblesuper, cd2);
192 private boolean isSuper(ClassDescriptor possiblesuper, ClassDescriptor cd2) {
195 if (cd2==possiblesuper)