From 0c006adb8c948ead585df1c56c5cec9eee9f6641 Mon Sep 17 00:00:00 2001 From: Christopher Pitt Date: Thu, 11 May 2017 09:19:35 +0200 Subject: [PATCH] The great refactoring! --- composer.json | 15 +++--- phpunit.xml | 3 +- readme.md | 6 --- src/bootstrap.php | 3 -- src/macros.pre | 18 ------- src/macros.yay | 94 +++++++++++++++++++++++++++++++++ tests/SpecTest.php | 2 +- tests/bootstrap.php | 11 ++-- tests/specs/async.spec | 14 ----- tests/specs/recursion.spec | 43 +++++++++------ tests/specs/short-closures.spec | 17 +++--- 11 files changed, 146 insertions(+), 80 deletions(-) delete mode 100644 src/bootstrap.php delete mode 100644 src/macros.pre create mode 100644 src/macros.yay delete mode 100644 tests/specs/async.spec diff --git a/composer.json b/composer.json index 6e619de..2975d28 100644 --- a/composer.json +++ b/composer.json @@ -1,20 +1,21 @@ { + "type": "pre-macro", "name": "pre/short-closures", "license": "MIT", "require": { - "pre/plugin": "^0.6" - }, - "autoload": { - "files": [ - "src/bootstrap.php" - ] + "pre/plugin": "^0.7" }, "require-dev": { - "phpunit/phpunit": "^5.0" + "phpunit/phpunit": "^5.0|^6.0" }, "autoload-dev": { "psr-4": { "Pre\\ShortClosures\\": "tests" } + }, + "extra": { + "macros": [ + "src/macros.yay" + ] } } diff --git a/phpunit.xml b/phpunit.xml index 829414b..bd5ed4c 100644 --- a/phpunit.xml +++ b/phpunit.xml @@ -9,7 +9,8 @@ convertWarningsToExceptions="false" processIsolation="false" stopOnFailure="false" - syntaxCheck="false"> + syntaxCheck="false" +> tests diff --git a/readme.md b/readme.md index 9e712ad..5d27894 100644 --- a/readme.md +++ b/readme.md @@ -1,9 +1,3 @@ # Pre Short Closures Documentation can be found at [preprocess.io](https://preprocess.io/docs#short-closures). - -## Versioning - -This library follows [Semver](http://semver.org). According to Semver, you will be able to upgrade to any minor or patch version of this library without any breaking changes to the public API. Semver also requires that we clearly define the public API for this library. - -All methods, with `public` visibility, are part of the public API. All other methods are not part of the public API. Where possible, we'll try to keep `protected` methods backwards-compatible in minor/patch versions, but if you're overriding methods then please test your work before upgrading. diff --git a/src/bootstrap.php b/src/bootstrap.php deleted file mode 100644 index 7c5622d..0000000 --- a/src/bootstrap.php +++ /dev/null @@ -1,3 +0,0 @@ - {···body} -} >> { - async function(···parameters) {···body} -} - -macro ·recursion { - (···parameters) => {···body} -} >> { - call_user_func(function($context) { - return function(···parameters) use ($context) { - extract($context); - ···body - }; - }, get_defined_vars()) -} diff --git a/src/macros.yay b/src/macros.yay new file mode 100644 index 0000000..2ec9c32 --- /dev/null +++ b/src/macros.yay @@ -0,0 +1,94 @@ +> function($ast) { + $defined = []; + + foreach ($ast->{"·args"} as $node) { + $name = (string) $node["·arg"]["·argName"]; + $defined[$name] = true; + } + + $bound = false; + $scope = new \Yay\Ast("·scope"); + + $pushed = []; + + foreach ($ast->{"·body"} as $token) { + $name = $token->value(); + + if (!$token->is(T_VARIABLE)) { + continue; + } + + if (isset($defined[$name]) || isset($pushed[$name])) { + continue; + } + + if (substr($name, 1) === "this") { + continue; + } + + $scope->push(new \Yay\Ast("·var", $token)); + $pushed[$name] = true; + $bound = true; + } + + if ($bound) { + $ast->append($scope); + } else { + $simple = new \Yay\Ast("·simple"); + $simple->push(new \Yay\Ast()); + + $ast->append($simple); + } +} >> {··trim( + ·scope ?·{ + [·scope ···(, ) { ·var = ·var ?? null}, "fn" => function (·args ···(, ) { ·arg ··· { ·argType ·argName ·argAssignment } }) use (·scope ···(, ) { &·var }) ·returnType { + ·body + }]["fn"] + } + + ·simple ?·{ + function (·args ···(, ) { ·arg ··· { ·argType ·argName ·argAssignment } }) ·returnType { + ·body + } + } +)} diff --git a/tests/SpecTest.php b/tests/SpecTest.php index 7337537..a0ed4a7 100644 --- a/tests/SpecTest.php +++ b/tests/SpecTest.php @@ -2,7 +2,7 @@ namespace Pre\ShortClosures; -use Pre\Testing\Runner; +use Pre\Plugin\Testing\Runner; class SpecTest extends Runner { diff --git a/tests/bootstrap.php b/tests/bootstrap.php index c24af13..db1be93 100644 --- a/tests/bootstrap.php +++ b/tests/bootstrap.php @@ -2,13 +2,12 @@ namespace Yay; -// let's use a namespace trick, to make non-colliding variables predictable. - -function md5($value) -{ +function md5($value) { return $value; } -putenv("PRE_BASE_DIR=" . __DIR__ . "/.."); - require __DIR__ . "/../vendor/autoload.php"; + +putenv("PRE_BASE_DIR=" . __DIR__ . "/../"); + +\Pre\Plugin\addMacroPath(__DIR__ . "/../src/macros.yay"); diff --git a/tests/specs/async.spec b/tests/specs/async.spec deleted file mode 100644 index 4c41fdc..0000000 --- a/tests/specs/async.spec +++ /dev/null @@ -1,14 +0,0 @@ ---DESCRIPTION-- - -Test async macro - ---GIVEN-- - -$async = * ($path) => { - return $path; -}; - ---EXPECT-- - -$async = async function($path) {return $path; -}; diff --git a/tests/specs/recursion.spec b/tests/specs/recursion.spec index 5509a4a..da395ff 100644 --- a/tests/specs/recursion.spec +++ b/tests/specs/recursion.spec @@ -12,21 +12,34 @@ $cb = () => { }; }; +$foo = "hello"; +$bar = "world"; + +$cb = () => { + return () => { + return () => { + print $foo . $bar; + }; + }; +}; + --EXPECT-- -$cb = call_user_func(function ($context·0) { - return function () use ($context·0) { - extract($context·0); - return call_user_func(function ($context·1) { - return function () use ($context·1) { - extract($context·1); - return call_user_func(function ($context·2) { - return function () use ($context·2) { - extract($context·2); - return "hello world"; - }; - }, get_defined_vars()); - }; - }, get_defined_vars()); +$cb = function () { + return function () { + return function () { + return "hello world"; + }; }; -}, get_defined_vars()); +}; + +$foo = "hello"; +$bar = "world"; + +$cb = [$foo = $foo ?? null, $bar = $bar ?? null, "fn" => function () use (&$foo, &$bar) { + return [$foo = $foo ?? null, $bar = $bar ?? null, "fn" => function () use (&$foo, &$bar) { + return [$foo = $foo ?? null, $bar = $bar ?? null, "fn" => function () use (&$foo, &$bar) { + print $foo . $bar; + }]["fn"]; + }]["fn"]; +}]["fn"]; diff --git a/tests/specs/short-closures.spec b/tests/specs/short-closures.spec index c0cad5e..b47dba9 100644 --- a/tests/specs/short-closures.spec +++ b/tests/specs/short-closures.spec @@ -6,9 +6,10 @@ Test short closure macros class Fixture { - public function foo($end) { + public function foo($end, $thing) { return ($name) => { - return "hello {$name}{$end}"; + $this->something(); + return "hello {$name}{$end}{$thing}"; }; } } @@ -17,13 +18,11 @@ class Fixture class Fixture { - public function foo($end) + public function foo($end, $thing) { - return call_user_func(function ($context·0) { - return function ($name) use ($context·0) { - extract($context·0); - return "hello {$name}{$end}"; - }; - }, get_defined_vars()); + return [$end = $end ?? null, $thing = $thing ?? null, "fn" => function ($name) use (&$end, &$thing) { + $this->something(); + return "hello {$name}{$end}{$thing}"; + }]["fn"]; } }