/** Add a symbol to our scope */
  void add(Definition def) {
    // Check to see if we already have a definition
    Definition oldDef = (Definition) elements.get(def.getName());

    // If so, we'll create a MultiDef to hold them
    if (oldDef != null) {
      // If the symbol there so far was not a MultiDef
      if (!(oldDef instanceof MultiDef)) {
        // remove the old definition
        elements.remove(oldDef);

        // create a new MultiDef
        MultiDef newMulti = new MultiDef(def.getName(), oldDef);

        // add the old symbol to the MultiDef
        newMulti.addDef(oldDef);
        oldDef = newMulti;

        // add the MultiDef back into the scope
        elements.put(def.getName(), oldDef);
      }

      // We now have a multidef, so add the new symbol to it
      ((MultiDef) oldDef).addDef(def);
    }

    // Otherwise, just add the new symbol to the scope
    else {
      elements.put(def.getName(), def);
      def.setParentScope(this);
    }
  }
 /** Resolve referenced names */
 void resolveTypes(SymbolTable symbolTable) {
   symbolTable.pushScope(this); // push the current scope
   elements.resolveTypes(symbolTable); // resolve elements in this scope
   if (unresolvedStuff != null) { // resolve refs to other syms
     unresolvedStuff.resolveRefs(symbolTable);
     unresolvedStuff = null;
   }
   symbolTable.popScope(); // pop back out of the scope
   super.resolveTypes(symbolTable); // let superclass resolve if needed
 }
  /**
   * Lookup a method in the scope This is usually just a hashtable lookup, but if the element
   * returned is a MultiDef, we need to ask it to find the best match
   */
  Definition lookup(String name, int numParams) {
    // Try to find the name in our scope
    Definition d = (Definition) elements.get(name);

    // if we found multiple defs of the same name, ask the multidef
    //  to do the resolution for us.
    if (d instanceof MultiDef) return d.lookup(name, numParams);

    // if we got a method back, check to see that the params apply
    else if (d instanceof MethodDef)
      if (((MethodDef) d).getParamCount() == numParams) return d;
      else return null;
    else return d;
  }
 /** Return whether or not this scope actually contains any elements */
 boolean hasElements() {
   return !elements.isEmpty();
 }
 void reportElements(DefaultMutableTreeNode out) {
   if (elements != null) {
     elements.reportIndented(out, null);
   }
 }
 /** Write information about all the elements to the report */
 void reportElements(IndentingPrintWriter out) {
   if (elements != null) {
     elements.reportIndented(out, null);
     out.println();
   }
 }