#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 ( doAll || 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 ) );
	    }
	}
	return typeInst;
    }

    Expression * ScrubTyVars::mutate( SizeofExpr *szeof ) {
	// sizeof( T ) => T parameter, which is the size of T
	if ( TypeInstType *typeInst = dynamic_cast< TypeInstType * >( szeof->get_type() ) ) {
	    Expression *expr = new NameExpr( typeInst->get_name() );
	    return expr;
	} else {
	    return Mutator::mutate( szeof );
	}
    }

    Type * ScrubTyVars::mutate( PointerType *pointer ) {
	if ( TypeInstType *typeInst = dynamic_cast< TypeInstType * >( pointer->get_base() ) ) {
	    if ( doAll || tyVars.find( typeInst->get_name() ) != tyVars.end() ) {
		Type *ret = mutate( typeInst );
		ret->get_qualifiers() += pointer->get_qualifiers();
		pointer->set_base( 0 );
		delete pointer;
		return ret;
	    }
	}
	return Mutator::mutate( pointer );
    }
} // namespace GenPoly
