/*
 * This file is part of the Cforall project
 *
 * $Id: ImplementationType.cc,v 1.4 2005/08/29 20:14:17 rcbilson Exp $
 *
 */

#include "ImplementationType.h"
#include "SynTree/Type.h"
#include "SynTree/Declaration.h"
#include "SynTree/Visitor.h"
#include "SymTab/Indexer.h"
#include "utility.h"


namespace SymTab {

class ImplementationType : public Visitor
{
public:
  ImplementationType( const SymTab::Indexer &indexer );
  
  Type *get_result() { return result; }

private:
  virtual void visit(VoidType *voidType);
  virtual void visit(BasicType *basicType);
  virtual void visit(PointerType *pointerType);
  virtual void visit(ArrayType *arrayType);
  virtual void visit(FunctionType *functionType);
  virtual void visit(StructInstType *aggregateUseType);
  virtual void visit(UnionInstType *aggregateUseType);
  virtual void visit(EnumInstType *aggregateUseType);
  virtual void visit(ContextInstType *aggregateUseType);
  virtual void visit(TypeInstType *aggregateUseType);
  virtual void visit(TupleType *tupleType);

  Type *result;			// synthesized
  const SymTab::Indexer &indexer;
};

Type*
implementationType( Type *type, const SymTab::Indexer& indexer )
{
  ImplementationType implementor( indexer );
  type->accept( implementor );
  if( implementor.get_result() == 0 ) {
    return type->clone();
  } else {
    return implementor.get_result();
  }
}

ImplementationType::ImplementationType( const SymTab::Indexer &indexer )
  : result( 0 ), indexer( indexer )
{
}

void 
ImplementationType::visit(VoidType *voidType)
{
}

void 
ImplementationType::visit(BasicType *basicType)
{
}

void 
ImplementationType::visit(PointerType *pointerType)
{
  PointerType *newType = pointerType->clone();
  newType->set_base( implementationType( pointerType->get_base(), indexer ) );
  result = newType;
}

void 
ImplementationType::visit(ArrayType *arrayType)
{
  ArrayType *newType = arrayType->clone();
  newType->set_base( implementationType( arrayType->get_base(), indexer ) );
  result = newType;
}

void 
ImplementationType::visit(FunctionType *functionType)
{
///   FunctionType *newType = functionType->clone();
///   for( std::list< DeclarationWithType* >::iterator i = newType->get_parameters().begin(); i != newType->get_parameters().end(); ++i ) {
///     i->set_type( implementationType( i->get_type(), indexer ) );
///   }
///   for( std::list< DeclarationWithType* >::iterator i = newType->get_parameters().begin(); i != newType->get_parameters().end(); ++i ) {
///     i->set_type( implementationType( i->get_type(), indexer ) );
///   }
}

void 
ImplementationType::visit(StructInstType *aggregateUseType)
{
}

void 
ImplementationType::visit(UnionInstType *aggregateUseType)
{
}

void 
ImplementationType::visit(EnumInstType *aggregateUseType)
{
}

void 
ImplementationType::visit(ContextInstType *aggregateUseType)
{
}

void 
ImplementationType::visit(TypeInstType *inst)
{
  NamedTypeDecl *typeDecl = indexer.lookupType( inst->get_name() );
  if( typeDecl && typeDecl->get_base() ) {
    Type *base = implementationType( typeDecl->get_base(), indexer );
    base->get_qualifiers() += inst->get_qualifiers();
    result = base;
  }
}

void 
ImplementationType::visit(TupleType *tupleType)
{
  TupleType *newType = new TupleType( Type::Qualifiers() );
  for( std::list< Type* >::iterator i = tupleType->get_types().begin(); i != tupleType->get_types().end(); ++i ) {
    Type *implType = implementationType( *i, indexer );
    implType->get_qualifiers() += tupleType->get_qualifiers();
    newType->get_types().push_back( implType );
  }
  result = newType;
}

} // namespace SymTab
