/***********************************
  (C) Copyright 1992-1993; dit/upm
  Distributed under the conditions stated in the
  TOPO General Public License (see file LICENSE)
  ***********************************/

/***********************************
  
  David Larrabeiti Lopez
  
  22-1-1991
  
  Module to compare syntactically two behaviours
  (or two attribute values), except for variables
  renaming . A variable table keeps track of the
  necessarily one-to-one correspondence between
  the variables of both behaviours ( or attribute
  values ), plus some additional information on
  which of the variables are being defined.
  
  Use :
  boolean x1_equal_x2;
  Init_VPTable();
  x1_equal_x2 = Comp_X( x1, x2 );
  
  
  COMPILATION OPTIONS: The behaviour of this module can be modified
  by the following compilation flags:
  
  (none)
  
  ************************************/

/* LINTLIBRARY */

#include "limisc.h"
#include "lilists.h"
#include "licell.h"
#include "lihash.h"
#include "balotosf.h"
#include "badefca.h"
#include "babeh.h"
#include "baexpr.h"
#include "baattr.h"
#include "batables.h"
#include "excomp.h"


/*----------------------------------------------------------------*/

/* Comp_Expr
 * Compares two Expressions. Returns TRUE iff the comparison succeeds.
 */
boolean Comp_Expr( e1, e2, def )
     ExprTyp e1,e2;
     boolean def;
{
  int n,i;
  ExprTyp a1,a2;
  
  LASSERT( !IsVoidE(e1) && !IsVoidE(e2) );
  if (IsVariableE(e1)) {
    if (IsVariableE(e2))                    /* checks sorts and descriptors */ 
      if (LookSortE(e1)==LookSortE(e2))   
	return Store_VP( e1, e2, def );
  }
  else {
    if (LookNameE(e1)==LookNameE(e2)) {
      n = NumArgE(e1);
      LASSERT(n==NumArgE(e2));
      for (i=1 ; i<=n ; i++) {
	a1 = LookArgE(e1,i);
	a2 = LookArgE(e2,i);
	if ( !Comp_Expr(a1,a2,FALSE) )
	  return FALSE;
      }
      return TRUE;
    }
  }
  return FALSE;
}

/*----------------------------------------------------------------*/

/* Comp_Offer
 * Compares two Offers. Returns TRUE iif the comparison succeeds.
 */
boolean Comp_Offer( o1, o2 )
     OfferListTyp o1,o2;
{
  if ( LookKindOffer(o1) == LookKindOffer(o2) )
    return Comp_Expr( LookExprOffer(o1),LookExprOffer(o2),
		     LookKindOffer(o1)==QUESTION );
  else
    return FALSE;
}

/*----------------------------------------------------------------*/

/* Comp_SortOL
 * Compares the sorts of the expressions of two OfferLists.
 * Returns TRUE iff the comparison succeeds.
 */
boolean Comp_SortOL ( ol1, ol2 )
     OfferListTyp ol1,ol2;
{
  boolean r;
  
  r = TRUE;
  if ( (ol1==NULL) && (ol2==NULL) ) 
    return TRUE;
  while ( r && (ol1!=NULL) && (ol2!=NULL) ) {
    r   = ( LookSortE(LookExprOffer(ol1))==LookSortE(LookExprOffer(ol2)) );
    ol1 = MvNextOffer(ol1);
    ol2 = MvNextOffer(ol2);
  }
  return r&&(ol1==NULL)&&(ol2==NULL);
}

/*----------------------------------------------------------------*/

/* Comp_OLG
 * Compares two OfferLists of two gates.
 * Returns TRUE iff the comparison succeeds.
 */
boolean Comp_OLG( ol1, ol2 )
     OfferListTyp ol1,ol2;
{
  boolean r;
  
  r = TRUE;
  if ( (ol1==NULL) && (ol2==NULL) ) 
    return TRUE;
  while ( r && (ol1!=NULL) && (ol2!=NULL) ) {
    r   = Comp_Offer( ol1, ol2 );
    ol1 = MvNextOffer(ol1);
    ol2 = MvNextOffer(ol2);
  }
  return r&&(ol1==NULL)&&(ol2==NULL);
}

