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

/***********************************
  
  David Larrabeiti Lopez
  
  19-02-91
  
  Plet_Processing.
  
  Processing of the PLet operator plet.
  
  plet = Plet v1:s1=E1,...,vn:sn=En in b
  
  where b is any behaviour.
  
  COMPILATION OPTIONS: The behaviour of this module can be modified
  by the following compilation flags:
  
  (none)

  05-10-94 
  Time Attributes Supported (G. Rabay)  
  
  ************************************/

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


static BehTyp PletProc();

static void PutPila( b, pila )
     BehTyp   b;
     PAttrTyp pila;
{
  if ( IS_STEP_EXP && pila!=NULL ) {
    LASSERT( LookA(b,STA)==NULL );
    PutA( b, pila );
  }
}

/*----------------------------------------------------------------*/
/*
   static void PutPilaEvent( b, pila )
   BehTyp   b;
   PAttrTyp pila;
   {
   LASSERT( LookTypeB(b)==GateC ||LookTypeB(b)==ExitC ||LookTypeB(b)==IC );
   if ( IS_STEP_EXP ) {
   if ( pila!=NULL ) {
   LASSERT( LookA(b,STA)==NULL );
   PutA( b, CopyA(pila) );
   }
   PutAInfo( LookA(b,STA),
   (AttrValueTyp)ConcatUB( (BehTyp)GetAInfo(LookA(b,STA)), b ) );
   }
   }
   */
/*----------------------------------------------------------------*/

static void Plet_On_VL( vlPt, valPt )
     ExprListTyp *vlPt;
     VarAssignListTyp *valPt;
{
  ExprTyp var,newv;
  DescriptorTyp dv;
  ExprListTyp vl;
  
  vl = *vlPt;
  for ( ; vl!= NULL; vl=Next_list( vl ) ) {
    var  = UnshareE((ExprTyp)GetInfo_list( vl ));
    dv   = LookNameE( var );
    newv = MakeE( EqualV_entry(dv), VariableC );
    PutInfo_list( vl, (DataListTyp)ShareE(newv) );
    *valPt = AddVAL( *valPt, dv, CopyE(newv) ); /*mse*/
    FreeE( var );
  }
}

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

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

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

/* ProcPlet_ena
 */
static BehTyp ProcPlet_ena( b, vala, psv, pila )
     BehTyp           b;
     PAttrTyp         vala, pila;
     SVdescriptorTyp *psv;
     
{
  VarAssignListTyp val, val2;
  ExprListTyp      el;
  SVdescriptorTyp  sv2;
  PAttrTyp         ela, vala2;
  
  PutArgB( b, PletProc( GetArgB(b,1), vala, psv, pila ), 1 );
  
  el = (ExprListTyp)LookAInfo( LookA( b, ELA ) );
  if ( el!=NULL ) {
    val  = (VarAssignListTyp)LookAInfo(vala);
    val2 = CopyVAL(val);
    UnshareA( b, ELA );
    ela = LookA( b, ELA );
    el = (ExprListTyp)GetAInfo( ela );
    Plet_On_VL( &el, &val2 );
    PutAInfo( ela, (AttrValueTyp)el );
    vala2 = MakeA( (AttrValueTyp)val2, VALA );
    sv2   = CreateSV();
    Insert_VAL_SV( val2, &sv2 );
    PutArgB( b, PletProc( GetArgB(b,2), vala2, &sv2, pila ), 2 );
    FreeSV( &sv2 );
    FreeA( vala2 );
  } 
  else
    PutArgB( b, PletProc( GetArgB(b,2), vala, psv,pila ), 2 );
  
  return b;
}

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

/* ProcPlet_i
 */
