Skip to content

Commit 322e614

Browse files
committed
Version 35: Backward/forward emulation of list() format
1 parent eded56d commit 322e614

File tree

4 files changed

+86
-19
lines changed

4 files changed

+86
-19
lines changed

README.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -445,6 +445,10 @@ Version changelog
445445
* The `class` node of `AST_CATCH` is now always represented as an `AST_NAME_LIST`. In lower
446446
versions: On PHP 7.0 it will always be an `AST_NAME`. In PHP 7.1 it will be an `AST_NAME` if
447447
there is only a single class and `AST_NAME_LIST` otherwise.
448+
* `list()` destructuring is now always represented as an `AST_ARRAY` with `ARRAY_SYNTAX_LIST` flag.
449+
In lower versions: On PHP 7.0 it will always be an `AST_LIST`. In PHP 7.1 it will be an
450+
`AST_ARRAY` if `list()` is used with keys. In PHP 7.1 destructuring using `[]` will always be
451+
represented using `AST_ARRAY`, independently of the version.
448452

449453
### 30 (current)
450454

ast.c

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -233,6 +233,22 @@ static inline zend_ast_attr ast_assign_op_to_binary_op(zend_ast_attr attr) {
233233
}
234234
}
235235

236+
static inline zend_bool ast_array_is_list(zend_ast *ast) {
237+
zend_ast_list *list = zend_ast_get_list(ast);
238+
uint32_t i;
239+
if (ast->attr != ZEND_ARRAY_SYNTAX_LIST) {
240+
return 0;
241+
}
242+
243+
for (i = 0; i < list->children; i++) {
244+
if (list->child[i]->child[1] != NULL || list->child[i]->attr) {
245+
return 0;
246+
}
247+
}
248+
249+
return 1;
250+
}
251+
236252
static inline zend_ast **ast_get_children(zend_ast *ast, uint32_t *count) {
237253
if (ast_kind_is_decl(ast->kind)) {
238254
zend_ast_decl *decl = (zend_ast_decl *) ast;
@@ -378,6 +394,15 @@ static void ast_fill_children_ht(HashTable *ht, zend_ast *ast, zend_long version
378394
&& (ast->kind == ZEND_AST_PROP_ELEM || ast->kind == ZEND_AST_CONST_ELEM)) {
379395
/* Skip docComment child -- It's handled separately */
380396
continue;
397+
#if PHP_VERSION_ID >= 70100
398+
} else if (ast->kind == ZEND_AST_LIST) {
399+
ast_to_zval(&child_zv, child->child[0], version);
400+
#else
401+
} else if (ast->kind == ZEND_AST_LIST && version >= 35) {
402+
zend_ast *new_child = zend_ast_create(ZEND_AST_ARRAY_ELEM, child, NULL);
403+
new_child->lineno = zend_ast_get_lineno(child);
404+
ast_to_zval(&child_zv, new_child, version);
405+
#endif
381406
} else {
382407
ast_to_zval(&child_zv, child, version);
383408
}
@@ -447,6 +472,18 @@ static void ast_to_zval(zval *zv, zend_ast *ast, zend_long version) {
447472
}
448473
}
449474

475+
#if PHP_VERSION_ID >= 70100
476+
if (version < 35 && ast->kind == ZEND_AST_ARRAY && ast_array_is_list(ast)) {
477+
ast->kind = ZEND_AST_LIST;
478+
ast->attr = 0;
479+
}
480+
#else
481+
if (version >= 35 && ast->kind == ZEND_AST_LIST) {
482+
ast->kind = ZEND_AST_ARRAY;
483+
ast->attr = ZEND_AST_LIST;
484+
}
485+
#endif
486+
450487
is_decl = ast_kind_is_decl(ast->kind);
451488
object_init_ex(zv, is_decl ? ast_decl_ce : ast_node_ce);
452489

tests/array_destructuring.phpt

Lines changed: 3 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@ require __DIR__ . '/../util.php';
99

1010
$code = <<<'PHP'
1111
<?php
12-
list($a, $b) = $x;
1312
list('foo' => $a, 'bar' => $b) = $x;
1413
[$a, $b] = $x;
1514
['foo' => $a, 'bar' => $b] = $x;
@@ -22,21 +21,6 @@ echo ast_dump(ast\parse_code($code, $version=30));
2221
--EXPECT--
2322
AST_STMT_LIST
2423
0: AST_ASSIGN
25-
var: AST_ARRAY
26-
flags: ARRAY_SYNTAX_LIST (1)
27-
0: AST_ARRAY_ELEM
28-
flags: 0
29-
value: AST_VAR
30-
name: "a"
31-
key: null
32-
1: AST_ARRAY_ELEM
33-
flags: 0
34-
value: AST_VAR
35-
name: "b"
36-
key: null
37-
expr: AST_VAR
38-
name: "x"
39-
1: AST_ASSIGN
4024
var: AST_ARRAY
4125
flags: ARRAY_SYNTAX_LIST (1)
4226
0: AST_ARRAY_ELEM
@@ -51,7 +35,7 @@ AST_STMT_LIST
5135
key: "bar"
5236
expr: AST_VAR
5337
name: "x"
54-
2: AST_ASSIGN
38+
1: AST_ASSIGN
5539
var: AST_ARRAY
5640
flags: ARRAY_SYNTAX_SHORT (3)
5741
0: AST_ARRAY_ELEM
@@ -66,7 +50,7 @@ AST_STMT_LIST
6650
key: null
6751
expr: AST_VAR
6852
name: "x"
69-
3: AST_ASSIGN
53+
2: AST_ASSIGN
7054
var: AST_ARRAY
7155
flags: ARRAY_SYNTAX_SHORT (3)
7256
0: AST_ARRAY_ELEM
@@ -81,7 +65,7 @@ AST_STMT_LIST
8165
key: "bar"
8266
expr: AST_VAR
8367
name: "x"
84-
4: AST_ASSIGN
68+
3: AST_ASSIGN
8569
var: AST_ARRAY
8670
flags: ARRAY_SYNTAX_SHORT (3)
8771
0: null

tests/array_destructuring_old.phpt

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
--TEST--
2+
Array destructuring (using unkeyed list())
3+
--FILE--
4+
<?php
5+
6+
require __DIR__ . '/../util.php';
7+
8+
$code = <<<'PHP'
9+
<?php
10+
list($a, $b) = $x;
11+
PHP;
12+
13+
echo ast_dump(ast\parse_code($code, $version=30)), "\n";
14+
echo ast_dump(ast\parse_code($code, $version=35));
15+
16+
?>
17+
--EXPECT--
18+
AST_STMT_LIST
19+
0: AST_ASSIGN
20+
var: AST_LIST
21+
0: AST_VAR
22+
name: "a"
23+
1: AST_VAR
24+
name: "b"
25+
expr: AST_VAR
26+
name: "x"
27+
AST_STMT_LIST
28+
0: AST_ASSIGN
29+
var: AST_ARRAY
30+
flags: ARRAY_SYNTAX_LIST (1)
31+
0: AST_ARRAY_ELEM
32+
flags: 0
33+
value: AST_VAR
34+
name: "a"
35+
key: null
36+
1: AST_ARRAY_ELEM
37+
flags: 0
38+
value: AST_VAR
39+
name: "b"
40+
key: null
41+
expr: AST_VAR
42+
name: "x"

0 commit comments

Comments
 (0)