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

/***********************************
  
  David Larrabeiti Lopez
  
  25-04-91
  
  GateChoice operator one-level Expansion.
  
  choice g1,..,gn in [ h1,...,h2 ] [] B
  
  where B is any behaviour.
  
  COMPILATION OPTIONS: The behaviour of this module can be modified
  by the following compilation flags:
  
  SDEBUG : activate debugging mode
  
  ************************************/


#include "expre_br.h"
#include "baattr.h"
#include "badefca.h"
#include "eximmed.h"
#include "excount.h"


#define MAXFORMALGATES 50
#define MAXACTUALGATES 50

static int m;            /* number of formal gates ( digits of the counter ) */
static int n;            /* number of actual gates ( module of the counter ) */
static DescriptorTyp formal[MAXFORMALGATES],
actual[MAXACTUALGATES];

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

/* Initialize_GateNames_and_Counter
 * Fills in formal[] and actual[] with the formalgatenames and with the
 * actualgatenames respectively , of the gate declaration list.
 */
static void Initialize_GateNames_and_Counter( gatedeclist )
     GateDecListTyp gatedeclist;
{
  PGateDecTyp gatedecPt;
  GateListTyp glist,glistNode;
  
  gatedecPt = (PGateDecTyp)LookInfo_list(gatedeclist);
  glist     = gatedecPt->agl;
  for ( n=0; glist!=NULL ; glist=Next_list(glist),n++ )
    actual[n] = (DescriptorTyp)LookInfo_list(glist);
  
  glist     = GateSet_to_GateList( gatedecPt->fgs );
  glistNode = glist;
  for ( m=0; glistNode!=NULL; glistNode=Next_list(glistNode),m++ )
    formal[m] = (DescriptorTyp)LookInfo_list(glistNode);
  FreeGL( glist );
  
  Initialize_Counter( m, n );
  
}

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

/* MakeRelabel
 * Builds a relabel cell with the combination of gates given by the current
 * value of "counter".
 */
static BehTyp MakeRelabel()
{
  int i;
  RelabFuncListTyp rfl;
  BehTyp relab;
  
  rfl = CreateRFL();
  
  for ( i=0 ; i<m ; i++ )
    rfl = AddRFL( rfl, actual[ counter[m-1-i] ], formal[ i ] );
  
  relab = MakeB(0,RelabellingC);
  PutA( relab, MakeA((AttrValueTyp)rfl,RFLA) );
  
  return relab;
  
}

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

/* SingleGateChoice_Expand
 * Expands a single gate declaration gate-choice into a beh-choice of relabels.
 */
static BehTyp SingleGateChoice_Expand( b )
     BehTyp b;
{
  BehTyp relab,bi,result;
  
  result = NULL;
  bi     = GetArgB(b,1);
  Initialize_GateNames_and_Counter( (GateDecListTyp)LookAInfo(LookA(b,GDLA)) );
  
  do
    {
      relab=MakeRelabel();
      result=AppendUB( result, relab );
      PutArgB( relab, CopyUntilActB(bi), 1 );
    }
  while (Increment());
  
  FreeB(b);
  FreeB(bi);
  
  return result;
}

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

/* Normalize_GateChoice
 * Splits a multiple gatechoice into a succesion of single ones.
 * Ex. choice a,b in [ x, y ], c in [ y ] [] B =
 *     choice a,b in [ x, y ] []
 *          choice c in [ y ] [] B 
 */
static BehTyp Normalize_GateChoice( b )
     BehTyp b;
{
  BehTyp         bi,newgc,out;
  GateDecListTyp gdl,gdnode;
  PAttrTyp       attr;
  
  if ( Length_list( (ListTyp)LookAInfo(LookA( b, GDLA )) ) == 1 )
    return b;
  else {
    bi = GetArgB( b, 1 );
    UnshareA( b, GDLA );
    attr = GetA( b, GDLA );
    gdl  = (GateDecListTyp)GetAInfo( attr );
    
    out = NULL;
    while ( gdl!=NULL ) {
      gdnode = gdl;
      gdl    = ExtractNode_list( gdnode, gdl );
      newgc  = MakeB( 0, GateChoiceC );
      PutA( newgc, MakeA((AttrValueTyp)gdnode,GDLA) );
      out = ConcatUB( out, newgc );
    }
    PutArgB( newgc, bi, 1 );
    
    FreeB(b);
    FreeA(attr);
    
    return out;
  }
  
}

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

/* Sum_Expr_Processing
 * Expands any gate-choice.
 */
BehTyp Sum_Expr_Processing( b )
     BehTyp b;
{
  return SingleGateChoice_Expand( Normalize_GateChoice( b ) );
}

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



