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

/***********************************
  
  TLet_Processing.
  
  Processing of the TLet operator tlet.
  
  tlet = Let v1:s1  in b
  
  where b is any behaviour.
  
  The processing stops after any gate or internal event. 
  This file was based in exlet.c  from which differs in 
  the processing of the gates, "i" and "let".  

  COMPILATION OPTIONS: The behaviour of this module can be modified
  by the following compilation flags:
  
  (none)
  
  ************************************/
#ifdef TIME 

#include "limisc.h"
#include "badefca.h"
#include "baattr.h"
#include "basust_v.h"
#include "expre_br.h"
#include "balotosf.h"
#include "batime.h"


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

/* ProcTLet_guard
 */
static BehTyp ProcTLet_guard ( b, vala, sv )
     BehTyp           b;
     PAttrTyp         vala;
     SVdescriptorTyp *sv;
{
  char r;
  PAttrTyp attr;
  PredicateTyp pred;
  
  if ( Var_in_Pred_SV((PredicateTyp)LookAInfo(LookA(b,PA)),sv) ) {
    UnshareA( b, PA );
    attr = LookA( b, PA );
    pred = (PredicateTyp)GetAInfo(attr);
    (void)SubstPredSV( &pred, sv );
    PutAInfo( attr, (AttrValueTyp)pred );
  }
  r = LookPredicate( b );
  SolvePredicateBeh( b );
  if (r == 'f')
    return b;
  else
    if (r == 't')
      return TLetProc( b, vala, sv );
    else {
      PutArgB( b, TLetProc( GetArgB( b,1 ), vala, sv ), 1 );
      return b;
    }
}

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

/* ProcTLet_par
 */
static BehTyp ProcTLet_par( b, vala, sv )
     BehTyp           b;
     PAttrTyp         vala;
     SVdescriptorTyp *sv;
     
{
  
    if ( IsUsedInBehSV( sv, LookArgB(b,1) ) ) 
      PutArgB( b, TLetProc( GetArgB(b,1), vala, sv ), 1 );
    if ( IsUsedInBehSV( sv, LookArgB(b,2) ) ) 
      PutArgB( b, TLetProc( GetArgB(b,2), vala, sv ), 2 );
  
  return b;
}

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

/* ProcTLet_ena
 */
static BehTyp ProcTLet_ena( b, vala, sv )
     BehTyp           b;
     PAttrTyp         vala;
     SVdescriptorTyp *sv;
     
{ 
 
  if ( IsUsedInBehSV( sv, LookArgB(b,1) ) ) 
    PutArgB( b, TLetProc( GetArgB(b,1), vala, sv ), 1 );
  
  if ( IsUsedInBehSV( sv, LookArgB(b,2) ) ) 
    PutArgB( b, TLetProc( GetArgB(b,2), vala, sv ), 2 );
  
  return b;
}

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

/* ProcTLet_dis
 */
static BehTyp ProcTLet_dis( b, vala, sv )
     BehTyp           b;
     PAttrTyp         vala;
     SVdescriptorTyp *sv;
     
{
  
  if ( IsUsedInBehSV( sv, LookArgB(b,1) ) ) 
    PutArgB( b, TLetProc( GetArgB(b,1), vala, sv ), 1 );
 
  if ( IsUsedInBehSV( sv, LookArgB(b,2) ) ) 
    PutArgB( b, TLetProc( GetArgB(b,2), vala, sv ), 2 );
  return b;
}

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

/* ProcTLet_alt
 */
static BehTyp ProcTLet_alt(b,vala,sv)
     BehTyp           b;
     PAttrTyp         vala;
     SVdescriptorTyp *sv;
{
  int n,i;
  
  n = NumArgB(b);
  for ( i=1; i<=n; i++ )
    if ( IsUsedInBehSV( sv, LookArgB(b,i) ) ) 
      PutArgB( b, TLetProc( GetArgB( b, i ), vala, sv ), i );
  return b;
}

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

/* ProcTLet_i
 */
static BehTyp ProcTLet_i( b,sv )
     BehTyp   b;
     SVdescriptorTyp *sv;
{
  PTimeTyp time;
  PAttrTyp a;
  
  if ( Var_in_TA_SV((PTimeTyp)LookAInfo(LookA(b,TA)),sv) ) {
    UnshareA( b, TA );
    a  = LookA( b, TA );
    time = (PTimeTyp)GetAInfo( a );
    Subst_TA_SV( time, sv ); 
    if (LookNameE(time->upper_bound)==FindO_time("neg")) {
      TrfStop(b);
      return b;  
    } 
    if (LookNameE(time->lower_bound)==FindO_time("neg")) 
      ChangeNameE(time->lower_bound,FindO_time("0")); 
    PutAInfo( a, (AttrValueTyp)time );
  }
  return b;
}

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

