package ilog.language.design.types;

/**
 * @version     Last modified on Sat Sep 21 03:40:47 2002 by hak
 * @version          modified on Wed Jun 12 19:40:11 2002 by pviry
 * @author      <a href="mailto:hak@ilog.fr">Hassan A&iuml;t-Kaci</a>
 * @copyright   &copy; 2000-2002 <a href="http://www.ilog.fr/">ILOG, S.A.</a>
 */

import java.util.HashMap;
import ilog.language.design.kernel.ParameterStack;

public class TypeConstant extends NamedType
{
  protected byte _sort = OBJECT_SORT;
  protected boolean _isBoxedType = true;

  /**
   * <a name="shadowType"></a>
   * This is used in <a href="../kernel/Homomorphism.html#typeChecking">
   * <tt>Homomorphism</tt></a> for typing irregular monoid operations in
   * the absence of a real mechanism for subtyping.
   */
  private Type _shadowType = this;

  public final Type shadowType ()
    {
      return _shadowType;
    }

  public final void setShadowType (Type type)
    {
      _shadowType = type;
    }

  public TypeConstant (String name)
    {
      _name = name;
    }

  public TypeConstant (String name, byte sort)
    {
      this(name);
      _sort = sort;
    }

  public TypeConstant (String name, byte sort, boolean isBoxedType)
    {
      this(name, sort);
      _isBoxedType = isBoxedType;
    }

  public final byte kind ()
    {
      return CONSTANT;
    }

  public final byte sort ()
    {
      return _sort;
    }

  public final boolean isBoxedType ()
    {
      return _isBoxedType;
    }

  public final void unify (Type type, TypeChecker typeChecker) throws FailedUnificationException
    {
      if ((type = type.value()) == this)
        return;

      switch (type.kind())
        {
        case BOXABLE:
          unify(((BoxableTypeConstant)type).type(),typeChecker);
          return;
        case PARAMETER:
          type.unify(this,typeChecker);
          return;
        default:
          typeChecker.error(new TypeClashException(this,type));
        }
    }

  public final boolean unify (Type type)
    {
      if ((type = type.findValue()) == this)
        return true;

      switch (type.kind())
        {
        case PARAMETER:
          ((TypeParameter)type).bind(this);
          return true;
        case BOXABLE:
          return unify(((BoxableTypeConstant)type).type());
        }

      return false;
    }

  /**
   * Returns true iff this type constant and the specified type
   * are identical objects (<i>i.e.</i>, same pointers).
   */
  public final boolean isEqualTo (Type type)
    {
      return (type == this);
    }

  /**
   * Returns true iff this type constant and the specified type
   * are identical objects (<i>i.e.</i>, same pointers).
   */
  public final boolean isEqualTo (Type type, HashMap parameters)
    {
      return isEqualTo(type);
    }

    public Type sanitizeTypeReferences(ParameterStack parameters, ClassTypeHandle handle)
    {
        return this;
    }

  final public String toString ()
    {
      return _name;
    }

}
