- 实现了 ??= 运算符的解析和编译功能 - 添加了变量存在性检查的改进实现 - 增加了左值有效性验证确保赋值操作合法 - 更新了测试用例覆盖空合并赋值的各种场景 - 修复了 stray code 检查的错误定位问题 - 在编译器基类中增加了 isset 和 empty 操作常量定义pull/1/head
parent
f2e7b70043
commit
e0a4e2f977
6 changed files with 214 additions and 8 deletions
@ -0,0 +1,15 @@ |
||||
--TEST-- |
||||
assign coalesce |
||||
--FILE-- |
||||
<?php |
||||
$a = 123; |
||||
$a ??= 456; |
||||
var_dump($a); |
||||
|
||||
$b = null; |
||||
$b ??= 'foo'; |
||||
var_dump($b); |
||||
?> |
||||
--EXPECT-- |
||||
int(123) |
||||
string(3) "foo" |
||||
@ -0,0 +1,119 @@ |
||||
--TEST-- |
||||
Coalesce assign (??=): Basic behavior |
||||
--FILE-- |
||||
<?php |
||||
// Identity function used to track single-evaluation |
||||
function id($arg) { |
||||
return $arg; |
||||
} |
||||
|
||||
class Test { |
||||
public static $foo; |
||||
public static $bar; |
||||
} |
||||
|
||||
function main() { |
||||
// Refcounted values |
||||
$foo = "fo"; |
||||
$foo .= "o"; |
||||
$bar = "ba"; |
||||
$bar .= "r"; |
||||
echo "Simple variables:\n"; |
||||
$a = 123; |
||||
$a ??= 456; |
||||
var_dump($a); |
||||
|
||||
$b = null; |
||||
$b ??= $foo; |
||||
var_dump($b); |
||||
|
||||
$c = $foo; |
||||
$c ??= $bar; |
||||
var_dump($c); |
||||
|
||||
$d ??= $foo; |
||||
var_dump($c); |
||||
|
||||
echo "\nArrays:\n"; |
||||
$ary = []; |
||||
$ary["foo"] ??= 123; |
||||
$ary[$foo] ??= $bar; |
||||
$ary[$bar] ??= $foo; |
||||
var_dump($ary); |
||||
|
||||
echo "\nArrays (identity):\n"; |
||||
$ary = []; |
||||
$ary[id($foo)] ??= 123; |
||||
$ary[id($foo)] ??= $bar; |
||||
$ary[id($bar)] ??= $foo; |
||||
var_dump($ary); |
||||
|
||||
echo "\nObjects:\n"; |
||||
$obj = new stdClass; |
||||
$obj->foo ??= 123; |
||||
$obj->$foo ??= $bar; |
||||
$obj->$bar ??= $foo; |
||||
var_dump($obj); |
||||
|
||||
$obj = new stdClass; |
||||
$obj->{id($foo)} ??= 123; |
||||
$obj->{id($foo)} ??= $bar; |
||||
$obj->{id($bar)} ??= $foo; |
||||
var_dump($obj); |
||||
|
||||
echo "\nStatic props:\n"; |
||||
Test::$foo ??= 123; |
||||
Test::$$foo ??= $bar; |
||||
Test::$$bar ??= $foo; |
||||
var_dump(Test::$foo, Test::$bar); |
||||
|
||||
Test::$foo = null; |
||||
Test::$bar = null; |
||||
Test::${id($foo)} ??= 123; |
||||
Test::${id($foo)} ??= $bar; |
||||
Test::${id($bar)} ??= $foo; |
||||
var_dump(Test::$foo, Test::$bar); |
||||
} |
||||
?> |
||||
--EXPECT-- |
||||
Simple variables: |
||||
int(123) |
||||
string(3) "foo" |
||||
string(3) "foo" |
||||
string(3) "foo" |
||||
|
||||
Arrays: |
||||
array(2) { |
||||
["foo"]=> |
||||
int(123) |
||||
["bar"]=> |
||||
string(3) "foo" |
||||
} |
||||
|
||||
Arrays (identity): |
||||
array(2) { |
||||
["foo"]=> |
||||
int(123) |
||||
["bar"]=> |
||||
string(3) "foo" |
||||
} |
||||
|
||||
Objects: |
||||
object(stdClass)#1 (2) { |
||||
["foo"]=> |
||||
int(123) |
||||
["bar"]=> |
||||
string(3) "foo" |
||||
} |
||||
object(stdClass)#2 (2) { |
||||
["foo"]=> |
||||
int(123) |
||||
["bar"]=> |
||||
string(3) "foo" |
||||
} |
||||
|
||||
Static props: |
||||
int(123) |
||||
string(3) "foo" |
||||
int(123) |
||||
string(3) "foo" |
||||
@ -0,0 +1,28 @@ |
||||
--TEST-- |
||||
import namespaced function |
||||
--FILE-- |
||||
<?php |
||||
|
||||
namespace foo\bar { |
||||
function baz() { |
||||
return 'foo.bar.baz'; |
||||
} |
||||
function qux() { |
||||
return baz(); |
||||
} |
||||
} |
||||
|
||||
namespace { |
||||
use function foo\bar\baz, foo\bar\qux; |
||||
function main() { |
||||
var_dump(baz()); |
||||
var_dump(qux()); |
||||
echo "Done\n"; |
||||
} |
||||
} |
||||
|
||||
?> |
||||
--EXPECT-- |
||||
string(11) "foo.bar.baz" |
||||
string(11) "foo.bar.baz" |
||||
Done |
||||
Loading…
Reference in new issue