Fortunately, Eelco Dolstra had some time to migrate php-front, php-sat and php-tools to Hydra, the new Nix-based continuous build system. After some tweaking we now again have access to unstable build for all PSAT-projects. Go Hydra!

defined-functions-main =
include-files-complex
; get-php-environment
; get-functions
; if ?[]
then !"No functions defined."
else map(transform-to-message)
; lines
end
<?phpIn this case, echo $bar will be flagged by the latest php-sat.
$foo = $_GET['asdf'];
$bar = 1;
$bar =& $foo;
echo $bar;
?>
add-php-simple-value(|val):This works perfectly, the annotations are matched as a list by the *-syntax, and a list is added as an annotation to the term again. The only problem with this is that the second time this rule is applied it matches the annotations as a list of a list of annotations, which was not the behavior I desired. This problem is easily solved by also adding a * to build the term:
t{a*} -> t{annos}
where b* :=a*
; annos := [PHPSimpleValue(val) | b*]
add-php-simple-value(|val):Now the list of annotations is not wrapped in an actual list anymore. I know it is documented somewhere, but this little explanation might save some others from an headache or a long debug-session.
t{a*} -> t{annos*}
where b* :=a*
; annos* := [PHPSimpleValue(val) | b*]
...which is not only tedious, but also a complete violation of the DRY principle.
echo "Type of 5/2 = ", gettype(5/2), "<br />";
...
foreach($types2 as $key2 => $val2){
$code = 'return ' . $val1 .' '.$op.' '.$val2. ';' ;
$result = eval($code);
echo ''. gettype($result) . ' (' . showval($result) . ') ';
}
$foo = 5
, PHP-Front will add a dynamic rule rewriting the variable to the known value. This dynamic rule can later be used to retrieve the value, for example in the expression $bar = $foo+1
. This last expression will then be rewritten to $bar = 5+1
which can be completely calculated again. $foo = 'say';
if($val){
$bar = 'hello';
} else {
$bar = 'world';
}
$bar
can not be statically determined, but we want to keep the knowledge about the variable $foo
. A valid way to do this is to take the intersection of the two sets of dynamic rules, the normal one and the one after evaluating the if-branch. This will keep all information about variables that are not used, or given the same value, within the branches of the if
.
if($val){
include_once 'foo.php';
} else {
//other things
}
//some code
include_once 'foo.php';
foo.php
might be included and introduce some dynamic-rules. The code for the if
will handle this probably so that is not a problem. include_once
-construct for the same file? Well, there are three different scenario's that can occur:
context-free priorities
"@" Expr -> Expr
<1> >
Expr "/" Expr -> Expr
context-free priorities
Expr "*" Expr -> Expr
<2> >
Expr "+" Expr -> Expr
context-free priorities
Expr "*" Expr -> Expr
<0> >
Expr "+" Expr -> Expr
Expr "*" Expr -> Expr
> Expr "+" Expr -> Expr
ConstantEncapsedString(
DoubleQuoted([Literal("hello ")
,Escape(116)
,Literal(" world")]
))
ConstantEncapsedString(
DoubleQuoted(
DQContent(Some("hello ")
,Escape(116)
,Some(" world"))
))
ConstantEncapsedString(
DoubleQuoted(
DQContent(Some("Hello ")
,DQContent(Escape(92)
,None
,OctaChar(48,49,50))
,Some("3"))
))
<?php
$foo = <<<BAR
foo...
BAR;
$bar = <<<BAR
bar
BAR;
?>
<?phpBecause we do not know the value of $bar we do not know the value of $foo after the condition. So the dynamic rule that maps $foo to the string-value "bar" should be undefined. Stratego has special syntax for these kind of situations and this makes the implementation very easy.
$foo = 'bar';
if($bar == 1){
$foo = 'foo';
}
//Value of $foo is unknown
?>