/*----------------------------------------------------------------*/

/* Comp_OLE
 * Compares two OfferLists in two exit cells.
 * Returns TRUE iif the comparison succeeds.The offers of kind QUESTION 
 * are ignored.
 */
boolean Comp_OLE( ol1, ol2 )
     OfferListTyp ol1,ol2;
{
  boolean r;
  int  ok1,ok2;
  
  r = TRUE;
  if ( (ol1==NULL) && (ol2==NULL) )
    return TRUE;
  while ( r && (ol1!=NULL) && (ol2!=NULL) ) {
    ok1 = LookKindOffer(ol1);
    ok2 = LookKindOffer(ol2);
    if ( ok1==EXCLAMATION && ok2==EXCLAMATION )
      r = Comp_Expr( LookExprOffer(ol1), LookExprOffer(ol2), FALSE );
    else
      r = (ok1==ok2);
    ol1 = MvNextOffer(ol1);
    ol2 = MvNextOffer(ol2);
  }
  return r&&(ol1==NULL)&&(ol2==NULL);
}

/*----------------------------------------------------------------*/

/* Comp_EL
 * Compares two Expression Lists. Returns TRUE iif the comparison succeeds.
 */
boolean Comp_EL( el1, el2 )
     ExprListTyp el1,el2;
{
  boolean r;
  
  r = TRUE;
  if ( (el1==NULL) && (el2==NULL) )
    return TRUE;
  while ( r && (el1!=NULL) && (el2!=NULL) ) {
    r = Comp_Expr((ExprTyp)LookInfo_list(el1),
                  (ExprTyp)LookInfo_list(el2),FALSE );
    el1 = Next_list(el1);
    el2 = Next_list(el2);
  }
  return r&&(el1==NULL)&&(el2==NULL);
}

/*----------------------------------------------------------------*/

/* Comp_VL
 * Compares two Variables Lists. Returns TRUE iff the comparison succeeds.
 */
boolean Comp_VL( vl1, vl2 )
     ExprListTyp vl1,vl2;
{
  boolean r;
  
  r = TRUE;
  if ( (vl1==NULL) && (vl2==NULL) )
    return TRUE;
  while ( r && (vl1!=NULL) && (vl2!=NULL) ) { 
    r = Comp_Expr( (ExprTyp)LookInfo_list(vl1),
		  (ExprTyp)LookInfo_list(vl2), TRUE );
    vl1 = Next_list(vl1);
    vl2 = Next_list(vl2);
  }
  return r&&(vl1==NULL)&&(vl2==NULL);
}

/*----------------------------------------------------------------*/

/* Comp_VAL_let
 * Compares two VarAssignLists of let. 
 * Returns TRUE iff the comparison succeeds. 
 */
boolean Comp_VAL_let( val1, val2 )
     VarAssignListTyp val1,val2;
{
  boolean r;
  ExprTyp e1,e2;
  DescriptorTyp v1,v2;
  VarAssignListTyp val1h,val2h;
  
  if ((val1==NULL) && (val2==NULL)) 
    return TRUE;
  
  val1h= val1;
  val2h= val2;
  r = TRUE;
  while ( r && (val1!=NULL) && (val2!=NULL) ) {
    e1 = LookExprVAL(val1);
    e2 = LookExprVAL(val2);
    r = Comp_Expr( e1, e2, FALSE );
    val1 = Next_list(val1); 
    val2 = Next_list(val2);
  }
  if (r && (val1==NULL) && (val2==NULL)) {
    while ( r && (val1h!=NULL) && (val2h!=NULL) ) {
      v1 = LookVarVAL(val1h);
      v2 = LookVarVAL(val2h);
      r = StoreD_VP( v1, v2, TRUE ) ;   
      val1h = Next_list(val1h); 
      val2h = Next_list(val2h);
    }
    return r;
  }
  else
    return FALSE;
}

/*----------------------------------------------------------------*/

/* Comp_VAL_plet
 * Compares two VarAssignLists of plet.
 * Returns TRUE iff the comparison succeeds.
 */
