Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse code

Support list in foreach

  • Loading branch information...
commit 35951d4be0bd27c85519995a95429bd0d0a76a00 1 parent e888d48
Xinchen Hui authored August 25, 2012
1  NEWS
@@ -3,6 +3,7 @@ PHP                                                                        NEWS
3 3
 ?? ??? 201?, PHP 5.5.0
4 4
 
5 5
 - General improvements:
  6
+  . Support list in foreach (https://wiki.php.net/rfc/foreachlist). (Laruence)
6 7
   . Implemented 'finally' keyword (https://wiki.php.net/rfc/finally). (Laruence)
7 8
   . Drop Windows XP and 2003 support. (Pierre)
8 9
   . Improve set_exception_handler while doing reset.(Laruence)
2  UPGRADING
@@ -31,6 +31,8 @@ PHP X.Y UPGRADE NOTES
31 31
 2. New Features
32 32
 ========================================
33 33
 
  34
+- Support list in foreach. (Laruence)
  35
+  (wiki.php.net/rfc/foreachlist)
34 36
 - Support finally keyword. (Laruence)
35 37
   (wiki.php.net/rfc/finally)
36 38
 - Support constant array/string dereferencing. (Laruence)
43  Zend/tests/foreach_list.phpt
... ...
@@ -0,0 +1,43 @@
  1
+--TEST--
  2
+foreach with list syntax
  3
+--FILE--
  4
+<?php
  5
+
  6
+foreach(array(array(1,2), array(3,4)) as list($a, $b)) {
  7
+    var_dump($a . $b);
  8
+}
  9
+
  10
+$array = array(
  11
+    array('a', 'b'),
  12
+    array('c', 'd'),
  13
+);
  14
+
  15
+foreach ($array as list($a, $b)) {
  16
+    var_dump($a . $b);
  17
+}
  18
+
  19
+
  20
+$multi = array(
  21
+    array(array(1,2), array(3,4)),
  22
+    array(array(5,6), array(7,8)),
  23
+);
  24
+
  25
+foreach ($multi as list(list($a, $b), list($c, $d))) {
  26
+    var_dump($a . $b . $c . $d);
  27
+}
  28
+
  29
+foreach ($multi as $key => list(list($a, $b), list($c, $d))) {
  30
+    var_dump($key . $a . $b . $c . $d);
  31
+}
  32
+
  33
+
  34
+?>
  35
+--EXPECT--
  36
+string(2) "12"
  37
+string(2) "34"
  38
+string(2) "ab"
  39
+string(2) "cd"
  40
+string(4) "1234"
  41
+string(4) "5678"
  42
+string(5) "01234"
  43
+string(5) "15678"
17  Zend/zend_compile.c
@@ -6320,13 +6320,18 @@ void zend_do_foreach_cont(znode *foreach_token, const znode *open_brackets_token
6320 6320
 
6321 6321
 	GET_NODE(&value_node, opline->result);
6322 6322
 
6323  
-	if (assign_by_ref) {
6324  
-		zend_do_end_variable_parse(value, BP_VAR_W, 0 TSRMLS_CC);
6325  
-		/* Mark FE_FETCH as IS_VAR as it holds the data directly as a value */
6326  
-		zend_do_assign_ref(NULL, value, &value_node TSRMLS_CC);
6327  
-	} else {
6328  
-		zend_do_assign(&dummy, value, &value_node TSRMLS_CC);
  6323
+	if (value->EA & ZEND_PARSED_LIST_EXPR) {
  6324
+		zend_do_list_end(&dummy, &value_node TSRMLS_CC);
6329 6325
 		zend_do_free(&dummy TSRMLS_CC);
  6326
+	} else {
  6327
+		if (assign_by_ref) {
  6328
+			zend_do_end_variable_parse(value, BP_VAR_W, 0 TSRMLS_CC);
  6329
+			/* Mark FE_FETCH as IS_VAR as it holds the data directly as a value */
  6330
+			zend_do_assign_ref(NULL, value, &value_node TSRMLS_CC);
  6331
+		} else {
  6332
+			zend_do_assign(&dummy, value, &value_node TSRMLS_CC);
  6333
+			zend_do_free(&dummy TSRMLS_CC);
  6334
+		}
6330 6335
 	}
6331 6336
 
6332 6337
 	if (key->op_type != IS_UNUSED) {
1  Zend/zend_compile.h
@@ -725,6 +725,7 @@ int zend_add_literal(zend_op_array *op_array, const zval *zv TSRMLS_DC);
725 725
 #define ZEND_PARSED_VARIABLE			(1<<4)
726 726
 #define ZEND_PARSED_REFERENCE_VARIABLE	(1<<5)
727 727
 #define ZEND_PARSED_NEW					(1<<6)
  728
+#define ZEND_PARSED_LIST_EXPR			(1<<7)
728 729
 
729 730
 
730 731
 /* unset types */
4  Zend/zend_language_parser.y
@@ -310,7 +310,7 @@ unticked_statement:
310 310
 		foreach_statement { zend_do_foreach_end(&$1, &$4 TSRMLS_CC); }
311 311
 	|	T_FOREACH '(' expr_without_variable T_AS
312 312
 		{ zend_do_foreach_begin(&$1, &$2, &$3, &$4, 0 TSRMLS_CC); }
313  
-		variable foreach_optional_arg ')' { zend_check_writable_variable(&$6); zend_do_foreach_cont(&$1, &$2, &$4, &$6, &$7 TSRMLS_CC); }
  313
+		foreach_variable foreach_optional_arg ')' { zend_check_writable_variable(&$6); zend_do_foreach_cont(&$1, &$2, &$4, &$6, &$7 TSRMLS_CC); }
314 314
 		foreach_statement { zend_do_foreach_end(&$1, &$4 TSRMLS_CC); }
315 315
 	|	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); }
316 316
 	|	';'		/* empty statement */
@@ -429,10 +429,10 @@ foreach_optional_arg:
429 429
 	|	T_DOUBLE_ARROW foreach_variable	{ $$ = $2; }
430 430
 ;
431 431
 
432  
-
433 432
 foreach_variable:
434 433
 		variable			{ zend_check_writable_variable(&$1); $$ = $1; }
435 434
 	|	'&' variable		{ zend_check_writable_variable(&$2); $$ = $2;  $$.EA |= ZEND_PARSED_REFERENCE_VARIABLE; }
  435
+	|	T_LIST '(' { zend_do_list_init(TSRMLS_C); } assignment_list ')' { $$ = $1; $$.EA = ZEND_PARSED_LIST_EXPR; }
436 436
 ;
437 437
 
438 438
 for_statement:
2  tests/lang/foreachLoop.007.phpt
@@ -8,4 +8,4 @@ foreach (array(1,2) as &$v) {
8 8
 }
9 9
 ?>
10 10
 --EXPECTF--
11  
-Parse error: %s on line 3
  11
+Fatal error: Cannot create references to elements of a temporary array expression in %sforeachLoop.007.php on line %d

0 notes on commit 35951d4

Please sign in to comment.
Something went wrong with that request. Please try again.