/**
* Constant propogation for variables in PHP.
*/
module php/strategy/evaluation/variables
/***********************************************************************\
Start Variable Handling
\***********************************************************************/
strategies
/**
* Variable-construct
*/
variable-const-prop(main,set,get,get-valid) =
?Variable(var)
; where ( name := <main ; php-get-raw-variable-name> var )
; try( add-php-simple-value(|<PHPSuperGlobalValue <+ php-variable-value> name))
; try( set(|<php-variable-value(get-valid)> name))
/**
* ConstantVariable-construct
*/
variable-const-prop(main,set,get,get-valid) =
?ConstantVariable(name)
; try(add-php-simple-value(|<php-constant-get-value> name))
; try(set(|<php-constant-get-value(get-valid)> name))
/**
* @type IndirectReference(_) -> PHPSimpleValue
*/
variable-const-prop(main,set,get,get-valid) =
?IndirectReference(expr)
; where( expr' := <main> expr
; varname := <get-simple-raw-string-value> expr'
; evalExpr := <main> Variable(Simple(varname))
)
; try(add-php-simple-value(|<get-php-simple-value> evalExpr))
; try(set(|<get> evalExpr))
/***********************************************************************\
End Variable Handling
\***********************************************************************/
/***********************************************************************\
Start ArrayAccess Handling
\***********************************************************************/
strategies
/**
* General array acces on an array.
* @type ArrayAccess(type:PHPArray,expr) -> value
*/
variable-const-prop(main,set,get,get-valid) =
variable-const-prop(main,set,get,get-valid
,array-access-on-array // this one incorperates const-prop itself
,id
,id
)
variable-const-prop(main,set,get,get-valid
,array-value
,string-value
,other-value) =
( ArrayAccess(main; ?array,main)
<+ StringAccess(main; ?array,main)
)
;(( where( <has-php-array-value> array)
; array-value(main,get,set,get-valid)
)
<+
( where( <has-php-string-value> array)
; array-access-on-string
; string-value
)
<+
( where( <has-php-boolean-value> array
<+ <has-php-integer-value> array
<+ <has-php-float-value> array
<+ <has-php-null-value> array
)
; array-access-on-other
; other-value
))
/**
* Special case for the GLOBALS array. This array holds all variables, so
* we try to extract the value of that variable first. If this fails then we
* try the integer value as a key.
*/
array-access-on-array(main,get,set,valid-get) =
?ArrayAccess(array,Some(expr))
; where( aid := <get-simple-array-value> array)
;(( where( <is-globals-array> aid
; strkey := <get-simple-raw-string-value> expr
; <explode-string; ?[<is-alpha> | _ ]> strkey
; evalExpr := <main> Variable(Simple(strkey))
)
; ( try(add-php-simple-value(|<get-php-simple-value> evalExpr))
; try(set(|<get> evalExpr))
)
)
<+
( try(add-php-simple-value(|<generic-arrayaccess-value> (aid,expr)))
; try(set(|<generic-arrayaccess-value(valid-get)> (aid,expr)))
))
array-access-on-string =
( ?StringAccess(array,expr)
<+ ?ArrayAccess(array,Some(expr))
)
; where( str := <get-simple-raw-string-value> array
; num := <get-simple-raw-integer-value> expr
; if <gt> (num, < string-length> str)
then value := ""
else <explode-string>str
; at-index( ?ch | num)
; value := <implode-string> [ch]
end
)
; add-php-simple-value(|PHPString(value))
array-access-on-other =
?ArrayAccess(val,_)
;( <has-php-boolean-value> val
<+ <has-php-integer-value> val
<+ <has-php-float-value> val
<+ <has-php-null-value> val
)
; add-php-simple-value(|PHPNull())
/**
* Generic array-acces for botht the special case for GLOBALS and the
* normal case.
*/
generic-arrayaccess-value =
generic-arrayaccess-value(php-val-id-get-rule)
generic-arrayaccess-value(valid-get) =
?(aid,expr)
; where (( strkey := <get-simple-raw-string-value> expr
; value := <get-array-entry(valid-get|strkey)> aid
)
<+
( intkey := <get-simple-raw-integer-value> expr
; value := <get-array-entry(valid-get|intkey)> aid
)
)
; !value
/**
* Checks wheter or not the ArrayId matches that of the GLOBALS-array
* @type PHPArray() -> _
*/
is-globals-array=
?PHPArray("superglobal_GLOBALS")
/***********************************************************************\
End ArrayAccess Handling
\***********************************************************************/
/***********************************************************************\
Begin Rules for Variables
\***********************************************************************/
/**
* Adds a rule that maps a variable to a value.
*
* @type (name,value) -> (name,value)
*/
add-php-variable-rule =
add-php-variable-rule(php-val-id-add-rule)
add-php-variable-rule(valid-put) =
?(Variable(var),value)
; name := <php-get-raw-variable-name> var
; value-identifier := <get-php-value-identifier> var
; rules(EvalPHPVar : name -> value-identifier) //extra pointer to make implementation
; valid-put(|value-identifier,value) //of references easy
/**
* Adds a mapping from a variable to a value-identifier.
*
* @type (name,value) -> (name,value)
*/
add-php-variable-identifier-rule =
?(Variable(var),value-identifier)
; name := <php-get-raw-variable-name> var
; rules(EvalPHPVar: name -> value-identifier)
/**
* Get's the real value of an variable. This means applying the strategy
* EvalPHPVar twice. First getting the pointer to the value and then getting
* the real value.
*
* @type String -> PHPSimpleValue
*/
php-variable-value =
php-variable-value(php-val-id-get-rule)
php-variable-value(s) =
EvalPHPVar;s
/**
* Makes a new identifier that is unique for each variable.
* Reuses an old identifier if it exists, otherwise it uses the
* name of the variable, which should be unique in the program.
*
* @type name -> String
*/
get-php-value-identifier =
( php-get-raw-variable-name
; EvalPHPVar
)
<+ // no old for variable
( EvalPHPArray
)
<+ // no old for array
(php-get-raw-variable-name
)
<+ // no name, try array
{?(aid,key)
; if <is-int> key
then key' := <int-to-string> key
else key' := key
end
; <?PHPArray(aid')> aid
; <conc-strings> (aid',key')
}
get-php-value-identifier-pair =
get-php-value-identifier-pair(php-val-id-get-rule)
get-php-value-identifier-pair(valid-get) =
?var
; identifier := <get-php-value-identifier> var
; value := <valid-get> identifier
; !(identifier,value)
/**
* Extracts the name of a variable. This strategy handles
* all the cases that can contain a variable name.
*
* @type Simple(_) OR Braced() -> String
*/
php-get-raw-variable-name =
( ?Braced(Simple(name))
<+ ?Simple(name)
<+ ( ?Braced(expr)
; name := <get-simple-raw-string-value> expr
)
)
; <rm-annotations> name
/**
* Removes the rule that maps a variable to a value.
*
* @type name -> name
*/
remove-php-variable-rule =
remove-php-variable-rule(php-val-id-remove-rule)
remove-php-variable-rule(valid-remove) =
?Variable(var)
; name := <php-get-raw-variable-name> var
; value-identifier := <get-php-value-identifier> var
; valid-remove(|value-identifier) // also remove mapping to value.
; rules(EvalPHPVar :- name) // unknown RHS also invalidates all aliases
/**
* Adds a dynamic rule for a PHP constant.
*
* @type (String,PHPValue) -> _
*/
add-php-constant-rule =
add-php-constant-rule(php-constant-put-value)
add-php-constant-rule(put-valid) =
?(name,value)
; value_identifier := <newname> "php_constant_"
; rules(EvalPHPConstant: name -> value_identifier)
; put-valid(|value_identifier,value)
php-constant-get-value =
php-constant-get-value(EvalPHPValId)
php-constant-get-value(get-valid) =
EvalPHPConstant ; get-valid
php-constant-put-value(|ident,val) =
rules(EvalPHPValId: ident -> val)
php-val-id-remove-rule(|key) =
rules(EvalPHPValId :- key)
php-val-id-add-rule(|key,val) =
rules(EvalPHPValId : key -> val)
php-val-id-get-rule =
EvalPHPValId
rules
/**
* Rules that rewrite the value of a superglobal to an
* array-type.
*
* @type: String -> PHPArray(_)
*/
PHPSuperGlobalValue:
"_GET" -> PHPArray("superglobal_GET")
PHPSuperGlobalValue:
"_POST" -> PHPArray("superglobal_POST")
PHPSuperGlobalValue:
"_REQUEST" -> PHPArray("superglobal_REQUEST")
PHPSuperGlobalValue:
"_SERVER" -> PHPArray("superglobal_SERVER")
PHPSuperGlobalValue:
"_FILES" -> PHPArray("superglobal_FILES")
PHPSuperGlobalValue:
"_ENV" -> PHPArray("superglobal_ENV")
PHPSuperGlobalValue:
"_COOKIE" -> PHPArray("superglobal_COOKIE")
PHPSuperGlobalValue:
"GLOBALS" -> PHPArray("superglobal_GLOBALS")
PHPSuperGlobalValue:
"_SESSION" -> PHPArray("superglobal_SESSION")
/***********************************************************************\
End Rules for Variables
\***********************************************************************/