/******************************************************************
 *  (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
 *
 *  17 Jan 1990
 *
 *  Management of variable assignment lists.
 *
 *  COMPILATION FLAGS:
 *
 *  LOG:
 *
 ******************************************************************/

/* LINTLIBRARY */

/* KJT 12/02/12: Added */
#include <stdlib.h>
#include "baattr.h"
#include "listdh.h"
#include "limisc.h"
#include "listrbk.h"
#include "batables.h"
#include "basust_v.h"
#include "badefca.h"


/******************************************************************
 *                                                                *
 *       VALA  -> Var Assign List (VarAssignListTyp)              *
 *                                                                *
 ******************************************************************/

/* KJT 22/01/23: added "int" type */
static int new_va_count      = 0;
static int released_va_count = 0;
static int max_va_count  = 0;

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

/* InitVA
 * Init the VA module
 */
void InitVA()
{
#ifdef SDEBUG
  new_va_count      = 0;
  released_va_count = 0;
  max_va_count      = 0;
#endif
}

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

/* StatVA
 * 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 StatVA( new, released, max )
     int *new, *released, *max;
{
  *new      = new_va_count;
  *released = released_va_count;
  *max      = max_va_count;
}

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

/* NewVarAssign
 * Get memory for a new VarAssign cell
 */
static PVarAssignTyp NewVarAssign()
{
  PVarAssignTyp p;

  p         = (PVarAssignTyp) NewCellM(sizeof(VarAssignTyp));
  p->varFor = (DescriptorTyp)NULL;
  p->expAct = NULL;
#ifdef SDEBUG
  new_va_count++;
  max_va_count=MAX( max_va_count, new_va_count-released_va_count );
#endif
  return p;
}

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

/* DispVarAssign
 * Free memory used by a VarAssign cell
 */
static void DispVarAssign( c )
     PVarAssignTyp c;
{
  FreeCellM( (void*)c, sizeof(VarAssignTyp) );
#ifdef SDEBUG
  released_va_count++;
#endif
}

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

/* StatisticVAL
 * Statistics of the variable assign list val.
 * Return the number of var-assign nodes (va) used in val,
 * the number of list nodes used to build the list (nl),
 * and the number of variable and operator cells and list nodes used
 * in the expressions.
 * nv,vv and ov are virtual values of number of list nodes, variables and
 * operation cells, i.e. without paying attention to the sharing feature.
 * nr,vr and or are the real values, i.e. nodes and cells already counted in
 * other expressions are not counted again here.
 */
void StatisticVAL( val,nv,vv,ov,nr,vr,or,va,nl )
     VarAssignListTyp val;
     int          *nv,*vv,*ov,*nr,*vr,*or,*va,*nl;
{
  int op,var,list,op2,var2,list2;

  *nv = *vv = *ov = *nr = *vr = *or = *va = *nl = 0;
  while (val != NULL) {
    (*nl)++;
    (*va)++;
    StatisticE(((PVarAssignTyp)LookInfo_list(val))->expAct,&list,&var,
	       &op,&list2,&var2,&op2);
    *vr += var2;
    *or += op2;
    *nr += list2;
    *vv += var;
    *ov += op;
    *nv += list;
    val = Next_list(val);
  }
}

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

/* CreateVAL
 * Create a VAL. (Returns an empty VarAssignList.)
 */
VarAssignListTyp CreateVAL()
{
  return Create_list();
}

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

/* FreeVA
 * Free a single var assign.
 */
void FreeVA(va)
     PVarAssignTyp  va;
{
  LASSERT(OwnersE(va->expAct)!=0);
  va->varFor= (DescriptorTyp)NULL;
  FreeE(UnshareE(va->expAct));
  DispVarAssign(va);
}

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

/* FreeVAL
 * Free the memory used by the VarAssignList val.
 */
void FreeVAL( val )
     VarAssignListTyp val;
{
  Free_list(val,FreeVA);
}

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

/* MakeVA
 * Create a node [variable/expression]
 */
PVarAssignTyp MakeVA( vf, ea )
     DescriptorTyp vf;
     ExprTyp       ea;
{
  PVarAssignTyp nVA;

  nVA         = NewVarAssign();
  nVA->expAct = ShareE(ea);
  nVA->varFor = vf;
  return nVA;
}

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

/* CopyVA
 * Copy a single var assign
 */
