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

package ilog.language.design.kernel;

/**
 * @version     Last modified on Fri Oct 18 17:50:02 2002 by hak
 * @version          modified on Wed Jul 24 12:17:49 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.*;

/**
 * This constructs enables the conversion from a (possibly mutidimensional) array to
 * a indexed map as long as the base type and the number of dimensions agree.
 */

public class ArrayToMap extends ProtoExpression 
{
  private Expression _array;
  private Expression _indexable;

  public ArrayToMap (Expression array, Expression indexable)
    {
      _array = array;
      _indexable = indexable;
    }  

  public final int numberOfSubexpressions ()
    {
      return 2;
    }

  public final Expression subexpression (int n) throws NoSuchSubexpressionException
    {
      switch (n)
        {
        case 0:
          return _array;
        case 1:
          return _indexable;
        }

      throw new NoSuchSubexpressionException(this,n);
    }

  public final Expression array ()
    {
      return _array;
    }

  public final Expression indexable ()
    {
      return _indexable;
    }

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

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

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

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

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

      TypeParameter baseType = new TypeParameter();
      ArrayType arrayType = new ArrayType(baseType,Type.INT());
      _array.typeCheck(arrayType,typeChecker);

//        Global indexable = Global.dummyIndexable();
//        indexable.typeCheck(typeChecker);
//        _indexable.typeCheck(indexable.typeRef(),typeChecker);

      _indexable.typeCheck(Global.dummyIndexable(),typeChecker);

      typeChecker.typeCheck(this,new ArrayType(baseType,_indexable.typeRef()));
    }
  
  public final void compile (Compiler compiler)
    { // compile the indexable first, then the array, then the 'ArrayToMap' instruction:

      _indexable.compile(compiler);
      _array.compile(compiler);

      switch (((ArrayType)_array.checkedType()).baseType().boxSort())
        {
        case Type.INT_SORT:
          compiler.generate(Instruction.ARRAY_TO_MAP_I);
          break;
        case Type.REAL_SORT:
          compiler.generate(Instruction.ARRAY_TO_MAP_R);
          break;
        default:
          compiler.generate(Instruction.ARRAY_TO_MAP_O);
        }
    }

  public final String toString ()
    {
      return "array2map" + "(" + _array + "," + _indexable + ")";
    }

  // Added by PV
  public final String toTypedString ()
    {
      return typed("array2map" + "(" + _array.toTypedString() + "," + _indexable.toTypedString() + ")");
    }
}
