@@ -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 ) {
@@ -1056,10 +1139,22 @@ static zend_result ZEND_FASTCALL zend_ast_evaluate_inner(
10561139 {
10571140 zend_function * fptr ;
10581141 zend_class_entry * called_scope = NULL ;
1142+
1143+ zend_ast * args_ast = zend_ast_call_get_args (ast );
1144+ ZEND_ASSERT (args_ast -> kind == ZEND_AST_CALLABLE_CONVERT );
1145+
1146+ zend_ast_fcc * fcc_ast = (zend_ast_fcc * )args_ast ;
1147+
1148+ zend_ast_list * args = zend_ast_get_list (fcc_ast -> args );
1149+ ZEND_ASSERT (args -> children > 0 );
1150+ if (args -> children != 1 || args -> child [0 ]-> attr != ZEND_PLACEHOLDER_VARIADIC ) {
1151+ /* TODO: PFAs */
1152+ zend_error_noreturn (E_COMPILE_ERROR , "Constant expression contains invalid operations" );
1153+ return FAILURE ;
1154+ }
1155+
10591156 switch (ast -> kind ) {
10601157 case ZEND_AST_CALL : {
1061- ZEND_ASSERT (ast -> child [1 ]-> kind == ZEND_AST_CALLABLE_CONVERT );
1062- zend_ast_fcc * fcc_ast = (zend_ast_fcc * )ast -> child [1 ];
10631158 fptr = ZEND_MAP_PTR_GET (fcc_ast -> fptr );
10641159
10651160 if (!fptr ) {
@@ -1084,9 +1179,6 @@ static zend_result ZEND_FASTCALL zend_ast_evaluate_inner(
10841179 break ;
10851180 }
10861181 case ZEND_AST_STATIC_CALL : {
1087- ZEND_ASSERT (ast -> child [2 ]-> kind == ZEND_AST_CALLABLE_CONVERT );
1088- zend_ast_fcc * fcc_ast = (zend_ast_fcc * )ast -> child [2 ];
1089-
10901182 zend_class_entry * ce = zend_ast_fetch_class (ast -> child [0 ], scope );
10911183 if (!ce ) {
10921184 return FAILURE ;
@@ -1243,7 +1335,8 @@ static size_t ZEND_FASTCALL zend_ast_tree_size(zend_ast *ast)
12431335 } else if (ast -> kind == ZEND_AST_OP_ARRAY ) {
12441336 size = sizeof (zend_ast_op_array );
12451337 } else if (ast -> kind == ZEND_AST_CALLABLE_CONVERT ) {
1246- size = sizeof (zend_ast_fcc );
1338+ zend_ast * args_ast = ((zend_ast_fcc * )ast )-> args ;
1339+ size = sizeof (zend_ast_fcc ) + zend_ast_tree_size (args_ast );
12471340 } else if (zend_ast_is_list (ast )) {
12481341 uint32_t i ;
12491342 const zend_ast_list * list = zend_ast_get_list (ast );
@@ -1320,6 +1413,8 @@ static void* ZEND_FASTCALL zend_ast_tree_copy(zend_ast *ast, void *buf)
13201413 new -> lineno = old -> lineno ;
13211414 ZEND_MAP_PTR_INIT (new -> fptr , ZEND_MAP_PTR (old -> fptr ));
13221415 buf = (void * )((char * )buf + sizeof (zend_ast_fcc ));
1416+ new -> args = buf ;
1417+ buf = zend_ast_tree_copy (old -> args , buf );
13231418 } else if (zend_ast_is_decl (ast )) {
13241419 /* Not implemented. */
13251420 ZEND_UNREACHABLE ();
@@ -1403,6 +1498,11 @@ ZEND_API void ZEND_FASTCALL zend_ast_destroy(zend_ast *ast)
14031498 zend_ast_destroy (decl -> child [3 ]);
14041499 ast = decl -> child [4 ];
14051500 goto tail_call ;
1501+ } else if (EXPECTED (ast -> kind == ZEND_AST_CALLABLE_CONVERT )) {
1502+ zend_ast_fcc * fcc_ast = (zend_ast_fcc * ) ast ;
1503+
1504+ ast = fcc_ast -> args ;
1505+ goto tail_call ;
14061506 }
14071507}
14081508
@@ -2299,6 +2399,13 @@ static ZEND_COLD void zend_ast_export_ex(smart_str *str, zend_ast *ast, int prio
22992399 EMPTY_SWITCH_DEFAULT_CASE ();
23002400 }
23012401 break ;
2402+ case ZEND_AST_PLACEHOLDER_ARG :
2403+ if (ast -> attr == ZEND_PLACEHOLDER_VARIADIC ) {
2404+ APPEND_STR ("..." );
2405+ } else {
2406+ APPEND_STR ("?" );
2407+ }
2408+ break ;
23022409
23032410 /* 1 child node */
23042411 case ZEND_AST_VAR :
@@ -2445,9 +2552,11 @@ static ZEND_COLD void zend_ast_export_ex(smart_str *str, zend_ast *ast, int prio
24452552 zend_ast_export_ex (str , ast -> child [1 ], 0 , indent );
24462553 smart_str_appendc (str , ')' );
24472554 break ;
2448- case ZEND_AST_CALLABLE_CONVERT :
2449- smart_str_appends (str , "..." );
2450- break ;
2555+ case ZEND_AST_CALLABLE_CONVERT : {
2556+ zend_ast_fcc * fcc_ast = (zend_ast_fcc * )ast ;
2557+ ast = fcc_ast -> args ;
2558+ goto simple_list ;
2559+ }
24512560 case ZEND_AST_CLASS_CONST :
24522561 zend_ast_export_ns_name (str , ast -> child [0 ], 0 , indent );
24532562 smart_str_appends (str , "::" );
@@ -2966,3 +3075,15 @@ zend_ast * ZEND_FASTCALL zend_ast_with_attributes(zend_ast *ast, zend_ast *attr)
29663075
29673076 return ast ;
29683077}
3078+
3079+ zend_ast * ZEND_FASTCALL zend_ast_call_get_args (zend_ast * ast )
3080+ {
3081+ if (ast -> kind == ZEND_AST_CALL ) {
3082+ return ast -> child [1 ];
3083+ } else if (ast -> kind == ZEND_AST_STATIC_CALL || ast -> kind == ZEND_AST_METHOD_CALL ) {
3084+ return ast -> child [2 ];
3085+ }
3086+
3087+ ZEND_UNREACHABLE ();
3088+ return NULL ;
3089+ }
0 commit comments