/**
* Evaluation of statements in PHP.
*
* @author Eric Bouwers
*/
module php/strategy/evaluation/statements
strategies
/**
* Echo, map evaluation over all expressions in list
*
*/
statement-const-prop(main,rule-union,rule-intersect|) =
Echo(map(main))
/**
* The Declare-construct
*/
statement-const-prop(main,rule-union,rule-intersect|) =
Declare(map(main),main)
// IF
strategies
/**
* If-statement without else or else-if.
* Condition is always evaluated, block is only checked.
*
* @type If(cond,stats) -> If(cond,stats)
*/
statement-const-prop(main,rule-union,rule-intersect|) =
If(main, id)
; maybe-inclusion-wrap(
rule-union(id
,If(id, main)
)
)
/**
* Evaluation of alternative If
* @type AltIf(_,_) -> AltIf(_,_)
*/
statement-const-prop(main,rule-union,rule-intersect|) =
?AltIf(cond,ifbranch)
; If(cond',Block(ifbranch')) := <main> If(cond,Block(ifbranch))
; !AltIf(cond',ifbranch')
/**
* If-statement with else or else-if.
* Condition is always evaluated, block is only checked.
*
* @type If(cond,stats,List(ElseIf)) -> If(cond,stats,List(ElseIf))
*/
statement-const-prop(main,rule-union,rule-intersect|) =
If(main, id, id) //always tries first if
; ?If(cond, ifbranch, ifelses)
; maybe-inclusion-wrap(
(ifbranch',ifelses') := <eval-php-cases(php-evaluate-elseif(main|),main,rule-union|ifbranch)> ifelses
)
; !If(cond, ifbranch', ifelses')
/**
* Evaluation of alternative If
* @type AltIf(_,_,_) -> AltIf(_,_,_)
*/
statement-const-prop(main,rule-union,rule-intersect|) =
?AltIf(cond,ifbranch,elseifs)
; If(cond',Block(ifbranch'),Block(elseifs')) :=
<main> If(cond,Block(ifbranch),elseifs)
; !AltIf(cond',ifbranch',elseifs')
/**
* If-statement with else and no else-ifs.
* Condition is always evaluated, block is only checked.
*
* @type If(cond,stats,List(ElseIf)) -> If(cond,stats,List(ElseIf))
*/
statement-const-prop(main,rule-union,rule-intersect|) =
?If(_, _, [], _) // basic if-else
; If(main, id, id, id) //always tries first if
; maybe-inclusion-wrap(
rule-union(If(id, main,id,id)
,If(id, id, id,main)
)
)
/**
* If-statement with else and else-ifs.
* Condition is always evaluated, block is only checked.
*
* @type If(cond,stats,List(ElseIf)) -> If(cond,stats,List(ElseIf))
*/
statement-const-prop(main,rule-union,rule-intersect|) =
not(?If(_, _, [], _)) // no empty else-ifs
; If(main, id, id, id) //always tries first if
; ?If(cond, ifbranch, ifelses,ifelse)
; maybe-inclusion-wrap(
rule-union(ifelse' := <main> ifelse
,(ifbranch',ifelses') :=
<eval-php-cases(php-evaluate-elseif(main|),main,rule-union|ifbranch)> ifelses
)
)
; !If(cond, ifbranch', ifelses',ifelse')
/**
* Evaluation of alternative If
* @type AltIf(_,_,_,_) -> AltIf(_,_,_,_)
*/
statement-const-prop(main,rule-union,rule-intersect|) =
?AltIf(cond,ifbranch,elseifs,elsebranch)
; If(cond',ifbranch',elseifs',elsebranch') :=
<main> If(cond,Block(ifbranch),elseifs,Block(elsebranch))
; !AltIf(cond',ifbranch',elseifs',elsebranch')
/**
* Evaluates a single ElseIf statement
* @type ElseIf() -> ElseIf()
*/
php-evaluate-elseif(main|) =
ElseIf(main,main)
<+ AltElseIf(main,map(main))
strategies
/**
* Evaluates a list of statements. It does this by a
* foldr in which each strategy splits and intersects a list of dynamic rules.
* This makes the ruleset complete for all different branches.
*
* @s Strategy Term -> Term The strategy to apply to the elements
* @sunit Strategy Term -> Term The strategy to apply to the unit element
* @param unit Statement The unit-statement for the intersection with the last
* statement
* @type List(Term) -> (Unit,List(Term))
*/
eval-php-cases(s,sunit,rule-union|unit) =
( ( ?[x]
; rule-union(x' := <s> x
, unit' := <sunit> unit
)
; !(unit',[x'])
)
<+
( ?[y|ys]
; rule-union( y' := <s> y
, (unit',ys') := <eval-php-cases(s,sunit,rule-union|unit)> ys
)
; !(unit',<conc>([y'],ys'))
)
)
//SWITCH
strategies
/**
* Evaluates a Switch statement.
* Almost the same semantics as an if-statement
* @type Switch() -> Switch
*/
statement-const-prop(main,rule-union,rule-intersect|) =
Switch(main,id)
; ?Switch(expr,cases)
;((where(<leq> (<length> cases,1))
; maybe-inclusion-wrap(
rule-union(id
,Switch(id, map(main))
)
)
)
<+
( <?[x|xs]> cases
; maybe-inclusion-wrap(
(x',xs') := <eval-php-cases(php-evaluate-case(main|),php-evaluate-case(main|),rule-union|x)> xs
)
; !Switch(expr,<conc>([x'],xs'))
)
<+
( !"Handling of cases in the Switch has failed."
; debug(!"Error code 001: "))
)
/**
* Evaluates an alternative Switch statement.
* Almost the same semantics as an if-statement
* @type AltSwitch() -> AltSwitch
*/
statement-const-prop(main,rule-union,rule-intersect|) =
?AltSwitch(cond, cases)
; Switch(cond',cases') := <main> Switch(cond, cases)
; !AltSwitch(cond', cases')
/**
* Evaluates a case statement
*/
php-evaluate-case(main|) =
Case(main,id,map(main))
<+ DefaultCase(id,map(main))
// WHILE
strategies
/**
* Evaluates a while. Condition is evaluated atleast once
* File within a while might be included, but nothing is sure.
*
* @type While() -> While()
*/
statement-const-prop(main,rule-union,rule-intersect|) =
?While(_, _)
; While(main,id)
; maybe-inclusion-wrap(
rule-intersect(While(id,main))
)
/**
* Evaluates an alternative while.
* Uses the normal intersect and iterate syntax
* @type AltWhile() -> AltWhile()
*/
statement-const-prop(main,rule-union,rule-intersect|) =
?AltWhile(cond, stats)
; While(cond',Block(stats')) := <main> While(cond, Block(stats))
; !AltWhile(cond', stats')
// DOWHILE
strategies
/**
* Evaluates a dowhile.
* DoWhile always takes 1 iteration for sure. After this it
* acts like a normal while.
*
* @type DoWhile() -> DoWhile()
*/
statement-const-prop(main,rule-union,rule-intersect|) =
?DoWhile(_, _)
; DoWhile(main, main)
; maybe-inclusion-wrap(
rule-intersect(
DoWhile(main, main)
)
)
// FOR
strategies
/**
* Evaluates a for.
* Is almost like the normal while. Initialization and test are performed
* atleast once while the rest is performed on every iteration.
*
* @type For() -> For()
*/
statement-const-prop(main,rule-union,rule-intersect|) =
?For(_, _, _, _)
; For(map(main), id, id, id)
; For(id,map(main), id, id)
; maybe-inclusion-wrap(
rule-intersect(
For(id,
map(main),
map(main),
main)
)
)
/**
* Evaluates an alternative for.
* Uses the normal intersect and iterate syntax
* @type AltFor() -> AltFor()
*/
statement-const-prop(main,rule-union,rule-intersect|) =
?AltFor(cond1, cond2, cond3, stats)
; For(cond1', cond2', cond3', Block(stats')) :=
<main> For(cond1, cond2, cond3, Block(stats))
; !AltFor(cond1', cond2', cond3', stats')
// FOREACH
strategies
/**
* Evaluates a foreach.
* Foreach is just a while with some extra initializations.
*
* @type ForEach() -> ForEach()
*/
statement-const-prop(main,rule-union,rule-intersect|) =
?ForEach(_, _, _)
; maybe-inclusion-wrap(
rule-intersect(
ForEach(main,
id, // pattern needs no evaluation
main)
)
)
/**
* Evaluates an alternative for.
* Uses the normal intersect and iterate syntax
* @type AltForEach() -> AltForEach()
*/
statement-const-prop(main,rule-union,rule-intersect|) =
?AltForEach(expr, pattern, stats)
; ForEach(expr', pattern', Block(stats')) := <main> ForEach(expr, pattern, Block(stats))
; !AltForEach(expr', pattern', stats')
// Control flow statements
strategies
statement-const-prop(main,rule-union,rule-intersect|) =
Break(id)