/* $Id$ 
 *
 * Visitor: base class for all visitors.
 *
 * Copyright (C) 2007-2009 FAUmachine Team <info@faumachine.org>.
 * This program is free software. You can redistribute it and/or modify it
 * under the terms of the GNU General Public License, either version 2 of
 * the License, or (at your option) any later version. See COPYING.
 */


#ifndef __VISITOR_HPP_INCLUDED
#define __VISITOR_HPP_INCLUDED

namespace ast {

/* cannot use includes here due to circular include problem, so
 * forward define all nodes.
 */
class AstNode;
class ElementAssociation;
class ConstInteger;
class ConstReal;
class ConstArray;
class Entity;
class SymbolDeclaration;
class ValDeclaration;
class SignalDeclaration;
class ConstantDeclaration;
class Expression;
class SeqStat;
class IfStat;
class NullStat;
class LoopStat;
class ForLoopStat;
class WhileLoopStat;
class NextStat;
class VarAssignStat;
class WaitStat;
class ExitStat;
class ConditionedStat;
class SigAssignStat;
class WaveFormElem;
class ReturnStat;
class ProcCallStat;
class AssertStat;
class VarDeclaration;
class DiscreteRange;
class CaseStat;
class CaseAlternative;
class Others;
class Architecture;
class AssociationElement;
class Callable;
class FunctionDeclaration;
class ProcedureDeclaration;
class CompInstStat;
class LibUnit;
class Package;
class PackageBody;
class Process;
class SubprogBody;
class CondalSigAssign;
class TypeDeclaration;
class EnumerationType;
class PhysicalType;
class PhysicalTypeUnit;
class RangeConstraintType;
class UnconstrainedArrayType;
class RecordType;
class RecordTypeElement;
class Aggregate;
class FunctionCall;
class Name;
class SubtypeIndication;
class Library;
class LibraryList;
class Subscript;
class Slice;
class TypeConversion;
class TemporaryName;
class SimpleName;
class AttributeName;
class SelectedName;
class PrefixedName;
class AttributeDeclaration;
class AttributeSpecification;
class AttributableDeclaration;
class ConcurrentStat;

//! Generic interface for AST vistitors.
/** This is an abstract base class for all AST visitors.
 */
class Visitor {
public:
	/* all non leaf nodes in the AST class hierarchy
         * (i.e. all nodes, that might get directly instantiated)
         * will get their visit method.
         */

	/** d'tor, not used in interface. */
	virtual ~Visitor() {}

	/** visit an ElementAssociation
         *  @param node node that gets visited.
         */
	virtual void visit(ElementAssociation &node) = 0;

	/** visit a ConstInteger
         *  @param node node that gets visited.
         */
	virtual void visit(ConstInteger &node) = 0;

	/** visit a ConstReal
         *  @param node node that gets visited.
         */
	virtual void visit(ConstReal &node) = 0;

	/** visit a ConstArray
         *  @param node node that gets visited.
         */
	virtual void visit(ConstArray &node) = 0;

	/** Visit an Entity declaration.
	 *  @param node Entity Declaration node that gets visited.
	 */
	virtual void visit(Entity &node) = 0;

	/** Visit an Signal declaration.
	 *  @param node SignalDeclaration node that gets visited.
	 */
	virtual void visit(SignalDeclaration &node) = 0;

	/** Visit an Constant declaration.
	 *  @param node ConstantDeclaration node that gets visited.
	 */
	virtual void visit(ConstantDeclaration &node) = 0;

	/** Visit an FunctionCall.
	 *  @param node FunctionCall node that gets visited.
	 */
	virtual void visit(FunctionCall &node) = 0;

	/** Visit an IfStat.
	 *  @param node IfStat node that gets visited.
	 */
	virtual void visit(IfStat &node) = 0;

	/** Visit a NullStat.
	 *  @param node NullStat node that gets visited.
	 */
	virtual void visit(NullStat &node) = 0;

	/** Visit a ForLoopStat
	 *  @param node ForLoopStat node that gets visited.
	 */
	virtual void visit(ForLoopStat &node) = 0;

