package code.type;

import java.util.Vector;
import java.util.Hashtable;
import code.stuff.Tracer;
import code.stuff.Logger;
import static code.type.PredefinedTypes.*;
import code.type.visitor.ToStringTypeVisitor;

// This class holds the actual type

// The latest modification allows this class to hold all types with a 
// given set of argument types.
// There is only one function with a given set of argument types,
// since functions are nameless.
// There can be multiple TCAs with different names and the same argument types.
// Each one is stored here separately, by name.
class TypeHolder extends Holder
{

  private static ToStringTypeVisitor stringer = new ToStringTypeVisitor();

  FunctionType ft = null;      // store the function type here

  // Store the TCAs here, mapped by name
  Hashtable<String, TypeConstructorApplication> tcas
    = new Hashtable<String, TypeConstructorApplication>();

  TypeHolder() {}


  TypeExpression getType(TypeConstructor tType, String name, int ii, TypeExpression ... args)
  {
    assert ii >= args.length;

    TypeExpression te = null;       // return value

    if (tType == functionType)
    {
      if (ft == null)               // create new function type
      {
        ft = new FunctionType(args[0], args[1]);
        if (Tracer.typecache)
          Logger.logln("NEW Function: " + ft.accept(stringer, null));
      }
      te = ft;
    }
    else if (tType == tcaType)
    {
      TypeConstructorApplication tca = null;

      if ((tca = tcas.get(name)) == null)    // create new TCA
      {
        tca = new TypeConstructorApplication(name, args);
        tcas.put(name, tca);
        if (Tracer.typecache)
          Logger.logln("NEW Application: " + tca.accept(stringer, null));
      }
      te = tca;
    }
    return te;
  }

  // Add type expressions contained herein to list of TEs
  void iterate(Vector<TypeExpression> tExprs)
  {
    if (ft != null)
      tExprs.add(ft);
    for (TypeConstructorApplication tca : tcas.values())
      tExprs.add(tca);
  }
}


