Skip to content

Commit fb980e3

Browse files
committed
Make array() a function
1 parent e844e68 commit fb980e3

10 files changed

+141
-7
lines changed

Zend/zend_API.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3650,6 +3650,7 @@ static void zend_disable_function(const char *function_name, size_t function_nam
36503650
(function_name_length == strlen("exit") && !memcmp(function_name, "exit", strlen("exit")))
36513651
|| (function_name_length == strlen("die") && !memcmp(function_name, "die", strlen("die")))
36523652
|| (function_name_length == strlen("clone") && !memcmp(function_name, "clone", strlen("clone")))
3653+
|| (function_name_length == strlen("array") && !memcmp(function_name, "array", strlen("array")))
36533654
)) {
36543655
zend_error(E_WARNING, "Cannot disable function %s()", function_name);
36553656
return;

Zend/zend_ast.c

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2173,9 +2173,20 @@ static ZEND_COLD void zend_ast_export_ex(smart_str *str, zend_ast *ast, int prio
21732173
zend_ast_export_list(str, zend_ast_get_list(ast), 1, 20, indent);
21742174
break;
21752175
case ZEND_AST_ARRAY:
2176-
smart_str_appendc(str, '[');
2177-
zend_ast_export_list(str, zend_ast_get_list(ast), 1, 20, indent);
2178-
smart_str_appendc(str, ']');
2176+
switch (ast->attr) {
2177+
case ZEND_ARRAY_SYNTAX_LONG:
2178+
case ZEND_ARRAY_SYNTAX_FUNCTION:
2179+
smart_str_appends(str, "array(");
2180+
zend_ast_export_list(str, zend_ast_get_list(ast), 1, 20, indent);
2181+
smart_str_appendc(str, ')');
2182+
break;
2183+
case ZEND_ARRAY_SYNTAX_SHORT:
2184+
default:
2185+
smart_str_appendc(str, '[');
2186+
zend_ast_export_list(str, zend_ast_get_list(ast), 1, 20, indent);
2187+
smart_str_appendc(str, ']');
2188+
break;
2189+
}
21792190
break;
21802191
case ZEND_AST_ENCAPS_LIST:
21812192
smart_str_appendc(str, '"');

Zend/zend_builtin_functions.c

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,43 @@ ZEND_FUNCTION(clone)
115115
}
116116
}
117117