static BehTyp ProcPlet_i( b, vala, pila, psv )
     BehTyp   b;
     PAttrTyp vala, pila;
     SVdescriptorTyp *psv;
{
  BehTyp plet,b1;

#ifdef TIME 
  PTimeTyp time;
  PAttrTyp a;
#endif 

  plet = MakeB(0,PletC);
  if (vala!=NULL)
    PutA(plet,vala);
  b1 = GetArgB( b, 1 );
  PutArgB( b, plet, 1 );
  PutArgB( plet, b1, 1 );
  PutPila( plet, pila );
  
#ifdef TIME
  if ( Var_in_TA_SV((PTimeTyp)LookAInfo(LookA(b,TA)),psv) ) {
    UnshareA( b, TA );
    a  = LookA( b, TA );
    time = (PTimeTyp)GetAInfo( a );
    Subst_TA_SV( time, psv ); 
    if (LookNameE(time->upper_bound)==FindO_time("neg")) {
      PutAInfo( a, (AttrValueTyp)time );
      TrfStop(b);
      return b;  
    } 
    if (LookNameE(time->lower_bound)==FindO_time("neg")) 
      ChangeNameE(time->lower_bound,FindO_time("0")); 
    PutAInfo( a, (AttrValueTyp)time );
  }
#else
 psv = psv; /* lint, don't complain */
#endif
  
  return b;
}

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

/* ProcPlet_parc
 */
static BehTyp ProcPlet_parc( b, vala, psv, pila )
     BehTyp           b;
     PAttrTyp         vala, pila;
     SVdescriptorTyp *psv;
{
  PutArgB( b, PletProc( GetArgB( b,1 ), vala, psv, pila ), 1 );
  return b;
}

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

/* ProcPlet_hid
 */
static BehTyp ProcPlet_hid( b, vala, psv, pila )
     BehTyp           b;
     PAttrTyp         vala, pila;
     SVdescriptorTyp *psv;
{
  PutArgB( b, PletProc( GetArgB( b,1 ), vala, psv, pila ), 1 );
  return b;
}

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

/* ProcPlet_rel
 */
static BehTyp ProcPlet_rel( b, vala, psv, pila )
     BehTyp           b;
     PAttrTyp         vala, pila;
     SVdescriptorTyp *psv;
{
  PutArgB( b, PletProc( GetArgB( b,1 ), vala, psv, pila ), 1 );
  return b;
}

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

/* ProcPlet_choice
 */
static BehTyp ProcPlet_choice ( b, vala, pila )
     BehTyp   b;
     PAttrTyp vala, pila;
{
  VarAssignListTyp val, val2;
  SVdescriptorTyp  sv2;
  PAttrTyp         attr, vala2;
  ExprListTyp      vl;
  
  val  = (VarAssignListTyp)LookAInfo(vala);
  val2 = CopyVAL(val);
  
  UnshareA(b,ELA);
  attr = LookA( b, ELA );
  vl   = (ExprListTyp)GetAInfo( attr );
  LASSERT( vl!=NULL );
  
  Plet_On_VL( &vl, &val2);
  
  PutAInfo( attr, (AttrValueTyp)vl );
  vala2 = MakeA( (AttrValueTyp)val2, VALA );
  sv2  = CreateSV();
  if ( val2!=NULL )
    Insert_VAL_SV( val2, &sv2 );
  PutArgB( b, PletProc( GetArgB(b,1), vala2, &sv2, pila ), 1 );
  FreeSV( &sv2 );
  FreeA( vala2 );
  
  return b;
  
}

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

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

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

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

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

/* ProcPlet_alt
 */
static BehTyp ProcPlet_alt( b, vala, psv, pila )
     BehTyp           b;
     PAttrTyp         vala, pila;
     SVdescriptorTyp *psv;
{
  int n,i;
  
  n = NumArgB(b);
  for ( i=1; i<=n; i++ )
    PutArgB( b, PletProc( GetArgB( b, i ), vala, psv, pila ), i );
  return b;
}

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

/* ProcPlet_dis
 */
static BehTyp ProcPlet_dis( b, vala, psv, pila )
     BehTyp           b;
     PAttrTyp         vala, pila;
     SVdescriptorTyp *psv;
{
  PutArgB( b, PletProc( GetArgB( b, 1 ), vala, psv, pila ), 1 );
  PutArgB( b, PletProc( GetArgB( b, 2 ), vala, psv, pila ), 2 );
  return b;
}

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

/* ProcPlet_par
 */
static BehTyp ProcPlet_par( b, vala, psv, pila )
     BehTyp           b;
     PAttrTyp         vala, pila;
     SVdescriptorTyp *psv;
{
  PutArgB( b, PletProc( GetArgB( b, 1 ), vala, psv, pila ), 1 );
  PutArgB( b, PletProc( GetArgB( b, 2 ), vala, psv, pila ), 2 );

  return b;
}

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

