]> granicus.if.org Git - php/commitdiff
Support list in foreach
authorXinchen Hui <laruence@php.net>
Sat, 25 Aug 2012 14:23:14 +0000 (22:23 +0800)
committerXinchen Hui <laruence@php.net>
Sat, 25 Aug 2012 14:23:57 +0000 (22:23 +0800)
RFC: https://wiki.php.net/rfc/foreachlist

NEWS
UPGRADING
Zend/tests/foreach_list.phpt [new file with mode: 0644]
Zend/zend_compile.c
Zend/zend_compile.h
Zend/zend_language_parser.y
tests/lang/foreachLoop.007.phpt

diff --git a/NEWS b/NEWS
index 00f8ec6be9ec055694a407dc25212c21b7ccf683..28b89baaac3796ec1e3acf7e096273724b45db9f 100644 (file)
--- 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)
index aeab14b48fce9b9af2137989c245859802ae276b..ba556357ed489c32ec6c22ccd2ea39b7934a598e 100755 (executable)
--- 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 (file)
index 0000000..a318f1a
--- /dev/null
@@ -0,0 +1,43 @@
+--TEST--
+foreach with list syntax
+--FILE--
+<?php
+
+foreach(array(array(1,2), array(3,4)) as list($a, $b)) {
+    var_dump($a . $b);
+}
+
+$array = array(
+    array('a', 'b'),
+    array('c', 'd'),
+);
+
+foreach ($array as list($a, $b)) {
+    var_dump($a . $b);
+}
+
+
+$multi = array(
+    array(array(1,2), array(3,4)),
+    array(array(5,6), array(7,8)),
+);
+
+foreach ($multi as list(list($a, $b), list($c, $d))) {
+    var_dump($a . $b . $c . $d);
+}
+
+foreach ($multi as $key => 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"
index 2665870ab4f7ca5bd90d18a0c901be911f4df552..b87b1908b6bdebdf4fd1efce18da0b9667ec8477 100644 (file)
@@ -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) {
index 971860602eeaf88fe89245ef28f712705b93fb31..15c2ab7bc7998b9d323e947b39bae35fab75e826 100644 (file)
@@ -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 */
index cef82e3353227fbb7da6ce2b0163779a241c863d..32f35fa25250d0f7e5618e4e30145014ed12b7f4 100644 (file)
@@ -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:
index f47fdc735fa36e00d86f65de00e9d6460bb4aa83..269286d02427d8c8fbf06fdf3d65f2a75a658112 100644 (file)
@@ -8,4 +8,4 @@ foreach (array(1,2) as &$v) {
 }\r
 ?>\r
 --EXPECTF--\r
-Parse error: %s on line 3\r
+Fatal error: Cannot create references to elements of a temporary array expression in %sforeachLoop.007.php on line %d\r