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

/***********************************
  
  David Larrabeiti Lopez
  
  20-2-1991
  
  Process instantiations expansion
  
  3 July 1992 David
  The names of the variables created during the parameterized expansion
  are copied from the process definition argument variables.
  
  15 Dec 1992 David
  In STEP Mode the plet carries a list of process instantiations in its
  Sync Tree Attribute.
  
  COMPILATION OPTIONS: The behaviour of this module can be modified
  by the following compilation flags:
  
  (none)
  
  
  ************************************/


#include "badefca.h"
#include "baattr.h"
#include "batables.h"
#include "basust_v.h"
#include "expre_br.h"
#include "eximmed.h"
#include "limisc.h"
#include "balotosf.h"

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

/* InsVinP
 * If any parameter of the instantation p is a expression (not 
 * a variable), then it is replaced with a new variable with the 
 * parameter as a parameterized value.
 */
static void InsVinP( p )
     BehTyp p;
{
  PAttrTyp    a;
  ExprTyp     e,v;
  ExprListTyp el,del;
  
  UnshareA( p, ELA ); /*mse*/
  if ( (a = LookA(p,ELA))!=NULL ) {
    del = (ExprListTyp)LookAInfo( LookA( GetP_def(LookNameB(p)), ELA ) );
    for ( el = (ExprListTyp)LookAInfo(a);
	 el!=NULL ;
	 el=Next_list(el), del=Next_list(del) ) {
      e = UnshareE((ExprTyp)GetInfo_list( el ));
      if ( LookTypeE(e)==OperationC ) {
        v = MakeE( EqualV_entry( LookNameE((ExprTyp)LookInfo_list(del)) ),
		  VariableC );
        PutPVarE( v, e );
        PutInfo_list( el, (DataListTyp)ShareE(v) );
      }
      else
	PutInfo_list( el, (DataListTyp)ShareE(e) );
    }
    LASSERT(del==NULL);
  }
}

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

/* ArrangeDef
 * if VarsOfEL(fvl) intersection VarsOfEL(ael) == V != 0
 *    return a copy of the definition where variables V are redefined
 * else
 *    return the definition itself
 */
static BehTyp ArrangeDef( inst )
     BehTyp inst;
{
  ListTyp l1,l2,l1h,conflictives;
  SVdescriptorTyp sv;
  BehTyp def;
  ExprListTyp fvl,ael;
  DescriptorTyp cvd;
  
  def = GetP_def( LookNameB(inst) );
  fvl = (ExprListTyp)LookAInfo(LookA(def,ELA));
  ael = (ExprListTyp)LookAInfo(LookA(inst,ELA));
  
  l1h = VarsOfEL( fvl );
  l2 = VarsOfEL( ael );
  conflictives = Create_list();
  if (l2!=NULL) {
    for ( l1=l1h; l1!=NULL ; l1=Next_list(l1) )
      if ( In_list( LookInfo_list(l1), l2, EqInt ) )
	conflictives = Add_list( LookInfo_list(l1), conflictives );
    Disp_list( l2 );
  }
  Disp_list( l1h );
  
  if ( conflictives != NULL ) {
    sv = CreateSV();
    for ( ; fvl!=NULL; fvl=Next_list(fvl), ael= Next_list(ael) )
      if ( In_list( (DataListTyp)(cvd=LookNameE((ExprTyp)LookInfo_list(fvl))), 
		   conflictives, EqInt ) )
	InsertSV( cvd, MakeE(EqualV_entry(cvd),VariableC), &sv );
    def = CopyB( def );
    
    /*
       InsertBehDefSV( LookArgB(def,1), &sv );
       */
    
    
    SubstBehSV( def, &sv );
    FreeSV(&sv);
    Disp_list( conflictives );
  }
  def = ShareB(def);
  return def;
}


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

/* Inst_Processing
 * Returns the process instantiation defined by the ProcessInstCell procInst.
 * It consists of :
 *                  RelabellingC * Only if the actual gatelist of the instCell
 *                       |         is different from the formal defCell's gl.
 *                       |
 *                     PLetC     * Always, although the VAL is empty .
 *                       |
 *                       B
 *            (shared with ProcessDefC)
 */
BehTyp Inst_Processing( procInst )
     BehTyp procInst;
{
  BehTyp           relab,pLet,def,pil,procInst2;
  RelabFuncListTyp rfl;
  ExprListTyp      formalVl,actualEl;
  GateListTyp      formalGl,actualGl;
  PAttrTyp         attr;
  
  LASSERT( LookTypeB( procInst ) == ProcessInstC );
  
  
  /*
     def = ArrangeDef( procInst );
     */
  
  def = GetP_def(LookNameB(procInst));
  
  if ( IS_STEP_EXP )
    procInst2 = CopyB( procInst );
  
  
  LASSERT( LookTypeB( def ) == ProcessDefC );
  
  /*------------- parameterized  -----------------*/
  if (IS_PARAMETERIZED_EXP) 
    InsVinP( procInst );
  
  /*----------- pLetCell ---------------*/
  
  pLet = MakeB( 0, PletC );
  attr = LookA( def, ELA );
  if ( attr!=NULL ) {
    if ( ! IS_PARAMETERIZED_EXP) 
      /*mse*/   UnshareA( procInst, ELA ); 
    formalVl = (ExprListTyp)LookAInfo( attr );
    LASSERT ( formalVl != NULL );
    attr     = GetA( procInst, ELA );
    actualEl = (ExprListTyp)GetAInfo( attr );
    PutA( pLet, MakeA( (AttrValueTyp)Mk_VLEL_VAL(formalVl,actualEl),
		      VALA ) );               /* no need to copy formalVl */
    FreeA(attr);
  }
  /*  else
      PutA( pLet, MakeA( (AttrValueTyp)NULL, VALA ) );
      */
  
  /*----------- RelabellingCell ---------------*/
  /* if both the definition and the instantiation have the same list of gates
   *  there is no need to relabel
   */
  
  relab    = NULL;
  formalGl = (GateListTyp)LookAInfo( LookA( def, GLA ) );
  if ( formalGl != NULL ) {
    attr     = LookA( procInst, GLA );
    actualGl = (GateListTyp)LookAInfo( attr );
    rfl      = Mk_GLs_RFL( actualGl, formalGl );  /* doesn't touch the lists */
    if ( rfl!=NULL ) {
      relab = MakeB(0, RelabellingC);
      PutA( relab, MakeA((AttrValueTyp)rfl, RFLA ) );
    }
  }
  
  PutArgB( pLet, LookArgB( def, 1 ), 1 );
  
  
  /* free the process definition cell. Shared in ArrangeDef 
     FreeB(UnshareB(def));  */
  
  if ( relab!=NULL )
    PutArgB( relab, pLet, 1 );
  else
    relab = pLet;
  LASSERT(LookCopy(relab)>=0);
  LASSERT(LookCopy(pLet)>=0);
  LASSERT(LookCopy(LookArgB( def, 1 ))>=0);
  
  /*  LASSERT(LookCopy(procInst)==0); */
  
  FreeB( procInst );
  
  if ( IS_STEP_EXP ) {
    if ( LookA(procInst2,STA)!=NULL ) {
      UnshareA( procInst2, STA );
      pil = (BehTyp)LookAInfo(LookA(procInst2,STA));
      LASSERT( LookTypeB(pil)==ProcessInstC );
      pil = ConcatUB( pil, procInst2 );
      PutA( pLet, GetA(procInst2,STA) ) ;
    }
    else
      PutA( pLet, MakeA( (AttrValueTyp)ShareB(procInst2), STA ) );
  }
  
  return relab;
  
}

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