#ifdef TIME
/* Plet_On_TA 
 * substitutes free variables in time bounds and 
 * and creates a new one, if there is a var in time, and adds it to 
 * the   VarAssignListTyp valPt
*/
static void Plet_On_TA( timePt, valPt, psv )
     PTimeTyp *timePt;
     VarAssignListTyp *valPt;
     SVdescriptorTyp *psv;
{
  ExprTyp var,newv;
  DescriptorTyp dv;
  PTimeTyp t;
  
  t = *timePt;
  Subst_TA_SV( t, psv );
  if (t->tvar != NULL){
    var = UnshareE(t->tvar);
    dv  = LookNameE( var );
    newv = MakeE( EqualV_entry(dv), VariableC );
    t->tvar = ShareE(newv );
    *valPt = AddVAL( *valPt, dv, CopyE(newv) ); /*mse*/
    FreeE( var );
  }
}
#endif

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

static void Plet_On_OL( olPt, valPt, psv )
     OfferListTyp *olPt;
     VarAssignListTyp *valPt;
     SVdescriptorTyp *psv;
{
  ExprTyp var,newv;
  DescriptorTyp dv;
  OfferListTyp ol;
  
  ol = *olPt;
  Subst_OL_SV( ol, psv );
  while (ol != NULL) {
    if ( LookKindOffer(ol)==QUESTION ) {
      var = GetExprOffer( ol );
      dv  = LookNameE( var );
      newv = MakeE( EqualV_entry(dv), VariableC );
      PutExprOffer( ol, newv );
      *valPt = AddVAL( *valPt, dv, CopyE(newv) ); /*mse*/
      FreeE( var );
    }
    /*  else {
        var= GetExprOffer( ol );
        (void)SubstExprSV(&var,psv);
        PutExprOffer( ol, var);
        }
        */
    ol=MvNextOffer( ol ); 
  }
}

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

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

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


/* ProcPlet_gate
 */
static BehTyp ProcPlet_gate ( b, vala, psv, pila )
     BehTyp           b;
     PAttrTyp         vala, pila;
     SVdescriptorTyp *psv;
{
  SVdescriptorTyp  sv2;
  BehTyp           bi,plet;
  PredicateTyp          pred;
  PAttrTyp         ola,pa;
  OfferListTyp     ol;
  VarAssignListTyp val,val2;
  char             r;
  boolean          sv2_is_sv;

#ifdef TIME 
  PTimeTyp   time;
  PAttrTyp   ta;
  VarAssignListTyp  tval;
#endif
  
  sv2_is_sv = TRUE;
  sv2       = *psv;
  val2      = NULL;
  ola       = LookA(b,OLA);
  if ( ola != NULL ) {
    ol = (OfferListTyp)LookAInfo(ola);
    if ( Var_in_OL_SV(ol,psv) || IsThereQuestionOL(ol) ) {
      val  = (VarAssignListTyp)LookAInfo(vala);
      val2 = CopyVAL(val);
      UnshareA(b,OLA);
      ola = LookA(b,OLA);
      ol  = (OfferListTyp)GetAInfo(ola);
      Plet_On_OL( &ol, &val2, psv ); /* val2 is modified */
      PutAInfo( ola, (AttrValueTyp)ol );
      LASSERT(val2!=NULL);
      sv2_is_sv = FALSE;
      sv2       = CreateSV();
      Insert_VAL_SV( val2, &sv2 );
    }
  }
  
 
#ifdef TIME
  ta = LookA(b,TA);
  time =(PTimeTyp)LookAInfo(ta);
 if ( ta != NULL ) {
  if ( Var_in_TA_SV(time,psv) || 
      ((time->tvar !=NULL) && IsVariableE(time->tvar))) {
    UnshareA( b, TA );
    ta  = GetA( b, TA );
    time = (PTimeTyp)GetAInfo( ta );
    if (!sv2_is_sv) { 
      tval = CreateVAL();
      Plet_On_TA( &time, &tval, psv );
      if (tval != NULL) {
	Insert_VAL_SV( tval, &sv2 );
	JoinVAL (val2,tval ); 
      }
      else 
        FreeVAL(tval);
      /*       FreeVAL(tval);   */
    }
    else {
      val  = (VarAssignListTyp)LookAInfo(vala);
      val2 = CopyVAL(val);
      Plet_On_TA( &time, &val2, psv );
      LASSERT(val2!=NULL);
      sv2_is_sv = FALSE;
      sv2       = CreateSV();
      Insert_VAL_SV( val2, &sv2 );
    }

    if (LookNameE(time->upper_bound)==FindO_time("neg")) {
      TrfStop(b);
      if (!sv2_is_sv)
	FreeSV( &sv2 );
      FreeVAL(val2);
      return b;  
    } 
    if (LookNameE(time->lower_bound)==FindO_time("neg")) 
      ChangeNameE(time->lower_bound,FindO_time("0")); 
    PutAInfo( ta, (AttrValueTyp)time );
    PutA( b, ta);
    
  }
}
#endif
  
  pred = (PredicateTyp)LookAInfo(LookA(b,PA));
  if (pred!=NULL)
    if ( Var_in_Pred_SV( pred, &sv2 ) ) {
      UnshareA( b, PA );
      pa   = LookA( b, PA );
      pred = (PredicateTyp)GetAInfo( pa );
      (void)SubstPredSV( &pred, &sv2 );
      PutAInfo( pa, (AttrValueTyp)pred );
      r = LookPredicate( b );
      if ( r == 'f' ) {
        SolvePredicateBeh( b );
        if (!sv2_is_sv)
          FreeSV( &sv2 );
        FreeVAL(val2);
        return b;
      }
      if ( r == 't' )
        SolvePredicateBeh( b );
    }
  
  if ( !sv2_is_sv )
    FreeSV( &sv2 );
  plet = MakeB( 0, PletC );
  if ( val2!=NULL )
    PutA( plet, MakeA( (AttrValueTyp)val2, VALA ) );
  else if ( vala!=NULL )
    PutA( plet, vala );
  bi = GetArgB( b, 1 );
  PutArgB( b, plet, 1 );
  PutArgB( plet, bi, 1 );
  PutPila( plet, pila );
  
  return b;
}

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

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

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