PVarAssignTyp CopyVA( pva )
     PVarAssignTyp pva;
{
  return MakeVA( pva->varFor, CopyE(pva->expAct) );
}

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

/* CopyVAL
 * Copy the VarAssignList val.
 */
VarAssignListTyp CopyVAL( val )
     VarAssignListTyp val;
{
  return Copy_list(val,(DataListTyp(*)()) CopyVA);
}

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

static void UnshareVALaux( va )
     PVarAssignTyp va;
{
  va->expAct = ShareE(GetE(UnshareE(va->expAct)));
}

/* UnshareVAL
 * Unshare the var assign list val.
 */
VarAssignListTyp UnshareVAL( val )
     VarAssignListTyp val;
{
  Apply_Proc_list(val,UnshareVALaux);
  return val;
}

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

static  StrBckTyp strBck;

/* SPrintVA
 *  return a string with the Var Assign pointed by pva.
 *  in the format x:t=expr
 */
static void SPrintVA( pva )
     PVarAssignTyp   pva;
{
  char * str;

  str     = SPrintV( pva->varFor, TRUE );
  strBck  = ConcatStrBck( strBck, str );
  free( str );
  strBck  = ConcatStrBck( strBck, "=" );
  str     = ExprToStringE( pva->expAct );
  strBck  = ConcatStrBck( strBck, str );
  free( str );
}


static boolean IsVoidVA( pva )
     PVarAssignTyp   pva;
{
  return IsVariableE(pva->expAct) && (LookNameE(pva->expAct)==pva->varFor);
}


/* PrintVAL
 * Print the var assign list val in the format x.s1=expr1, y.s2=expr2,...
 * pstr is the function used to print strings.
 */
void PrintVAL( val, pstr )
     VarAssignListTyp   val;
     void (*pstr)();
{
  char * str;

  str = SPrintVAL( val );
  pstr(str);
  (void)free(str);
}

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

/* SPrintVAL
 * return a string with the var assign list val
 * in the format x:s1=expr1, y:s2=expr2,...
 * all => print even x:s=x assignments.
 */
char * SPrintVAL( val )
     VarAssignListTyp val;
{
  char * str;

  strBck = CreateStrBck();
  while (val!=NULL) {
    if ( ! IsVoidVA((PVarAssignTyp)LookInfo_list(val)) ) {
      SPrintVA((PVarAssignTyp)LookInfo_list(val));
      val    = Next_list(val);
      break;
    }
    val = Next_list(val);
  }
  while (val!=NULL) {
    if ( ! IsVoidVA((PVarAssignTyp)LookInfo_list(val)) ) {
      strBck = ConcatStrBck( strBck, "," );
      SPrintVA((PVarAssignTyp)LookInfo_list(val));
    }
    val = Next_list(val);
  }
  str = GetStrStrBck( strBck );
  FreeStrBck( strBck );
  return str;
}

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

/* DrawVA
 * Print the var assign pva in a not LOTOS format.
 * pstr is the function used to print strings.
 */
void DrawVA( pva, pstr )
     PVarAssignTyp   pva;
     void (*pstr)();
{
  PrintV( pva->varFor, TRUE, pstr);
  pstr(" = ");
  DrawE( pva->expAct, pstr);
}

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

static void (*stpstr)();

     static void DrawVarAssign( pva )
     PVarAssignTyp   pva;
{
  DrawVA( pva, stpstr);
}


/* DrawVAL
 * Prints the var assign list val.
 * pstr is the function used to print strings.
 */
void DrawVAL( val, pstr )
     VarAssignListTyp val;
     void            (*pstr)();
{
  stpstr = pstr;
  Apply_Proc_list(val,DrawVarAssign);
}

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

/* JoinVAL
 * Join two var assign lists.
 * If the expressions of val2 contain variables defined ( "assigned") in val1,
 * these variables are replaced in the output VAL with the expressions assigned
 * in val1.   val1      EX.: ..,x=3,..
 *              |                |
 *            val2           ..,y=x+1,..        ==>    ..,x=3,..,y=3+1,..
 *              |                |                             |
 *              B                B                             B
 */
