import java.util.*;
import org.objectweb.asm.*;
/**
* A symbol-table representation of a type.
*/
public class Klass implements Scope{
//The type that this class directly extends,
//or null if it extends Object or isn't a reference type.
private Klass superKlass;
//The name of this Klass.
private String name;
//The symbol table containing all fields and methods.
//Methods in this symbol table always have a () on the
//end of their name to distinguish them from variables.
//eg.
//int f;
//is different and distinguishable from
//int f(){
// return 0;
//}
private Map symTable = new HashMap();
/**
* Constructs a new Klass with the given name
* @param name The name of the class that you are representing
*/
public Klass(String name){
this.name = name;
}
/**
* sets the superclass of this klass
* @param superKlass the super of this klass
*/
public void setSuperKlass(Klass superKlass){
this.superKlass = superKlass;
}
/**
* @return the symbol-table representation of this klass's superclass
*/
public Klass getSuperKlass(){
return this.superKlass;
}
@Override public String getScopeName(){
return name;
}
/** This is the highest scope level, so this method returns null. */
@Override public Scope getEnclosingScope(){return null;}
/**
* Define a symbol in the current scope
* @param sym The symbol that you want to define.
*/
@Override public void define(Symbol sym){
symTable.put(sym.getName(), sym);
}
/**
* Since all fields of a class are initialized to 0,
* false or null by default, this method should never be called.
*/
@Override public void initialize(Symbol sym){
assert false;
}
/**
* @param other the klass that may be this klass's ancestor
* @return true if this klass is a descendant(direct or indirect) of other, false otherwise
*/
public boolean isDescendantOf(Klass other){
if(this.superKlass==null&&other!=this){
return false;
}else if(other==this){
return true;
}else{
return this.superKlass.isDescendantOf(other);
}
}
/**
* Searches this klass for a symbol with the given name.
* If no such symbol exists,
* returns getSuperKlass()==null? null : getSuperKlass().lookup(name)
* @param name The name of the symbol to search for
* @return the symbol with symbolName equal to name.
*/
@Override public Symbol lookup(String name){
Symbol symbol = null;
for(Klass klass = this; symbol==null&&klass!=null; klass=klass.getSuperKlass()){
symbol = klass.symTable.get(name);
}
return symbol;
}
/**
* Searches this klass for a symbol with the given name.
* If no such symbol exists, return null.
* @param name The name of the symbol to search for.
* @return the symbol with the given name, or null if no such symbol exists.
*/
@Override public Symbol lookupLocally(String name){
return symTable.get(name);
}
/**
* Since all field variables are intialized upon construction of an object,
* this method returns true if this.lookup(name)!=null
* and false otherwise.
* @param name The name of the symbol to search for.
* @return true if this klass contains the field with the given name.
*/
@Override public boolean hasBeenInitialized(String name){
return this.lookup(name)!=null;
}
/**
* This method should never be called.
* @return null
*/
@Override public Set getInitializedVariables(){
assert false;
return null;
}
/**
* @return The name of this klass
*/
public String toString(){
return name;
}
/**
* @return an asm Type representation of this class.
*/
public Type asAsmType(){
if(this.name.equals("int")){
return Type.INT_TYPE;
}else if(this.name.equals("boolean")){
return Type.BOOLEAN_TYPE;
}else if(this.name.equals("int[]")){
return Type.getType(int[].class);
}else{
return Type.getType("L" + this.name + ";");
}
}
}