Skip to content

Commit d4cac8f

Browse files
committed
Convert between AST_EXIT and AST_CALL
1 parent ffdd968 commit d4cac8f

File tree

6 files changed

+131
-5
lines changed

6 files changed

+131
-5
lines changed

README.md

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -394,7 +394,7 @@ AST_CLASS: name, docComment, extends, implements, stmts, (for enu
394394
AST_CLASS_CONST: class, const
395395
AST_CLASS_CONST_GROUP class, attributes, type // version 80+
396396
AST_CLASS_NAME: class // version 70+
397-
AST_CLONE: expr // version <120
397+
AST_CLONE: expr // prior to version 120
398398
AST_CLOSURE: name, docComment, params, uses, stmts, returnType, attributes // name removed in version 110
399399
AST_CLOSURE_VAR: name
400400
AST_CONDITIONAL: cond, true, false
@@ -407,7 +407,7 @@ AST_DO_WHILE: stmts, cond
407407
AST_ECHO: expr
408408
AST_EMPTY: expr
409409
AST_ENUM_CASE: name, expr, docComment, attributes // php 8.1+ enums
410-
AST_EXIT: expr
410+
AST_EXIT: expr // prior to version 120
411411
AST_FOR: init, cond, loop, stmts
412412
AST_FOREACH: expr, value, key, stmts
413413
AST_FUNC_DECL: name, docComment, params, stmts, returnType, attributes
@@ -515,7 +515,8 @@ are listed.
515515

516516
Supported since 1.1.3 (TBD).
517517

518-
* `clone $expr` is now represented like a `clone($expr)` function call (using `AST_CALL`).
518+
* `clone $expr` is now represented like a function call (using `AST_CALL` instead of `AST_CLONE`).
519+
* `exit($expr)` is now represented like a function call (using `AST_CALL` instead of `AST_EXIT`).
519520

520521
### 110 (current)
521522

ast.c

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1106,14 +1106,23 @@ static void ast_to_zval(zval *zv, zend_ast *ast, ast_state_info_t *state) {
11061106
ast_create_virtual_node(zv, ZEND_AST_CLONE, 0, arg, state);
11071107
return;
11081108
}
1109+
if (zend_string_equals_literal_ci(name, "exit")) {
1110+
ast_create_virtual_node(zv, ZEND_AST_EXIT, 0, arg, state);
1111+
return;
1112+
}
11091113
}
11101114
break;
11111115
case ZEND_AST_CLONE:
1116+
case ZEND_AST_EXIT:
11121117
if (state->version >= 120) {
11131118
// Convert to call node.
11141119
uint32_t lineno = zend_ast_get_lineno(ast);
11151120
zval name_str_zv, name_node_zv, args_zv, arg_zv;
1116-
ZVAL_STR(&name_str_zv, AST_STR(str_clone));
1121+
if (ast->kind == ZEND_AST_CLONE) {
1122+
ZVAL_STR(&name_str_zv, AST_STR(str_clone));
1123+
} else {
1124+
ZVAL_STR(&name_str_zv, AST_STR(str_exit));
1125+
}
11171126
ast_to_zval(&arg_zv, ast->child[0], state);
11181127
ast_create_virtual_node_ex(
11191128
&name_node_zv, AST_NAME, ZEND_NAME_FQ, lineno, state, 1, &name_str_zv);

ast_str_defs.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
X(__declId, "__declId") \
1313
X(flagsCombinable, "flagsCombinable") \
1414
X(clone, "clone") \
15+
X(exit, "exit") \
1516
X(type, "type") \
1617
X(params, "params") \
1718
X(uses, "uses") \

scripts/generate_ast_data.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -278,7 +278,7 @@ function get_possible_strings(array $spec) {
278278
$strings = array_fill_keys([
279279
'kind', 'flags', 'lineno', 'children',
280280
'name', 'docComment', 'endLineno', '__declId',
281-
'flagsCombinable', 'clone',
281+
'flagsCombinable', 'clone', 'exit',
282282
], true);
283283

284284
foreach ($spec as $kind => $children) {

tests/exit.phpt

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
--TEST--
2+
Simple exit
3+
--FILE--
4+
<?php
5+
6+
require __DIR__ . '/../util.php';
7+
8+
$code = <<<'PHP'
9+
<?php
10+
exit($foo);
11+
PHP;
12+
13+
$node = ast\parse_code($code, $version=110);
14+
echo ast_dump($node), "\n";
15+
$node = ast\parse_code($code, $version=120);
16+
echo ast_dump($node), "\n";
17+
--EXPECT--
18+
AST_STMT_LIST
19+
0: AST_EXIT
20+
expr: AST_VAR
21+
name: "foo"
22+
AST_STMT_LIST
23+
0: AST_CALL
24+
expr: AST_NAME
25+
flags: NAME_FQ (0)
26+
name: "exit"
27+
args: AST_ARG_LIST
28+
0: AST_VAR
29+
name: "foo"

tests/php84_exit.phpt

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
--TEST--
2+
Complex exit
3+
--SKIPIF--
4+
<?php if (PHP_VERSION_ID < 80500) die('skip PHP >= 8.5 only'); ?>
5+
--FILE--
6+
<?php
7+
8+
require __DIR__ . '/../util.php';
9+
10+
$code = <<<'PHP'
11+
<?php
12+
exit($foo, $bar);
13+
exit(a: $foo);
14+
exit(...$foo);
15+
exit(...);
16+
PHP;
17+
18+
$node = ast\parse_code($code, $version=110);
19+
echo ast_dump($node), "\n";
20+
$node = ast\parse_code($code, $version=120);
21+
echo ast_dump($node), "\n";
22+
--EXPECT--
23+
AST_STMT_LIST
24+
0: AST_CALL
25+
expr: AST_NAME
26+
flags: NAME_FQ (0)
27+
name: "exit"
28+
args: AST_ARG_LIST
29+
0: AST_VAR
30+
name: "foo"
31+
1: AST_VAR
32+
name: "bar"
33+
1: AST_CALL
34+
expr: AST_NAME
35+
flags: NAME_FQ (0)
36+
name: "exit"
37+
args: AST_ARG_LIST
38+
0: AST_NAMED_ARG
39+
name: "a"
40+
expr: AST_VAR
41+
name: "foo"
42+
2: AST_CALL
43+
expr: AST_NAME
44+
flags: NAME_FQ (0)
45+
name: "exit"
46+
args: AST_ARG_LIST
47+
0: AST_UNPACK
48+
expr: AST_VAR
49+
name: "foo"
50+
3: AST_CALL
51+
expr: AST_NAME
52+
flags: NAME_FQ (0)
53+
name: "exit"
54+
args: AST_CALLABLE_CONVERT
55+
AST_STMT_LIST
56+
0: AST_CALL
57+
expr: AST_NAME
58+
flags: NAME_FQ (0)
59+
name: "exit"
60+
args: AST_ARG_LIST
61+
0: AST_VAR
62+
name: "foo"
63+
1: AST_VAR
64+
name: "bar"
65+
1: AST_CALL
66+
expr: AST_NAME
67+
flags: NAME_FQ (0)
68+
name: "exit"
69+
args: AST_ARG_LIST
70+
0: AST_NAMED_ARG
71+
name: "a"
72+
expr: AST_VAR
73+
name: "foo"
74+
2: AST_CALL
75+
expr: AST_NAME
76+
flags: NAME_FQ (0)
77+
name: "exit"
78+
args: AST_ARG_LIST
79+
0: AST_UNPACK
80+
expr: AST_VAR
81+
name: "foo"
82+
3: AST_CALL
83+
expr: AST_NAME
84+
flags: NAME_FQ (0)
85+
name: "exit"
86+
args: AST_CALLABLE_CONVERT

0 commit comments

Comments
 (0)