From: Xinchen Hui Date: Sat, 25 Aug 2012 14:23:14 +0000 (+0800) Subject: Support list in foreach X-Git-Tag: php-5.5.0alpha1~20^2~22^2~27 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=35951d4be0bd27c85519995a95429bd0d0a76a00;p=php Support list in foreach RFC: https://wiki.php.net/rfc/foreachlist --- diff --git a/NEWS b/NEWS index 00f8ec6be9..28b89baaac 100644 --- a/NEWS +++ b/NEWS @@ -3,6 +3,7 @@ PHP NEWS ?? ??? 201?, PHP 5.5.0 - General improvements: + . Support list in foreach (https://wiki.php.net/rfc/foreachlist). (Laruence) . Implemented 'finally' keyword (https://wiki.php.net/rfc/finally). (Laruence) . Drop Windows XP and 2003 support. (Pierre) . Improve set_exception_handler while doing reset.(Laruence) diff --git a/UPGRADING b/UPGRADING index aeab14b48f..ba556357ed 100755 --- a/UPGRADING +++ b/UPGRADING @@ -31,6 +31,8 @@ PHP X.Y UPGRADE NOTES 2. New Features ======================================== +- Support list in foreach. (Laruence) + (wiki.php.net/rfc/foreachlist) - Support finally keyword. (Laruence) (wiki.php.net/rfc/finally) - Support constant array/string dereferencing. (Laruence) diff --git a/Zend/tests/foreach_list.phpt b/Zend/tests/foreach_list.phpt new file mode 100644 index 0000000000..a318f1aad9 --- /dev/null +++ b/Zend/tests/foreach_list.phpt @@ -0,0 +1,43 @@ +--TEST-- +foreach with list syntax +--FILE-- + list(list($a, $b), list($c, $d))) { + var_dump($key . $a . $b . $c . $d); +} + + +?> +--EXPECT-- +string(2) "12" +string(2) "34" +string(2) "ab" +string(2) "cd" +string(4) "1234" +string(4) "5678" +string(5) "01234" +string(5) "15678" diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c index 2665870ab4..b87b1908b6 100644 --- a/Zend/zend_compile.c +++ b/Zend/zend_compile.c @@ -6320,13 +6320,18 @@ void zend_do_foreach_cont(znode *foreach_token, const znode *open_brackets_token GET_NODE(&value_node, opline->result); - if (assign_by_ref) { - zend_do_end_variable_parse(value, BP_VAR_W, 0 TSRMLS_CC); - /* Mark FE_FETCH as IS_VAR as it holds the data directly as a value */ - zend_do_assign_ref(NULL, value, &value_node TSRMLS_CC); - } else { - zend_do_assign(&dummy, value, &value_node TSRMLS_CC); + if (value->EA & ZEND_PARSED_LIST_EXPR) { + zend_do_list_end(&dummy, &value_node TSRMLS_CC); zend_do_free(&dummy TSRMLS_CC); + } else { + if (assign_by_ref) { + zend_do_end_variable_parse(value, BP_VAR_W, 0 TSRMLS_CC); + /* Mark FE_FETCH as IS_VAR as it holds the data directly as a value */ + zend_do_assign_ref(NULL, value, &value_node TSRMLS_CC); + } else { + zend_do_assign(&dummy, value, &value_node TSRMLS_CC); + zend_do_free(&dummy TSRMLS_CC); + } } if (key->op_type != IS_UNUSED) { diff --git a/Zend/zend_compile.h b/Zend/zend_compile.h index 971860602e..15c2ab7bc7 100644 --- a/Zend/zend_compile.h +++ b/Zend/zend_compile.h @@ -725,6 +725,7 @@ int zend_add_literal(zend_op_array *op_array, const zval *zv TSRMLS_DC); #define ZEND_PARSED_VARIABLE (1<<4) #define ZEND_PARSED_REFERENCE_VARIABLE (1<<5) #define ZEND_PARSED_NEW (1<<6) +#define ZEND_PARSED_LIST_EXPR (1<<7) /* unset types */ diff --git a/Zend/zend_language_parser.y b/Zend/zend_language_parser.y index cef82e3353..32f35fa252 100644 --- a/Zend/zend_language_parser.y +++ b/Zend/zend_language_parser.y @@ -310,7 +310,7 @@ unticked_statement: foreach_statement { zend_do_foreach_end(&$1, &$4 TSRMLS_CC); } | T_FOREACH '(' expr_without_variable T_AS { zend_do_foreach_begin(&$1, &$2, &$3, &$4, 0 TSRMLS_CC); } - variable foreach_optional_arg ')' { zend_check_writable_variable(&$6); zend_do_foreach_cont(&$1, &$2, &$4, &$6, &$7 TSRMLS_CC); } + foreach_variable foreach_optional_arg ')' { zend_check_writable_variable(&$6); zend_do_foreach_cont(&$1, &$2, &$4, &$6, &$7 TSRMLS_CC); } foreach_statement { zend_do_foreach_end(&$1, &$4 TSRMLS_CC); } | T_DECLARE { $1.u.op.opline_num = get_next_op_number(CG(active_op_array)); zend_do_declare_begin(TSRMLS_C); } '(' declare_list ')' declare_statement { zend_do_declare_end(&$1 TSRMLS_CC); } | ';' /* empty statement */ @@ -429,10 +429,10 @@ foreach_optional_arg: | T_DOUBLE_ARROW foreach_variable { $$ = $2; } ; - foreach_variable: variable { zend_check_writable_variable(&$1); $$ = $1; } | '&' variable { zend_check_writable_variable(&$2); $$ = $2; $$.EA |= ZEND_PARSED_REFERENCE_VARIABLE; } + | T_LIST '(' { zend_do_list_init(TSRMLS_C); } assignment_list ')' { $$ = $1; $$.EA = ZEND_PARSED_LIST_EXPR; } ; for_statement: diff --git a/tests/lang/foreachLoop.007.phpt b/tests/lang/foreachLoop.007.phpt index f47fdc735f..269286d024 100644 --- a/tests/lang/foreachLoop.007.phpt +++ b/tests/lang/foreachLoop.007.phpt @@ -8,4 +8,4 @@ foreach (array(1,2) as &$v) { } ?> --EXPECTF-- -Parse error: %s on line 3 +Fatal error: Cannot create references to elements of a temporary array expression in %sforeachLoop.007.php on line %d