// $Id: SymbolTable.java,v 1.1.1.1 1999/12/05 22:19:52 mpp Exp $

package IR2;

import java.util.*;

public class SymbolTable extends Hashtable implements Walkable {
  protected SymbolTable parent;
  protected RValue next_offset = new IntImmedExpr(0);

  public SymbolTable(SymbolTable p) {
    super();
    parent = p;
  }

  public SymbolTable get_parent() {
    return parent;
  }
  
  public RValue get_next_offset() {return next_offset;}
  public void set_next_offset(RValue o) {next_offset = o;}
  public void inc_next_offset(RValue o) {try {next_offset = new AddArithOpExpr(next_offset, o);} catch (SemanticTypeException e) {}}

  // Methods overridden from Hashtable to take the parent table into account.
  public boolean contains(Object value) {
	if (super.contains(value))
	  return true;
	if (parent != null)
	  return parent.contains(value);
	return false;
  }

  public boolean containsKey(Object key) {
	if (super.containsKey(key))
	  return true;
	if (parent != null)
	  return parent.containsKey(key);
	return false;
  }

  public Object get(Object key) {
	Object value = super.get(key);
	if (value != null)
	  return value;
	if (parent != null)
	  return parent.get(key);
	return null;
  }

  // A version of put which does not allow a second value with the same
  // key to be inserted.
  public synchronized Object put_unique(Object key, Object value) {
	Object result = super.put(key, value);

	if (result != null) {
	  super.put(key, result);
	}
	return result;
  }
  
  /* Walkable implementation. */
  public String node_name() {
	return "symbol_table";
  }
  public Enumeration neighbors() {
	return elements();
  }
    public String pretty_print(int indent, boolean recursive) {
	String output = new String();
	
	for (int i = 0; i < indent; i++) output += " ";
	if (recursive) {
	    indent += 2;
	    output += "(" + this.node_name() + "\n";
	    /* stuff - calls to prettyprints of internals of this node*/
	    for (Enumeration e = this.neighbors(); e.hasMoreElements();) {
		Walkable foo = (Walkable)e.nextElement();
		output += foo.pretty_print(indent, true);
	    }
	    for (int i = 0; i < indent; i++) output += " ";
	    output += ") /* "+ this.node_name() + " */\n";
	} else {
	    output += "(" + this.node_name() + ")\n";
	}
	return output;
    }
}