VarAssignListTyp JoinVAL( val1, val2 )
     VarAssignListTyp val1,val2;
{
  ExprTyp          e;
  SVdescriptorTyp  tableSV;
  VarAssignListTyp val2n;

  tableSV = CreateSV();
  Insert_VAL_SV( val1, &tableSV );
  for ( val2n=val2; val2n!=NULL; val2n=Next_list(val2n) ) {
    e = GetExprVAL( val2n );
    (void)SubstExprSV ( &e , &tableSV );
    PutExprVAL( val2n, e );
  }
  FreeSV( &tableSV );
  return Join_list( val1, val2 );
}

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

/* InsertVAL
 * Insert VA item 'let var=exp' into the VarAssignList val.
 * (No previous check : variable var may have two assignations, that's to say,
 * if 'let x:s=E' were inserted , another 'let x:s=E2' could be unnoticeably
 * inserted.)
 */
VarAssignListTyp InsertVAL( val, vd, e )
     VarAssignListTyp val;
     DescriptorTyp    vd;
     ExprTyp      e;
{
  return  Insert_list( (DataListTyp)MakeVA( vd, e ) , val );
}

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

/* AddVAL
 * Add item 'let var=exp' into the VarAssignList val.
 * (No previous check : variable var may have two assignations, that's to say,
 * if 'let x=anyexpr' was inserted , another 'let x=...' could be unnoticeably
 * inserted.)
 */
VarAssignListTyp AddVAL( val, vd, e )
     VarAssignListTyp val;
     DescriptorTyp    vd;
     ExprTyp          e;
{
  return  Add_list( (DataListTyp)MakeVA( vd, e ) , val );
}

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

/*
 *  Return true if the formalvariable of pva is vd.
 */
static boolean EqualVarFor( vd, pva)
     DescriptorTyp vd;
     PVarAssignTyp pva;
{
  return( vd == pva->varFor );
}


/* ActExprVAL
 * Return the Actual Expression associated to the var descriptor vd.
 * If it doesn't exist : return NULL.
 */
DescriptorTyp ActExprVAL( val, vd )
     VarAssignListTyp val;
     DescriptorTyp    vd;
{
  if ((val = LookFor_list( (DataListTyp)vd, val, EqualVarFor))==NULL)
    return (DescriptorTyp)NULL;
  else
    return LookVarVAL(val);
}

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

/* Mk_VLEL_VAL
 * Make a new var assign list by combining
 * an Actual Var list ,vl, and a Formal Expression list , el.
 * The lists lengths must be equal.
 * The val is a literal transcription of v1:s1=e1, v2:s2=e2,...as
 * the VAs are joined together through the InsertVAL function, which
 * does not test inequality of FormalVars v1 v2 ... .
 * vl is used only to look at its var names, so it can be reused.
 */
VarAssignListTyp Mk_VLEL_VAL( vl, el )
     ExprListTyp vl, el;
{
  ExprListTyp      eln,vln;
  VarAssignListTyp val;

  eln = el;
  vln = vl;
  val = CreateVAL();
  while (( vln != NULL) && ( eln != NULL )){
    LASSERT( LookSortE((ExprTyp)LookInfo_list(vln))==
	    LookSortE((ExprTyp)LookInfo_list(eln)) );
    val = AddVAL( val, LookNameE((ExprTyp)LookInfo_list(vln)),
		 UnshareE((ExprTyp)GetInfo_list(eln)) );
    vln = Next_list( vln );
    eln = Next_list( eln );
  }
  LASSERT( vln==NULL && eln==NULL );
  Disp_list(el);
  return val;
}

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

/* LookVarVAL
 * Look at (return) the formal variable in the current VarAssign node valn.
 */
DescriptorTyp LookVarVAL( valn )
     VarAssignListTyp valn;
{
  return (*(PVarAssignTyp) LookInfo_list( valn ) ).varFor;
}

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

/* GetVarVAL
 * Get (return) the formal variable in the current VarAssign node valn
 * (of a list) and the varFor is set to 0.
 */
DescriptorTyp GetVarVAL( valn )
     VarAssignListTyp valn;
{
  DescriptorTyp  aux;
  PVarAssignTyp pva;

  pva         = (PVarAssignTyp)GetInfo_list( valn );
  aux         = pva->varFor;
  pva->varFor = (DescriptorTyp) NULL;
  PutInfo_list( valn, (DataListTyp) pva );
  return aux;
}

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

/* PutVarVAL
 * Put a new formal variable to the current VarAssign node valn (of a list)
 * The old varFor must be NULL.
 */