/* ProcTLet_hid
 */
static BehTyp ProcTLet_hid( b, vala, sv )
     BehTyp           b;
     PAttrTyp         vala;
     SVdescriptorTyp *sv;
{
    PutArgB( b, TLetProc( GetArgB( b,1 ), vala, sv ), 1 );
  return b;
}

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

/* ProcTLet_rel
 */
static BehTyp ProcTLet_rel( b, vala, sv )
     BehTyp           b;
     PAttrTyp         vala;
     SVdescriptorTyp *sv;
{
    PutArgB( b, TLetProc( GetArgB( b,1 ), vala, sv ), 1 );
  return b;
}

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

/* ProcTLet_parc
 */
static BehTyp ProcTLet_parc( b, vala, sv )
     BehTyp           b;
     PAttrTyp         vala;
     SVdescriptorTyp *sv;
{
    PutArgB( b, TLetProc( GetArgB( b,1 ), vala, sv ), 1 );
  return b;
}

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

/* ProcTLet_choice
 */
static BehTyp ProcTLet_choice ( b, vala, sv )
     BehTyp           b;
     PAttrTyp         vala;
     SVdescriptorTyp *sv;
{
  PutArgB( b, TLetProc( GetArgB( b,1 ), vala, sv ), 1 );
  return b;
}

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

/* ProcTLet_stop
 */
static BehTyp ProcTLet_stop( b )
     BehTyp b;
{  
  return b;
}

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

/* ProcTLet_term
 * Only possible when expanding something iexpanded.
 */
static BehTyp ProcTLet_term( b, sv )
     BehTyp b;
     SVdescriptorTyp *sv;
{  
  PAttrTyp ela;
  ExprListTyp el;
  
  if ( Var_in_EL_SV((ExprListTyp)LookAInfo(LookA(b,ELA)),sv) ) {
    UnshareA(b,ELA);
    ela = LookA(b,ELA);
    el  = (ExprListTyp)GetAInfo(ela);
    Subst_EL_SV( el, sv );
    PutAInfo( ela, (AttrValueTyp)el );
  }
  return b;
}

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

/* ProcTLet_exit
 */
static BehTyp ProcTLet_exit ( b,sv )
     BehTyp           b;
     SVdescriptorTyp *sv;
{
  PAttrTyp ola;
  OfferListTyp ol;
  
  if ( Var_in_OL_SV( (OfferListTyp)LookAInfo(LookA(b,OLA)), sv ) ) {
    UnshareA(b,OLA);
    ola = LookA(b,OLA);
    ol  = (OfferListTyp)GetAInfo(ola);
    Subst_OL_SV( ol, sv );
    PutAInfo( ola, (AttrValueTyp)ol );
  }
  return b;
}

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


/* ProcTLet_gate
 */
static BehTyp ProcTLet_gate ( b, sv )
     BehTyp           b;
     SVdescriptorTyp *sv;
{
  PAttrTyp a;
  char     r;
  OfferListTyp ol;
  PredicateTyp p;
  PTimeTyp   time;

 
  if ( Var_in_OL_SV((OfferListTyp)LookAInfo(LookA(b,OLA)),sv) ){
    UnshareA( b, OLA );
    a  = GetA( b, OLA );
    ol = (OfferListTyp)GetAInfo( a );
    Subst_OL_SV( ol, sv );
    PutAInfo( a, (AttrValueTyp)ol );
    PutA( b, a );
  }
  
  
  time= (PTimeTyp)LookAInfo(LookA(b,TA));
  if ( Var_in_TA_SV((PTimeTyp)LookAInfo(LookA(b,TA)),sv) ) {
    UnshareA( b, TA );
    a  = GetA( b, TA );
    time = (PTimeTyp)GetAInfo( a );
    Subst_TA_SV( time, sv ); 
    if (LookNameE(time->upper_bound)==FindO_time("neg")) {
      TrfStop(b);
      return b;  
    } 
    if (LookNameE(time->lower_bound)==FindO_time("neg")) 
      ChangeNameE(time->lower_bound,FindO_time("0")); 
    PutAInfo( a, (AttrValueTyp)time );
    PutA( b, a );
    
  }
  
  p = (PredicateTyp)LookAInfo(LookA(b,PA));
  if ( p!=NULL )
    if ( Var_in_Pred_SV( p, sv ) )
      { UnshareA( b, PA );
        a = GetA( b, PA );
        p = (PredicateTyp)GetAInfo( a );
        (void)SubstPredSV( &p, sv );
        PutAInfo( a, (AttrValueTyp)p );
        PutA( b, a );
      }
  r = LookPredicate( b );
  SolvePredicateBeh( b );
  return b;
}


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

/* ProcTLet_proc
 */
