From f3e5bbe6f37ce52a9ecd42812389e6aaf3aa2892 Mon Sep 17 00:00:00 2001 From: Nikita Popov Date: Thu, 2 May 2019 14:57:16 +0200 Subject: Implement arrow functions Per RFC: https://wiki.php.net/rfc/arrow_functions_v2 Co-authored-by: Levi Morrison Co-authored-by: Bob Weinand --- Zend/tests/arrow_functions/001.phpt | 45 +++++++++++++++++++++++++++++++ Zend/tests/arrow_functions/002.phpt | 13 +++++++++ Zend/tests/arrow_functions/003.phpt | 21 +++++++++++++++ Zend/tests/arrow_functions/004.phpt | 13 +++++++++ Zend/tests/arrow_functions/005.phpt | 54 +++++++++++++++++++++++++++++++++++++ Zend/tests/arrow_functions/006.phpt | 44 ++++++++++++++++++++++++++++++ Zend/tests/arrow_functions/007.phpt | 14 ++++++++++ Zend/tests/arrow_functions/008.phpt | 28 +++++++++++++++++++ 8 files changed, 232 insertions(+) create mode 100644 Zend/tests/arrow_functions/001.phpt create mode 100644 Zend/tests/arrow_functions/002.phpt create mode 100644 Zend/tests/arrow_functions/003.phpt create mode 100644 Zend/tests/arrow_functions/004.phpt create mode 100644 Zend/tests/arrow_functions/005.phpt create mode 100644 Zend/tests/arrow_functions/006.phpt create mode 100644 Zend/tests/arrow_functions/007.phpt create mode 100644 Zend/tests/arrow_functions/008.phpt (limited to 'Zend/tests/arrow_functions') diff --git a/Zend/tests/arrow_functions/001.phpt b/Zend/tests/arrow_functions/001.phpt new file mode 100644 index 0000000000..27b2557b99 --- /dev/null +++ b/Zend/tests/arrow_functions/001.phpt @@ -0,0 +1,45 @@ +--TEST-- +Basic arrow function functionality check +--FILE-- + 1; +var_dump($foo()); + +$foo = fn($x) => $x; +var_dump($foo(2)); + +$foo = fn($x, $y) => $x + $y; +var_dump($foo(1, 2)); + +// Closing over $var +$var = 4; +$foo = fn() => $var; +var_dump($foo()); + +// Not closing over $var, it's a parameter +$foo = fn($var) => $var; +var_dump($foo(5)); + +// Close over $var by-value, not by-reference +$var = 5; +$foo = fn() => ++$var; +var_dump($foo()); +var_dump($var); + +// Nested arrow functions closing over variable +$var = 6; +var_dump((fn() => fn() => $var)()()); +var_dump((fn() => function() use($var) { return $var; })()()); + +?> +--EXPECT-- +int(1) +int(2) +int(3) +int(4) +int(5) +int(6) +int(5) +int(6) +int(6) diff --git a/Zend/tests/arrow_functions/002.phpt b/Zend/tests/arrow_functions/002.phpt new file mode 100644 index 0000000000..52c8020c19 --- /dev/null +++ b/Zend/tests/arrow_functions/002.phpt @@ -0,0 +1,13 @@ +--TEST-- +Arrow functions implicit use must be throwing notices only upon actual use +--FILE-- + $b + $c)()); + +?> +--EXPECTF-- +Notice: Undefined variable: c in %s on line %d +int(1) diff --git a/Zend/tests/arrow_functions/003.phpt b/Zend/tests/arrow_functions/003.phpt new file mode 100644 index 0000000000..5e77743fad --- /dev/null +++ b/Zend/tests/arrow_functions/003.phpt @@ -0,0 +1,21 @@ +--TEST-- +Variable-variables inside arrow functions +--FILE-- + $$var; +var_dump($fn()); + +${5} = 2; +$fn = fn() => ${5}; +var_dump($fn()); + +?> +--EXPECTF-- +Notice: Undefined variable: a in %s on line %d +NULL + +Notice: Undefined variable: 5 in %s on line %d +NULL diff --git a/Zend/tests/arrow_functions/004.phpt b/Zend/tests/arrow_functions/004.phpt new file mode 100644 index 0000000000..51467dae1d --- /dev/null +++ b/Zend/tests/arrow_functions/004.phpt @@ -0,0 +1,13 @@ +--TEST-- +Auto-globals in arrow functions +--FILE-- + $GLOBALS['a']; +var_dump($fn()); + +?> +--EXPECT-- +int(123) diff --git a/Zend/tests/arrow_functions/005.phpt b/Zend/tests/arrow_functions/005.phpt new file mode 100644 index 0000000000..7371be57bb --- /dev/null +++ b/Zend/tests/arrow_functions/005.phpt @@ -0,0 +1,54 @@ +--TEST-- +Arrow function $this binding +--FILE-- + 42; + $r = new ReflectionFunction($fn); + var_dump($r->getClosureThis()); + + $fn = fn() => $this; + var_dump($fn()); + + $fn = fn() => Test::method2(); + $fn(); + + $fn = fn() => call_user_func('Test::method2'); + $fn(); + + $thisName = "this"; + $fn = fn() => $$thisName; + var_dump($fn()); + + $fn = fn() => self::class; + var_dump($fn()); + + // static can be used to unbind $this + $fn = static fn() => isset($this); + var_dump($fn()); + } + + public function method2() { + var_dump($this); + } +} + +(new Test)->method(); + +?> +--EXPECT-- +object(Test)#1 (0) { +} +object(Test)#1 (0) { +} +object(Test)#1 (0) { +} +object(Test)#1 (0) { +} +object(Test)#1 (0) { +} +string(4) "Test" +bool(false) diff --git a/Zend/tests/arrow_functions/006.phpt b/Zend/tests/arrow_functions/006.phpt new file mode 100644 index 0000000000..16427146a8 --- /dev/null +++ b/Zend/tests/arrow_functions/006.phpt @@ -0,0 +1,44 @@ +--TEST-- +Arrow functions syntax variations +--FILE-- + $x; +$ref =& $id($var); +$ref++; +var_dump($var); + +// int argument and return type +$var = 10; +$int_fn = fn(int $x): int => $x; +var_dump($int_fn($var)); +try { + $int_fn("foo"); +} catch (TypeError $e) { + echo $e->getMessage(), "\n"; +} + +$varargs = fn(?int... $args): array => $args; +var_dump($varargs(20, null, 30)); +try { + $varargs(40, "foo"); +} catch (TypeError $e) { + echo $e->getMessage(), "\n"; +} + +?> +--EXPECTF-- +int(2) +int(10) +Argument 1 passed to {closure}() must be of the type int, string given, called in %s on line %d +array(3) { + [0]=> + int(20) + [1]=> + NULL + [2]=> + int(30) +} +Argument 2 passed to {closure}() must be of the type int or null, string given, called in %s on line %d diff --git a/Zend/tests/arrow_functions/007.phpt b/Zend/tests/arrow_functions/007.phpt new file mode 100644 index 0000000000..0fcc4930d1 --- /dev/null +++ b/Zend/tests/arrow_functions/007.phpt @@ -0,0 +1,14 @@ +--TEST-- +Pretty printing for arrow functions +--FILE-- + false)()); +assert((fn&(int... $args): ?bool => $args[0])(false)); + +?> +--EXPECTF-- +Warning: assert(): assert(fn() => false()) failed in %s on line %d + +Warning: assert(): assert(fn&(int ...$args): ?bool => $args[0](false)) failed in %s on line %d diff --git a/Zend/tests/arrow_functions/008.phpt b/Zend/tests/arrow_functions/008.phpt new file mode 100644 index 0000000000..df3fe5dba7 --- /dev/null +++ b/Zend/tests/arrow_functions/008.phpt @@ -0,0 +1,28 @@ +--TEST-- +Yield inside arrow functions +--FILE-- + yield 123; +foreach ($fn() as $val) { + var_dump($val); +} + +$fn = fn() => yield from [456, 789]; +foreach ($fn() as $val) { + var_dump($val); +} + +$fn = fn() => fn() => yield 987; +foreach ($fn()() as $val) { + var_dump($val); +} + +?> +--EXPECT-- +int(123) +int(456) +int(789) +int(987) -- cgit v1.2.1