#include "ResolveTypeof.h"
#include "Alternative.h"
#include "AlternativeFinder.h"
#include "Resolver.h"
#include "TypeEnvironment.h"
#include "SynTree/Expression.h"
#include "SynTree/Type.h"

namespace ResolvExpr {
    namespace {
#if 0
	void
	printAlts( const AltList &list, std::ostream &os, int indent = 0 )
	{
	    for( AltList::const_iterator i = list.begin(); i != list.end(); ++i ) {
		i->print( os, indent );
		os << std::endl;
	    }
	}
#endif
    }

    class ResolveTypeof : public Mutator {
      public:
	ResolveTypeof( const SymTab::Indexer &indexer ) : indexer( indexer ) {}
	Type *mutate( TypeofType *typeofType );

      private:
	const SymTab::Indexer &indexer;
    };

    Type *resolveTypeof( Type *type, const SymTab::Indexer &indexer ) {
	ResolveTypeof mutator( indexer );
	return type->acceptMutator( mutator );
    }

    Type *ResolveTypeof::mutate( TypeofType *typeofType ) {
#if 0
	std::cout << "resolving typeof: ";
	typeofType->print( std::cout );
	std::cout << std::endl;
#endif
	if ( typeofType->get_expr() ) {
	    Expression *newExpr = resolveInVoidContext( typeofType->get_expr(), indexer );
	    assert( newExpr->get_results().size() > 0 );
	    Type *newType;
	    if ( newExpr->get_results().size() > 1 ) {
		TupleType *tupleType = new TupleType( Type::Qualifiers() );
		cloneAll( newExpr->get_results(), tupleType->get_types() );
		newType = tupleType;
	    } else {
		newType = newExpr->get_results().front()->clone();
	    }
	    delete typeofType;
	    return newType;
	}
	return typeofType;
    }

} // namespace ResolvExpr
