#ifndef LABEL_FIXER_H
#define LABEL_FIXER_H

#include "utility.h"

#include "SynTree/SynTree.h"
#include "SynTree/Visitor.h"

#include "LabelGenerator.h"

#include <map>

namespace ControlStruct {
    class LabelFixer : public Visitor {
	typedef Visitor Parent;
      public:
	LabelFixer( LabelGenerator *gen = 0 );

	std::map < Label, Statement * > *resolveJumps() throw ( SemanticError );

	// Declarations
	virtual void visit( FunctionDecl *functionDecl );

	// Statements
	void visit( Statement *stmt );

	virtual void visit( CompoundStmt *stmt ) { visit( (Statement *)stmt ); return Parent::visit( stmt ); }
	virtual void visit( NullStmt *stmt ) { visit( (Statement *)stmt ); return Parent::visit( stmt ); }
	virtual void visit( ExprStmt *stmt ) { visit( (Statement *)stmt ); return Parent::visit( stmt ); }
	virtual void visit( IfStmt *stmt ) { visit( (Statement *)stmt ); return Parent::visit( stmt ); }
	virtual void visit( WhileStmt *stmt ) { visit( (Statement *)stmt ); return Parent::visit( stmt ); }
	virtual void visit( ForStmt *stmt ) { visit( (Statement *)stmt ); return Parent::visit( stmt ); }
	virtual void visit( SwitchStmt *stmt ) { visit( (Statement *)stmt ); return Parent::visit( stmt ); }
	virtual void visit( ChooseStmt *stmt ) { visit( (Statement *)stmt ); return Parent::visit( stmt ); }
	virtual void visit( FallthruStmt *stmt ) { visit( (Statement *)stmt ); return Parent::visit( stmt ); }
	virtual void visit( CaseStmt *stmt ) { visit( (Statement *)stmt ); return Parent::visit( stmt ); }
	virtual void visit( ReturnStmt *stmt ) { visit( (Statement *)stmt ); return Parent::visit( stmt ); }
	virtual void visit( TryStmt *stmt ) { visit( (Statement *)stmt ); return Parent::visit( stmt ); }
	virtual void visit( CatchStmt *stmt ) { visit( (Statement *)stmt ); return Parent::visit( stmt ); }
	virtual void visit( DeclStmt *stmt ) { visit( (Statement *)stmt ); return Parent::visit( stmt ); }
	virtual void visit( BranchStmt *branchStmt );

	Label setLabelsDef( std::list< Label > &, Statement *definition );
	Label setLabelsUsg( Label, Statement *usage = 0 );

      private:
	class Entry {
	  public:
	    Entry( Statement *to = 0, Statement *from = 0 );
	    bool used() { return ( usage.empty() ); }
	    bool defined() { return ( definition != 0 ); }
	    bool insideLoop();

	    Label get_label() const { return label; }
	    Statement *get_definition() const { return definition; }
	    std::list< Statement *> &get_uses() { return usage; }

	    void add_use ( Statement *use ) { usage.push_back( use ); }
	    void add_uses ( std::list<Statement *> uses ) { usage.insert( usage.end(), uses.begin(), uses.end() ); }
	    void set_definition( Statement *def ) { definition = def; }

	    void set_label( Label lab ) { label = lab; }
	    Label gset_label() const { return label; }
	  private:
	    Label label;  
	    Statement *definition;
	    std::list<Statement *> usage;
	};
              
	std::map < Label, Entry *> labelTable;
	LabelGenerator *generator;
    };
} // namespace ControlStruct

#endif // LABEL_FIXER_H

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