/* ProcPlet_plet
 */
static BehTyp ProcPlet_plet( b, vala, psv, pila )
     BehTyp           b;
     PAttrTyp         vala, pila;
     SVdescriptorTyp *psv;
{
  VarAssignListTyp val,val2;
  PAttrTyp         attr;
  BehTyp           pil;
  
  if ( IS_STEP_EXP && pila!=NULL )
    if ( LookA(b,STA)==NULL )
      PutA( b, pila );
    else {
      UnshareA( b, STA );
      pil = (BehTyp)LookAInfo(LookA(b,STA));
      pil = ConcatUB( pil, CopyB((BehTyp)LookAInfo(pila)) );
      LASSERT(LookTypeB(pil)==ProcessInstC);
    }
  
  val = (VarAssignListTyp)LookAInfo(vala);
  if (val == NULL)
    return Plet_Processing( b );
  else {
    val2 = (VarAssignListTyp)LookAInfo(LookA(b,VALA));
    if ( val2==NULL ) 
      return b;
    else {
      if ( Var_in_VAL_RightSide_SV(val2,psv) ) {
	UnshareA( b, VALA );      
	attr = LookA( b, VALA );
	val2 = (VarAssignListTyp)GetAInfo( attr );
	Subst_VAL_RightSide_SV( val2, psv );
	PutAInfo( attr, (AttrValueTyp)val2 );
      }
      return Plet_Processing( b );
    }
  }
}

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

/* ProcPlet_let
 */
static BehTyp ProcPlet_let( b, vala, psv, pila )
     BehTyp           b;
     PAttrTyp         vala, pila;
     SVdescriptorTyp *psv;
{
  VarAssignListTyp val, val2;
  PAttrTyp         vala2;
  SVdescriptorTyp  sv2;
  BehTyp           a, res;
  
  a   = GetArgB(b,1);
  val = (VarAssignListTyp)LookAInfo(vala);
  if (val != NULL) {
    UnshareA( b, VALA );      
    vala2 = LookA( b, VALA );
    val2  = (VarAssignListTyp)GetAInfo(vala2);
    LASSERT(val2!=NULL); 
    if ( Var_in_VAL_BothSides_SV( val2, psv ) )
      Subst_VAL_BothSides_SV( val2, psv );
    val2 = Join_list( val2, CopyVAL(val) );
    PutAInfo( vala2, (AttrValueTyp)val2 );
  }
  else {
    vala2 = LookA(b,VALA);
    val2 = (VarAssignListTyp)LookAInfo(vala2);
    LASSERT(val2!=NULL); 
  }
  sv2 = CreateSV();
  Insert_VAL_SV( val2, &sv2 );
  res =  PletProc( a , vala2 , &sv2, pila );
  FreeSV( &sv2 );
  FreeB(b);
  return res;
}

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

