/*******************************************************************************
 * Author : Sreenivasa R. Viswanadha <sreeni@metamata.com>
 * Modified version: there was a bug in TypeTable.
 * Modificatio made by: Ferenc Magyar <magyar@inf.u-szeged.hu>
 *			MTA-JATE Research Group on Artificial Intelligence
 *			11/20/97
 *
 * Mark Donszelmann
 *      - Added usingTable and methods
 *
 * @author Mark Donszelmann
 * @version $Id: Scope.java,v 1.1.1.1 2004/05/31 05:08:51 kuromaru Exp $
*******************************************************************************/
package org.freehep.jaco.rtti.cpp;

import java.util.Hashtable;

public class Scope
{
   /**
    * Name of the scope (set only for class/function scopes).
    */
   public String scopeName;

   /**
    * Indicates whether this is a class scope or not.
    */
   boolean type;     // Indicates if this is a type.

   /**
    * (partial) table of type symbols introduced in this scope.
    */
   Hashtable typeTable = new Hashtable();

    /*
     * stores namespace usage "A::B::C" by name "C"
     * the resulting namespace may be empty, as in under name "D" there is no namespace
     */
    Hashtable usingTable = new Hashtable();
  
   /**
    * Parent scope. (null if it is the global scope).
    */
   Scope parent;

   /**
    * Creates a scope object with a given name.
    */
   public Scope(String name, boolean isType, Scope p)
   {
      scopeName = name;
      type = isType;
      parent = p;
   }

   /**
    * Creates an unnamed scope (like for compound statements).
    */
   public Scope(Scope p)
   {
      type = false;
      parent = p;
   }

   /**
    * Inserts a name into the table to say that it is the name of a type.
    * There was a bug. The simple type declarartion override the existing type
    * definition.
    * Correction made: 11/20/97 by Ferenc Magyar <magyar@inf.u-szeged.hu>
    */
   public void putTypeName(String name)
   {
     if (typeTable.get(name)==null )
        typeTable.put(name, name);
   }

   /**
    * A type with a scope (class/struct/union).
    */
   public void putTypeName(String name, Scope sc)
   {
      typeTable.put(name, sc);
   }

   /** 
    * Checks if a given name is the name of a type in this scope.
    */
   public boolean isTypeName(String name)
   {
      return typeTable.get(name) != null;
   }

   public Scope getScope(String name)
   {
      Object sc = typeTable.get(name);

      if (sc instanceof Scope || sc instanceof ClassScope)
         return (Scope)sc;

      return null;
   }
   
    /**
     * Puts a using declaration into the usingTable. The key is
     * the className, while the value is the fullName
     * 
     * FIXME: if the className exists in the local table, this is an 
     * error but nothing special is done
     */
    public void putUsingName(String name) {
        int pos = name.lastIndexOf("::");
        if (pos == -1) {
            usingTable.put(name, name); 
        } else {
            usingTable.put(name.substring(pos+2), name);
        }
    }
   
    /**
     * looks up the name in this scope. If it does not exist,
     * the lookup is done in the usingTable. null is returned
     * if it also does not exist there
     */
    public String getName(String name) {
        if (isTypeName(name)) return name;
        return (String)usingTable.get(name);
    }
}
