-
Notifications
You must be signed in to change notification settings - Fork 8k
[PFA 1/n] Support PFA syntax #20717
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
[PFA 1/n] Support PFA syntax #20717
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,10 @@ | ||
| --TEST-- | ||
| First class callable error: more than one argument | ||
| --FILE-- | ||
| <?php | ||
|
|
||
| foo(1, ...); | ||
|
|
||
| ?> | ||
| --EXPECTF-- | ||
| Fatal error: Cannot create a Closure for call expression with more than one argument, or non-variadic placeholders in %s on line %d |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,10 @@ | ||
| --TEST-- | ||
| First class callable error: non-variadic placeholder | ||
| --FILE-- | ||
| <?php | ||
|
|
||
| foo(?); | ||
|
|
||
| ?> | ||
| --EXPECTF-- | ||
| Fatal error: Cannot create a Closure for call expression with more than one argument, or non-variadic placeholders in %s on line %d |
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -54,13 +54,14 @@ ZEND_API zend_ast * ZEND_FASTCALL zend_ast_create_znode(const znode *node) { | |||||||||||||||||||||||||
| return (zend_ast *) ast; | ||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| ZEND_API zend_ast * ZEND_FASTCALL zend_ast_create_fcc(void) { | ||||||||||||||||||||||||||
| ZEND_API zend_ast * ZEND_FASTCALL zend_ast_create_fcc(zend_ast *args) { | ||||||||||||||||||||||||||
| zend_ast_fcc *ast; | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| ast = zend_ast_alloc(sizeof(zend_ast_fcc)); | ||||||||||||||||||||||||||
| ast->kind = ZEND_AST_CALLABLE_CONVERT; | ||||||||||||||||||||||||||
| ast->attr = 0; | ||||||||||||||||||||||||||
| ast->lineno = CG(zend_lineno); | ||||||||||||||||||||||||||
| ast->args = args; | ||||||||||||||||||||||||||
| ZEND_MAP_PTR_INIT(ast->fptr, NULL); | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| return (zend_ast *) ast; | ||||||||||||||||||||||||||
|
|
@@ -157,6 +158,12 @@ ZEND_API zend_ast *zend_ast_create_decl( | |||||||||||||||||||||||||
| return (zend_ast *) ast; | ||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| static bool zend_ast_is_placeholder_arg(zend_ast *arg) { | ||||||||||||||||||||||||||
| return arg->kind == ZEND_AST_PLACEHOLDER_ARG | ||||||||||||||||||||||||||
| || (arg->kind == ZEND_AST_NAMED_ARG | ||||||||||||||||||||||||||
| && arg->child[1]->kind == ZEND_AST_PLACEHOLDER_ARG); | ||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| #if ZEND_AST_SPEC | ||||||||||||||||||||||||||
| ZEND_API zend_ast * ZEND_FASTCALL zend_ast_create_0(zend_ast_kind kind) { | ||||||||||||||||||||||||||
| zend_ast *ast; | ||||||||||||||||||||||||||
|
|
@@ -400,6 +407,30 @@ ZEND_API zend_ast * ZEND_FASTCALL zend_ast_create_list_2(zend_ast_kind kind, zen | |||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| return ast; | ||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| ZEND_API zend_ast * ZEND_FASTCALL zend_ast_create_arg_list_0(zend_ast_kind kind) { | ||||||||||||||||||||||||||
| return zend_ast_create_list(0, kind); | ||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| ZEND_API zend_ast * ZEND_FASTCALL zend_ast_create_arg_list_1(zend_ast_kind kind, zend_ast *arg) { | ||||||||||||||||||||||||||
| zend_ast *list = zend_ast_create_list(1, kind, arg); | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| if (zend_ast_is_placeholder_arg(arg)) { | ||||||||||||||||||||||||||
| return zend_ast_create_fcc(list); | ||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| return list; | ||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| ZEND_API zend_ast * ZEND_FASTCALL zend_ast_create_arg_list_2(zend_ast_kind kind, zend_ast *arg1, zend_ast *arg2) { | ||||||||||||||||||||||||||
| zend_ast *list = zend_ast_create_list(2, kind, arg1, arg2); | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| if (zend_ast_is_placeholder_arg(arg1) || zend_ast_is_placeholder_arg(arg2)) { | ||||||||||||||||||||||||||
| return zend_ast_create_fcc(list); | ||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| return list; | ||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||
| #else | ||||||||||||||||||||||||||
| static zend_ast *zend_ast_create_from_va_list(zend_ast_kind kind, zend_ast_attr attr, va_list va) { | ||||||||||||||||||||||||||
| 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 | |||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| return ast; | ||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| ZEND_API zend_ast *zend_ast_create_arg_list(uint32_t init_children, zend_ast_kind kind, ...) { | ||||||||||||||||||||||||||
| zend_ast *ast; | ||||||||||||||||||||||||||
| zend_ast_list *list; | ||||||||||||||||||||||||||
| bool has_placeholders = false; | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| ast = zend_ast_alloc(zend_ast_list_size(4)); | ||||||||||||||||||||||||||
| list = (zend_ast_list *) ast; | ||||||||||||||||||||||||||
| list->kind = kind; | ||||||||||||||||||||||||||
| list->attr = 0; | ||||||||||||||||||||||||||
| list->lineno = CG(zend_lineno); | ||||||||||||||||||||||||||
| list->children = 0; | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| { | ||||||||||||||||||||||||||
| va_list va; | ||||||||||||||||||||||||||
| uint32_t i; | ||||||||||||||||||||||||||
| va_start(va, kind); | ||||||||||||||||||||||||||
| for (i = 0; i < init_children; ++i) { | ||||||||||||||||||||||||||
| zend_ast *child = va_arg(va, zend_ast *); | ||||||||||||||||||||||||||
| ast = zend_ast_list_add(ast, child); | ||||||||||||||||||||||||||
| uint32_t lineno = zend_ast_get_lineno(child); | ||||||||||||||||||||||||||
| if (lineno < ast->lineno) { | ||||||||||||||||||||||||||
| ast->lineno = lineno; | ||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||
| has_placeholders = has_placeholders || zend_ast_is_placeholder_arg(child); | ||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||
| va_end(va); | ||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| if (has_placeholders) { | ||||||||||||||||||||||||||
| return zend_ast_create_fcc(list); | ||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| return ast; | ||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||
| #endif | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| zend_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 | |||||||||||||||||||||||||
| return (zend_ast *) list; | ||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| ZEND_API zend_ast * ZEND_FASTCALL zend_ast_arg_list_add(zend_ast *list, zend_ast *arg) | ||||||||||||||||||||||||||
| { | ||||||||||||||||||||||||||
| if (list->kind == ZEND_AST_CALLABLE_CONVERT) { | ||||||||||||||||||||||||||
| zend_ast_fcc *fcc_ast = (zend_ast_fcc*)list; | ||||||||||||||||||||||||||
| fcc_ast->args = zend_ast_list_add(fcc_ast->args, arg); | ||||||||||||||||||||||||||
| return (zend_ast*)fcc_ast; | ||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| ZEND_ASSERT(list->kind == ZEND_AST_ARG_LIST); | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| if (zend_ast_is_placeholder_arg(arg)) { | ||||||||||||||||||||||||||
| return zend_ast_create_fcc(zend_ast_list_add(list, arg)); | ||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| return zend_ast_list_add(list, arg); | ||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| static zend_result zend_ast_add_array_element(const zval *result, zval *offset, zval *expr) | ||||||||||||||||||||||||||
| { | ||||||||||||||||||||||||||
| if (Z_TYPE_P(offset) == IS_UNDEF) { | ||||||||||||||||||||||||||
|
|
@@ -1060,6 +1143,14 @@ static zend_result ZEND_FASTCALL zend_ast_evaluate_inner( | |||||||||||||||||||||||||
| case ZEND_AST_CALL: { | ||||||||||||||||||||||||||
| ZEND_ASSERT(ast->child[1]->kind == ZEND_AST_CALLABLE_CONVERT); | ||||||||||||||||||||||||||
| zend_ast_fcc *fcc_ast = (zend_ast_fcc*)ast->child[1]; | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| zend_ast_list *args = zend_ast_get_list(fcc_ast->args); | ||||||||||||||||||||||||||
| ZEND_ASSERT(args->children > 0); | ||||||||||||||||||||||||||
| if (args->children != 1 || args->child[0]->attr != _IS_PLACEHOLDER_VARIADIC) { | ||||||||||||||||||||||||||
| /* TODO: PFAs */ | ||||||||||||||||||||||||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||||||||||||||||||||
| return FAILURE; | ||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| fptr = ZEND_MAP_PTR_GET(fcc_ast->fptr); | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| if (!fptr) { | ||||||||||||||||||||||||||
|
|
@@ -1087,6 +1178,13 @@ static zend_result ZEND_FASTCALL zend_ast_evaluate_inner( | |||||||||||||||||||||||||
| ZEND_ASSERT(ast->child[2]->kind == ZEND_AST_CALLABLE_CONVERT); | ||||||||||||||||||||||||||
| zend_ast_fcc *fcc_ast = (zend_ast_fcc*)ast->child[2]; | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| zend_ast_list *args = zend_ast_get_list(fcc_ast->args); | ||||||||||||||||||||||||||
| ZEND_ASSERT(args->children > 0); | ||||||||||||||||||||||||||
| if (args->children != 1 || args->child[0]->attr != _IS_PLACEHOLDER_VARIADIC) { | ||||||||||||||||||||||||||
| /* TODO: PFAs */ | ||||||||||||||||||||||||||
| return FAILURE; | ||||||||||||||||||||||||||
|
Comment on lines
+1184
to
+1185
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I believe the expectation for
Suggested change
|
||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| zend_class_entry *ce = zend_ast_fetch_class(ast->child[0], scope); | ||||||||||||||||||||||||||
| if (!ce) { | ||||||||||||||||||||||||||
| return FAILURE; | ||||||||||||||||||||||||||
|
|
@@ -1124,12 +1222,12 @@ static zend_result ZEND_FASTCALL zend_ast_evaluate_inner( | |||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| if (!(fptr->common.fn_flags & ZEND_ACC_STATIC)) { | ||||||||||||||||||||||||||
| zend_non_static_method_call(fptr); | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
|
Comment on lines
-1127
to
+1225
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Whoops. Sorry for introducing these. Can you push the a commit to trim the trailing spaces straight to master to denoise the diff? |
||||||||||||||||||||||||||
| return FAILURE; | ||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||
| if ((fptr->common.fn_flags & ZEND_ACC_ABSTRACT)) { | ||||||||||||||||||||||||||
| zend_abstract_method_call(fptr); | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| return FAILURE; | ||||||||||||||||||||||||||
| } else if (fptr->common.scope->ce_flags & ZEND_ACC_TRAIT) { | ||||||||||||||||||||||||||
| zend_error(E_DEPRECATED, | ||||||||||||||||||||||||||
|
|
@@ -1243,7 +1341,8 @@ static size_t ZEND_FASTCALL zend_ast_tree_size(zend_ast *ast) | |||||||||||||||||||||||||
| } else if (ast->kind == ZEND_AST_OP_ARRAY) { | ||||||||||||||||||||||||||
| size = sizeof(zend_ast_op_array); | ||||||||||||||||||||||||||
| } else if (ast->kind == ZEND_AST_CALLABLE_CONVERT) { | ||||||||||||||||||||||||||
| size = sizeof(zend_ast_fcc); | ||||||||||||||||||||||||||
| zend_ast *args_ast = ((zend_ast_fcc*)ast)->args; | ||||||||||||||||||||||||||
| size = sizeof(zend_ast_fcc) + zend_ast_tree_size(args_ast); | ||||||||||||||||||||||||||
| } else if (zend_ast_is_list(ast)) { | ||||||||||||||||||||||||||
| uint32_t i; | ||||||||||||||||||||||||||
| 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) | |||||||||||||||||||||||||
| new->lineno = old->lineno; | ||||||||||||||||||||||||||
| ZEND_MAP_PTR_INIT(new->fptr, ZEND_MAP_PTR(old->fptr)); | ||||||||||||||||||||||||||
| buf = (void*)((char*)buf + sizeof(zend_ast_fcc)); | ||||||||||||||||||||||||||
| new->args = buf; | ||||||||||||||||||||||||||
| buf = zend_ast_tree_copy(old->args, buf); | ||||||||||||||||||||||||||
| } else if (zend_ast_is_decl(ast)) { | ||||||||||||||||||||||||||
| /* Not implemented. */ | ||||||||||||||||||||||||||
| ZEND_UNREACHABLE(); | ||||||||||||||||||||||||||
|
|
@@ -1403,6 +1504,10 @@ ZEND_API void ZEND_FASTCALL zend_ast_destroy(zend_ast *ast) | |||||||||||||||||||||||||
| zend_ast_destroy(decl->child[3]); | ||||||||||||||||||||||||||
| ast = decl->child[4]; | ||||||||||||||||||||||||||
| goto tail_call; | ||||||||||||||||||||||||||
| } else if (EXPECTED(ast->kind == ZEND_AST_CALLABLE_CONVERT)) { | ||||||||||||||||||||||||||
| zend_ast_fcc *fcc_ast = (zend_ast_fcc*) ast; | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| zend_ast_destroy(fcc_ast->args); | ||||||||||||||||||||||||||
|
Comment on lines
+1508
to
+1510
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
? |
||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
|
|
@@ -2299,6 +2404,13 @@ static ZEND_COLD void zend_ast_export_ex(smart_str *str, zend_ast *ast, int prio | |||||||||||||||||||||||||
| EMPTY_SWITCH_DEFAULT_CASE(); | ||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||
| break; | ||||||||||||||||||||||||||
| case ZEND_AST_PLACEHOLDER_ARG: | ||||||||||||||||||||||||||
| if (ast->attr == _IS_PLACEHOLDER_ARG) { | ||||||||||||||||||||||||||
| APPEND_STR("?"); | ||||||||||||||||||||||||||
| } else if (ast->attr == _IS_PLACEHOLDER_VARIADIC) { | ||||||||||||||||||||||||||
| APPEND_STR("..."); | ||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||
|
Comment on lines
+2408
to
+2412
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||||||||||||||||||||
| break; | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| /* 1 child node */ | ||||||||||||||||||||||||||
| case ZEND_AST_VAR: | ||||||||||||||||||||||||||
|
|
@@ -2445,9 +2557,11 @@ static ZEND_COLD void zend_ast_export_ex(smart_str *str, zend_ast *ast, int prio | |||||||||||||||||||||||||
| zend_ast_export_ex(str, ast->child[1], 0, indent); | ||||||||||||||||||||||||||
| smart_str_appendc(str, ')'); | ||||||||||||||||||||||||||
| break; | ||||||||||||||||||||||||||
| case ZEND_AST_CALLABLE_CONVERT: | ||||||||||||||||||||||||||
| smart_str_appends(str, "..."); | ||||||||||||||||||||||||||
| break; | ||||||||||||||||||||||||||
| case ZEND_AST_CALLABLE_CONVERT: { | ||||||||||||||||||||||||||
| zend_ast_fcc *fcc_ast = (zend_ast_fcc*)ast; | ||||||||||||||||||||||||||
| ast = fcc_ast->args; | ||||||||||||||||||||||||||
| goto simple_list; | ||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||
| case ZEND_AST_CLASS_CONST: | ||||||||||||||||||||||||||
| zend_ast_export_ns_name(str, ast->child[0], 0, indent); | ||||||||||||||||||||||||||
| smart_str_appends(str, "::"); | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -638,6 +638,10 @@ struct _zend_ast_ref { | |
| #define _IS_BOOL 18 | ||
| #define _IS_NUMBER 19 | ||
|
|
||
| /* used for PFAs/FCCs */ | ||
| #define _IS_PLACEHOLDER_ARG 20 | ||
| #define _IS_PLACEHOLDER_VARIADIC 21 | ||
|
Comment on lines
+641
to
+643
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Are these required to be a zval type for the following implementation? Other AST attributes use a “distinct” set of values. |
||
|
|
||
| /* guard flags */ | ||
| #define ZEND_GUARD_PROPERTY_GET (1<<0) | ||
| #define ZEND_GUARD_PROPERTY_SET (1<<1) | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not sure if this is clearer (the
fcc_astdoesn't actually change):