118+
ZEND_FUNCTION(array)
119+
{
120+
zval *args;
121+
uint32_t argc;
122+
HashTable *named_params;
123+
124+
ZEND_PARSE_PARAMETERS_START(0, -1)
125+
Z_PARAM_VARIADIC_WITH_NAMED(args, argc, named_params);
126+
ZEND_PARSE_PARAMETERS_END();
127+
128+
if (EXPECTED(argc == 0)) {
129+
if (EXPECTED(named_params != NULL)) {
130+
GC_ADDREF(named_params);
131+
RETURN_ARR(named_params);
132+
} else {
133+
RETURN_EMPTY_ARRAY();
134+
}
135+
} else {
136+
HashTable *entries;
137+
138+
ALLOC_HASHTABLE(entries);
139+
zend_hash_init(entries, argc + (named_params ? zend_hash_num_elements(named_params) : 0), NULL, NULL, false);
140+
for (uint32_t i = 0; i < argc; i++) {
141+
zend_hash_index_add_new(entries, i, &args[i]);
142+
}
143+
if (named_params != NULL) {
144+
zend_string *key;
145+
zval *val;
146+
ZEND_HASH_FOREACH_STR_KEY_VAL(named_params, key, val) {
147+
zend_hash_update(entries, key, val);
148+
} ZEND_HASH_FOREACH_END();
149+
}
150+
151+
RETURN_ARR(entries);
152+
}
153+
}
154+
118155
ZEND_FUNCTION(exit)
119156
{
120157
zend_string *str = NULL;

Zend/zend_builtin_functions.stub.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ class stdClass
1010
/** @refcount 1 */
1111
function clone(object $object, array $withProperties = []): object {}
1212

13+
function _array(mixed ...$entries): array {}
14+
1315
function exit(string|int $status = 0): never {}
1416

1517
/** @alias exit */

Zend/zend_builtin_functions_arginfo.h

Lines changed: 7 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Zend/zend_compile.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1054,6 +1054,7 @@ ZEND_API zend_string *zend_type_to_string(zend_type type);
10541054
#define ZEND_ARRAY_SYNTAX_LIST 1 /* list() */
10551055
#define ZEND_ARRAY_SYNTAX_LONG 2 /* array() */
10561056
#define ZEND_ARRAY_SYNTAX_SHORT 3 /* [] */
1057+
#define ZEND_ARRAY_SYNTAX_FUNCTION 4 /* array(key: "val") */
10571058

10581059
/* var status for backpatching */
10591060
#define BP_VAR_R 0

Zend/zend_language_parser.y

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -287,7 +287,7 @@ static YYSIZE_T zend_yytnamerr(char*, const char*);
287287
%type <ast> enum_declaration_statement enum_backing_type enum_case enum_case_expr
288288
%type <ast> function_name non_empty_member_modifiers
289289
%type <ast> property_hook property_hook_list optional_property_hook_list hooked_property property_hook_body
290-
%type <ast> optional_parameter_list clone_argument_list non_empty_clone_argument_list
290+
%type <ast> optional_parameter_list clone_argument_list non_empty_clone_argument_list non_empty_array_function_argument_list array_function_argument
291291

292292
%type <num> returns_ref function fn is_reference is_variadic property_modifiers property_hook_modifiers
293293
%type <num> method_modifiers class_const_modifiers member_modifier optional_cpp_modifiers
@@ -1489,11 +1489,30 @@ ctor_arguments:
14891489

14901490
dereferenceable_scalar:
14911491
T_ARRAY '(' array_pair_list ')' { $$ = $3; $$->attr = ZEND_ARRAY_SYNTAX_LONG; }
1492+
| T_ARRAY '(' non_empty_array_function_argument_list possible_comma ')'
1493+
{ $$ = $3; $$->attr = ZEND_ARRAY_SYNTAX_FUNCTION; }
1494+
| T_ARRAY '(' T_ELLIPSIS ')' {
1495+
zend_ast *name = zend_ast_create_zval_from_str(ZSTR_KNOWN(ZEND_STR_ARRAY));
1496+
name->attr = ZEND_NAME_FQ;
1497+
$$ = zend_ast_create(ZEND_AST_CALL, name, zend_ast_create_fcc());
1498+
}
14921499
| '[' array_pair_list ']' { $$ = $2; $$->attr = ZEND_ARRAY_SYNTAX_SHORT; }
14931500
| T_CONSTANT_ENCAPSED_STRING { $$ = $1; }
14941501
| '"' encaps_list '"' { $$ = $2; }
14951502
;
14961503

1504+
non_empty_array_function_argument_list:
1505+
array_function_argument
1506+
{ $$ = zend_ast_create_list(1, ZEND_AST_ARRAY, $1); }
1507+
| non_empty_array_function_argument_list ',' array_function_argument
1508+
{ $$ = zend_ast_list_add($1, $3); }
1509+
;
1510+
1511+
array_function_argument:
1512+
identifier ':' expr
1513+
{ $$ = zend_ast_create(ZEND_AST_NAMED_ARG, $1, $3); }
1514+
;
1515+
14971516
scalar:
14981517
T_LNUMBER { $$ = $1; }
14991518
| T_DNUMBER { $$ = $1; }

build/gen_stub.php

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -959,6 +959,9 @@ class FunctionName implements FunctionOrMethodName {
959959
private /* readonly */ Name $name;
960960

961961
public function __construct(Name $name) {
962+
if ($name->name === '_array') {
963+
$name = new Name('array', $name->getAttributes());
964+
}
962965
$this->name = $name;
963966
}
964967

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
--TEST--
2+
Test array() function
3+
--FILE--
4+
<?php
5+
var_dump(\array(1, 2, 3));
6+
var_dump(\array(foo: "bar", baz: "quux"));
7+
var_dump(array(foo: "bar", baz: "quux"));
8+
9+
try {
10+
assert(false && \array(foo: "bar", baz: "quux"));
11+
} catch (AssertionError $e) {
12+
echo $e->getMessage(), PHP_EOL;
13+
}
14+
15+
var_dump(array_map(array(...), [1, 2, 3]));
16+
17+
?>
18+
--EXPECT--
19+
array(3) {
20+
[0]=>
21+
int(1)
22+
[1]=>
23+
int(2)
24+
[2]=>
25+
int(3)
26+
}
27+
array(2) {
28+
["foo"]=>
29+
string(3) "bar"
30+
["baz"]=>
31+
string(4) "quux"
32+
}
33+
array(2) {
34+
["bar"]=>
35+
string(3) "foo"
36+
["quux"]=>
37+
string(3) "baz"
38+
}
39+
assert(false && \array(foo: 'bar', baz: 'quux'))
40+
array(3) {
41+
[0]=>
42+
array(1) {
43+
[0]=>
44+
int(1)
45+
}
46+
[1]=>
47+
array(1) {
48+
[0]=>
49+
int(2)
50+
}
51+
[2]=>
52+
array(1) {
53+
[0]=>
54+
int(3)
55+
}
56+
}

ext/standard/tests/array/array_map_variation16.phpt

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@ $arg = [1, 2];
88
// built-in functions & language constructs
99
$callbacks = [
1010
'echo',
11-
'array',
1211
'empty',
1312
'eval',
1413
'isset',
@@ -29,7 +28,6 @@ echo "Done";
2928
?>
3029
--EXPECT--
3130
array_map(): Argument #1 ($callback) must be a valid callback or null, function "echo" not found or invalid function name
32-
array_map(): Argument #1 ($callback) must be a valid callback or null, function "array" not found or invalid function name
3331
array_map(): Argument #1 ($callback) must be a valid callback or null, function "empty" not found or invalid function name
3432
array_map(): Argument #1 ($callback) must be a valid callback or null, function "eval" not found or invalid function name
3533
array_map(): Argument #1 ($callback) must be a valid callback or null, function "isset" not found or invalid function name

0 commit comments

Comments
 (0)