/* $Id$ 
 *
 * Gather implicitly needed variables (e.g. drivers).
 *
 * Copyright (C) 2008-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 __GATHER_IMPLICITS_HPP_INCLUDED
#define __GATHER_IMPLICITS_HPP_INCLUDED

#include "frontend/visitor/TopDownVisitor.hpp"
#include <set>
#include <map>
#include "frontend/misc/Driver.hpp"

namespace ast {


//! gather drivers and formal parameters and register these to the processes
/** This visitor will gather all implicit defined entities and register 
 *  these to the process statements or callable's.
 *  It will pickup
 *  	- drivers of signals in a process.
 *  	- formal parameters of subprogram calls
 *
 *  Dependencies: NormalizeAssocs and probably a few more.
 */
class GatherImplicits : public TopDownVisitor {
public:
	//! dummy c'tor, initilize members.
	GatherImplicits();

private:
	/** Visit a SigAssignStat
	 *  @param node SigAssignStat node that get's visited.
	 */
	virtual void visit(SigAssignStat& node);

	/** Visit a VarAssignStat
	 *  @param node VarAssignStat node that get's visited.
	 */
	virtual void visit(VarAssignStat& node);

	/** visit a SimpleName
         *  @param node node that get's visited.
         */
	virtual void visit(SimpleName &node);

	/** visit a Process
         *  @param node node that get's visited.
         */
	virtual void visit(Process &node);

	/** Visit a FunctionCall.
	 *  @param node FunctionCall node that get's visited.
	 */
	virtual void visit(FunctionCall &node);

	/** Visit a ProcCallStat.
	 *  @param node ProcCallStat node that get's visited.
	 */
	virtual void visit(ProcCallStat &node);

	/** Visit a FunctionDeclaration node.
	 *  @param node FunctionDeclaration node that get's visited.
	 */
	virtual void visit(FunctionDeclaration &node);

	/** Visit a ProcedureDeclaration node.
	 *  @param node ProcedureDeclaration node that get's visited.
	 */
	virtual void visit(ProcedureDeclaration &node);

	/** Visit an Architecture node.
	 *  @param node Architecture node that get's visited.
	 */
	virtual void visit(Architecture &node);

	/** Visit a CompInstStat node.
	 *  @param node CompInstStat node that get's visited.
	 */
	virtual void visit(CompInstStat &node);

	/** process a function/procedure declaration.
	 *  @param node Callable node.
	 */
	void processCallable(Callable &node);

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

	/** pick up implicits (drivers, hidden formals) from 
	  * an AssociationElement with the corresponding 
	  * declaration.
	  * @param formalDecl the corresponsing declaration of the formal.
	  * @parma assoc AssociationElement to pick up.
	  */
	void 
	pickupImplicits(
		ValDeclaration &formalDecl, 
		AssociationElement &assoc);


	/** register a driver for given signal declaration.
	 *  @param decl SignalDeclaration for which a driver should get 
	 *              registered.
	 *  @param n SimpleName that references the signal.
	 *  @return generated driver or present driver.
	 */
	Driver *
	registerDriver(const SignalDeclaration &decl, SimpleName &n);

	/** register a driver for given signal declaration, that possibly
	 *  isn't used, but needs to be there due to being a parameter.
	 *  @param decl SignalDeclaration for which a driver should get 
	 *              registered.
	 *  @param t symbol type for the hidden name that will be generated
	 *         on the fly.
	 *  @return generated driver or present driver.
	 */
	void
	registerDriver(ValDeclaration &decl, enum symType t);


	/** register/generate a hidden formal of a subprogram call.
	 *  @param formal declaration corresponding to the formal part.
	 *  @param actualType type of the actual (needed for unconstraints)
	 *  @return SimpleName referring to the generated hidden declaration.
	 */
	SimpleName *
	registerFormal(
		const ValDeclaration *formal,
		TypeDeclaration *actualType);
	
	enum VMode {
		/** target signal expression. */
		VMODE_TARGET_SIGNAL,
		/** target variable expression */
		VMODE_TARGET_VAR,
		/** any read value */
		VMODE_SOURCE
	};

	//! current visitor mode
	enum VMode mode;

	/** map of current set of signal declarations to drivers */
	std::map<const SignalDeclaration*, Driver*> drivers;

	/** map of formal declarations of subprograms to 
	 *  hidden formal declarations together with a Name 
	 *  referring to it.
	 */
	typedef 
	std::map< const ValDeclaration *, 
		std::pair<ValDeclaration *, SimpleName *> > formalMapT;

	/** map of formal declarations of subprograms to 
	 *  hidden formal declarations together with a Name 
	 *  referring to it.
	 */
	formalMapT formals;

	/** counter to make driver names unique */
	unsigned int driverCounter;
	/** counter to make hidden formals of unconstraint arrays unique */
	unsigned int uhfCounter;
};

}; /* namespace ast */

#endif /* __GATHER_IMPLICITS_HPP_INCLUDED */
