
/* -------------------------------------------------------------------------
 * Projet E C 2 O C
 * -------------------------------------------------------------------------
 * module   : gbdd_ctr.h
 *
 * date     : 10/1/94
 * auteurs  : Pascal Raymond
 *--------------------------------------------------------------------------
 * ADAPTATION DE bdd_ctr AU NOUVEAUX gbdd
 *
 * nature   : Definition de la classe BddConstructor :
 *            C'est une classe "generique" destinee a construire des
 *          expression gardees sous forme de Bdd a partir d'expression
 *          (i.e. des fonctions de 2n dans Exp).
 *            Cette classe est parametree par quatre fonctions virtuelles,
 *          qu'il faut definir dans une classe derivee :
 *          -  int is_argument(Exp* e) est vrai si "e" corespond a un
 *          argument. 
 *          -  GBdd argument_value(Exp* e) renvoie le bdd correspondant
 *          a "e" si "e" est un argument.
 *          -  int is_leaf(Exp* e) est vrai si "e" doit etre considere
 *          comme une feuille.
 *          -  GBdd leaf_value(Exp* e) renvoie le bdd correspondant
 *          a "e" si "e" est une feuille. 
 *       
 *          -  GBdd build_bdd_leaf(Exp* e) renvoie le bdd (a piori une
 *				feuille) associee a ``e'' => cette methode est appellee
 *				pour les expressions non booleennes.
 *       
 *             La classe "connait" tous les operateurs arithmetiques
 *          et logique de Lustre (et donc de ec) :
 *          -  elle "sait" traiter tous les operateurs strictement booleen
 *          (operateurs evaluables statiquement en fonction des arguments).
 *          -  partiellement les operateurs de comparaison "EQUAL_n" et
 *          "NEQ_n", en se basant sur l'equivalence syntaxique des
 *          expressions.
 *          -  partiellement certains operateurs arithmetiques, via
 *          une instance de la classe "net_sem.h" (qui fait un traitement
 *          semantique des expressions).
 *--------------------------------------------------------------------------
 * Modifs   :
 * -----------------------------------------------------------------------*/

class BddConstructor;

typedef GBdd (BddConstructor::* CanStopFuncType)
(const GBdd&, const GBdd&);

class BddConstructor {

	// Le constructeur d'expression utilise pour combiner les feuilles :
	NetCtr* netify;

	// La constante nil :
	GBdd nil_bdd;

	// Les arguments de la construction :
	virtual int is_argument(Exp*){ return 0; };
	virtual int is_leaf(Exp*){ return 0; };
	virtual GBdd argument_value(Exp*){ return null_bdd(); };
	virtual GBdd leaf_value(Exp*){ return null_bdd();};

	virtual GBdd build_bdd_leaf(Exp*){ return null_bdd();};

	virtual void set_result(Exp*, const GBdd&){ };

	// Application des operateurs aux bdds :
	GBdd apply_not(const GBdd& bdd);
	GBdd apply_uminus(const GBdd& bdd);
	GBdd apply_call(int func_name, const GBdd& bdd);
	GBdd apply_tuple(GBdd* tab, int nb);

	/*-------------------------------------------------------
		 Aplication des op. binaires :
	-------------------------------------------------------*/
	// Procedure principale :
	GBdd apply_binary(const GBdd& bdd1, const GBdd& bdd2);

	// Parametres de la combinaison :
	// Les differentes valeurs pour Can_stop :
	GBdd stop_on_OR(const GBdd& bdd1, const GBdd& bdd2);
	GBdd stop_on_AND(const GBdd& bdd1, const GBdd& bdd2);
	GBdd stop_on_EQUAL(const GBdd& bdd1, const GBdd& bdd2);
	GBdd stop_on_NEQ(const GBdd& bdd1, const GBdd& bdd2);
	GBdd stop_on_IMPL(const GBdd& bdd1, const GBdd& bdd2);
	GBdd stop_on_NIL(const GBdd& bdd1, const GBdd& bdd2);

	ExpNature Current_op;
#ifdef cxx
	GBdd Can_stop(const GBdd&, const GBdd&);
#else
	GBdd (BddConstructor::*Can_stop)(const GBdd&, const GBdd&);
#endif


	// Combinaison des feuilles :
	GBdd combine_binary_op(ExpNature op, const GBdd& bdd1, const GBdd& bdd2);

	/*-------------------------------------------------------
		 Application de l'op. "if then else" :
	-------------------------------------------------------*/
	// Procedure principale :
	GBdd apply_if(const GBdd& bdd0, const GBdd& bdd1, const GBdd& bdd2);

	// Utilitaire :
	GBdd stop_on_IF(const GBdd& bdd0, const GBdd& bdd1, const GBdd& bdd2);

	// Combinaison des feuilles :
	GBdd combine_if_op(const GBdd& bdd0, const GBdd& bdd1, const GBdd& bdd2);

	/*-------------------------------------------------------
		 Application des operateurs n-aires :
	-------------------------------------------------------*/
	GBdd apply_exclusion(Exp** tab, int nb_ops);
	GBdd apply_exactone(Exp** tab, int nb_ops);
	GBdd apply_nor(Exp** tab, int nb_ops);

	GBdd exp_to_bdd(Exp*);
public :
	BddConstructor(
		NetCtr* nety
	){
		netify = nety;
		nil_bdd = leaf((void*)(netify->nil_exp()));
	};
	virtual ~BddConstructor(){}
	inline GBdd operator()(Exp* e){
		return exp_to_bdd(e );
	};
	GBdd get_idy(int i);
	GBdd get_leaf(Exp* e);
	void print(const GBdd&){};
};