	/** Visit a WhileLoopStat
	 *  @param node WhileLoopStat node that gets visited.
	 */
	virtual void visit(WhileLoopStat &node) = 0;

	/** Visit a NextStat
	 *  @param node NextStat node that gets visited.
	 */
	virtual void visit(NextStat &node) = 0;

	/** Visit a VarAssignStat
	 *  @param node VarAssignStat node that gets visited.
	 */
	virtual void visit(VarAssignStat &node) = 0;

	/** Visit a WaitStat
	 *  @param node WaitStat node that gets visited.
	 */
	virtual void visit(WaitStat &node) = 0;

	/** Visit a ExitStat
	 *  @param node ExitStat node that gets visited.
	 */
	virtual void visit(ExitStat &node) = 0;

	/** Visit a SigAssignStat
	 *  @param node SigAssignStat node that gets visited.
	 */
	virtual void visit(SigAssignStat &node) = 0;

	/** Visit a WaveFormElem
	 *  @param node WaveFormElem node that gets visited.
	 */
	virtual void visit(WaveFormElem &node) = 0;
	
	/** Visit a ReturnStat
	 *  @param node ReturnStat node that gets visited.
	 */
	virtual void visit(ReturnStat &node) = 0;

	/** Visit a ProcCallStat
	 *  @param node ProcCallStat node that gets visited.
	 */
	virtual void visit(ProcCallStat &node) = 0;

	/** Visit a AssertStat
	 *  @param node AssertStat node that gets visited.
	 */
	virtual void visit(AssertStat &node) = 0;

	/** Visit a VarDeclaration
	 *  @param node VarDeclaration node that gets visited.
	 */
	virtual void visit(VarDeclaration &node) = 0;
	
	/** Visit a DiscreteRange
	 *  @param node DiscreteRange node that gets visited.
	 */
	virtual void visit(DiscreteRange &node) = 0;

	/** Visit a CaseStat
	 *  @param node CaseStat node that gets visited.
	 */
	virtual void visit(CaseStat &node) = 0;

	/** Visit a CaseAlternative
	 *  @param node CaseAlternative node that gets visited.
	 */
	virtual void visit(CaseAlternative &node) = 0;

	/** Visit a Others node.
	 *  @param node Others node that gets visited.
	 */
	virtual void visit(Others &node) = 0;

	/** Visit a Architecture node.
	 *  @param node Architecture node that gets visited.
	 */
	virtual void visit(Architecture &node) = 0;

	/** Visit a AssociationElement node.
	 *  @param node AssociationElement node that gets visited.
	 */
	virtual void visit(AssociationElement &node) = 0;

	/** Visit a FunctionDeclaration node.
	 *  @param node FunctionDeclaration node that gets visited.
	 */
	virtual void visit(FunctionDeclaration &node) = 0;

	/** Visit a ProcedureDeclaration node.
	 *  @param node ProcedureDeclaration node that gets visited.
	 */
	virtual void visit(ProcedureDeclaration &node) = 0;

	/** Visit a CompInstStat node.
	 *  @param node CompInstStat node that gets visited.
	 */
	virtual void visit(CompInstStat &node) = 0;

	/** Visit a Package node.
	 *  @param node Package node that gets visited.
	 */
	virtual void visit(Package &node) = 0;

	/** Visit a PackageBody node.
	 *  @param node PackageBody node that gets visited.
	 */
	virtual void visit(PackageBody &node) = 0;

	/** Visit a Process node.
	 *  @param node Process node that gets visited.
	 */
	virtual void visit(Process &node) = 0;

	/** Visit a SubprogBody node.
	 *  @param node SubprogBody node that gets visited.
	 */
	virtual void visit(SubprogBody &node) = 0;
	
	/** Visit a CondalSigAssign node.
	 *  @param node CondalSigAssign node that gets visited.
	 */
	virtual void visit(CondalSigAssign &node) = 0;

	/** Visit an EnumerationType node.
	 *  @param node EnumerationType node that gets visited.
	 */
	virtual void visit(EnumerationType &node) = 0;

