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