//
// 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 : Peter A. Buhr
// Last Modified On : Wed Jul  6 18:16:26 2016
// Update Count     : 33
//

#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 "SynTree/Label.h"

#include "LabelGenerator.h"

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

		virtual CompoundStmt *mutate( CompoundStmt *cmpndStmt ) override;
		virtual Statement *mutate( WhileStmt *whileStmt ) override;
		virtual Statement *mutate( ForStmt *forStmt ) override;
		virtual Statement *mutate( BranchStmt *branchStmt ) throw ( SemanticError ) override;
		virtual Statement *mutate( CaseStmt *caseStmt ) override;
		virtual Statement *mutate( IfStmt *ifStmt ) override;
		virtual Statement *mutate( SwitchStmt *switchStmt ) override;
		virtual Statement *mutate( ChooseStmt *switchStmt ) override;

		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_controlStructure() ); }

			Statement *get_controlStructure() 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 > enclosingControlStructures;
		Label breakLabel;
		LabelGenerator *generator;

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

		template< typename IfClass >
		Statement *handleIfStmt( IfClass *switchStmt );

		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: //
