/******************************************************************
 *  (C) Copyright 1994; dit/upm
 *  Distributed under the conditions stated in the
 *  TOPO General Public License (see file LICENSE)
 ******************************************************************
 *  $Log$
 ******************************************************************/


#ifndef lint
static char rcsid[]= "$Id$";
#endif

/******************************************************************
 *
 *  Santiago Pavon Gomez
 *  David Larrabeiti Lopez
 *
 *  19 Jan 1990
 *
 *  Management of selection predicates
 *  
 *  COMPILATION FLAGS:
 *      
 *  LOG:
 *     25/06/92. santiago.
 *     New function to decompose a multiple predicate into single
 *     predicates.
 *
 *     17/07/92. dlarra.
 *     The inverse.
 *
 ******************************************************************/

/* LINTLIBRARY */

#include "baattr.h"
#include "babool.h"
#include "limisc.h"
#include "listrbk.h"


/* 
 *  count of predicate structs used and released.
 */
static int new_pred_count      = 0;
static int released_pred_count = 0;
static int max_pred_count      = 0;

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

/* InitPred
 * Init the module
 */
void InitPred()
{
#ifdef SDEBUG
  new_pred_count      = 0;
  released_pred_count = 0;
  max_pred_count      = 0;
#endif
}

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

/* StatPred
 * new      : number of cell queries the system has granted this module with.
 * released : number of cell releases.
 * max      : max number of cells hold on by this module till now.
 */
void StatPred( new, released, max )
     int * new, *released, *max;
{
  *new      = new_pred_count;
  *released = released_pred_count;
  *max      = max_pred_count;
}

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

/* NewPred
 * Create a predicate.
 */
PredicateTyp NewPred(er,eo)
     ExprTyp er,eo;
{
  PredNodeTyp  pn;
  PredicateTyp p;
  
#ifdef SDEBUG
  new_pred_count++;
  max_pred_count = MAX( max_pred_count, new_pred_count-released_pred_count );
#endif
  pn            = (PredNodeTyp)NewCellM(sizeof(struct predicate));
  pn->rewritten = ShareE(er);
  if (eo!=NULL)
    pn->original = ShareE(eo);
  else
    pn->original = NULL;
  p = CreateNode_list();
  PutInfo_list(p,(DataListTyp)pn);
  
  return p;
}

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

/* AddPremisePred
 * Add another premise to the predicate p.
 */
PredicateTyp AddPremisePred( p,er,eo )
     PredicateTyp  p;
     ExprTyp       er,eo; 
{
  return Join_list(p,NewPred(er,eo));
}

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

/* PrintPred
 * Prints the predicate p
 * pstr is the function used to print strings.
 */
void PrintPred( p, pstr )
     PredicateTyp  p;
     void         (*pstr)(); 
{
  PredNodeTyp pn;
  
  while (p!=NULL) {
    pn = (PredNodeTyp)LookInfo_list(p);
    LASSERT(OwnersE(pn->rewritten)!=0);
    if (pn->original == NULL)
      PrintE( pn->rewritten, pstr );
    else {
      PrintE( pn->original, pstr );
      /*
	 pstr("(*)");
	 PrintE( pn->rewritten, pstr );
	 pstr("*)");
	 */
    }
    p = Next_list(p);
    if (p!=NULL)
      pstr(" , ");
  }
}

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

/* SPrintPred
 * return a char string block with the predicate p.
 */
char * SPrintPred( p )
     PredicateTyp   p;
{
  StrBckTyp strbuff;
  PredNodeTyp pn;
  
  strbuff = CreateStrBck();
  while (p!=NULL) {
    pn = (PredNodeTyp)LookInfo_list(p);
    LASSERT(OwnersE(pn->rewritten)!=0);
    if (pn->original == NULL)
      strbuff = ConcatStrBck(strbuff,ExprToStringE(pn->rewritten));
    else
      strbuff = ConcatStrBck(strbuff,ExprToStringE(pn->original));
    p = Next_list(p);
    if (p!=NULL)
      strbuff = ConcatStrBck(strbuff," , ");
  }
  return GetStrStrBck(strbuff);
}


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

static void FreePaux( pn )
     PredNodeTyp pn; 
{
  LASSERT(OwnersE(pn->rewritten)!=0);
  FreeE(UnshareE(pn->rewritten));
  if (pn->original != NULL)
    FreeE(UnshareE(pn->original));
#ifdef SDEBUG
  released_pred_count++;
#endif
  FreeCellM( (void*)pn , sizeof(struct predicate) );
}

/* FreePred
 * Free a predicate p
 */
void FreePred( p )
     PredicateTyp p; 
{
  Free_list(p,FreePaux);
}

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

