package symtable;
import java.util.*;
import ast.node.*;
import exceptions.InternalException;
/**
* SymTable
* ....
* The symbol table also keeps a mapping of expression nodes to
* types because that information is needed elsewhere especially
* when looking up method call information.
*
* @author mstrout
*
*/
public class SymTable {
private final Scope mGlobalScope;
private final Stack<Scope> mScopeStack = new Stack();
private final HashMap<Node, String> mNodeStr = new HashMap<Node, String>();
private final HashMap<Node, Type> mExpType = new HashMap<Node, Type>();
private final HashMap<Node, STE> mNodeSTE = new HashMap<Node, STE>();
private final HashMap<Node, Integer> mExpReg = new HashMap();
private boolean debug = false;
private boolean verbose = false;
public SymTable() {
//Set up the Global Scope
mGlobalScope = new Scope(null);
mScopeStack.push(mGlobalScope);
}
/** Lookup a symbol in this symbol table.
* Starts looking in innermost scope and then
* look in enclosing scopes.
* Returns null if the symbol is not found.
*/
public STE lookup(String sym) {
Scope currentScope = (Scope)mScopeStack.peek();
return currentScope.lookup(sym);
}
/** Lookup a symbol in innermost scope only.
* return null if the symbol is not found
*/
public STE lookupInnermost(String sym) {
Scope currentScope = (Scope)mScopeStack.peek();
return currentScope.lookupInnermost(sym);
}
public ClassSTE lookupClass(String name) {
Scope currentScope = (Scope)mScopeStack.peek();
return currentScope.lookupClass(name);
}
/** When inserting an STE will just insert
* it into the scope at the top of the scope stack.
*/
public void insert(STE ste) {
Scope currentScope = (Scope)mScopeStack.peek();
if(verbose) System.out.println("InsertSTE -- " + ste.getName());
currentScope.insert(ste);
}
public void insertScope(ScopeSTE scope) {
insert(scope);
scope.setScope(new Scope((Scope)this.mScopeStack.peek()));
if(verbose) System.out.println("InsertScope -- " + scope.getName());
this.mScopeStack.push(scope.getScope());
}
/**
* Lookup the given method scope and make it the innermost
* scope. IOW make it the top of the scope stack.
*/
public void pushScope(String id) {
STE currentSTE = lookup(id);
if((currentSTE instanceof ScopeSTE)) {
ScopeSTE methodSTE = (ScopeSTE)currentSTE;
if(verbose) System.out.println("PushScope -- " + id);
mScopeStack.push(methodSTE.getScope());
}
else {
throw new InternalException("Unable to find method scope");
}
}
public void popScope() {
mScopeStack.pop();
if(verbose) System.out.println("PopScope");
}
public void setExpType(Node exp, Type t)
{
mExpType.put(exp, t);
if(debug) System.out.println("Type --> " + t.toString() );
}
public Type getExpType(Node exp)
{
return mExpType.get(exp);
}
public void setNodeId(Node node, String id)
{
mNodeStr.put(node, id);
}
public void setExpReg(Node node, int reg)
{
this.mExpReg.put(node, reg);
}
public Integer getExpReg(Node node)
{
return (Integer)this.mExpReg.get(node);
}
public void setNodeSTE(Node node, STE ste) {
mNodeSTE.put(node, ste);
if(debug) System.out.println("STE --> " + ste.getName());
}
public STE getNodeSTE(Node node) {
return (STE)this.mNodeSTE.get(node);
}
public HashMap<Node, String> getMap()
{
return mNodeStr;
}
}