@@ -54,13 +54,14 @@ ZEND_API zend_ast * ZEND_FASTCALL zend_ast_create_znode(const znode *node) {
5454 return (zend_ast * ) ast ;
5555}
5656
57- ZEND_API zend_ast * ZEND_FASTCALL zend_ast_create_fcc (void ) {
57+ ZEND_API zend_ast * ZEND_FASTCALL zend_ast_create_fcc (zend_ast * args ) {
5858 zend_ast_fcc * ast ;
5959
6060 ast = zend_ast_alloc (sizeof (zend_ast_fcc ));
6161 ast -> kind = ZEND_AST_CALLABLE_CONVERT ;
6262 ast -> attr = 0 ;
6363 ast -> lineno = CG (zend_lineno );
64+ ast -> args = args ;
6465 ZEND_MAP_PTR_INIT (ast -> fptr , NULL );
6566
6667 return (zend_ast * ) ast ;
@@ -157,6 +158,12 @@ ZEND_API zend_ast *zend_ast_create_decl(
157158 return (zend_ast * ) ast ;
158159}
159160
161+ static bool zend_ast_is_placeholder_arg (zend_ast * arg ) {
162+ return arg -> kind == ZEND_AST_PLACEHOLDER_ARG
163+ || (arg -> kind == ZEND_AST_NAMED_ARG
164+ && arg -> child [1 ]-> kind == ZEND_AST_PLACEHOLDER_ARG );
165+ }
166+
160167#if ZEND_AST_SPEC
161168ZEND_API zend_ast * ZEND_FASTCALL zend_ast_create_0 (zend_ast_kind kind ) {
162169 zend_ast * ast ;
@@ -400,6 +407,30 @@ ZEND_API zend_ast * ZEND_FASTCALL zend_ast_create_list_2(zend_ast_kind kind, zen
400407
401408 return ast ;
402409}
410+
411+ ZEND_API zend_ast * ZEND_FASTCALL zend_ast_create_arg_list_0 (zend_ast_kind kind ) {
412+ return zend_ast_create_list (0 , kind );
413+ }
414+
415+ ZEND_API zend_ast * ZEND_FASTCALL zend_ast_create_arg_list_1 (zend_ast_kind kind , zend_ast * arg ) {
416+ zend_ast * list = zend_ast_create_list (1 , kind , arg );
417+
418+ if (zend_ast_is_placeholder_arg (arg )) {
419+ return zend_ast_create_fcc (list );
420+ }
421+
422+ return list ;
423+ }
424+
425+ ZEND_API zend_ast * ZEND_FASTCALL zend_ast_create_arg_list_2 (zend_ast_kind kind , zend_ast * arg1 , zend_ast * arg2 ) {
426+ zend_ast * list = zend_ast_create_list (2 , kind , arg1 , arg2 );
427+
428+ if (zend_ast_is_placeholder_arg (arg1 ) || zend_ast_is_placeholder_arg (arg2 )) {
429+ return zend_ast_create_fcc (list );
430+ }
431+
432+ return list ;
433+ }
403434#else
404435static zend_ast * zend_ast_create_from_va_list (zend_ast_kind kind , zend_ast_attr attr , va_list va ) {
405436 uint32_t i , children = kind >> ZEND_AST_NUM_CHILDREN_SHIFT ;
@@ -479,6 +510,41 @@ ZEND_API zend_ast *zend_ast_create_list(uint32_t init_children, zend_ast_kind ki
479510
480511 return ast ;
481512}
513+
514+ ZEND_API zend_ast * zend_ast_create_arg_list (uint32_t init_children , zend_ast_kind kind , ...) {
515+ zend_ast * ast ;
516+ zend_ast_list * list ;
517+ bool has_placeholders = false;
518+
519+ ast = zend_ast_alloc (zend_ast_list_size (4 ));
520+ list = (zend_ast_list * ) ast ;
521+ list -> kind = kind ;
522+ list -> attr = 0 ;
523+ list -> lineno = CG (zend_lineno );
524+ list -> children = 0 ;
525+
526+ {
527+ va_list va ;
528+ uint32_t i ;
529+ va_start (va , kind );
530+ for (i = 0 ; i < init_children ; ++ i ) {
531+ zend_ast * child = va_arg (va , zend_ast * );
532+ ast = zend_ast_list_add (ast , child );
533+ uint32_t lineno = zend_ast_get_lineno (child );
534+ if (lineno < ast -> lineno ) {
535+ ast -> lineno = lineno ;
536+ }
537+ has_placeholders = has_placeholders || zend_ast_is_placeholder_arg (child );
538+ }
539+ va_end (va );
540+ }
541+
542+ if (has_placeholders ) {
543+ return zend_ast_create_fcc (list );
544+ }
545+
546+ return ast ;
547+ }
482548#endif
483549
484550zend_ast * zend_ast_create_concat_op (zend_ast * op0 , zend_ast * op1 ) {
@@ -508,6 +574,23 @@ ZEND_ATTRIBUTE_NODISCARD ZEND_API zend_ast * ZEND_FASTCALL zend_ast_list_add(zen
508574 return (zend_ast * ) list ;
509575}
510576
577+ ZEND_API zend_ast * ZEND_FASTCALL zend_ast_arg_list_add (zend_ast * list , zend_ast * arg )
578+ {
579+ if (list -> kind == ZEND_AST_CALLABLE_CONVERT ) {
580+ zend_ast_fcc * fcc_ast = (zend_ast_fcc * )list ;
581+ fcc_ast -> args = zend_ast_list_add (fcc_ast -> args , arg );
582+ return (zend_ast * )fcc_ast ;
583+ }
584+
585+ ZEND_ASSERT (list -> kind == ZEND_AST_ARG_LIST );
586+
587+ if (zend_ast_is_placeholder_arg (arg )) {
588+ return zend_ast_create_fcc (zend_ast_list_add (list , arg ));
589+ }
590+
591+ return zend_ast_list_add (list , arg );
592+ }
593+
511594static zend_result zend_ast_add_array_element (const zval * result , zval * offset , zval * expr )
512595{
513596 if (Z_TYPE_P (offset ) == IS_UNDEF ) {
@@ -1060,6 +1143,15 @@ static zend_result ZEND_FASTCALL zend_ast_evaluate_inner(
10601143 case ZEND_AST_CALL : {
10611144 ZEND_ASSERT (ast -> child [1 ]-> kind == ZEND_AST_CALLABLE_CONVERT );
10621145 zend_ast_fcc * fcc_ast = (zend_ast_fcc * )ast -> child [1 ];
1146+
1147+ zend_ast_list * args = zend_ast_get_list (fcc_ast -> args );
1148+ ZEND_ASSERT (args -> children > 0 );
1149+ if (args -> children != 1 || args -> child [0 ]-> attr != ZEND_PLACEHOLDER_VARIADIC ) {
1150+ /* TODO: PFAs */
1151+ zend_error_noreturn (E_COMPILE_ERROR , "Constant expression contains invalid operations" );
1152+ return FAILURE ;
1153+ }
1154+
10631155 fptr = ZEND_MAP_PTR_GET (fcc_ast -> fptr );
10641156
10651157 if (!fptr ) {
@@ -1087,6 +1179,14 @@ static zend_result ZEND_FASTCALL zend_ast_evaluate_inner(
10871179 ZEND_ASSERT (ast -> child [2 ]-> kind == ZEND_AST_CALLABLE_CONVERT );
10881180 zend_ast_fcc * fcc_ast = (zend_ast_fcc * )ast -> child [2 ];
10891181
1182+ zend_ast_list * args = zend_ast_get_list (fcc_ast -> args );
1183+ ZEND_ASSERT (args -> children > 0 );
1184+ if (args -> children != 1 || args -> child [0 ]-> attr != ZEND_PLACEHOLDER_VARIADIC ) {
1185+ /* TODO: PFAs */
1186+ zend_error_noreturn (E_COMPILE_ERROR , "Constant expression contains invalid operations" );
1187+ return FAILURE ;
1188+ }
1189+
10901190 zend_class_entry * ce = zend_ast_fetch_class (ast -> child [0 ], scope );
10911191 if (!ce ) {
10921192 return FAILURE ;
@@ -1243,7 +1343,8 @@ static size_t ZEND_FASTCALL zend_ast_tree_size(zend_ast *ast)
12431343 } else if (ast -> kind == ZEND_AST_OP_ARRAY ) {
12441344 size = sizeof (zend_ast_op_array );
12451345 } else if (ast -> kind == ZEND_AST_CALLABLE_CONVERT ) {
1246- size = sizeof (zend_ast_fcc );
1346+ zend_ast * args_ast = ((zend_ast_fcc * )ast )-> args ;
1347+ size = sizeof (zend_ast_fcc ) + zend_ast_tree_size (args_ast );
12471348 } else if (zend_ast_is_list (ast )) {
12481349 uint32_t i ;
12491350 const zend_ast_list * list = zend_ast_get_list (ast );
@@ -1320,6 +1421,8 @@ static void* ZEND_FASTCALL zend_ast_tree_copy(zend_ast *ast, void *buf)
13201421 new -> lineno = old -> lineno ;
13211422 ZEND_MAP_PTR_INIT (new -> fptr , ZEND_MAP_PTR (old -> fptr ));
13221423 buf = (void * )((char * )buf + sizeof (zend_ast_fcc ));
1424+ new -> args = buf ;
1425+ buf = zend_ast_tree_copy (old -> args , buf );
13231426 } else if (zend_ast_is_decl (ast )) {
13241427 /* Not implemented. */
13251428 ZEND_UNREACHABLE ();
@@ -1403,6 +1506,11 @@ ZEND_API void ZEND_FASTCALL zend_ast_destroy(zend_ast *ast)
14031506 zend_ast_destroy (decl -> child [3 ]);
14041507 ast = decl -> child [4 ];
14051508 goto tail_call ;
1509+ } else if (EXPECTED (ast -> kind == ZEND_AST_CALLABLE_CONVERT )) {
1510+ zend_ast_fcc * fcc_ast = (zend_ast_fcc * ) ast ;
1511+
1512+ ast = fcc_ast -> args ;
1513+ goto tail_call ;
14061514 }
14071515}
14081516
@@ -2299,6 +2407,13 @@ static ZEND_COLD void zend_ast_export_ex(smart_str *str, zend_ast *ast, int prio
22992407 EMPTY_SWITCH_DEFAULT_CASE ();
23002408 }
23012409 break ;
2410+ case ZEND_AST_PLACEHOLDER_ARG :
2411+ if (ast -> attr == ZEND_PLACEHOLDER_VARIADIC ) {
2412+ APPEND_STR ("..." );
2413+ } else {
2414+ APPEND_STR ("?" );
2415+ }
2416+ break ;
23022417
23032418 /* 1 child node */
23042419 case ZEND_AST_VAR :
@@ -2445,9 +2560,11 @@ static ZEND_COLD void zend_ast_export_ex(smart_str *str, zend_ast *ast, int prio
24452560 zend_ast_export_ex (str , ast -> child [1 ], 0 , indent );
24462561 smart_str_appendc (str , ')' );
24472562 break ;
2448- case ZEND_AST_CALLABLE_CONVERT :
2449- smart_str_appends (str , "..." );
2450- break ;
2563+ case ZEND_AST_CALLABLE_CONVERT : {
2564+ zend_ast_fcc * fcc_ast = (zend_ast_fcc * )ast ;
2565+ ast = fcc_ast -> args ;
2566+ goto simple_list ;
2567+ }
24512568 case ZEND_AST_CLASS_CONST :
24522569 zend_ast_export_ns_name (str , ast -> child [0 ], 0 , indent );
24532570 smart_str_appends (str , "::" );
0 commit comments