//
// 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 : Thu Mar 16 15:54:08 2017
// Update Count     : 4
//

#include "ImplementationType.h"

#include <list>                   // for list, _List_iterator, list<>::iterator

#include "SymTab/Indexer.h"       // for Indexer
#include "SynTree/Declaration.h"  // for NamedTypeDecl
#include "SynTree/Type.h"         // for TupleType, Type, ArrayType, Pointer...
#include "SynTree/Visitor.h"      // for Visitor


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);
		virtual void visit(ZeroType *zeroType);
		virtual void visit(OneType *oneType);

		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( __attribute__((unused)) VoidType *voidType ) {}
	void ImplementationType::visit( __attribute__((unused)) 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( __attribute__((unused)) FunctionType *functionType ) {}
	void ImplementationType::visit( __attribute__((unused)) StructInstType * aggregateUseType ) {}
	void ImplementationType::visit( __attribute__((unused)) UnionInstType * aggregateUseType ) {}
	void ImplementationType::visit( __attribute__((unused)) EnumInstType * aggregateUseType ) {}
	void ImplementationType::visit( __attribute__((unused)) 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) {
		std::list< Type * > types;
		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();
			types.push_back( implType );
		} // for
		result = new TupleType( Type::Qualifiers(), types );
	}

	void ImplementationType::visit( __attribute__((unused)) VarArgsType *varArgsType ) {}
	void ImplementationType::visit( __attribute__((unused)) ZeroType *zeroType ) {}
	void ImplementationType::visit( __attribute__((unused)) OneType *oneType ) {}
} // namespace SymTab

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