static BehTyp ProcTLet_proc( b,sv )
     BehTyp           b;
     SVdescriptorTyp *sv;
{
  PAttrTyp ela;
  ExprListTyp el;
  
  if ( Var_in_EL_SV((ExprListTyp)LookAInfo(LookA(b,ELA)),sv) ) {
    UnshareA(b,ELA);
    ela = LookA(b,ELA);
    el  = (ExprListTyp)GetAInfo(ela);
    Subst_EL_SV( el, sv );
    PutAInfo( ela, (AttrValueTyp)el );
  }
  return b;
}

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

/* ProcTLet_plet
 */
static BehTyp ProcTLet_plet( b, sv )
     BehTyp           b;
     SVdescriptorTyp *sv;
{
  VarAssignListTyp val2;
  PAttrTyp attr;
  
  val2 = (VarAssignListTyp)LookAInfo(LookA(b,VALA));
  if ( val2==NULL ) 
    return b;
  else {
    if ( Var_in_VAL_RightSide_SV(val2,sv) ) {
      UnshareA( b, VALA );      
      attr = LookA( b, VALA );
      val2 = (VarAssignListTyp)GetAInfo( attr );
      Subst_VAL_RightSide_SV( val2, sv );
      PutAInfo( attr, (AttrValueTyp)val2 );
    }
    return b;
  }
}

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

/* ProcTLet_Let
 */
static BehTyp ProcTLet_let( b, vala, sv )
     BehTyp           b;
     PAttrTyp         vala;
     SVdescriptorTyp *sv;
{
  VarAssignListTyp val,val2;
  PAttrTyp         vala2;
  BehTyp           b1,res;
  
  b1   = GetArgB(b,1);
  val = (VarAssignListTyp)LookAInfo(vala);
  UnshareA( b, VALA );      
  vala2 = LookA( b, VALA );
  val2 = (VarAssignListTyp)GetAInfo(vala2);
  LASSERT(val2!=NULL); 
  
  if ( Var_in_VAL_BothSides_SV( val2, sv ) )
    Subst_VAL_BothSides_SV( val2, sv );
  PutAInfo( vala2, (AttrValueTyp)val2 );
  res =  TLetProc( b1 , vala , sv );
  PutArgB(b,res,1)  ;
  return b;
}


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


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

/* ProcTLet_it
 * notice that the TLet advances more than one action.
 */
static BehTyp ProcTLet_it( b, vala, sv )
     BehTyp           b;
     PAttrTyp         vala;
     SVdescriptorTyp *sv;
{
  PutArgB( b, TLetProc( GetArgB( b, 1 ), vala, sv ), 1 );
  return b;
}

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

/* TLetProc
 * Adds a TLet(vala) after the first actions of the behaviour b.
 * If a variable definition is found then a new vala is created adding
 * the redefinition of the variable.
 * sv is the replacement table of vala.
 * Warning: val can not be NULL 
 */
BehTyp TLetProc( b, vala, sv )
     BehTyp           b;
     PAttrTyp         vala;
     SVdescriptorTyp *sv;
{
  BehTyp res;
  
  res = b;
  switch ( LookTypeB(b) )
    { case IC:
	res = ProcTLet_i( b, sv );
	break;
      case ChoiceC:
	res = ProcTLet_choice( b, vala, sv );
	break;
      case ContSetC:
      case StopC :
	res = ProcTLet_stop( b );
	break;
      case ParallelC :
	res = ProcTLet_par( b, vala, sv );
	break;
      case AlternativeC :
	res = ProcTLet_alt( b, vala, sv );
	break;
      case DisablingC :
	res = ProcTLet_dis( b, vala, sv );
	break;
      case LetC :
	res = ProcTLet_let( b, vala, sv );
	break;
      case PletC :
	res = ProcTLet_plet( b, sv );
	break;
      case GuardC :
	res = ProcTLet_guard( b, vala, sv );
	break;
      case GateC :
	res = ProcTLet_gate( b,sv );
	break;
      case ExitC : 
	res = ProcTLet_exit( b, sv );
	break;
      case ProcessInstC :
	res = ProcTLet_proc( b, sv );
	break;
      case TerminationC :
	res = ProcTLet_term( b, sv );
	break;
      case HidingC:
	res = ProcTLet_hid( b, vala, sv );
	break;
      case EnablingC :
	res = ProcTLet_ena( b, vala, sv );
	break;
      case RelabellingC :
	res = ProcTLet_rel( b, vala, sv );
	break;
      case ParC:
      case GateChoiceC:
	res = ProcTLet_parc( b, vala, sv );
	break;
      case InterleavedC :
	res = ProcTLet_it( b, vala, sv );
	break;
	
      default :
	Error("TLetProc: Unexpected Cell Type." );
      }
  return res;
}

/*----------------------------------------------------------------*/
#endif 
