//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
// 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:33 2002 by hak
 * @version          modified on Wed Jul 24 12:18:52 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 ilog.language.design.types.*;
import ilog.language.design.base.*;

public class IfThenElse extends ProtoExpression
{
  private Expression _condition;
  private Expression _thenExpression;
  private Expression _elseExpression;

  public IfThenElse (Expression condition, Expression thenExpression, Expression elseExpression)
    {
      _condition = condition;
      _thenExpression = thenExpression;
      _elseExpression = elseExpression;
    }

  public final int numberOfSubexpressions ()
    {
      return 3;
    }

  public final Expression subexpression (int n) throws NoSuchSubexpressionException
    {
      switch (n)
        {
        case 0:
          return _condition;
        case 1:
          return _thenExpression;
        case 2:
          return _elseExpression;
        }

      throw new NoSuchSubexpressionException(this,n);
    }

  public final Expression sanitizeNames (ParameterStack parameters, ClassTypeHandle handle)
    {
      _condition = _condition.sanitizeNames(parameters, handle);
      _thenExpression = _thenExpression.sanitizeNames(parameters, handle);
      _elseExpression = _elseExpression.sanitizeNames(parameters, handle);

      return this;
    }

  public final void sanitizeSorts (Enclosure enclosure)
    {
      _condition.sanitizeSorts(enclosure);
      _thenExpression.sanitizeSorts(enclosure);
      _elseExpression.sanitizeSorts(enclosure);
    }

  public final Expression shiftOffsets (int intShift, int realShift, int objectShift,
                                        int intDepth, int realDepth, int objectDepth)
    {
      _condition = _condition.shiftOffsets(intShift,realShift,objectShift,
                                           intDepth,realDepth,objectDepth);

      _thenExpression = _thenExpression.shiftOffsets(intShift,realShift,objectShift,
                                                     intDepth,realDepth,objectDepth);

      _elseExpression = _elseExpression.shiftOffsets(intShift,realShift,objectShift,
                                                     intDepth,realDepth,objectDepth);

      return this;
    }

  public final void setCheckedType ()
    {
      if (isSetCheckedType()) return;
      setCheckedType(type().copy());
      _condition.setCheckedType();
      _thenExpression.setCheckedType();
      _elseExpression.setCheckedType();
    }

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

      _condition.typeCheck(Type.BOOLEAN(),typeChecker);
      _thenExpression.typeCheck(typeRef(),typeChecker);
      _elseExpression.typeCheck(typeRef(),typeChecker);
    }      

  public final void compile (Compiler compiler)
    {
      _condition.compile(compiler);
      if (_condition.checkedType().isBoxedType())
        compiler.generateUnwrapper(Type.INT_SORT);

      JumpOnFalse jof = new JumpOnFalse();
      compiler.generate(jof);

      _thenExpression.compile(compiler);

      Jump jmp = new Jump();
      compiler.generate(jmp);

      jof.setAddress(compiler.targetAddress());

      _elseExpression.compile(compiler);

      jmp.setAddress(compiler.targetAddress());
    }

  final public String toString ()
    {
      return "if " + _condition + " then " + _thenExpression + " else  " + _elseExpression;
    }

  // Added by PV
  final public String toTypedString ()
    {
        return typed("if " + _condition.toTypedString() + " then " + _thenExpression.toTypedString() + " else  " + _elseExpression.toTypedString());
    }
}
