package IR; import java.util.*; public class TypeUtil { public static final String StringClass="String"; public static final String ObjectClass="Object"; public static final String StartupClass="StartupObject"; public static final String TagClass="TagDescriptor"; State state; Hashtable supertable; Hashtable subclasstable; public TypeUtil(State state) { this.state=state; createTables(); } public ClassDescriptor getClass(String classname) { ClassDescriptor cd=(ClassDescriptor)state.getClassSymbolTable().get(classname); return cd; } private void createTables() { supertable=new Hashtable(); Iterator classit=state.getClassSymbolTable().getDescriptorsIterator(); while(classit.hasNext()) { ClassDescriptor cd=(ClassDescriptor)classit.next(); String superc=cd.getSuper(); if (superc!=null) { ClassDescriptor cd_super=getClass(superc); supertable.put(cd,cd_super); } } } public ClassDescriptor getMainClass() { return getClass(state.main); } public MethodDescriptor getMain() { ClassDescriptor cd=getMainClass(); Set mainset=cd.getMethodTable().getSet("main"); for(Iterator mainit=mainset.iterator();mainit.hasNext();) { MethodDescriptor md=(MethodDescriptor)mainit.next(); if (md.numParameters()!=1) continue; Descriptor pd=md.getParameter(0); TypeDescriptor tpd=(pd instanceof TagVarDescriptor)?((TagVarDescriptor)pd).getType():((VarDescriptor)pd) .getType(); if (tpd.getArrayCount()!=1) continue; if (!tpd.getSymbol().equals("String")) continue; if (!md.getModifiers().isStatic()) throw new Error("Error: Non static main"); return md; } throw new Error(cd+" has no main"); } public void createFullTable() { subclasstable=new Hashtable(); Iterator classit=state.getClassSymbolTable().getDescriptorsIterator(); while(classit.hasNext()) { ClassDescriptor cd=(ClassDescriptor)classit.next(); ClassDescriptor tmp=cd.getSuperDesc(); while(tmp!=null) { if (!subclasstable.containsKey(tmp)) subclasstable.put(tmp,new HashSet()); HashSet hs=(HashSet)subclasstable.get(tmp); hs.add(cd); tmp=tmp.getSuperDesc(); } } } public Set getSubClasses(ClassDescriptor cd) { return (Set)subclasstable.get(cd); } public ClassDescriptor getSuper(ClassDescriptor cd) { return (ClassDescriptor)supertable.get(cd); } public boolean isCastable(TypeDescriptor original, TypeDescriptor casttype) { if (original.isChar()&& (casttype.isByte()|| casttype.isShort())) return true; if (casttype.isChar()&& (original.isByte()|| original.isShort()|| original.isInt()|| original.isLong()|| original.isFloat()|| original.isDouble())) return true; return false; } public boolean isSuperorType(TypeDescriptor possiblesuper, TypeDescriptor cd2) { //Matching type are always okay if (possiblesuper.equals(cd2)) return true; if ((possiblesuper.isTag() && !cd2.isTag())|| (!possiblesuper.isTag() && cd2.isTag())) return false; //Handle arrays if (cd2.isArray()||possiblesuper.isArray()) { // Object is super class of all arrays if (possiblesuper.getSymbol().equals(ObjectClass)&&!possiblesuper.isArray()) return true; // If we have the same dimensionality of arrays & both are classes, we can default to the normal test if (cd2.isClass()&&possiblesuper.isClass() &&(possiblesuper.getArrayCount()==cd2.getArrayCount())&& isSuperorType(possiblesuper.getClassDesc(), cd2.getClassDesc())) return true; // Object is superclass of all array classes if (possiblesuper.getSymbol().equals(ObjectClass)&&cd2.isClass() &&(possiblesuper.getArrayCount()