//
// 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.
//
// ScrubTyVars.cc -- 
//
// Author           : Richard C. Bilson
// Created On       : Mon May 18 07:44:20 2015
// Last Modified By : Peter A. Buhr
// Last Modified On : Tue May 19 16:42:42 2015
// Update Count     : 2
//

#include <sstream>
#include <string>

#include "GenPoly.h"
#include "ScrubTyVars.h"

#include "SynTree/Mutator.h"
#include "SynTree/Type.h"
#include "SynTree/Expression.h"

namespace GenPoly {
	Type * ScrubTyVars::mutate( TypeInstType *typeInst ) {
		TyVarMap::const_iterator tyVar = tyVars.find( typeInst->get_name() );
		if ( tyVar != tyVars.end() ) {
			switch ( tyVar->second ) {
			  case TypeDecl::Any:
			  case TypeDecl::Dtype:
				{
					PointerType *ret = new PointerType( Type::Qualifiers(), new VoidType( typeInst->get_qualifiers() ) );
					delete typeInst;
					return ret;
				}
			  case TypeDecl::Ftype:
				delete typeInst;
				return new PointerType( Type::Qualifiers(), new FunctionType( Type::Qualifiers(), true ) );
			} // switch
		} // if
		return typeInst;
	}

	Type * ScrubTyVars::mutateAggregateType( Type *ty ) {
		if ( isPolyType( ty, tyVars ) ) {
			PointerType *ret = new PointerType( Type::Qualifiers(), new VoidType( ty->get_qualifiers() ) );
			delete ty;
			return ret;
		}
		return ty;
	}
	
	Type * ScrubTyVars::mutate( StructInstType *structInst ) {
		return mutateAggregateType( structInst );
	}

	Type * ScrubTyVars::mutate( UnionInstType *unionInst ) {
		return mutateAggregateType( unionInst );
	}

	Expression * ScrubTyVars::mutate( SizeofExpr *szeof ) {
		// sizeof( T ) => _sizeof_T parameter, which is the size of T
		if ( Type *polyType = isPolyType( szeof->get_type() ) ) {
			Expression *expr = new NameExpr( sizeofName( mangleType( polyType ) ) );
			return expr;
		} else {
			return Mutator::mutate( szeof );
		} // if
	}

	Expression * ScrubTyVars::mutate( AlignofExpr *algnof ) {
		// alignof( T ) => _alignof_T parameter, which is the alignment of T
		if ( Type *polyType = isPolyType( algnof->get_type() ) ) {
			Expression *expr = new NameExpr( alignofName( mangleType( polyType ) ) );
			return expr;
		} else {
			return Mutator::mutate( algnof );
		} // if
	}

	Type * ScrubTyVars::mutate( PointerType *pointer ) {
		if ( Type *polyType = isPolyType( pointer->get_base(), tyVars ) ) {
			Type *ret = polyType->acceptMutator( *this );
			ret->get_qualifiers() += pointer->get_qualifiers();
			pointer->set_base( 0 );
			delete pointer;
			return ret;
		}
		return Mutator::mutate( pointer );
	}
} // namespace GenPoly

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