【发布时间】:2011-10-07 06:46:52
【问题描述】:
在another question 中指出,将 PHP 函数调用的结果包装在括号中可以以某种方式将结果转换为成熟的表达式,因此以下工作:
<?php
error_reporting(E_ALL | E_STRICT);
function get_array() {
return array();
}
function foo() {
// return reset(get_array());
// ^ error: "Only variables should be passed by reference"
return reset((get_array()));
// ^ OK
}
foo();
我试图在文档中找到任何内容以明确并明确地解释这里发生的事情。与 C++ 不同,我对 PHP 语法及其对语句/表达式的处理知之甚少,无法自己派生它。
文档中是否隐藏了有关此行为的任何内容?如果不是,其他人可以不依靠假设来解释吗?
更新
我首先发现this EBNF声称代表PHP语法,并尝试自己解码我的脚本,但最终放弃了。
然后,using phc 生成两个foo() 变体的.dot 文件,我使用以下命令为两个脚本的produced AST 图像:
$ yum install phc graphviz
$ phc --dump-ast-dot test1.php > test1.dot
$ dot -Tpng test1.dot > test1.png
$ phc --dump-ast-dot test2.php > test2.dot
$ dot -Tpng test2.dot > test2.png
在这两种情况下,结果完全相同:
【问题讨论】:
-
看起来这是专门针对单个函数调用形式的表达式。
-
Array()带有大写 A? afaik,语言结构写成array() -
PHP,因此不区分大小写。
-
只有一个函数调用可以有这个的原因是只有一个变量或一个通过引用返回的函数可以是
reset的正确输入。一个变量显然总是通过引用工作,这给我们留下了只在执行时检查的函数调用,因为可能有类似$variablewithafunctionname()的东西。为什么()会让reset不抱怨...这意味着在reset获得其输入时它是 引用(refcount > 1),这意味着表达式@ 987654339@ 在内存中留下一些 zval... -
进一步挖掘,严格的警告来自 VM 部分/运行时。致命错误(不在 Q 的示例中,一个是:
return reset((get_array()?:0));)已经在编译时,措辞更加苛刻:“致命错误:只能通过引用传递变量” (而且错了,如果一个函数返回一个引用,那一切都很好)。在发出严格通知之前检查了许多标志,我在其中的某个地方闻到了它,但我对 PHP 内部了解不多:php-trunk/Zend/zend_vm_execute.h 第 10853 行~
标签: php php-internals