Skip to content

Make array() a function #18613

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

Draft
wants to merge 4 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Zend/zend_API.c
Original file line number Diff line number Diff line change
Expand Up @@ -3641,6 +3641,7 @@ static void zend_disable_function(const char *function_name, size_t function_nam
if (UNEXPECTED(
(function_name_length == strlen("exit") && !memcmp(function_name, "exit", strlen("exit")))
|| (function_name_length == strlen("die") && !memcmp(function_name, "die", strlen("die")))
|| (function_name_length == strlen("array") && !memcmp(function_name, "array", strlen("array")))
)) {
zend_error(E_WARNING, "Cannot disable function %s()", function_name);
return;
Expand Down
17 changes: 14 additions & 3 deletions Zend/zend_ast.c
Original file line number Diff line number Diff line change
Expand Up @@ -2173,9 +2173,20 @@ static ZEND_COLD void zend_ast_export_ex(smart_str *str, zend_ast *ast, int prio
zend_ast_export_list(str, (zend_ast_list*)ast, 1, 20, indent);
break;
case ZEND_AST_ARRAY:
smart_str_appendc(str, '[');
zend_ast_export_list(str, (zend_ast_list*)ast, 1, 20, indent);
smart_str_appendc(str, ']');
switch (ast->attr) {
case ZEND_ARRAY_SYNTAX_LONG:
case ZEND_ARRAY_SYNTAX_FUNCTION:
smart_str_appends(str, "array(");
zend_ast_export_list(str, (zend_ast_list*)ast, 1, 20, indent);
smart_str_appendc(str, ')');
break;
case ZEND_ARRAY_SYNTAX_SHORT:
default:
smart_str_appendc(str, '[');
zend_ast_export_list(str, (zend_ast_list*)ast, 1, 20, indent);
smart_str_appendc(str, ']');
break;
}
break;
case ZEND_AST_ENCAPS_LIST:
smart_str_appendc(str, '"');
Expand Down
37 changes: 37 additions & 0 deletions Zend/zend_builtin_functions.c
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,43 @@ zend_result zend_startup_builtin_functions(void) /* {{{ */
}
/* }}} */

ZEND_FUNCTION(array)
{
zval *args;
uint32_t argc;
HashTable *named_params;

ZEND_PARSE_PARAMETERS_START(0, -1)
Z_PARAM_VARIADIC_WITH_NAMED(args, argc, named_params);
ZEND_PARSE_PARAMETERS_END();

if (EXPECTED(argc == 0)) {
if (EXPECTED(named_params != NULL)) {
GC_ADDREF(named_params);
RETURN_ARR(named_params);
} else {
RETURN_EMPTY_ARRAY();
}
} else {
HashTable *entries;

ALLOC_HASHTABLE(entries);
zend_hash_init(entries, argc + (named_params ? zend_hash_num_elements(named_params) : 0), NULL, NULL, false);
for (uint32_t i = 0; i < argc; i++) {
zend_hash_index_add_new(entries, i, &args[i]);
}
if (named_params != NULL) {
zend_string *key;
zval *val;
ZEND_HASH_FOREACH_STR_KEY_VAL(named_params, key, val) {
zend_hash_update(entries, key, val);
} ZEND_HASH_FOREACH_END();
}

RETURN_ARR(entries);
}
}

ZEND_FUNCTION(exit)
{
zend_string *str = NULL;
Expand Down
2 changes: 2 additions & 0 deletions Zend/zend_builtin_functions.stub.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ class stdClass
{
}

function _array(mixed ...$entries): array {}

function exit(string|int $status = 0): never {}

/** @alias exit */
Expand Down
8 changes: 7 additions & 1 deletion Zend/zend_builtin_functions_arginfo.h

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Zend/zend_compile.h
Original file line number Diff line number Diff line change
Expand Up @@ -1053,6 +1053,7 @@ ZEND_API zend_string *zend_type_to_string(zend_type type);
#define ZEND_ARRAY_SYNTAX_LIST 1 /* list() */
#define ZEND_ARRAY_SYNTAX_LONG 2 /* array() */
#define ZEND_ARRAY_SYNTAX_SHORT 3 /* [] */
#define ZEND_ARRAY_SYNTAX_FUNCTION 4 /* array(key: "val") */

/* var status for backpatching */
#define BP_VAR_R 0
Expand Down
20 changes: 20 additions & 0 deletions Zend/zend_language_parser.y
Original file line number Diff line number Diff line change
Expand Up @@ -286,6 +286,7 @@ static YYSIZE_T zend_yytnamerr(char*, const char*);
%type <ast> function_name non_empty_member_modifiers
%type <ast> property_hook property_hook_list optional_property_hook_list hooked_property property_hook_body
%type <ast> optional_parameter_list
%type <ast> non_empty_array_function_argument_list array_function_argument

%type <num> returns_ref function fn is_reference is_variadic property_modifiers property_hook_modifiers
%type <num> method_modifiers class_const_modifiers member_modifier optional_cpp_modifiers
Expand Down Expand Up @@ -1447,11 +1448,30 @@ ctor_arguments:

dereferenceable_scalar:
T_ARRAY '(' array_pair_list ')' { $$ = $3; $$->attr = ZEND_ARRAY_SYNTAX_LONG; }
| T_ARRAY '(' non_empty_array_function_argument_list possible_comma ')'
{ $$ = $3; $$->attr = ZEND_ARRAY_SYNTAX_FUNCTION; }
| T_ARRAY '(' T_ELLIPSIS ')' {
zend_ast *name = zend_ast_create_zval_from_str(ZSTR_KNOWN(ZEND_STR_ARRAY));
name->attr = ZEND_NAME_FQ;
$$ = zend_ast_create(ZEND_AST_CALL, name, zend_ast_create_fcc());
}
| '[' array_pair_list ']' { $$ = $2; $$->attr = ZEND_ARRAY_SYNTAX_SHORT; }
| T_CONSTANT_ENCAPSED_STRING { $$ = $1; }
| '"' encaps_list '"' { $$ = $2; }
;

non_empty_array_function_argument_list:
array_function_argument
{ $$ = zend_ast_create_list(1, ZEND_AST_ARRAY, $1); }
| non_empty_array_function_argument_list ',' array_function_argument
{ $$ = zend_ast_list_add($1, $3); }
;

array_function_argument:
identifier ':' expr
{ $$ = zend_ast_create(ZEND_AST_NAMED_ARG, $1, $3); }
;

scalar:
T_LNUMBER { $$ = $1; }
| T_DNUMBER { $$ = $1; }
Expand Down
3 changes: 3 additions & 0 deletions build/gen_stub.php
Original file line number Diff line number Diff line change
Expand Up @@ -1009,6 +1009,9 @@ class FunctionName implements FunctionOrMethodName {
private /* readonly */ Name $name;

public function __construct(Name $name) {
if ($name->name === '_array') {
$name = new Name('array', $name->getAttributes());
}
$this->name = $name;
}

Expand Down
56 changes: 56 additions & 0 deletions ext/standard/tests/array/array_function.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
--TEST--
Test array() function
--FILE--
<?php
var_dump(\array(1, 2, 3));
var_dump(\array(foo: "bar", baz: "quux"));
var_dump(array(foo: "bar", baz: "quux"));

try {
assert(false && \array(foo: "bar", baz: "quux"));
} catch (AssertionError $e) {
echo $e->getMessage(), PHP_EOL;
}

var_dump(array_map(array(...), [1, 2, 3]));

?>
--EXPECT--
array(3) {
[0]=>
int(1)
[1]=>
int(2)
[2]=>
int(3)
}
array(2) {
["foo"]=>
string(3) "bar"
["baz"]=>
string(4) "quux"
}
array(2) {
["bar"]=>
string(3) "foo"
["quux"]=>
string(3) "baz"
}
assert(false && \array(foo: 'bar', baz: 'quux'))
array(3) {
[0]=>
array(1) {
[0]=>
int(1)
}
[1]=>
array(1) {
[0]=>
int(2)
}
[2]=>
array(1) {
[0]=>
int(3)
}
}
2 changes: 0 additions & 2 deletions ext/standard/tests/array/array_map_variation16.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ $arg = [1, 2];
// built-in functions & language constructs
$callbacks = [
'echo',
'array',
'empty',
'eval',
'isset',
Expand All @@ -29,7 +28,6 @@ echo "Done";
?>
--EXPECT--
array_map(): Argument #1 ($callback) must be a valid callback or null, function "echo" not found or invalid function name
array_map(): Argument #1 ($callback) must be a valid callback or null, function "array" not found or invalid function name
array_map(): Argument #1 ($callback) must be a valid callback or null, function "empty" not found or invalid function name
array_map(): Argument #1 ($callback) must be a valid callback or null, function "eval" not found or invalid function name
array_map(): Argument #1 ($callback) must be a valid callback or null, function "isset" not found or invalid function name
Expand Down