boolean Comp_VAL_plet( val1, val2 )
     VarAssignListTyp val1,val2;
{
  boolean r;
  ExprTyp e1,e2;
  DescriptorTyp v1,v2;
  VarAssignListTyp val1h,val2h;
  
  if ( IsVoidVAL(val1) && IsVoidVAL(val2) ) 
    return TRUE;
  
  val1h= val1;
  val2h= val2;
  r = TRUE;
  while ( r && (val1!=NULL) && (val2!=NULL) ) {
    e1 = LookExprVAL(val1);
    e2 = LookExprVAL(val2);
    r = Comp_Expr( e1, e2, FALSE );
    val1 = Next_list(val1); 
    val2 = Next_list(val2);
  }
  
  if (r && (val1==NULL) && (val2==NULL)) {
    while ( r && (val1h!=NULL) && (val2h!=NULL) ) {
      v1 = LookVarVAL(val1h);
      v2 = LookVarVAL(val2h);
      
      if (v1 != v2)
	r = StoreD_VP( v1, v2, TRUE ) ;   
      
      /*
	 r = StoreD_VP( v1, v2, TRUE ) ;   
	 
	 r = v1 == v2;   
	 */
      
      
      val1h = Next_list(val1h); 
      val2h = Next_list(val2h);
    }
    return r;
  }
  else
    return FALSE;
}

/*----------------------------------------------------------------*/

/* Comp_Beh
 * Compares two behaviour trees and the attributes in their cells:
 *           PA, VALA, OLA, ELA, GLA, GSA & RFLA.
 * Returns TRUE only if the comparison succeeds. This happens when these behs
 * are equal except for one-to-one variable renaming.
 * The comparison does not stop until all the free variables of both behaviours
 * are captured.
 */
