/** 
 * Module for the so called 'wrapper' constructs.
 */
module php/strategy/const-prop/analysis/wrappers

strategies  
  /**
   * Wrapper constructors are:
   *  - Expr   - InternalFunction
   *  - Param
   *  - Some 
   */ 
  wrapper-const-prop(main,get,set|)=
    Expr(main)
  ; ?Expr(expr) 
  ; generic-wrapper(main,get,set|expr) 

  // for braced variables, just a wrapper for an expression
  wrapper-const-prop(main,get,set|)=
    Braced(main) 
  ; ?Braced(expr)
  ; generic-wrapper(main,get,set|expr) 

  wrapper-const-prop(main,get,set|)=
    Param(main)
  ; ?Param(expr)  
  ; generic-wrapper(main,get,set|expr)
  
  wrapper-const-prop(main,get,set|)=
    Some(main)
  ; ?Some(expr)  
  ; generic-wrapper(main,get,set|expr) 
  
  // Nothing
  wrapper-const-prop(main,get,set|)=
     ?None()
  <+ ?Simple(_) 
  
  wrapper-const-prop(main,get,set|)=
    ?Pair(key,expr) 
  ; where( key' := <main> key)   
  ; where( expr':= <main> expr)   
  ; !Pair(key',expr')
  ; generic-wrapper(main,get,set|expr')
  
  wrapper-const-prop(main,get,set|)=
     Key(main)
  ; ?Key(expr) 
  ; generic-wrapper(main,get,set|expr) 
  
  wrapper-const-prop(main,get,set|)=
     Value(main)
  ; ?Value(expr)
  ; generic-wrapper(main,get,set|expr) 
  
  wrapper-const-prop(main,get,set|)=
    InternalFunction(main)
  ; ?InternalFunction(expr)  
  ; generic-wrapper(main,get,set|expr) 
  ; try(
      where( iid := <get-inclusion-id> expr)
    ; add-inclusion-id(|iid) 
  )
  
  /**
   * Generic functionality for the wrapper. 
   * Retrieves simple value, then the extra 
   * getter and setter.
   */
  generic-wrapper(main,get,set|expr) =
      try(
       where( value := <get-php-simple-value>  expr)
     ; add-php-simple-value(|value) 
    ) 
    ; try(
        where( val := <get>  expr )
      ; set(|val) 
    )

  wrapper-const-prop(main,get,set|) =  // a += $b -> $a = $a + $b
     ?PlusAssign(var, expr)
   ; where ( expr' := <main> Assign(var,(Plus(var,expr)))) 
   ; generic-wrapper(main,get,set|expr') 

   wrapper-const-prop(main,get,set|) =  // $a -= $b -> $a = $a - $b
     ?MinAssign(var,expr)
   ; where ( expr' := <main> Assign(var,(Min(var,expr)))) 
   ; generic-wrapper(main,get,set|expr') 

   wrapper-const-prop(main,get,set|) =  // $a *= $b -> $a = $a * $b
     ?MulAssign(var,expr)
   ; where ( expr' := <main> Assign(var,(Mul(var,expr)))) 
   ; generic-wrapper(main,get,set|expr') 

   wrapper-const-prop(main,get,set|) =  // $a /= $b -> $a = $a / $b
     ?DivAssign(var,expr)
   ; where ( expr' := <main> Assign(var,(Div(var,expr)))) 
   ; generic-wrapper(main,get,set|expr') 

   wrapper-const-prop(main,get,set|) =  // $a %= $b -> $a = $a % $b
     ?ModAssign(var,expr)
   ; where ( expr' := <main> Assign(var,(Mod(var,expr)))) 
   ; generic-wrapper(main,get,set|expr') 

   wrapper-const-prop(main,get,set|) = // $a .= $b -> $a = $a . $b
     ?ConcatAssign(var,expr)
   ; where ( expr' := <main> Assign(var,(Concat(var,expr)))) 
   ; generic-wrapper(main,get,set|expr') 
  
   wrapper-const-prop(main,get,set|) = // $a &= $b -> $a = $a & $b
     ?AndAssign(var,expr)
   ; where ( expr' := <main> Assign(var,(BinAnd(var,expr)))) 
   ; generic-wrapper(main,get,set|expr') 
  
   wrapper-const-prop(main,get,set|) = // $a |= $b -> $a = $a | $b
     ?OrAssign(var,expr)
   ; where ( expr' := <main> Assign(var,(BinOr(var,expr)))) 
   ; generic-wrapper(main,get,set|expr') 
  
   wrapper-const-prop(main,get,set|) = // $a ^= $b -> $a = $a ^ $b
     ?XorAssign(var,expr)
   ; where ( expr' := <main> Assign(var,(BinXor(var,expr)))) 
   ; generic-wrapper(main,get,set|expr') 
  
   wrapper-const-prop(main,get,set|) = // $a <<= $b -> $a = $a << $b
     ?SLAssign(var,expr)
   ; where ( expr' := <main> Assign(var,(SR(var,expr)))) 
   ; generic-wrapper(main,get,set|expr') 
  
   wrapper-const-prop(main,get,set|) = // $a >>= $b -> $a = $a >> $b
     ?SRAssign(var,expr)
   ; where ( expr' := <main> Assign(var,(SR(var,expr)))) 
   ; generic-wrapper(main,get,set|expr') 
  

strategies
  /**
   * A block is essence just list, just map the main strategy 
   */
  wrapper-const-prop(main,get,set|) = 
    Block(map(main))