/**
 * Module for the common literals to analyse the constant 
 * propogation
 */
module php/strategy/const-prop/analysis/common/literals

strategies

  /**
   * Extracting integer
   */
  literal-const-prop(main|) =
     ?LNumber(Deci(i))
   ; where( val := PHPInteger(<string-to-int> i))   
   ; add-php-simple-value(|val)
  
  literal-const-prop(main|) =
     ?LNumber(Octa(i))
   ; where ( 
        i' := <explode-string;take-until(?56 <+ ?57);implode-string> i   //drop everything after a 8 or 9
     ; val := PHPInteger(<oct-string-to-int> i')
   )
   ; add-php-simple-value(|val)

  literal-const-prop(main|) =
     ?LNumber(Hexa(i)) 
   ; where(
       i'  := <explode-string;drop(|2);implode-string> i  //dropping leading 0x
     ; val := PHPInteger(<hex-string-to-int> i')
   )
   ; add-php-simple-value(|val)

strategies
  /**
   * Extracting float
   */
  literal-const-prop(main|) =
     ?DNumber(i) 
   ; where( val := PHPFloat(<string-to-real> i)
   )
   ; add-php-simple-value(|val)

strategies
  /**
   * Extracting boolean
   */
  literal-const-prop(main|) =
    ?True()
   ; add-php-simple-value(|PHPBoolean(True()))

  literal-const-prop(main|) =
    ?False() 
   ; add-php-simple-value(|PHPBoolean(False()))

strategies
  /**
   * Extracting null
   */
  literal-const-prop(main|) =
     Null()
   ; add-php-simple-value(|PHPNull())

strategies
  /**
   * Extracting string value
   */
  literal-const-prop(main|) =
    (  ?ConstantEncapsedString(SingleQuoted(parts))
    <+ ?ConstantEncapsedString(DoubleQuoted(parts))
    <+ ?ConstantEncapsedString(HereDoc(_,parts,_))
    )
  ; where( parts' := <map(eval-part(main))> parts
         ; val    := PHPString(<concat-strings> parts')
  )
  ; add-php-simple-value(|val)


// Processing of strings
rules
  eval-part(main):
    Literal(str) -> str

  eval-part(main):
    Escape(esc) -> str
      where str := <eval-asc-char> esc

  eval-part(main):
    esc@Variable(_) -> str
      where str := <main; get-simple-raw-string-value> esc 

rules
// Hexachars
  eval-part(main):
    HexaChar(b1)    -> str
       where  res := <hex-chars-to-int> [ b1 ]
            ; str := <implode-string> [res]

  eval-part(main):
    HexaChar(b1,b2)    -> str
       where  res := <hex-chars-to-int> [ b1, b2 ]
            ; str := <implode-string> [res]

// Octachars
  eval-part(main):
    OctaChar(b1)       -> str
       where  res := <oct-chars-to-int> [ b1 ]
            ; str := <implode-string> [res]

  eval-part(main):
    OctaChar(b1,b2)    -> str
       where  res := <oct-chars-to-int> [ b1, b2]
            ; str := <implode-string> [res]

  eval-part(main):
    OctaChar(b1,b2,b3) -> str
       where  res := <oct-chars-to-int> [ b1, b2, b3 ]
            ; str := <implode-string> [res]

//ascii characters
rules
  eval-asc-char :
    34 ->  "\""

  eval-asc-char :
    36 ->  "$"

  eval-asc-char :
    39 ->  "'"

  eval-asc-char :
    48 -> 0

  eval-asc-char :
    49 -> 1

  eval-asc-char :
    50 -> 2

  eval-asc-char :
    51 -> 3

  eval-asc-char :
    52 -> 4

  eval-asc-char :
    53 -> 5

  eval-asc-char :
    54 -> 6

  eval-asc-char :
    55 -> 7

  eval-asc-char :
    56 -> 8

  eval-asc-char :
    57 -> 9

  eval-asc-char :
    92 ->  "\\"

  eval-asc-char :
    96 ->  "`"

  eval-asc-char :
    110 ->  "\n"

  eval-asc-char :
    114 ->  "\r"

  eval-asc-char :
    116 ->  "\t"