//
// Cforall Version 1.0.0 Copyright (C) 2015 University of Waterloo
//
// The contents of this file are covered under the licence agreement in the
// file "LICENCE" distributed with Cforall.
//
// ImplementationType.cc -- 
//
// Author           : Richard C. Bilson
// Created On       : Sun May 17 21:32:01 2015
// Last Modified By : Peter A. Buhr
// Last Modified On : Wed Mar  2 17:31:20 2016
// Update Count     : 3
//

#include "ImplementationType.h"
#include "SynTree/Type.h"
#include "SynTree/Declaration.h"
#include "SynTree/Visitor.h"
#include "SymTab/Indexer.h"
#include "Common/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(TraitInstType *aggregateUseType);
		virtual void visit(TypeInstType *aggregateUseType);
		virtual void visit(TupleType *tupleType);
		virtual void visit(VarArgsType *varArgsType);

		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();
		} // if
	}

	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(TraitInstType *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;
		} // if
	}

	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 );
		} // for
		result = newType;
	}

	void ImplementationType::visit(VarArgsType *varArgsType) {
	}
} // namespace SymTab

// Local Variables: //
// tab-width: 4 //
// mode: c++ //
// compile-command: "make install" //
// End: //