boolean Comp_Beh( b1, b2 )
     BehTyp b1,b2;
{
  register boolean r;
  int n;
  DescriptorTyp syncClass;
  ITContListTyp itcl1, itcl2;
  PITContTyp itc1,itc2;
  PredicateTyp p1,p2;
  
  LASSERT(b1!=NULL && b2!=NULL);
  
  for ( ;; ) {
    if ( LookTypeB(b1)==LookTypeB(b2) ) {
      n = NumArgB(b1);
      if ( NumArgB(b2)!=n ) 
	return FALSE;
      
      switch ( LookTypeB(b1) )
	{
	case RelabellingC:
	  r = EqualRFL( (RelabFuncListTyp)LookAInfo( LookA(b1,RFLA) ),
		       (RelabFuncListTyp)LookAInfo( LookA(b2,RFLA) ) );
	  break;
	  
	case HidingC:
	  r = EqualGS( (GateSetTyp)LookAInfo( LookA(b1,GSA) ),
		      (GateSetTyp)LookAInfo( LookA(b2,GSA) ) );
	  break;
	  
	case ChoiceC:
	  r = Comp_VL( (ExprListTyp)LookAInfo( LookA(b1,ELA) ),
		      (ExprListTyp)LookAInfo( LookA(b2,ELA) ) );
	  break;
	  
	case PletC:
	  if ( LookArgB(b1,1)==LookArgB(b2,1) ) {
	    r = Comp_VAL_plet( (VarAssignListTyp)LookAInfo( LookA(b1,VALA) ),
			      (VarAssignListTyp)LookAInfo( LookA(b2,VALA) ) );
	    return r;
	  }
	  else 
	    r = Comp_VAL_let( (VarAssignListTyp)LookAInfo( LookA(b1,VALA) ),
			     (VarAssignListTyp)LookAInfo( LookA(b2,VALA) ) );
	  break;
	  
	case LetC:
	  r = Comp_VAL_let( (VarAssignListTyp)LookAInfo( LookA(b1,VALA) ),
			   (VarAssignListTyp)LookAInfo( LookA(b2,VALA) ) );
	  break;
	  
	case EnablingC:
	  r = Comp_VL( (ExprListTyp)LookAInfo( LookA(b1,ELA) ),
		      (ExprListTyp)LookAInfo( LookA(b2,ELA) ) );
	  break;
	  
	case DisablingC:
	  r = TRUE;
	  break;
	  
	case ParallelC:
	  r = LookNameB(b1)==LookNameB(b2) &&
	    EqualGS( (GateSetTyp)LookAInfo( LookA(b1,GSA) ),
		    (GateSetTyp)LookAInfo( LookA(b2,GSA) ) );
	  break;
	  
	case AlternativeC:
	  r = TRUE;
	  break;
	  
	case GuardC:
	  p1 = (PredicateTyp)LookAInfo(LookA(b1,PA));
	  p2 = (PredicateTyp)LookAInfo(LookA(b2,PA));
	  r = Comp_Expr(LookRwPred(p1),LookRwPred(p2),FALSE);
	  break;
	  
	case GateC:
	  if ( LookNameB(b1)==LookNameB(b2) ) {
	    r = Comp_OLG((OfferListTyp)LookAInfo(LookA(b1,OLA)),
			 (OfferListTyp)LookAInfo(LookA(b2,OLA)));
	    if (r==TRUE) {
	      p1 = (PredicateTyp)LookAInfo(LookA(b1,PA));
	      p2 = (PredicateTyp)LookAInfo(LookA(b2,PA));
	      if ((p1==NULL)||(p2==NULL))
		r = p1==p2;
	      else 
		r = Comp_Expr(LookRwPred(p1),LookRwPred(p2),FALSE);
	    }
	  }
	  else
	    return FALSE;
	  break;
	  
	case IC:
	  r = TRUE;
	  break;
	  
	case ExitC:
	  r = Comp_OLE( (OfferListTyp)LookAInfo( LookA(b1,OLA) ),
		       (OfferListTyp)LookAInfo( LookA(b2,OLA) ) );
	  break;
	  
	case StopC:
	  r = TRUE;
	  break;
	  
	case ProcessInstC:
	  if ( (LookNameB(b1)==LookNameB(b2)) &&
	      EqualGL( (GateListTyp)LookAInfo( LookA(b1,GLA) ),
		      (GateListTyp)LookAInfo( LookA(b2,GLA) ) ) )
	    
	    
	    r = Comp_EL( (ExprListTyp)LookAInfo( LookA(b1,ELA) ),
			(ExprListTyp)LookAInfo( LookA(b2,ELA) ) );
	  else
	    return FALSE;
	  break;
	  
	case GateChoiceC:
	  r = EqualGDL( (GateDecListTyp)LookAInfo( LookA(b1,GDLA) ),
		       (GateDecListTyp)LookAInfo( LookA(b2,GDLA) ) );
	  break;
	  
	case ParC:
	  r = TRUE;
	  if ( (syncClass=LookNameB(b1))==LookNameB(b2) ) {
	    if ( syncClass==PART_SYNC)
	      r = EqualGS( (GateSetTyp)LookAInfo( LookA(b1,GSA) ),
			  (GateSetTyp)LookAInfo( LookA(b2,GSA) ) );
	    r = r && EqualGDL( (GateDecListTyp)LookAInfo( LookA(b1,GDLA) ),
			      (GateDecListTyp)LookAInfo( LookA(b2,GDLA) ) );
	  }
	  else
	    return FALSE;
	  break;
	  
	case InterleavedC:
	  r = TRUE;
	  break;
	  
	case TerminationC:
	  /* when implemented this should also have into account
	     terminations renaming   */
	  if ( LookNameB(b1)==LookNameB(b2) )
	    r = Comp_EL( (ExprListTyp)LookAInfo( LookA(b1,ELA) ),
			(ExprListTyp)LookAInfo( LookA(b2,ELA) ) );
	  else
	    return FALSE;
	  break;
	  
	case ContSetC:
	  r = TRUE;
	  itcl1 = (ITContListTyp)LookAInfo(LookA(b1,ITCLA));
	  itcl2 = (ITContListTyp)LookAInfo(LookA(b2,ITCLA));
	  while ( itcl1!=NULL && itcl2!=NULL && r) {
	    itc1 = (PITContTyp)LookInfo_list(itcl1);
	    itc2 = (PITContTyp)LookInfo_list(itcl2);
	    /* be careful with variables */
	    r = EqualLabel( itc1->label, itc2->label );
	    itcl1 = Next_list(itcl1);
	    itcl2 = Next_list(itcl2);
	  }     
	  break;
	  
	  
	default:
	  Error("Comp_Beh : Unexpected Cell Type");
	  break;
	  
	}
      for ( ; (r==TRUE) && (n>1) ; n-- ) {
	r = Comp_Beh( LookArgB(b1,n), LookArgB(b2,n) );
      }
      if (!r)
	return FALSE;
      b1 = LookArgB(b1,1);
      b2 = LookArgB(b2,1);
      if ( b1==NULL )
	return b2==NULL;
      
    }
    else
      {
	if ( LookTypeB(b1)==PletC &&
	    IsVoidVAL((VarAssignListTyp)LookAInfo(LookA(b1,VALA))) )
	  return Comp_Beh(LookArgB(b1,1),b2);
        
	if ( LookTypeB(b2)==PletC &&
	    IsVoidVAL((VarAssignListTyp)LookAInfo(LookA(b2,VALA))) )
	  return Comp_Beh(b1,LookArgB(b2,1));
	
	return FALSE;
      }
  }
}
/*----------------------------------------------------------------*/



