#ifndef MLE_MUTATOR_H
#define MLE_MUTATOR_H

#include <map>
#include <list>

#include "utility.h"
#include "SynTree/SynTree.h"
#include "SynTree/Mutator.h"

#include "LabelGenerator.h"

namespace ControlStruct {
    class MLEMutator : public Mutator {
	class Entry;
      public:
	MLEMutator( std::map<Label, Statement *> *t, LabelGenerator *gen = 0 ) : targetTable( t ), breakLabel(std::string("")), generator( gen ) {}
	~MLEMutator();

	CompoundStmt *mutate( CompoundStmt *cmpndStmt );
	Statement *mutate( WhileStmt *whileStmt );
	Statement *mutate( ForStmt *forStmt );
	Statement *mutate( BranchStmt *branchStmt ) throw ( SemanticError );

	Statement *mutate( SwitchStmt *switchStmt );
	Statement *mutate( ChooseStmt *switchStmt );

	Statement *mutateLoop( Statement *bodyLoop, Entry &e );

	Label &get_breakLabel() { return breakLabel; }
	void set_breakLabel( Label newValue ) { breakLabel = newValue; }
      private:
	class Entry {
	  public:
	    explicit Entry( Statement *_loop = 0, Label _contExit = Label(""), Label _breakExit = Label("") ) :
		loop( _loop ), contExit( _contExit ), breakExit( _breakExit ), contExitUsed( false ), breakExitUsed( false ) {}

	    bool operator==( const Statement *stmt ) { return ( loop == stmt ); }
	    bool operator!=( const Statement *stmt ) { return ( loop != stmt ); }

	    bool operator==( const Entry &other ) { return ( loop == other.get_loop() ); }

	    Statement *get_loop() const { return loop; }

	    Label get_contExit() const { return contExit; }
	    void set_contExit( Label );

	    Label get_breakExit() const { return breakExit; }
	    void set_breakExit( Label );

	  private:
	    Statement *loop;
	    Label contExit, breakExit;
	  public: // hack, provide proper [sg]etters
	    bool contExitUsed, breakExitUsed;
	};

	std::map< Label, Statement * > *targetTable;
	std::list< Entry > enclosingBlocks, enclosingLoops, enclosingSwitches;
	Label breakLabel;
	LabelGenerator *generator;
    };

} // namespace ControlStruct

#endif

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