	/** Visit an PhysicalType node.
	 *  @param node PhysicalType node that gets visited.
	 */
	virtual void visit(PhysicalType &node) = 0;

	/** Visit an PhysicalTypeUnit node.
	 *  @param node PhysicalTypeUnit node that gets visited.
	 */
	virtual void visit(PhysicalTypeUnit &node) = 0;

	/** Visit an RangeConstraintType node.
	 *  @param node RangeConstraintType node that gets visited.
	 */
	virtual void visit(RangeConstraintType &node) = 0;

	/** Visit an UnconstrainedArrayType node.
	 *  @param node UnconstrainedArrayType node that gets visited.
	 */
	virtual void visit(UnconstrainedArrayType &node) = 0;

	/** Visit an RecordType node.
	 *  @param node RecordType node that gets visited.
	 */
	virtual void visit(RecordType &node) = 0;

	/** Visit an RecordTypeElement node.
	 *  @param node RecordTypeElement node that gets visited.
	 */
	virtual void visit(RecordTypeElement &node) = 0;

	/** Visit an Aggregate node.
	 *  @param node Aggregate node that gets visited.
	 */
	virtual void visit(Aggregate &node) = 0;

	/** Visit a SubtypeIndication node.
	 *  @param node SubtypeIndication node that gets visited.
	 */
	virtual void visit(SubtypeIndication &node) = 0;

	/** Visit a Library node.
	 *  @param node Library node that gets visited.
	 */
	virtual void visit(Library& node) = 0;

	/** Visit a LibraryList node.
	 *  @param node LibraryList node that gets visited.
	 */
	virtual void visit(LibraryList& node) = 0;

	/** Visit a Subscript node.
	 *  @param node Subscript node that gets visited.
	 */
	virtual void visit(Subscript& node) = 0;

	/** Visit a Slice node.
	 *  @param node Slice node that gets visited.
	 */
	virtual void visit(Slice& node) = 0;

	/** Visit a TypeConversion node.
	 *  @param node TypeConversion node that gets visited.
	 */
	virtual void visit(TypeConversion &node) = 0;

	/** Visit a SimpleName node.
	 *  @param node TemporaryName node that gets visited.
	 */
	virtual void visit(SimpleName &node) = 0;

	/** Visit a TemporaryName node.
	 *  @param node TemporaryName node that gets visited.
	 */
	virtual void visit(TemporaryName &node) = 0;

	/** Visit an AttributeName node.
	 *  @param node AttributeName node that gets visited.
	 */
	virtual void visit(AttributeName &node) = 0;

	/** Visit a SelectedName node.
	 *  @param node SelectedName node that gets visited.
	 */
	virtual void visit(SelectedName &node) = 0;

	/** Visit an AttributeDeclaration node.
	 *  @param node AttributeDeclaration node that gets visited.
	 */
	virtual void visit(AttributeDeclaration &node) = 0;

	/** Visit an AttributeSpecification node.
	 *  @param node AttributeSpecification node that gets visited.
	 */
	virtual void visit(AttributeSpecification &node) = 0;

protected:
	//! Process a generic AstNode.
        /** This function will get called for each AstNode
         *  that gets visited.
         *
         *  @param node AstNode
         */
	virtual void process(AstNode &node) {}

	//! Process a generic ValDeclaration.
        /** This function will get called for each ValDeclaration (or class 
         *  derived from ValDeclaration) that gets visited.
         *
         *  @param node ValDeclaration instance.
         */
	virtual void process(ValDeclaration &node) {}

	//! Process a generic SymbolDeclaration.
        /** This function will get called for each SymbolDeclaration (or class
         *  derived from SymbolDeclaration) that gets visited.
         *
         *  @param node SymbolDeclaration instance.
         */
	virtual void process(SymbolDeclaration &node) {}

	//! Process a generic Expression.
        /** This function will get called for each Expression (or class
         *  derived from Expression) that gets visited.
         *
         *  @param node Expression instance.
         */
	virtual void process(Expression &node) {}