void PutVarVAL( valn, fv )
     VarAssignListTyp valn;
     DescriptorTyp    fv;
{
  PVarAssignTyp pva;

  pva = (PVarAssignTyp) GetInfo_list( valn );
  LASSERT ( pva->varFor == (DescriptorTyp)NULL );
  pva->varFor = fv;
  PutInfo_list( valn, (DataListTyp) pva );
}

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

/* LookExprVAL
 * Look at (return) the actual Expression in the current VarAssign node valn
 */
ExprTyp LookExprVAL( valn )
     VarAssignListTyp valn;
{
  return (*(PVarAssignTyp) LookInfo_list( valn ) ).expAct;
}

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

/* GetExprVAL
 * Get the actual actual Expression in the current VarAssign node valn
 * and the actExp is set to NULL.
 */
ExprTyp GetExprVAL( valn )
     VarAssignListTyp valn;
{
  ExprTyp       aux;
  PVarAssignTyp pva;

  pva         = (PVarAssignTyp)LookInfo_list(valn);
  LASSERT(OwnersE(pva->expAct)!=0);
  aux         = UnshareE(pva->expAct);
  pva->expAct = (ExprTyp) NULL;
  return aux;
}

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

/* PutExprVAL
 * Put a new actual Expr to the current VarAssign node valn (of a list)
 * The old actExpr must be NULL.
 */
void PutExprVAL( valn, ae )
     VarAssignListTyp valn;
     ExprTyp          ae;
{
  PVarAssignTyp pva;

  pva = (PVarAssignTyp) LookInfo_list( valn );
  LASSERT ( pva->expAct == (ExprTyp) NULL );
  pva->expAct = ShareE(ae);
}

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

/* FormalVL_VAL
 * Build the formal variable list of a VAL.
 */
ExprListTyp FormalVL_VAL( val )
     VarAssignListTyp val;
{
  ExprListTyp vl;
  VarAssignTyp va;

  vl = CreateEL();
  for ( ;val!=NULL; val=Next_list(val) ) {
    va = (*(PVarAssignTyp) LookInfo_list( val ) );
    vl = AddEL( MakeE(va.varFor,VariableC), vl );
  }
  return vl;
}

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

/* ActualEL_VAL
 * Make the actual expression list of a VAL.
 */
ExprListTyp ActualEL_VAL( val )
     VarAssignListTyp val;
{
  ExprListTyp   el;
  PVarAssignTyp pva;

  el = CreateEL();
  for ( ;val!=NULL; val=Next_list(val) ) {
    pva = (PVarAssignTyp) LookInfo_list( val );
    el  = AddEL( CopyE(pva->expAct), el ); /*mse*/
  }
  return el;
}

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

/* IsNotPrintableVAL
 * Say whether the val contains only void assignments:
 * val == NULL  or  val == x:s=x, y:s=y, ...
 */
boolean IsNotPrintableVAL( val )
     VarAssignListTyp val;
{
  /*
   * return val==NULL;
   */

  boolean       isVoid;
  PVarAssignTyp pva;

  for ( isVoid=TRUE; val!=NULL && isVoid; val=Next_list(val) ) {
    pva    = (PVarAssignTyp) LookInfo_list( val );
    isVoid = IsVariableE(pva->expAct) && pva->varFor==LookNameE(pva->expAct);
  }
  return isVoid;
}

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

/* IsVoidVAL
 * Say if the val contains only void assignments:
 * val == NULL  or  val == x:s=x, y:s=y, ...
 */
boolean IsVoidVAL( val )
     VarAssignListTyp val;
{
  boolean       isVoid;
  PVarAssignTyp pva;

  for ( isVoid=TRUE; val!=NULL && isVoid; val=Next_list(val) ) {
    pva    = (PVarAssignTyp) LookInfo_list( val );
    isVoid = IsVariableE(pva->expAct) && pva->varFor==LookNameE(pva->expAct);
  }
  return isVoid;
}

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

/* EqualVA
 * Say if two VarAssigns are equal
 */
boolean EqualVA( pva1, pva2 )
     PVarAssignTyp pva1, pva2;
{
  return
    ( pva1->varFor == pva2->varFor ) &&
      EqualE( pva1->expAct, pva2->expAct );
}

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

/* SubSet_VAL
 * Determine if every VA of val1 is in val2.
 */
boolean SubSet_VAL( val1, val2 )
     VarAssignListTyp val1,val2;
{
  return SubSet_list( val1, val2, EqualVA );
}

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











