#include "SynTree/Declaration.h"
#include "SynTree/Expression.h"
#include "SynTree/Type.h"
#include "ResolvExpr/AlternativeFinder.h"

#include <vector>
#include <string>
#include <list>
#include <map>

namespace Designators {
  class Matcher;
  class GenSym;

  template < class OutputIterator >  bool extractNames( std::list< DeclarationWithType * > &, OutputIterator );
  template < class OutputIterator >  bool extractNames( Expression *, OutputIterator, Matcher );
  void check_alternative( FunctionType *, ResolvExpr::AltList & );
  ObjectDecl *extractTupleV( Matcher, TupleExpr *names );
  bool fixDesignations( ResolvExpr::AlternativeFinder &finder, Expression *designation );
  DeclarationWithType *gensym( GenSym &, DeclarationWithType * );

  class GenSym {
  public:
    GenSym( std::string prefix = "" ) : gensym_count(0) {}
    GenSym( GenSym &other ) { gensym_count = other.gensym_count; }

//    std::string get_symbol() { }
  private:
    std::string prefix;
    int gensym_count;
  };

  // template< typename Key >
  class Matcher {
  public:
    typedef std::vector< std::string >::iterator iterator;

    Matcher( const std::list< DeclarationWithType * > & );
    ~Matcher() {}

    template< class OutputIterator > bool get_reorderedCall( OutputIterator );
    template< class InputIterator >  bool add(InputIterator, InputIterator, ResolvExpr::Alternative &);
    template< class InputIterator, class OutputIterator >  bool slice(InputIterator begin, InputIterator end, OutputIterator );
    //std::vector<std::string> &get_order() const { return order; }

    iterator begin() { return order.begin(); }
    iterator end() { return order.end(); }

    //Expression *operator[]( int idx ) { return table( order[ idx ] ); }
  private:
    std::map< std::string, int > table;
    std::vector<std::string> order;
    std::vector<DeclarationWithType *> declarations;
    std::vector<ResolvExpr::Alternative *> alternatives;
  };
  //  void pruneAlternatives( Expression *expr, ResolvExpr::AlternativeFinder & );

} // namespace Designators

/*
  Local Variables:
  mode: c++
  End:
*/