/* ProcPlet_it
 * notice that the plet advances more than one action.
 */
static BehTyp ProcPlet_it( b, vala, psv, pila )
     BehTyp           b;
     PAttrTyp         vala, pila;
     SVdescriptorTyp *psv;
{
  int cero=0;
  
  PutArgB( b,
	  PletProc( Pre_Processing( GetArgB( b,1 ), &cero ), vala, psv, pila )
	  , 1 );
  return b;
}

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

/* PletProc
 * Adds a plet(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 be NULL 
 */
static BehTyp PletProc( b, vala, psv, pila )
     BehTyp           b;
     PAttrTyp         vala, pila;
     SVdescriptorTyp *psv;
{
  BehTyp res;
  
  switch ( LookTypeB(b) )
    { 
    case IC:
      res = ProcPlet_i( b, vala, pila,psv ); /* sv include in timed version */
      PutPila( res, pila );
      break;
    case ChoiceC:
      res = ProcPlet_choice( b, vala, pila );
      break;
    case ContSetC:
    case StopC :
      res = ProcPlet_stop( b );
      break;
    case ParallelC :
      PutPila( b, pila );
      res = ProcPlet_par( b, vala, psv, (PAttrTyp)NULL );
      break;
    case AlternativeC :
      res = ProcPlet_alt( b, vala, psv, pila );
      break;
    case DisablingC :
      res = ProcPlet_dis( b, vala, psv, pila );
      break;
    case GuardC :
      res = ProcPlet_guard( b, vala, psv, pila );
      break;
    case PletC :
      res = ProcPlet_plet( b, vala, psv, pila );
      break;
    case LetC :
      res = ProcPlet_let( b, vala, psv, pila );
      break;
    case GateC :
      res = ProcPlet_gate( b, vala, psv, pila );
      if ( LookTypeB(res)==GateC )
	PutPila( res, pila );
      break;
    case ExitC :
      res = ProcPlet_exit( b, psv );
      if ( LookTypeB(res)==ExitC )
	PutPila( res, pila );
      break;
    case ProcessInstC :
      res = ProcPlet_proc( b, psv, pila );
      break;
    case EnablingC :
      res = ProcPlet_ena( b, vala, psv, pila );
      break;
    case TerminationC :
      res = ProcPlet_term( b, psv );
      break;
    case HidingC:
      res = ProcPlet_hid( b, vala, psv, pila );
      break;
    case RelabellingC :
      res = ProcPlet_rel( b, vala, psv, pila );
      break;
    case ParC:
    case GateChoiceC:
      res = ProcPlet_parc( b, vala, psv, pila );
      break;
    case InterleavedC :
      res = ProcPlet_it( b, vala, psv, pila );
      break;
      
    default :
      Error("Plet_processing: unexpected cell." );
    }
  return res;
}

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

/* Plet_Processing
 * Processing of the Plet operator plet.
 *
 *      plet = Plet v1:s1=E1,...,vn:sn=En in b
 *
 * where b is any behaviour.
 *
 * This operator is moved after the actions.
 */
BehTyp Plet_Processing( plet )
     BehTyp plet;
{
  BehTyp           a, res;
  VarAssignListTyp val;
  PAttrTyp         vala, pila;
  SVdescriptorTyp  sv;
  
  LASSERT ( LookTypeB( plet )==PletC );
  LASSERT ( OwnersB( plet )>=0);
  
  a = GetUntilActB(GetArgB(plet,1));
  
  sv   = CreateSV();
  vala = LookA( plet, VALA );
  val  = (VarAssignListTyp) LookAInfo( vala );
  if (val!=NULL)
    Insert_VAL_SV( val, &sv );
  
  pila = ( IS_STEP_EXP ? LookA(plet,STA) : NULL );
  
  res = PletProc( a, vala, &sv, pila );
  
  FreeB( plet );
  FreeSV( &sv );
  return res;
  
}
