//
// Copyright (C) 1991 Texas Instruments Incorporated.
//
// Permission is granted to any individual or institution to use, copy, modify,
// and distribute this software, provided that this complete copyright and
// permission notice is maintained, intact, in all copies and supporting
// documentation.
//
// Texas Instruments Incorporated provides this software "as is" without
// express or implied warranty.
//
// Created: LGO 05/22/89 -- Initial design and implementation
// Updated: MBN 09/16/89 -- Added conditional exception handling
// Updated: LGO 11/24/89 -- Forward reference Properties,
//                          get and remove are no longer inline.
//
// The Symbol class  is publicly derived from the  Generic class and implements
// the notion of a symbol that has a  name with  an optional value and property
// list.   Symbols are interned in a  package, which is  merely a mechanism for
// establishing a name-space  where  by there  is only one  symbol with a given
// name in a given package. Packages are implemented as hash tables by the COOL
// Package class,  which  is a friend of the  Symbol class. Because  each named
// Symbol  is unique  within its own package,  they  can be used  as a "dynamic
// enumeration"  type and as run-time variables,  with the Package  acting as a
// symbol-table.
//
// In addition to dynamic run time symbols, the COOL defpackage extension makes
// it possible  to define constant pointers  to symbols at  compile-time.   The
// compile-time symbols are interned in the package with the Initialize_Package
// method   of  Package.   This allows  for   efficient   symbol   and  package
// manipulation and is  used extensively by  COOL to  implement  run time  type
// checking and type query.
//
// The Symbol class three protected data slots. The first is a character string
// that holds the symbol name. The second is a pointer to a Generic object that
// contains the optional symbol  value. The third  is a pointer to the property
// list  of the symbol that is  maintained  as a list  of  associations between
// symbols  and generic  values. There   is one  protected  constructor for the
// Symbol class that takes a character string  argument representing the symbol
// name  and  is used by the  Package::intern()  method. One public constructor
// that takes no arguments and merely initializes the slots of a Symbol is used
// to create arrays of constant symbols.
//
// Methods are provided to get and set the value of a Symbol, get the name of a
// Symbol, and get the property list  associated with a  Symbol. Methods to add
// and  remove  values from the property  list allow a Symbol  to  take on  new
// properties at runtime. Finally, the output operator is overloaded to provide
// a print capability for the Symbol class.
//

#ifndef SYMBOLH					// If no Symbol definition
#define SYMBOLH

#ifndef GEN_CLASSH				// If no Generic class defined
#include <cool/Gen_class.h>				// Include header file
#endif

typedef Generic* Symbol_GenericP;

#ifndef PROPERTIESH
class Association<Symbol*, Generic*>;		// Forward reference
#endif

#ifndef STREAMH
class Stream;
#endif

class Symbol : public Generic {			// Define the Symbol class
  friend class Package;				// Package class needs access
  
protected:
  const char* pname;				// Symbol name
  Generic* val;					// Symbol value
  Association<Symbol*, Generic*>* proplist;	// Property list
  inline Symbol (const char* name);		// Use Package::intern()

public:
  Symbol ();					// Used for constant symbol[]
  ~Symbol();					// Destructor
  Boolean get (const Symbol*, Symbol_GenericP&); // Lookup value
  void put (const Symbol*, Generic*);		// set plist value
  Boolean remove (const Symbol*);		// Remove value from plist
  inline const char* name () CONST;		// Accessor for pname
  inline Generic* value ();			// Accessor for value
  inline Generic* set (Generic*);		// Set new value
  inline Association<Symbol*, Generic*>* plist(); // Accessor for properties
  friend ostream& operator<< (ostream&, const Symbol*);// Print symbol  
  friend ostream& operator<< (ostream&, const Symbol&);// Print symbol  
};


// Symbol -- Protected constructor for Symbol class to be used by friend Package
//           class. User should create symbols by using Package::intern()
// Input:    Character string name
// Output:   None

inline Symbol::Symbol (const char* name) {
  pname = name;					// Initialize name string
  val = NULL;					// Set value pointer to NULL
  proplist = NULL;				// Set plist to NULL
}


// name -- Accessor to return symbol name
// Input:  None
// Output: Constant pointer to symbol name slot

inline const char* Symbol::name() CONST {
  return pname;					// Return symbol name
}


// value -- Accessor to return symbol value
// Input:   None
// Output:  Generic pointer to symbol value

inline Generic* Symbol::value() {
  return val;					// Return symbol value
}


// set -- Accessor to set the value of the symbol
// Input: Generic pointer to new value
// Output:Generic pointer to updated symbol value

inline Generic* Symbol::set(Generic* value) {
  return val = value;				// Set/return symbol value
}


// plist -- Accessor to Symbol property list
// Input:   None
// Output:  Pointer to symbol property list

inline Association<Symbol*, Generic*>* Symbol::plist() {
  return proplist;				// Return property list
}

#endif
