Commit:    35951d4be0bd27c85519995a95429bd0d0a76a00
Author:    Xinchen Hui <larue...@php.net>         Sat, 25 Aug 2012 22:23:14 
+0800
Parents:   e888d48d9ba9adbd37d8c102c40b90bedf20ca7a
Branches:  master

Link:       
http://git.php.net/?p=php-src.git;a=commitdiff;h=35951d4be0bd27c85519995a95429bd0d0a76a00

Log:
Support list in foreach

RFC: https://wiki.php.net/rfc/foreachlist

Changed paths:
  M  NEWS
  M  UPGRADING
  A  Zend/tests/foreach_list.phpt
  M  Zend/zend_compile.c
  M  Zend/zend_compile.h
  M  Zend/zend_language_parser.y
  M  tests/lang/foreachLoop.007.phpt


Diff:
diff --git a/NEWS b/NEWS
index 00f8ec6..28b89ba 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 aeab14b..ba55635 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 0000000..a318f1a
--- /dev/null
+++ b/Zend/tests/foreach_list.phpt
@@ -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"
diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c
index 2665870..b87b190 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 9718606..15c2ab7 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 cef82e3..32f35fa 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 f47fdc7..269286d 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


--
PHP CVS Mailing List (http://www.php.net/)
To unsubscribe, visit: http://www.php.net/unsub.php

Reply via email to