/******************************************************************
 *                                                                *
 *                Table of Pairs of Variables                     *
 *                                                                *
 ******************************************************************/

/*  
 * The following section manages a table of variable pairs
 * which keeps track of a possible var renaming
 * while comparing two behaviours with Comp_Beh.
 * Therefore, it is checked the one-to-one relationship
 * between the names of the variables being stored.
 * If the comparison succeeds then the list of vars renaming
 * is returned if so asked for.
 * 
 *  Sequence of Operation:
 *
 *    Init_VPTable();
 *    (* begin comparison *)
 *    Store_VP(x,y,TRUE)...
 *    (* end comparison   *)
 *    if ( the_comparison_succeeds )
 *      {
 *        vl1 = Mk_VPTable_VL1();
 *        vl2 = Mk_VPTable_VL2();
 *       }
 *    (* release table *)       
 *    Init_VPTable();
 *
 *  FUNCTIONS :
 *
 *   Init_VPTable   : initialize and reset VP table
 *   Print_VP       : prints the VP table into a file
 *   Store_VP       : Looks up & store variables in the VP table
 *                    There can be parameterized values.
 *   StoreD_VP      : Looks up & store variables descriptors in the VP table.
 *                    There are not parameterized values.
 *   Mk_VPTable_VL1 : Makes a variable list with the first components 
 *                    of the VP table that remain undefined.
 *   Mk_VPTable_VL2 : Makes a variable list with the second components 
 *                    of the VP table that remain undefined.
 *
 */


#define MAX_VP_TABLE  200

static boolean first_init = TRUE;

typedef struct { DescriptorTyp v1;
				 ExprTyp       v1PValue;
				 DescriptorTyp v2;
				 ExprTyp       v2PValue;
				 boolean       defined;
			   } VPtableEntryTyp, *PVPtableEntryTyp;


typedef HashDTyp VarPairTableTyp;

static VarPairTableTyp vpTab1, vpTab2;
static ListTyp vpList;

/*----------------------------------------------------------------*/

static int new_vp_count      = 0;
static int released_vp_count = 0;


/* InitVP
 * Init the module
 */
void InitVP()
{
#ifdef SDEBUG
  new_vp_count      = 0;
  released_vp_count = 0;
#endif
}


/* StatVP
 * Number of asked  and released vp nodes
 */
void StatVP( new, released )
     int * new, *released;
{
  *new      = new_vp_count;
  *released = released_vp_count;
}


/* NewVPtableEntry
 * Get memory for a new entry
 */
static PVPtableEntryTyp NewVPtableEntry()
{
  PVPtableEntryTyp p;
  
  p     = (PVPtableEntryTyp) NewCellM(sizeof(VPtableEntryTyp));
  p->v1 = 0;
  p->v1PValue = NULL;
  p->v2PValue = NULL;
#ifdef SDEBUG
  new_vp_count++;
#endif
  return p;
}

/*----------------------------------------------------------------*/

