Skip to content

Commit 28f5201

Browse files
authored
Support php 8.1 enums (#197)
* Support php 8.1 enums * Test with travis and php 8.0, again * AST_ENUM_CASE can have attributes * Set `type` property of `AST_CLASS` iff ast version 85+ (iff === if and only if) * Add AST_CLASS's type in version 85+ prior to php 8.1 * [skip ci] Document support for php 8.1 enums
1 parent 72f459a commit 28f5201

13 files changed

+314
-34
lines changed

.appveyor.yml

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -32,22 +32,22 @@ environment:
3232
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2019
3333
ARCH: x86
3434
VC: vs16
35-
PHP_VER: 8.0.0
35+
PHP_VER: 8.0.3
3636
TS: 1
3737
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2019
3838
ARCH: x64
3939
VC: vs16
40-
PHP_VER: 8.0.0
40+
PHP_VER: 8.0.3
4141
TS: 1
4242
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2019
4343
ARCH: x86
4444
VC: vs16
45-
PHP_VER: 8.0.0
45+
PHP_VER: 8.0.3
4646
TS: 0
4747
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2019
4848
ARCH: x64
4949
VC: vs16
50-
PHP_VER: 8.0.0
50+
PHP_VER: 8.0.3
5151
TS: 0
5252
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015
5353
ARCH: x64
@@ -117,37 +117,37 @@ environment:
117117
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017
118118
ARCH: x64
119119
VC: vc15
120-
PHP_VER: 7.3.25
120+
PHP_VER: 7.3.27
121121
TS: 1
122122
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017
123123
ARCH: x86
124124
VC: vc15
125-
PHP_VER: 7.3.25
125+
PHP_VER: 7.3.27
126126
TS: 0
127127
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017
128128
ARCH: x86
129129
VC: vc15
130-
PHP_VER: 7.3.25
130+
PHP_VER: 7.3.27
131131
TS: 1
132132
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017
133133
ARCH: x64
134134
VC: vc15
135-
PHP_VER: 7.4.13
135+
PHP_VER: 7.4.16
136136
TS: 0
137137
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017
138138
ARCH: x64
139139
VC: vc15
140-
PHP_VER: 7.4.13
140+
PHP_VER: 7.4.16
141141
TS: 1
142142
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017
143143
ARCH: x86
144144
VC: vc15
145-
PHP_VER: 7.4.13
145+
PHP_VER: 7.4.16
146146
TS: 0
147147
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017
148148
ARCH: x86
149149
VC: vc15
150-
PHP_VER: 7.4.13
150+
PHP_VER: 7.4.16
151151
TS: 1
152152

153153
build_script:

.travis.yml

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,7 @@ php:
77
- 7.2
88
- 7.3
99
- 7.4
10-
# https://travis-ci.community/t/php-8-0-missing/10132
11-
# - 8.0snapshot
10+
- 8.0
1211
- nightly
1312

1413
before_script:

README.md

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -246,12 +246,13 @@ ast\flags\FUNC_GENERATOR // used only in PHP >= 7.1
246246
// Used by ast\AST_CLOSURE_VAR
247247
ast\flags\CLOSURE_USE_REF
248248
249-
// Used by ast\AST_CLASS (exclusive)
249+
// Used by ast\AST_CLASS (combinable since PHP 8.1 enums)
250250
ast\flags\CLASS_ABSTRACT
251251
ast\flags\CLASS_FINAL
252252
ast\flags\CLASS_TRAIT
253253
ast\flags\CLASS_INTERFACE
254254
ast\flags\CLASS_ANONYMOUS
255+
ast\flags\CLASS_ENUM
255256
256257
// Used by ast\AST_PARAM (combinable)
257258
ast\flags\PARAM_REF
@@ -374,7 +375,7 @@ AST_BREAK: depth
374375
AST_CALL: expr, args
375376
AST_CAST: expr
376377
AST_CATCH: class, var, stmts
377-
AST_CLASS: name, docComment, extends, implements, stmts
378+
AST_CLASS: name, docComment, extends, implements, stmts, (for enums) type
378379
AST_CLASS_CONST: class, const
379380
AST_CLASS_CONST_GROUP class, attributes // version 80+
380381
AST_CLASS_NAME: class // version 70+
@@ -390,6 +391,7 @@ AST_DIM: expr, dim
390391
AST_DO_WHILE: stmts, cond
391392
AST_ECHO: expr
392393
AST_EMPTY: expr
394+
AST_ENUM_CASE: name, expr, attributes // php 8.1+ enums
393395
AST_EXIT: expr
394396
AST_FOR: init, cond, loop, stmts
395397
AST_FOREACH: expr, value, key, stmts

ast.c

Lines changed: 39 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,7 @@ static const char *class_flags[] = {
132132
AST_FLAG(CLASS_TRAIT),
133133
AST_FLAG(CLASS_INTERFACE),
134134
AST_FLAG(CLASS_ANONYMOUS),
135+
AST_FLAG(CLASS_ENUM),
135136
NULL
136137
};
137138

@@ -294,7 +295,7 @@ static const char *conditional_flags[] = {
294295

295296
static const ast_flag_info flag_info[] = {
296297
{ AST_NAME, 0, name_flags },
297-
{ ZEND_AST_CLASS, 0, class_flags },
298+
{ ZEND_AST_CLASS, 1, class_flags },
298299
{ ZEND_AST_PARAM, 1, param_flags },
299300
{ ZEND_AST_TYPE, 0, type_flags },
300301
{ ZEND_AST_CAST, 0, type_flags },
@@ -448,6 +449,12 @@ static inline zend_bool ast_is_name(zend_ast *ast, zend_ast *parent, uint32_t i)
448449
|| parent->kind == ZEND_AST_METHOD;
449450
}
450451

452+
#if PHP_VERSION_ID >= 80100
453+
if (i == 4) {
454+
return parent->kind == ZEND_AST_CLASS;
455+
}
456+
#endif
457+
451458
return 0;
452459
}
453460

@@ -472,6 +479,11 @@ static inline zend_bool ast_is_type(zend_ast *ast, zend_ast *parent, uint32_t i)
472479
#endif
473480
|| parent->kind == ZEND_AST_METHOD;
474481
}
482+
#if PHP_VERSION_ID >= 80100
483+
if (i == 4) {
484+
return parent->kind == ZEND_AST_CLASS;
485+
}
486+
#endif
475487
return 0;
476488
}
477489

