/** * 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)