/* DispVPtableEntry
 * Free memory of a entry
 */
static void DispVPtableEntry( c )
     PVPtableEntryTyp c; 
{
#ifdef SDEBUG
  released_vp_count++;
#endif
  
  if (c->v1PValue != NULL)
    FreeE(UnshareE(c->v1PValue));
  if (c->v2PValue != NULL)
    FreeE(UnshareE(c->v2PValue));
  FreeCellM((void*)c,sizeof(VPtableEntryTyp));
}

/*----------------------------------------------------------------*/

/* KeyVPtableEntry1
 * Gets the hash key according to v1.
 */
static int KeyVPtableEntry1( pe )
     PVPtableEntryTyp pe;
{
  return -pe->v1;
}

/*----------------------------------------------------------------*/

/* KeyVPtableEntry2
 * Gets the hash key according to v2.
 */
static int KeyVPtableEntry2( pe )
     PVPtableEntryTyp pe;
{
  return -pe->v2;
}

/*----------------------------------------------------------------*/

/* CompVPtableEntry1
 * Compares two entries according to v1.
 */
static boolean CompVPtableEntry1(pe1,pe2)
     PVPtableEntryTyp pe1,pe2;
{
  return pe1->v1==pe2->v1;
}

/*----------------------------------------------------------------*/

/* CompVPtableEntry2
 * Compares two entries according to v2.
 */
static boolean CompVPtableEntry2( pe1, pe2 )
     PVPtableEntryTyp pe1,pe2;
{
  return pe1->v2==pe2->v2;
}

/*----------------------------------------------------------------*/

/* PrintVPtableEntry
 * Prints an entry
 * "pstr" is the function used to print strings.
 */
static void PrintVPtableEntry( pstr, pe )
     void (*pstr)();
     PVPtableEntryTyp pe;
{
  PrintV( pe->v1, TRUE, pstr );
  if ( pe->v1PValue != NULL ) {
    pstr(" = ");
    PrintE( pe->v1PValue, pstr );
  }
  pstr("  ");
  PrintV( pe->v2, TRUE, pstr );
  if ( pe->v2PValue != NULL ) {
    pstr(" = ");
    PrintE( pe->v2PValue, pstr );
  }
  pstr("        def=");
  PrintInt(pstr,pe->defined);
  pstr("\n");
}

/*----------------------------------------------------------------*/

/* Init_VPTable()
 * Init a VP table
 */
void Init_VPTable()
{
  if (first_init) {
    first_init = FALSE;
    vpTab1 = Create_HT( MAX_VP_TABLE, (void(*)())NULL, KeyVPtableEntry1,
		       CompVPtableEntry1, PrintVPtableEntry );
    vpTab2 = Create_HT( MAX_VP_TABLE, (void(*)())NULL, KeyVPtableEntry2,
		       CompVPtableEntry2, PrintVPtableEntry );
    vpList = Create_list();
  }
  else {
    Clean_HT( vpTab1 );
    Clean_HT( vpTab2 );
    Free_list( vpList, DispVPtableEntry );
    vpList = Create_list();
  }
}

/*----------------------------------------------------------------*/


/* Print_VP
 * Prints the VP table.
 * "pstr" is the function used to print strings.
 */
void Print_VP(  pstr )
     void (*pstr)();
{
  Print_HT( vpTab1, pstr );
}

/*----------------------------------------------------------------*/

/* Store_VP
 * Looks up (v1,v2,def) in the table and :
 * if found update def ( only in the sense FALSE->TRUE ) and return TRUE.
 * if (v1,v3,*) or (v3,v2,*) is found ,the comparison fails => return FALSE.
 * else , (v1,v2,def) is appended to the table and return TRUE.
 */
