/**
* Constant propogation for common expressions.
*/
module php/strategy/const-prop/analysis/common/expressions
strategies
/**
* Print-construct
*/
expression-const-prop(main,get,set,valid-get,valid-put,valid-remove|) =
Print(main)
; add-php-simple-value(|PHPInteger(0))
strategies
/**
* Exit, should actually terminate the program and stop the analysis.
* TODO
*/
expression-const-prop(main,get,set,valid-get,valid-put,valid-remove|) =
Exit(main)
<+ Die(main)
strategies
/**
* Echo, does not have a value-type
*/
expression-const-prop(main,get,set,valid-get,valid-put,valid-remove|) =
Echo(map(main))
strategies
/**
* Eval, either value of a 'return' in the code or False.
* TODO
*/
expression-const-prop(main,get,set,valid-get,valid-put,valid-remove|) =
Eval(main)
strategies
// tmp-strategy, will be expanded with real functioncalls
expression-const-prop(main,get,set,valid-get,valid-put,valid-remove|) =
FunctionCall(id,map(main))
/***********************************************************************\
Start Array Handling
\***********************************************************************/
strategies
/**
* Creation of an array
*/
expression-const-prop(main,get,set,valid-get,valid-put,valid-remove|) =
?term@Array(_)
; where( aid := <get-new-php-array-id>)
; Array(map(try(main ; add-array-pairs-to-array(main,get,valid-put,valid-remove|aid))))
; add-php-simple-value(|aid)
; try(
where(tmpval := <get> term)
; set(|tmpval)
)
/**
* Adds a array pair to a given ArrayObject.
* If the value cannot be retrieved the strategy will update
* the highest index and fail.
*
* @type (None(),value) -> Value
*/
add-array-pairs-to-array(main,get,valid-put,valid-remove|aid) =
?Pair(None(),Value(value))
; where(
( value' := <get-php-simple-value> value
; key := <add-array-entry(|value')> aid
; try(
<add-array-entry(valid-put|key,<get> value)> aid
))
<+
<add-array-entry(valid-put|<get> value)> aid
<+
(<increase-highest-array-index(|1)> aid
; fail
)
)
/**
* @type (None(),RefValue) -> Value
*/
add-array-pairs-to-array(main,get,valid-put,valid-remove|aid) =
?Pair(None(),RefValue(<main ; ?cvar>))
; where(
if (value-identifier,_) := <extract-php-value-identifier-kind(main,valid-remove|)
; (get-php-value-identifier-pair
<+ get-php-value-identifier-pair(get)
)> cvar
then <add-array-entry-reference(|value-identifier)> aid
else <increase-highest-array-index(|1)> aid
; fail
end
)
/**
* Adds a array pair to a given Array.
* Returns the value that is inserted
*
* @type (Some(Key(key)),value) -> value
*/
add-array-pairs-to-array(main,get,valid-put,valid-remove|aid) =
?Pair(Some(Key(<main ; ?key>)),Value(value))
; where(
finalkey := <map-type-to-php-array-key(main,valid-remove|aid)> key
;(( value' := <get-php-simple-value> value
; <add-array-entry(|finalkey,value')> aid
; try(
<add-array-entry(valid-put|finalkey,<get> value)> aid
)
)
<+
(try(
<add-array-entry(valid-put|finalkey,<get> value)> aid
<+
<remove-array-entry(valid-remove|finalkey)> aid
)
; <remove-array-entry(|finalkey)> aid // assignment with unknown value
)
)
)
/**
* @type (Some(Key(key)),RefValue) -> value
*/
add-array-pairs-to-array(main,get,valid-put,valid-remove|aid) =
?Pair(Some(Key(<main ; ?key>)),RefValue(<main ; ?cvar>))
; where(
finalkey := <map-type-to-php-array-key(main,valid-remove|aid)> key
; if (value-identifier,_) := <extract-php-value-identifier-kind(main,valid-remove|)
; (get-php-value-identifier-pair
<+ get-php-value-identifier-pair(get))
> cvar
then <add-array-entry-reference(|finalkey,value-identifier)> aid
else <remove-array-entry(|finalkey)> aid // assignment to an unknown entry
; try(
<remove-array-entry(valid-remove|finalkey)> aid
)
; fail // should fail, otherwise the expression will have a value
end
)
extract-php-value-identifier-kind(main,valid-remove|) =
( ?Variable(kind)
<+ ( ( ?ArrayAccess(<main ; ?var>,Some(<main ; ?key>))
<+ ?StringAccess(<main ; ?var>,<main ; ?key>)
)
; aid := <get-simple-array-value> var
; finalkey := <map-type-to-php-array-key(main,valid-remove|aid)> key
; kind := (aid,finalkey)
)
); !kind
/**
* Extracts the type of an expression and maps this to
* an array-key.
*
* @type Expr -> arraykey
*/
map-type-to-php-array-key(main,valid-remove|aid) = ?key ;
if key' := <main ; get-simple-raw-value> key
then ( (<?True() > key' ; finalkey := 1)
<+ (<?False()> key' ; finalkey := 0)
<+ (<?PHPArray(_)> key' ; fail) // array's can not be keys
<+ (<is-string> key' ; finalkey := key')
<+ (<is-int> key' ; finalkey := key')
<+ (<is-real> key' ; finalkey := <int> key' )
<+ (<?PHPNull()> key' ; finalkey := "" )
)
else <remove-all-array-entries> aid
; try(
<remove-all-array-entries(valid-remove)> aid
)
end
/***********************************************************************\
End Array Handling
\***********************************************************************/
/***********************************************************************\
Start List Handling
\***********************************************************************/
strategies
expression-const-prop(main,get,set,valid-get,valid-put,valid-remove|) =
ListAssign(id ,main)
; ?ListAssign(List(vars),array)
; where( <has-php-array-value> array
; aid := <get-simple-array-value> array
; <eval-php-list-expression(valid-get,valid-put|)> (List(vars),aid)
)
; add-php-simple-value(|aid)
; try(
where(tmpval := <get> array)
; set(|tmpval)
)
/**
* Evaluates a tuple of a List(vars) and a given
* Array Id. The values of the array are retrieved and assigned
* to the values in vars, if any.
*
* @type (List(vars),aid) -> ([],[])
*/
eval-php-list-expression(valid-get,valid-put|) =
?(List(vars),aid)
; values := <get-array-values> aid
; <ZipAndAssignLists> (vars, values)
; try(
values' := <get-array-values(valid-get)> aid
; <ZipAndAssignLists(valid-get,valid-put|)> (vars, values)
)
/***********************************************************************\
End List Handling
\***********************************************************************/
/***********************************************************************\
Start Inclusion Handling
\***********************************************************************/
strategies
/**
* Evaluates an inclusion of an file if the expression given to the
* include-function can be evaluated.
*/
inclusion-const-prop(main,get,set,rule-union|)=
( Include(main)
<+ Require(main)
)
;( ?term@Include(expr)
<+ ?term@Require(expr)
)
; where( (value,requireid) := <php-generic-always-include(main|)> expr)
; try(
add-inclusion-id(|requireid)
; add-php-simple-value(|value)
)
;try(
where (val := <get> term)
; set(|val)
)
inclusion-const-prop(main,get,set,rule-union|) =
( IncludeOnce(main)
<+ RequireOnce(main)
)
;( ?term@IncludeOnce(expr)
<+ ?term@RequireOnce(expr)
)
; where( (value,requireid) := <php-generic-once-include(main,rule-union|)> expr)
; try(
add-inclusion-id(|requireid)
; add-php-simple-value(|value)
)
;try(
where (val := <get> term)
; set(|val)
)
/**
* Evaluates a "no-inclusion". This an inclusion that is not possible.
* It will remove _all_ dynamic rules that are involved in this evaluation.
*
* @type include-term -> include-term
*/
no-inclusion-const-prop(main|name) =
( RequireOnce(main) <+ Include(main)
<+ Require(main) <+ IncludeOnce(main)
);
where( php-remove-all-eval-dynamic-rules
; try(php-remove-all-eval-dynamic-rules(|name))
)
strategies
/**
* Always includes a file with a given filename
*
* @type Expr -> (Expr(evaluated),value)
*/
php-generic-always-include(main|) = ?expr;
filename := <get-simple-raw-string-value> expr
; inclusionId := <process-inclusion(php-generic-include-strategy(main|))> filename
; !(PHPInteger(1),inclusionId) //for now we always return one if suceeded. Should check for an return
/**
* Includes a file with a given filename if it is
* not already in the environment
*
* @type Expr -> (Expr(evaluated),value,InclusionId)
*/
php-generic-once-include(main,rule-union|) = ?expr;
filename := <get-simple-raw-string-value> expr
; file := <find-php-file>
; <?FILE(filepath)> file
; env := <get-php-environment>
; if <is-file-included(|filepath); ?iid> env
then log(|Debug(), "This file was previously included: ", filepath)
; inclusionId := iid
else if <is-file-maybe-included(|filepath); ?iid> env
then log(|Debug(), "This file could be previously included: ", filepath)
; inclusionId := iid
; {| InclusionMode :
rules(InclusionMode: _ -> DefIncluded() )
; <add-inclusion-filename(|filepath,iid)> env
|}
; rule-union(id, <process-inclusion(php-generic-include-strategy(main|))> filename)
else inclusionId := <process-inclusion(php-generic-include-strategy(main|))> filename // not yet included
end
end
; !(PHPInteger(1),inclusionId) //for now we always return one if suceeded. Should check for an return
/**
* Generic part for the inclusion strategy. This strategy is applied
* to every file that is included. Environment is updated and then the
* file is evaluated.
*
* @type AST -> AST
*/
php-generic-include-strategy(main|) =
?doc
; fill-php-environment(|doc)
; <main> doc
/***********************************************************************\
End Inclusion Handling
\***********************************************************************/