	//! Process a generic SeqStat.
        /** This function will get called for each SeqStat (or class
         *  derived from SeqStat) that gets visited.
         *
         *  @param node SeqStat instance.
         */
	virtual void process(SeqStat &node) {}

	//! Process a generic LoopStat.
        /** This function will get called for each LoopStat (or class
         *  derived from LoopStat) that gets visited.
         *
         *  @param node LoopStat instance.
         */
	virtual void process(LoopStat &node) {}

	//! Process a generic ConditionedStat.
        /** This function will get called for each ConditionedStat (or class
         *  derived from ConditionedStat) that gets visited.
         *
         *  @param node ConditionedStat instance.
         */
	virtual void process(ConditionedStat &node) {}

	//! Process a generic Callable.
        /** This function will get called for each Callable (or class
         *  derived from Callable) that gets visited.
         *
         *  @param node Callable instance.
         */
	virtual void process(Callable &node) {}

	//! Process a generic LibUnit.
        /** This function will get called for each LibUnit (or class
         *  derived from LibUnit) that gets visited.
         *
         *  @param node LibUnit instance.
         */
	virtual void process(LibUnit &node) {}

	//! Process a generic TypeDeclaration.
        /** This function will get called for each TypeDeclaration (or class
         *  derived from TypeDeclaration) that gets visited.
         *
         *  @param node TypeDeclaration instance.
         */
	virtual void process(TypeDeclaration &node) {}

	//! Process a generic PrefixedName.
        /** This function will get called for each PrefixedName (or class
         *  derived from PrefixedName) that gets visited.
         *
         *  @param node PrefixedName instance.
         */
	virtual void process(PrefixedName &node) {}

	//! Process a generic Name.
        /** This function will get called for each Name (or class
         *  derived from Name) that gets visited.
         *
         *  @param node Name instance.
         */
	virtual void process(Name &node) {}

	//! Process a AttributableDeclaration.
        /** This function will get called for each AttributableDeclaration 
	 *  (or class derived from it) that gets visited.
         *
         *  @param node AttributableDeclaration instance.
         */
	virtual void process(AttributableDeclaration &node) {}

	//! traverse a list of AST nodes.
	/** This template function traverses a list of AST nodes.
	  * You can only instantiate this with a T=std::list<AstNode> (or
	  * list's of classes derived from AstNodes.
	  * @param l list of AST nodes that should get traversed.
	  */
	template <typename T>
	void listTraverse(const T &l);

	//! traverse a list of AST nodes, eventually deleting a node.
	/** This template function traverses a list of AST nodes.
	  * You can only instantiate this with a T=std::list<AstNode> (or
	  * list's of classes derived from AstNodes.)
	  * @param l list of AST nodes that should get traversed.
	  * @param deleteFlag after a node has been visited, deleteFlag will
	  *        be checked and if it is true, the last visited node
	  *        will get deleted from the list and deleteFlag gets
	  *        reset to false.
	  */
	template <typename T>
	void listTraverse(T &l, bool &deleteFlag);

	//! traverse a list of AST nodes, eventually replacing a node.
	/** This template function traverses a list of AST nodes.
	 *  If replaceFlag is true, the current traversed item is 
	 *  replaced by the contents of replace.
	 *  @param l std::list to traverse
	 *  @param replaceFlag if set to true, the current node
	 *         will get replaced with replace. Will be set to
	 *         false after node has been replaced.
	 *  @param replace list with nodes to replace the current
	 *         node. Will get cleared after the node has
	 *         been replaced.
	 */
	template <typename T>
	void listTraverse(T &l, bool &replaceFlag, T &replace);

	//! traverse a list of AST nodes, eventually inserting a node.
	/** This template function traverses a list of AST nodes.
	 *  The nodes in insert will be inserted before the
	 *  last traversed node, and insert will be cleared.
	 *  @param l list to traverse
	 *  @param insert list to insert.
	 */
	template <typename T>
	void listTraverse(T &l, T &insert);
};

}; /* namespace ast */

// template definitions
#include "frontend/visitor/Visitor.tpp"

#endif /* __AST_VISITOR_HPP_INCLUDED */