boolean Store_VP( v1, v2, def )
     ExprTyp   v1, v2;
     boolean     def;
{
  PVPtableEntryTyp pe,aux;
  ExprTyp pv;
  
  pe     = NewVPtableEntry();
  pe->v1 = LookNameE(v1);
  pe->v2 = LookNameE(v2);
  
  aux    = (PVPtableEntryTyp) LookFor_HT( vpTab1, (DataHashTyp)pe );
  if ( aux==NULL ) {
    aux = (PVPtableEntryTyp) LookFor_HT( vpTab2, (DataHashTyp)pe );
    if ( aux==NULL ) {
      pv = LookPVarE( v1 );
      if (pv != NULL) 
	pe->v1PValue = ShareE(pv);
      pv = LookPVarE( v2 );
      if (pv != NULL) 
	pe->v2PValue = ShareE(pv);
      pe->defined  = def;
      Insert_HT( vpTab1, (DataHashTyp)pe );
      Insert_HT( vpTab2, (DataHashTyp)pe );
      vpList = Insert_list( (DataListTyp)pe, vpList );
      return TRUE;
    }
    else {
      DispVPtableEntry( pe );
      return FALSE;
    }
  }
  else {
    DispVPtableEntry( pe );
    if ( aux->v2 != LookNameE(v2) ) {
      return FALSE;
    }
    else {
      /* aux->defined = aux->defined||def; */
      /* Non-defined variables are not changed to defined. */
      return TRUE;
    }
  }
}

/*----------------------------------------------------------------*/

/* StoreD_VP
 * Like Store_VP but v1 and v2 are descriptorTyp, and
 * there are not parameterized values.
 */
boolean StoreD_VP( v1, v2, def )
     DescriptorTyp v1, v2;
     boolean def; 
{
  PVPtableEntryTyp pe, aux;
  
  pe     = NewVPtableEntry();
  pe->v1 = v1;
  pe->v2 = v2;
  
  aux = (PVPtableEntryTyp) LookFor_HT( vpTab1, (DataHashTyp)pe );
  if ( aux==NULL ) {
    aux = (PVPtableEntryTyp) LookFor_HT( vpTab2, (DataHashTyp)pe );
    if ( aux==NULL ) {
      pe->defined  = def;
      Insert_HT( vpTab1, (DataHashTyp)pe );
      Insert_HT( vpTab2, (DataHashTyp)pe );
      vpList = Insert_list( (DataListTyp)pe, vpList );
      return TRUE;
    }
    else {
      DispVPtableEntry(pe);
      return FALSE;
    }
  }
  else {
    DispVPtableEntry( pe );
    if ( aux->v2 != v2 ) {
      return FALSE;
    }
    else {
      /* aux->defined = aux->defined||def; */
      /* Non-defined variables are not changed to defined. */
      return TRUE;
    }
  }
}

/*----------------------------------------------------------------*/

/* Mk_VPTable_VL1
 * Makes a varlist with the first components of the pairs of variables that 
 * remain undefined in the varpairtable.
 */
ExprListTyp Mk_VPTable_VL1()
{
  ExprListTyp vl;
  ExprTyp v;
  ListTyp aux;
  PVPtableEntryTyp pe;
  
  vl = Create_list();
  
  for ( aux = vpList ; aux!=NULL ; aux = Next_list(aux) ) {
    pe = (PVPtableEntryTyp)LookInfo_list(aux);
    if ( pe->defined==FALSE ) {
      vl = AddEL( v = MakeE(pe->v1,VariableC), vl );
      if ( pe->v1PValue != NULL ) {
	PutPVarE( v, pe->v1PValue ); /*mse*/
      }
    }
  }
  return vl;
}

/*----------------------------------------------------------------*/

/* Mk_VPTable_VL2
 * Makes a varlist with the second components of the pairs of variables that 
 * remain undefined in the varpairtable.
 */
ExprListTyp Mk_VPTable_VL2()
{
  ExprListTyp vl;
  ExprTyp v;
  ListTyp aux;
  PVPtableEntryTyp pe;
  
  vl = Create_list();
  
  for ( aux = vpList ; aux!=NULL ; aux = Next_list(aux) ) {
    pe = (PVPtableEntryTyp)LookInfo_list( aux );
    if ( pe->defined==FALSE ) {
      vl = AddEL( v = MakeE(pe->v2,VariableC), vl );
      if ( pe->v2PValue != NULL ) {
	PutPVarE( v, pe->v2PValue ); /*mse*/
      }
    }
  }
  return vl;
}

/*----------------------------------------------------------------*/









