//
// 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.
//
// MLEMutator.h -- 
//
// Author           : Rodolfo G. Esteves
// Created On       : Mon May 18 07:44:20 2015
// Last Modified By : Rob Schluntz
// Last Modified On : Wed Jun 03 15:06:36 2015
// Update Count     : 25
//

#ifndef MLE_MUTATOR_H
#define MLE_MUTATOR_H

#include <map>
#include <list>

#include "Common/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( CaseStmt *caseStmt ); 
		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, Label _breakExit, Label _contExit = Label("") ) :
				loop( _loop ), breakExit( _breakExit ), contExit( _contExit ), breakUsed(false), contUsed(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 useContExit() { contUsed = true; return contExit; }
			Label useBreakExit() { breakUsed = true; return breakExit; }

			bool isContUsed() const { return contUsed; }
			bool isBreakUsed() const { return breakUsed; }

		  private:
			Statement *loop;
			Label breakExit, contExit;
			bool breakUsed, contUsed;
		};

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

		template< typename LoopClass >
		Statement *handleLoopStmt( LoopClass *loopStmt );

		template< typename SwitchClass > 
		Statement *handleSwitchStmt( SwitchClass *switchStmt );

		void fixBlock( std::list< Statement * > &kids );
	};
} // namespace ControlStruct

#endif // MLE_MUTATOR_H

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