@@ -557,10 +569,12 @@ static inline zend_ast_attr ast_assign_op_to_binary_op(zend_ast_attr attr) {
557569
}
558570
#endif
559571

560-
static inline zend_ast **ast_get_children(zend_ast *ast, uint32_t *count) {
572+
static inline zend_ast **ast_get_children(zend_ast *ast, ast_state_info_t *state, uint32_t *count) {
561573
if (ast_kind_is_decl(ast->kind)) {
562574
zend_ast_decl *decl = (zend_ast_decl *) ast;
563-
#if PHP_VERSION_ID >= 80000
575+
#if PHP_VERSION_ID >= 80100
576+
*count = decl->kind == ZEND_AST_CLASS ? (state->version >= 85 ? 5 : 4) : 5;
577+
#elif PHP_VERSION_ID >= 80000
564578
*count = decl->kind == ZEND_AST_CLASS ? 4 : 5;
565579
#else
566580
*count = decl->kind == ZEND_AST_CLASS ? 3 : 4;
@@ -662,7 +676,7 @@ static inline void ast_name_to_zval(zend_ast *child, zend_ast *ast, zval *child_
662676
static void ast_fill_children_ht(HashTable *ht, zend_ast *ast, ast_state_info_t *state) {
663677
uint32_t i, count;
664678
zend_bool is_list = zend_ast_is_list(ast);
665-
zend_ast **children = ast_get_children(ast, &count);
679+
zend_ast **children = ast_get_children(ast, state, &count);
666680
const zend_ast_kind ast_kind = ast->kind;
667681
for (i = 0; i < count; ++i) {
668682
zend_ast *child = children[i];
@@ -697,7 +711,7 @@ static void ast_fill_children_ht(HashTable *ht, zend_ast *ast, ast_state_info_t
697711
}
698712
break;
699713
case ZEND_AST_CLASS:
700-
if (i == 3) {
714+
if (i >= 3) {
701715
continue;
702716
}
703717
break;
@@ -708,6 +722,13 @@ static void ast_fill_children_ht(HashTable *ht, zend_ast *ast, ast_state_info_t
708722
break;
709723
}
710724
}
725+
#if PHP_VERSION_ID >= 80100
726+
if (ast_kind == ZEND_AST_CLASS && i == 4) {
727+
if (state->version < 85) {
728+
continue;
729+
}
730+
}
731+
#endif
711732
#endif
712733
/* This AST_CATCH check should occur before ast_is_name() */
713734
#if PHP_VERSION_ID < 70100
@@ -809,6 +830,17 @@ static void ast_fill_children_ht(HashTable *ht, zend_ast *ast, ast_state_info_t
809830
zend_hash_add_new(ht, AST_STR(str_attributes), &tmp);
810831
}
811832
#endif
833+
834+
#if PHP_VERSION_ID < 80100
835+
if (ast_kind == ZEND_AST_CLASS) {
836+
if (state->version >= 85) {
837+
zval tmp;
838+
ZVAL_NULL(&tmp);
839+
zend_hash_add_new(ht, AST_STR(str_type), &tmp);
840+
}
841+
}
842+
#endif
843+
812844
ZVAL_LONG(&id_zval, state->declIdCounter);
813845
state->declIdCounter++;
814846
zend_hash_add_new(ht, AST_STR(str___declId), &id_zval);
@@ -1027,7 +1059,7 @@ static void ast_to_zval(zval *zv, zend_ast *ast, ast_state_info_t *state) {
10271059
#endif
10281060
}
10291061

1030-
static const zend_long versions[] = {50, 60, 70, 80};
1062+
static const zend_long versions[] = {50, 60, 70, 80, 85};
10311063
static const size_t versions_count = sizeof(versions)/sizeof(versions[0]);
10321064

10331065
static inline zend_bool ast_version_deprecated(zend_long version) {
@@ -1377,6 +1409,7 @@ PHP_MINIT_FUNCTION(ast) {
13771409
ast_register_flag_constant("CLASS_TRAIT", ZEND_ACC_TRAIT);
13781410
ast_register_flag_constant("CLASS_INTERFACE", ZEND_ACC_INTERFACE);
13791411
ast_register_flag_constant("CLASS_ANONYMOUS", ZEND_ACC_ANON_CLASS);
1412+
ast_register_flag_constant("CLASS_ENUM", ZEND_ACC_ENUM);
13801413

13811414
ast_register_flag_constant("PARAM_REF", ZEND_PARAM_REF);
13821415
ast_register_flag_constant("PARAM_VARIADIC", ZEND_PARAM_VARIADIC);

ast_data.c

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,7 @@ const zend_ast_kind ast_kinds[] = {
9797
ZEND_AST_MATCH,
9898
ZEND_AST_MATCH_ARM,
9999
ZEND_AST_NAMED_ARG,
100+
ZEND_AST_ENUM_CASE,
100101
ZEND_AST_METHOD_CALL,
101102
ZEND_AST_NULLSAFE_METHOD_CALL,
102103
ZEND_AST_STATIC_CALL,
@@ -208,6 +209,7 @@ const char *ast_kind_to_name(zend_ast_kind kind) {
208209
case ZEND_AST_MATCH: return "AST_MATCH";
209210
case ZEND_AST_MATCH_ARM: return "AST_MATCH_ARM";
210211
case ZEND_AST_NAMED_ARG: return "AST_NAMED_ARG";
212+
case ZEND_AST_ENUM_CASE: return "AST_ENUM_CASE";
211213
case ZEND_AST_METHOD_CALL: return "AST_METHOD_CALL";
212214
case ZEND_AST_NULLSAFE_METHOD_CALL: return "AST_NULLSAFE_METHOD_CALL";
213215
case ZEND_AST_STATIC_CALL: return "AST_STATIC_CALL";
@@ -281,6 +283,7 @@ zend_string *ast_kind_child_name(zend_ast_kind kind, uint32_t child) {
281283
case 1: return AST_STR(str_implements);
282284
case 2: return AST_STR(str_stmts);
283285
case 3: return AST_STR(str_attributes);
286+
case 4: return AST_STR(str_type);
284287
}
285288
return NULL;
286289
case ZEND_AST_MAGIC_CONST:
@@ -651,6 +654,13 @@ zend_string *ast_kind_child_name(zend_ast_kind kind, uint32_t child) {
651654
case 1: return AST_STR(str_expr);
652655
}
653656
return NULL;
657+
case ZEND_AST_ENUM_CASE:
658+
switch (child) {
659+
case 0: return AST_STR(str_name);
660+
case 1: return AST_STR(str_expr);
661+
case 2: return AST_STR(str_attributes);
662+
}
663+
return NULL;
654664
case ZEND_AST_METHOD_CALL:
655665
switch (child) {
656666
case 0: return AST_STR(str_expr);
@@ -820,6 +830,7 @@ void ast_register_kind_constants(INIT_FUNC_ARGS) {
820830
REGISTER_NS_LONG_CONSTANT("ast", "AST_MATCH", ZEND_AST_MATCH, CONST_CS | CONST_PERSISTENT);
821831
REGISTER_NS_LONG_CONSTANT("ast", "AST_MATCH_ARM", ZEND_AST_MATCH_ARM, CONST_CS | CONST_PERSISTENT);
822832
REGISTER_NS_LONG_CONSTANT("ast", "AST_NAMED_ARG", ZEND_AST_NAMED_ARG, CONST_CS | CONST_PERSISTENT);
833+
REGISTER_NS_LONG_CONSTANT("ast", "AST_ENUM_CASE", ZEND_AST_ENUM_CASE, CONST_CS | CONST_PERSISTENT);
823834
REGISTER_NS_LONG_CONSTANT("ast", "AST_METHOD_CALL", ZEND_AST_METHOD_CALL, CONST_CS | CONST_PERSISTENT);
824835
REGISTER_NS_LONG_CONSTANT("ast", "AST_NULLSAFE_METHOD_CALL", ZEND_AST_NULLSAFE_METHOD_CALL, CONST_CS | CONST_PERSISTENT);
825836
REGISTER_NS_LONG_CONSTANT("ast", "AST_STATIC_CALL", ZEND_AST_STATIC_CALL, CONST_CS | CONST_PERSISTENT);

ast_stub.php

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,7 @@
103103
const AST_MATCH = 548;
104104
const AST_MATCH_ARM = 549;
105105
const AST_NAMED_ARG = 550;
106+
const AST_ENUM_CASE = 777;
106107
const AST_METHOD_CALL = 768;
107108
const AST_NULLSAFE_METHOD_CALL = 769;
108109
const AST_STATIC_CALL = 770;
@@ -138,6 +139,7 @@
138139
const CLASS_TRAIT = 2;
139140
const CLASS_INTERFACE = 1;
140141
const CLASS_ANONYMOUS = 4;
142+
const CLASS_ENUM = 268435456;
141143
const PARAM_REF = 8;
142144
const PARAM_VARIADIC = 16;
143145
const TYPE_NULL = 1;
@@ -191,14 +193,14 @@
191193
const USE_NORMAL = 1;
192194
const USE_FUNCTION = 2;
193195
const USE_CONST = 4;
194-
const MAGIC_LINE = 375;
195-
const MAGIC_FILE = 376;
196-
const MAGIC_DIR = 377;
197-
const MAGIC_NAMESPACE = 382;
198-
const MAGIC_FUNCTION = 381;
199-
const MAGIC_METHOD = 380;
200-
const MAGIC_CLASS = 378;
201-
const MAGIC_TRAIT = 379;
196+
const MAGIC_LINE = 376;
197+
const MAGIC_FILE = 377;
198+
const MAGIC_DIR = 378;
199+
const MAGIC_NAMESPACE = 383;
200+
const MAGIC_FUNCTION = 382;
201+
const MAGIC_METHOD = 381;
202+
const MAGIC_CLASS = 379;
203+
const MAGIC_TRAIT = 380;
202204
const ARRAY_SYNTAX_LIST = 1;
203205
const ARRAY_SYNTAX_LONG = 2;
204206
const ARRAY_SYNTAX_SHORT = 3;

package.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
</stability>
3030
<license uri="https://github.com/nikic/php-ast/blob/master/LICENSE">BSD-3-Clause</license>
3131
<notes>
32+
- Support php 8.1 enums, add 'type' (for enum type) to AST_CLASS nodes in AST version 85+.
3233
</notes>
3334
<contents>
3435
<dir name="/">

php_ast.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,12 @@ extern ast_str_globals str_globals;
7575
// NOTE: The first hex digit is the number of child nodes a given kind has
7676
#endif
7777

78+
#if PHP_VERSION_ID < 80100
79+
# define ZEND_ACC_ENUM (1 << 22)
80+
/* 3 child nodes - name, expr, attributes */
81+
# define ZEND_AST_ENUM_CASE 0x3fe
82+
#endif
83+
7884
/* Pretend it still exists */
7985
#if PHP_VERSION_ID >= 70100
8086
# define ZEND_AST_LIST ((1 << (ZEND_AST_IS_LIST_SHIFT + 1)) - 1)

scripts/generate_ast_data.php

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@
5858
'ZEND_AST_CLOSURE' => $funcNames,
5959
'ZEND_AST_METHOD' => $funcNames,
6060
'ZEND_AST_ARROW_FUNC' => $funcNames,
61-
'ZEND_AST_CLASS' => ['extends', 'implements', 'stmts', 'attributes'],
61+
'ZEND_AST_CLASS' => ['extends', 'implements', 'stmts', 'attributes', 'type'],
6262

6363
/* 0 child nodes */
6464
'ZEND_AST_MAGIC_CONST' => [],
@@ -134,6 +134,7 @@
134134
'ZEND_AST_MATCH' => ['cond', 'stmts'],
135135
'ZEND_AST_MATCH_ARM' => ['cond', 'expr'],
136136
'ZEND_AST_NAMED_ARG' => ['name', 'expr'],
137+
'ZEND_AST_ENUM_CASE' => ['name', 'expr', 'attributes'],
137138

138139
/* 3 child nodes */
139140
'ZEND_AST_METHOD_CALL' => ['expr', 'method', 'args'],

0 commit comments

Comments
 (0)