package ilog.language.design.types;

import ilog.language.design.kernel.Expression;
import ilog.language.design.kernel.Sanitizer;
import ilog.language.design.kernel.ParameterStack;

import java.util.HashMap;
import java.util.ArrayList;

/**
 * An object of this class is of the form <tt>SameType(expr)</tt> and stands for "<i>the type
 * of the expression <tt>expr</tt></i>." It is used as a temporary reference to the actual
 * type of an expression <tt>expr</tt> when that type is not known at the time of the
 * construction of a type expression; <i>e.g.</i>, because of dependencies with variables
 * that may not have been declared yet. Note that <tt>SameType(expr)</tt> is simply a type
 * <i>proto-</i>expression and not exactly a type <i>expression</i> because it does not
 * implement any of the methods of <a href="Type.html"><tt>Type</tt></a> except for
 * <tt>sanitizeTypeReferences(ParameterStack,ClassTypeHandle)</tt> which "evaluates" [<i>perhaps
 * "dereferences" might be a better word? -hak</i>] the type of <tt>expr</tt> in the context
 * provided (<i>i.e</i>, a <a href="../kernel/ParameterStack.html"><tt>ParameterStack</tt></a>
 * and a <a href="ClassTypeHandle.html"><tt>ClassTypeHandle</tt></a>), and returns the
 * corresponding actual type expression. This mechanism of forward referencing (a type, in
 * this case) is the same as that used for referencing an actual (global or local) symbol
 * expression from a name occurrence in an expression (using a <a href="../kernel/Dummy.html">
 * <tt>Dummy</tt></a>).
 *
 *  @version     Last modified on Tue Sep 10 15:55:14 2002 by paulin
 *  @version          modified on Fri Jul 19 15:18:28 2002 by pviry
 *  @author      <a href="mailto:pviry@ilog.fr">Patrick Viry</a>
 *  @copyright &copy; 2000-2002 <a href="http://www.ilog.fr/">ILOG, S.A.</a>
 */

public class SameType extends ProtoType
{
//     static int nextID = 1;
//     int ID = nextID++;
//     static boolean debug = false;

  Expression _expr;
  private static Sanitizer sanitizer = new Sanitizer();

  public SameType(Expression expr)
    {
        _expr = expr;
    }

  public Type sanitizeTypeReferences (ParameterStack parameters, ClassTypeHandle handle)
    {
      Type t = _expr.checkedType();
      Type result;

      if (t != null) {
        result = t.sanitizeTypeReferences();
      }
      else
        {
          _expr = _expr.sanitizeNames(parameters, handle);

          try {
              _expr.typeCheck(new TypeChecker());
          } catch (TypingErrorException error) {
              throw new java.lang.Error("SameType: cannot find a type for " + _expr./*toTypedString*/toString());
          }

          // ensure that the type is ground
          if(_expr.type().isPolymorphic())
              throw new java.lang.Error("NonGroundType"); //        ???? -hak
          
          result = _expr.type().sanitizeTypeReferences();


//           ArrayList a = new TypeChecker().allTypes(_expr);
//           if (a.size() == 1)
//             { // ensure that the type is ground
//               if (((Type)a.get(0)).isPolymorphic())
//                 throw new java.lang.Error("NonGroundType"); //        ???? -hak

// // don't set the checked type - very strange things happen
// // maybe problems related to sharing of expressions ?
// //               _expr.setCheckedType();
//               result = ((Type)a.get(0)).sanitizeTypeReferences();
//             }
//           else if(a.size() == 0) {
//               throw new java.lang.Error("SameType: cannot find a type for " + _expr./*toTypedString*/toString());
//           } else {
//               throw new java.lang.Error("SameType: found multiple types for " + _expr./*toTypedString*/toString() + " : " + a);
//           }
        }
      return result;
    }

  public String toString ()
    {
//         return "SameType#" + ID + "(" + _expr./*toTypedString*/toString() + ")";
        return "SameType(" + _expr./*toTypedString*/toString() + ")";
    }    

}

