//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
// PLEASE DO NOT EDIT WITHOUT THE EXPLICIT CONSENT OF THE AUTHOR! \\
//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\

package ilog.language.design.kernel;

/**
 * @version     Last modified on Fri Oct 18 17:51:21 2002 by hak
 * @version          modified on Wed Jul 24 12:18:50 2002 by pviry
 * @author      <a href="mailto:hak@ilog.fr">Hassan A&iuml;t-Kaci</a>
 * @copyright   &copy; 2002 <a href="http://www.ilog.fr/">ILOG, S.A.</a>
 */

import ilog.language.design.types.*;

/**
 * This kernel expression is used on an expression and defined opaque type, such that
 * the expression's type is the definition of the defined opaque type.  The semantics
 * consists simply in "hiding" the expression's type into the opaque type;
 * <i>i.e.</i>, its value is that of the expression seen as having the opaque
 * type. The inverse operation, which consists in opening an expression's opaque type
 * into its definition type is <a href="OpenType.html"><tt>OpenType</tt></a>.
 */
public class HideType extends ProtoExpression
{
  private Expression _expression;
  private Type _opaqueType;

  public HideType (Expression expression, Type type)
    {
      _expression = expression;
      _opaqueType = type;
    }

  public final Expression expression ()
    {
      return _expression;
    }

  public final Type opaqueType ()
    {
      return _opaqueType;
    }

  public final int numberOfSubexpressions ()
    {
      return 1;
    }

  public final Expression subexpression (int n) throws NoSuchSubexpressionException
    {
      if (n == 0)
        return _expression;

      throw new NoSuchSubexpressionException(this,n);
    }

  public final void setCheckedType ()
    {
      if (isSetCheckedType()) return;
      setCheckedType(type().copy());
      _expression.setCheckedType();
    }

  public final Expression sanitizeNames (ParameterStack parameters, ClassTypeHandle handle)
    {
      _expression = _expression.sanitizeNames(parameters,handle);
      return this;
    }

  public final void sanitizeSorts (Enclosure enclosure)
    {
      _expression.sanitizeSorts(enclosure);
    }

  public final Expression shiftOffsets (int intShift, int realShift, int objectShift,
                                       int intDepth, int realDepth, int objectDepth)
    {
      _expression = _expression.shiftOffsets(intShift,realShift,objectShift,
                                             intDepth,realDepth,objectDepth);
      return this;
    }

  public final void typeCheck (TypeChecker typeChecker) throws TypingErrorException
    {
      if (typeCheckLocked()) return;

      if (_opaqueType.kind() != Type.DEFINED)
        typeChecker.error(locate(new TypingErrorException("can't hide into a non-opaque type: "
                                                          +_opaqueType)));

      _expression.typeCheck(((DefinedType)_opaqueType).definition(),typeChecker);
      typeChecker.unify(_type,_opaqueType,this);
    }

  public final void compile (Compiler compiler)
    {
      _expression.compile(compiler);
    }

  public final String toString ()
    {
      return _expression+" as "+_opaqueType;
    }

  // Added by PV
  public final String toTypedString ()
    {
        return typed(_expression.toTypedString()+" as "+_opaqueType);
    }
}