static PredNodeTyp CopyPaux( pn )
     PredNodeTyp pn; 
{
  PredNodeTyp pn2;
  
  LASSERT(OwnersE(pn->rewritten)!=0);
#ifdef SDEBUG
  new_pred_count++;
  max_pred_count = MAX( max_pred_count, new_pred_count-released_pred_count );
#endif
  pn2 = (PredNodeTyp)NewCellM(sizeof(struct predicate));
  pn2->rewritten = ShareE(CopyE(pn->rewritten));
  if (pn->original!=NULL)
    pn2->original = ShareE(CopyE(pn->original)); /*mse*/
  else
    pn2->original = ShareE(CopyE(pn->rewritten)); /*mse*/
  return pn2;
}

/* CopyPred
 * Copy a predicate p
 */
PredicateTyp CopyPred( p )
     PredicateTyp p; 
{
  return Copy_list(p,(DataListTyp(*)())CopyPaux);
}

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

static PredNodeTyp SharePaux( pn )
     PredNodeTyp pn; 
{
  PredNodeTyp pn2;
  
  LASSERT(OwnersE(pn->rewritten)!=0);
#ifdef SDEBUG
  new_pred_count++;
  max_pred_count = MAX( max_pred_count, new_pred_count-released_pred_count );
#endif
  pn2 = (PredNodeTyp)NewCellM(sizeof(struct predicate));
  pn2->rewritten = ShareE(pn->rewritten);
  if (pn->original!=NULL)
    pn2->original = ShareE(pn->original); /*mse*/
  else
    pn2->original = ShareE(pn->rewritten); /*mse*/
  return pn2;
}


/* SharePred
 * Share a predicate p.
 */
PredicateTyp SharePred( p )
     PredicateTyp p; 
{
  return Copy_list(p,(DataListTyp(*)())SharePaux);
}

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

/* UnsharePred
 * Unshare a predicate p.
 */
PredicateTyp UnsharePred( p )
     PredicateTyp p; 
{
  PredicateTyp p2; 
  PredNodeTyp pn;
  
  for (p2=p ; p2!=NULL ; p2=Next_list(p2)) {
    pn = (PredNodeTyp)LookInfo_list(p2);
    LASSERT(OwnersE(pn->rewritten)!=0);
    if (pn->original != NULL)
      pn->original = ShareE(GetE(UnshareE(pn->original)));
    pn->rewritten = ShareE(GetE(UnshareE(pn->rewritten)));
  }
  return p;
}

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

/* MakeAndPred
 * Create a new predicate that is equal to "p1 and p2".
 */
PredicateTyp MakeAndPred( p1, p2 )
     PredicateTyp p1,p2;
{
  if ( IsTrue(LookRwPred(p1)) )
    return SharePred(p2);
  else
    if ( IsTrue(LookRwPred(p2)) )
      return SharePred(p1);
  
  return RemoveEqualExprPred(Join_list(SharePred(p1),SharePred(p2)));  /*mse*/
}

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


static ExprListTyp le;

static void VarInExprAux( e )
     ExprTyp e;
{
  int n,i;
  
  if ( IsVariableE(e) ) {
    if ( !In_list((DataListTyp)e,le,EqualE) )
      le = InsertEL(MakeE(LookNameE(e),VariableC),le);
  }
  else /* operation */ {
    n = NumArgE(e);
    for ( i=1 ; i<=n ; i++ ) 
      VarInExprAux( LookArgE(e,i) );
  }
}

/* VarsInPred
 * Return a list with the variables used in the predicate p.
 */
ExprListTyp VarsInPred( p )
     PredicateTyp p;
{
  le = CreateEL();
  for ( ; p!=NULL ; p=Next_list(p) ) 
    VarInExprAux( LookRwPred(p) );
  return le;
}

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

/* LookRwPred
 * Look at the rewritten value of the first node of p
 */
ExprTyp LookRwPred( p )
     PredicateTyp p; 
{
  return ((PredNodeTyp)LookInfo_list(p))->rewritten;
}

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

/* LookOrPred
 * Look the original value of the first node of p.
 */
extern ExprTyp LookOrPred( p )
     PredicateTyp p;
{
  return ((PredNodeTyp)LookInfo_list(p))->original;
}

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

/* RemoveEqualExprPred
 * Remove from the predicate p the duplicated premises.
 */
PredicateTyp RemoveEqualExprPred (p)
     PredicateTyp p;
{
  ListTyp      dupli,p1,p2;
  
  dupli = Create_list();
  for (p1=p ; p1!=NULL ; p1=Next_list(p1)) {
    for (p2=Next_list(p1) ; p2!=NULL ; p2=Next_list(p2)) {
      if (!In_list((DataListTyp)p2,dupli,EqInt))
	if (EqualE(LookRwPred(p1),LookRwPred(p2))) 
	  dupli = Insert_list((DataListTyp)p2,dupli);
    }
  }
  for (p1=dupli ; p1!=NULL ; p1=Next_list(p1)) {
    p2 = (ListTyp)LookInfo_list(p1);
    p = ExtractNode_list( p2 , p );
    FreePred(p2);
  }
  return p;
}

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






