@@ -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,14 @@ 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 != _IS_PLACEHOLDER_VARIADIC ) {
1150+ /* TODO: PFAs */
1151+ return FAILURE ;
1152+ }
1153+
10631154 fptr = ZEND_MAP_PTR_GET (fcc_ast -> fptr );
10641155
10651156 if (!fptr ) {
@@ -1087,6 +1178,13 @@ static zend_result ZEND_FASTCALL zend_ast_evaluate_inner(
10871178 ZEND_ASSERT (ast -> child [2 ]-> kind == ZEND_AST_CALLABLE_CONVERT );
10881179 zend_ast_fcc * fcc_ast = (zend_ast_fcc * )ast -> child [2 ];
10891180
1181+ zend_ast_list * args = zend_ast_get_list (fcc_ast -> args );
1182+ ZEND_ASSERT (args -> children > 0 );
1183+ if (args -> children != 1 || args -> child [0 ]-> attr != _IS_PLACEHOLDER_VARIADIC ) {
1184+ /* TODO: PFAs */
1185+ return FAILURE ;
1186+ }
1187+
10901188 zend_class_entry * ce = zend_ast_fetch_class (ast -> child [0 ], scope );
10911189 if (!ce ) {
10921190 return FAILURE ;
@@ -1124,12 +1222,12 @@ static zend_result ZEND_FASTCALL zend_ast_evaluate_inner(
11241222
11251223 if (!(fptr -> common .fn_flags & ZEND_ACC_STATIC )) {
11261224 zend_non_static_method_call (fptr );
1127-
1225+
11281226 return FAILURE ;
11291227 }
11301228 if ((fptr -> common .fn_flags & ZEND_ACC_ABSTRACT )) {
11311229 zend_abstract_method_call (fptr );
1132-
1230+
11331231 return FAILURE ;
11341232 } else if (fptr -> common .scope -> ce_flags & ZEND_ACC_TRAIT ) {
11351233 zend_error (E_DEPRECATED ,
@@ -1243,7 +1341,8 @@ static size_t ZEND_FASTCALL zend_ast_tree_size(zend_ast *ast)
12431341 } else if (ast -> kind == ZEND_AST_OP_ARRAY ) {
12441342 size = sizeof (zend_ast_op_array );
12451343 } else if (ast -> kind == ZEND_AST_CALLABLE_CONVERT ) {
1246- size = sizeof (zend_ast_fcc );
1344+ zend_ast * args_ast = ((zend_ast_fcc * )ast )-> args ;
1345+ size = sizeof (zend_ast_fcc ) + zend_ast_tree_size (args_ast );
12471346 } else if (zend_ast_is_list (ast )) {
12481347 uint32_t i ;
12491348 const zend_ast_list * list = zend_ast_get_list (ast );
@@ -1320,6 +1419,8 @@ static void* ZEND_FASTCALL zend_ast_tree_copy(zend_ast *ast, void *buf)
13201419 new -> lineno = old -> lineno ;
13211420 ZEND_MAP_PTR_INIT (new -> fptr , ZEND_MAP_PTR (old -> fptr ));
13221421 buf = (void * )((char * )buf + sizeof (zend_ast_fcc ));
1422+ new -> args = buf ;
1423+ buf = zend_ast_tree_copy (old -> args , buf );
13231424 } else if (zend_ast_is_decl (ast )) {
13241425 /* Not implemented. */
13251426 ZEND_UNREACHABLE ();
@@ -1403,6 +1504,10 @@ ZEND_API void ZEND_FASTCALL zend_ast_destroy(zend_ast *ast)
14031504 zend_ast_destroy (decl -> child [3 ]);
14041505 ast = decl -> child [4 ];
14051506 goto tail_call ;
1507+ } else if (EXPECTED (ast -> kind == ZEND_AST_CALLABLE_CONVERT )) {
1508+ zend_ast_fcc * fcc_ast = (zend_ast_fcc * ) ast ;
1509+
1510+ zend_ast_destroy (fcc_ast -> args );
14061511 }
14071512}
14081513
@@ -2299,6 +2404,13 @@ static ZEND_COLD void zend_ast_export_ex(smart_str *str, zend_ast *ast, int prio
22992404 EMPTY_SWITCH_DEFAULT_CASE ();
23002405 }
23012406 break ;
2407+ case ZEND_AST_PLACEHOLDER_ARG :
2408+ if (ast -> attr == _IS_PLACEHOLDER_ARG ) {
2409+ APPEND_STR ("?" );
2410+ } else if (ast -> attr == _IS_PLACEHOLDER_VARIADIC ) {
2411+ APPEND_STR ("..." );
2412+ }
2413+ break ;
23022414
23032415 /* 1 child node */
23042416 case ZEND_AST_VAR :
@@ -2445,9 +2557,11 @@ static ZEND_COLD void zend_ast_export_ex(smart_str *str, zend_ast *ast, int prio
24452557 zend_ast_export_ex (str , ast -> child [1 ], 0 , indent );
24462558 smart_str_appendc (str , ')' );
24472559 break ;
2448- case ZEND_AST_CALLABLE_CONVERT :
2449- smart_str_appends (str , "..." );
2450- break ;
2560+ case ZEND_AST_CALLABLE_CONVERT : {
2561+ zend_ast_fcc * fcc_ast = (zend_ast_fcc * )ast ;
2562+ ast = fcc_ast -> args ;
2563+ goto simple_list ;
2564+ }
24512565 case ZEND_AST_CLASS_CONST :
24522566 zend_ast_export_ns_name (str , ast -> child [0 ], 0 , indent );
24532567 smart_str_appends (str , "::" );
0 commit comments