Skip to content

Commit 11123b8

Browse files
committed
partial application
1 parent 787db3a commit 11123b8

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

54 files changed

+2380
-439
lines changed

Zend/Optimizer/zend_call_graph.c

+2
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,7 @@ ZEND_API int zend_analyze_calls(zend_arena **arena, zend_script *script, uint32_
106106
case ZEND_DO_ICALL:
107107
case ZEND_DO_UCALL:
108108
case ZEND_DO_FCALL_BY_NAME:
109+
case ZEND_DO_FCALL_PARTIAL:
109110
func_info->flags |= ZEND_FUNC_HAS_CALLS;
110111
if (call_info) {
111112
call_info->caller_call_opline = opline;
@@ -122,6 +123,7 @@ ZEND_API int zend_analyze_calls(zend_arena **arena, zend_script *script, uint32_
122123
case ZEND_SEND_VAR_NO_REF:
123124
case ZEND_SEND_VAR_NO_REF_EX:
124125
case ZEND_SEND_USER:
126+
case ZEND_SEND_PLACEHOLDER:
125127
if (call_info) {
126128
if (opline->op2_type == IS_CONST) {
127129
call_info->named_args = 1;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
--TEST--
2+
Partial application compile errors: multiple ...
3+
--FILE--
4+
<?php
5+
foo(..., ...);
6+
?>
7+
--EXPECTF--
8+
Fatal error: Multiple argument place holder may only appear once in %s on line %d
9+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
--TEST--
2+
Partial application compile errors: only named arguments after ...
3+
--FILE--
4+
<?php
5+
foo(..., ?);
6+
?>
7+
--EXPECTF--
8+
Fatal error: Only named arguments may follow multiple place holder in %s on line %d
9+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
--TEST--
2+
Partial application compile errors: named arguments must come after place holder
3+
--FILE--
4+
<?php
5+
foo(n: 5, ?);
6+
?>
7+
--EXPECTF--
8+
Fatal error: Named arguments must come after all place holders in %s on line %d
9+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
--TEST--
2+
Partial application compile errors: named arguments must come after multi place holder
3+
--FILE--
4+
<?php
5+
foo(n: 5, ...);
6+
?>
7+
--EXPECTF--
8+
Fatal error: Named arguments must come after all place holders in %s on line %d
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
--TEST--
2+
Partial application compile errors: follow multiple with un-named arg
3+
--FILE--
4+
<?php
5+
foo(..., $a);
6+
?>
7+
--EXPECTF--
8+
Fatal error: Only named arguments may follow multiple place holder in %s on line %d
9+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
--TEST--
2+
Partial application compile errors: follow multiple with unpack
3+
--FILE--
4+
<?php
5+
foo(..., ...[$a]);
6+
?>
7+
--EXPECTF--
8+
Fatal error: Only named arguments may follow multiple place holder in %s on line %d
9+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
--TEST--
2+
Partial application errors: place holder count errors
3+
--FILE--
4+
<?php
5+
function foo($a, $b, $c) {
6+
7+
}
8+
9+
try {
10+
foo(?);
11+
} catch (Error $ex) {
12+
printf("%s\n", $ex->getMessage());
13+
}
14+
15+
try {
16+
foo(?, ?, ?, ?);
17+
} catch (Error $ex) {
18+
printf("%s\n", $ex->getMessage());
19+
}
20+
21+
try {
22+
property_exists(?);
23+
} catch (Error $ex) {
24+
printf("%s\n", $ex->getMessage());
25+
}
26+
27+
try {
28+
usleep(?, ?);
29+
} catch (Error $ex) {
30+
printf("%s\n", $ex->getMessage());
31+
}
32+
?>
33+
--EXPECTF--
34+
not enough arguments and or place holders for foo, 1 given and at least 3 expected, declared in %s on line 2
35+
too many arguments and or place holders for foo, 4 given and a maximum of 3 expected, declared in %s on line 2
36+
not enough arguments and or place holders for property_exists, 1 given and at least 2 expected
37+
too many arguments and or place holders for usleep, 2 given and a maximum of 1 expected
38+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
--TEST--
2+
Partial application errors: named parameter overwrites place holder
3+
--FILE--
4+
<?php
5+
function foo($a) {
6+
7+
}
8+
9+
try {
10+
foo(?, a: 1);
11+
} catch (Error $ex) {
12+
printf("%s\n", $ex->getMessage());
13+
}
14+
?>
15+
--EXPECT--
16+
Named parameter $a overwrites previous place holder
17+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
--TEST--
2+
Partial application errors: missing parameters
3+
--FILE--
4+
<?php
5+
function foo($a, ...$b) {
6+
7+
}
8+
9+
$foo = foo(?);
10+
11+
try {
12+
$foo();
13+
} catch (Error $ex) {
14+
printf("%s\n", $ex->getMessage());
15+
}
16+
17+
$foo = foo(?, ?);
18+
19+
try {
20+
$foo(1);
21+
} catch (Error $ex) {
22+
printf("%s\n", $ex->getMessage());
23+
}
24+
25+
$usleep = usleep(...);
26+
27+
try {
28+
$usleep();
29+
} catch (Error $ex) {
30+
printf("%s\n", $ex->getMessage());
31+
}
32+
?>
33+
--EXPECTF--
34+
not enough arguments and or place holders for foo, 0 given and at least 1 expected, declared in %s on line 2
35+
not enough arguments and or place holders for foo, 1 given and at least 2 expected, declared in %s on line 2
36+
not enough arguments provided for usleep, 0 given and at least 1 expected
37+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
--TEST--
2+
Partial application ast export
3+
--INI--
4+
assert.exception=1
5+
--FILE--
6+
<?php
7+
try {
8+
assert(0 && foo(?) && foo(...));
9+
} catch (Error $ex) {
10+
printf("%s\n", $ex->getMessage());
11+
}
12+
?>
13+
--EXPECT--
14+
assert(0 && foo(?) && foo(...))
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
--TEST--
2+
Partial application named parameters: extra collection
3+
--FILE--
4+
<?php
5+
function foo(...$args) {
6+
var_dump($args);
7+
}
8+
9+
$foo = foo(..., foo: "foo");
10+
11+
$bar = $foo(..., bar: "bar");
12+
13+
$baz = $bar(..., baz: "baz");
14+
15+
$baz();
16+
17+
$foo = foo(...);
18+
19+
$bar = $foo(..., bar: "bar");
20+
21+
$baz = $bar(..., baz: "baz");
22+
23+
$baz();
24+
25+
$foo = foo(..., foo: "foo");
26+
27+
$foo(bar: "bar");
28+
?>
29+
--EXPECT--
30+
array(3) {
31+
["foo"]=>
32+
string(3) "foo"
33+
["bar"]=>
34+
string(3) "bar"
35+
["baz"]=>
36+
string(3) "baz"
37+
}
38+
array(2) {
39+
["bar"]=>
40+
string(3) "bar"
41+
["baz"]=>
42+
string(3) "baz"
43+
}
44+
array(2) {
45+
["foo"]=>
46+
string(3) "foo"
47+
["bar"]=>
48+
string(3) "bar"
49+
}
50+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
--TEST--
2+
Partial application factory: pass
3+
--FILE--
4+
<?php
5+
class Foo {
6+
7+
}
8+
9+
$foo = new Foo(...);
10+
11+
$two = [$foo(), $foo()];
12+
13+
if ($two[0] === $two[1]) {
14+
var_dump($two);
15+
} else {
16+
echo "OK";
17+
}
18+
?>
19+
--EXPECTF--
20+
OK
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
--TEST--
2+
Partial application factory: normal
3+
--FILE--
4+
<?php
5+
class Foo {
6+
public function __construct($a) {
7+
printf("%s\n", __METHOD__);
8+
}
9+
}
10+
11+
$foo = new Foo(...);
12+
13+
$two = [$foo(1), $foo(1)];
14+
15+
if ($two[0] === $two[1]) {
16+
var_dump($two);
17+
} else {
18+
echo "OK";
19+
}
20+
?>
21+
--EXPECTF--
22+
Foo::__construct
23+
Foo::__construct
24+
OK
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
--TEST--
2+
Partial application magic: __call
3+
--FILE--
4+
<?php
5+
class Foo {
6+
public function __call($method, $args) {
7+
printf("%s::%s\n", __CLASS__, $method);
8+
}
9+
}
10+
11+
$foo = new Foo;
12+
13+
$bar = $foo->method(...);
14+
15+
$bar();
16+
?>
17+
--EXPECT--
18+
Foo::method
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
--TEST--
2+
Partial application magic: __callStatic
3+
--FILE--
4+
<?php
5+
class Foo {
6+
public static function __callStatic($method, $args) {
7+
printf("%s::%s\n", __CLASS__, $method);
8+
}
9+
}
10+
11+
$foo = Foo::method(...);
12+
13+
$foo();
14+
?>
15+
--EXPECT--
16+
Foo::method
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
--TEST--
2+
Partial application reflection: required parameters
3+
--FILE--
4+
<?php
5+
function foo($a = 1, $b = 5, $c = 10) {
6+
7+
}
8+
9+
$foo = foo(...);
10+
11+
echo (string) new Reflectionfunction($foo);
12+
13+
$foo = foo(?, ...);
14+
15+
echo (string) new Reflectionfunction($foo);
16+
17+
$foo = foo(?, ?, ...);
18+
19+
echo (string) new ReflectionFunction($foo);
20+
21+
$foo = foo(?, ?, ?);
22+
23+
echo (string) new ReflectionFunction($foo);
24+
?>
25+
--EXPECTF--
26+
Function [ <user> partial function foo ] {
27+
@@ %s 2 - 4
28+
29+
- Parameters [3] {
30+
Parameter #0 [ <optional> $a = 1 ]
31+
Parameter #1 [ <optional> $b = 5 ]
32+
Parameter #2 [ <optional> $c = 10 ]
33+
}
34+
}
35+
Function [ <user> partial function foo ] {
36+
@@ %s 2 - 4
37+
38+
- Parameters [3] {
39+
Parameter #0 [ <required> $a ]
40+
Parameter #1 [ <optional> $b = 5 ]
41+
Parameter #2 [ <optional> $c = 10 ]
42+
}
43+
}
44+
Function [ <user> partial function foo ] {
45+
@@ %s 2 - 4
46+
47+
- Parameters [3] {
48+
Parameter #0 [ <required> $a ]
49+
Parameter #1 [ <required> $b ]
50+
Parameter #2 [ <optional> $c = 10 ]
51+
}
52+
}
53+
Function [ <user> partial function foo ] {
54+
@@ %s 2 - 4
55+
56+
- Parameters [3] {
57+
Parameter #0 [ <required> $a ]
58+
Parameter #1 [ <required> $b ]
59+
Parameter #2 [ <required> $c ]
60+
}
61+
}
62+

0 commit comments

Comments
 (0)