From 5228af041e66dbe72ab49767213e5a461be648d0 Mon Sep 17 00:00:00 2001 From: Daniil Gentili Date: Mon, 24 Aug 2020 12:25:35 +0200 Subject: [PATCH] Regenerator progress --- src/Plugin/ReGenerator.php | 22 +++++++ .../ReGenerator/ReGenerator.php | 24 ++++---- src/Target/Php55/YieldDetector.php | 30 ++++++++++ src/Target/Php70/YieldFromReplacer.php | 42 ------------- src/Target/Php70/YieldFromReturnDetector.php | 59 +++++++++++++++++++ 5 files changed, 123 insertions(+), 54 deletions(-) create mode 100644 src/Plugin/ReGenerator.php rename src/{Target/Php70 => Plugin}/ReGenerator/ReGenerator.php (89%) create mode 100644 src/Target/Php55/YieldDetector.php delete mode 100644 src/Target/Php70/YieldFromReplacer.php create mode 100644 src/Target/Php70/YieldFromReturnDetector.php diff --git a/src/Plugin/ReGenerator.php b/src/Plugin/ReGenerator.php new file mode 100644 index 0000000..8bf12dc --- /dev/null +++ b/src/Plugin/ReGenerator.php @@ -0,0 +1,22 @@ +getAttribute(self::SHOULD_ATTRIBUTE, false)) { + return; + } + + } + public function runAfter(): array + { + return [ArrowClosure::class]; + } +} diff --git a/src/Target/Php70/ReGenerator/ReGenerator.php b/src/Plugin/ReGenerator/ReGenerator.php similarity index 89% rename from src/Target/Php70/ReGenerator/ReGenerator.php rename to src/Plugin/ReGenerator/ReGenerator.php index 8b16ecb..8f061f6 100644 --- a/src/Target/Php70/ReGenerator/ReGenerator.php +++ b/src/Plugin/ReGenerator/ReGenerator.php @@ -1,6 +1,6 @@ started) { - ($this->generator)($this->state, $this->variables, $this->yieldKey, $this->yieldValue, $this->sentValue, $this->sentException, $this->returnValue, $this->returned); + ($this->generator)($this->state, $this->variables, $this->yieldKey, $this->yieldValue, $this->sentValue, $this->sentException, $this->returnValue, $this->returned, $this->yieldedFrom); $this->started = true; } } @@ -112,9 +112,9 @@ class ReGenerator implements \Iterator $e = $exception; } if (!$this->yieldedFrom->valid()) { // Returned from yield from - $returnValue = $this->yieldedFrom->getReturn(); + $returnValue = \method_exists($this->yieldedFrom, 'getReturn') ? $this->yieldedFrom->getReturn() : null; $this->yieldedFrom = null; - if ($e) { + if (isset($e)) { return $this->throw($e); } return $this->send($returnValue); @@ -125,7 +125,7 @@ class ReGenerator implements \Iterator if (!$this->returned) { $this->sentValue = $value; try { - ($this->generator)($this->state, $this->variables, $this->yieldKey, $this->yieldValue, $this->sentValue, $this->sentException, $this->returnValue, $this->returned); + ($this->generator)($this->state, $this->variables, $this->yieldKey, $this->yieldValue, $this->sentValue, $this->sentException, $this->returnValue, $this->returned, $this->yieldedFrom); } catch (\Throwable $e) { $this->returned = true; throw $e; @@ -145,9 +145,9 @@ class ReGenerator implements \Iterator $e = $exception; } if (!$this->yieldedFrom->valid()) { // Returned from yield from - $returnValue = $this->yieldedFrom->getReturn(); + $returnValue = \method_exists($this->yieldedFrom, 'getReturn') ? $this->yieldedFrom->getReturn() : null; $this->yieldedFrom = null; - if ($e) { + if (isset($e)) { return $this->throw($e); } return $this->send($returnValue); @@ -158,7 +158,7 @@ class ReGenerator implements \Iterator if (!$this->returned) { $this->sentException = $value; try { - ($this->generator)($this->variables, $this->yieldKey, $this->yieldValue, $this->sentValue, $this->sentException, $this->returnValue, $this->returned); + ($this->generator)($this->variables, $this->yieldKey, $this->yieldValue, $this->sentValue, $this->sentException, $this->returnValue, $this->returned, $this->yieldedFrom); } catch (\Throwable $e) { $this->returned = true; throw $e; @@ -171,18 +171,18 @@ class ReGenerator implements \Iterator public function current() { - $this->start(); if ($this->yieldedFrom) { return $this->yieldedFrom->current(); } + $this->start(); return $this->yieldValue; } public function key() { - $this->start(); if ($this->yieldedFrom) { return $this->yieldedFrom->key(); } + $this->start(); return $this->yieldKey; } public function next(): void diff --git a/src/Target/Php55/YieldDetector.php b/src/Target/Php55/YieldDetector.php new file mode 100644 index 0000000..2090332 --- /dev/null +++ b/src/Target/Php55/YieldDetector.php @@ -0,0 +1,30 @@ +parents as $parent) { + if ($parent instanceof FunctionLike) { + $parent->setAttribute(ReGenerator::SHOULD_ATTRIBUTE, true); + return; + } + } + } + public function runBefore(): array + { + return [ReGenerator::class]; + } + public function runAfter(): array + { + return [ArrowClosure::class]; + } +} diff --git a/src/Target/Php70/YieldFromReplacer.php b/src/Target/Php70/YieldFromReplacer.php deleted file mode 100644 index d59e826..0000000 --- a/src/Target/Php70/YieldFromReplacer.php +++ /dev/null @@ -1,42 +0,0 @@ -phabelVar = 'phabelGeneratorYieldFrom'.\hash('sha256', $file); - return parent::shouldRunFile($file); - } - public function enterNode(YieldFrom $node, Context $ctx) - { - $var = new Variable($this->phabelVar.($this->phabelCount++)); - $assign = new Assign($var, $node->expr); - $ifInstanceof = new If_(new Instanceof_(Plugin::callMethod($var, 'valid'), new FullyQualified(\YieldReturnValue::class)), ['stmts' => [new Assign()]]); - $while = new While_(new MethodCall($var, new Identifier('valid'))); - foreach ($ctx->parents as $node) { - if ($node->hasAttribute('currentNodeIndex')) { - $ctx->insertBefore($node, $node->expr); - } - } - $generator = $node->expr; - - return new Node\Expr\Yield_($generator); - } -} diff --git a/src/Target/Php70/YieldFromReturnDetector.php b/src/Target/Php70/YieldFromReturnDetector.php new file mode 100644 index 0000000..2334f2a --- /dev/null +++ b/src/Target/Php70/YieldFromReturnDetector.php @@ -0,0 +1,59 @@ +parents as $parent) { + if ($parent instanceof FunctionLike) { + $parent->setAttribute(ReGenerator::SHOULD_ATTRIBUTE, true); + return; + } + } + } + public function enterYield(Yield_ $node, Context $ctx): void + { + foreach ($ctx->parents as $parent) { + if ($parent instanceof FunctionLike) { + $parent->setAttribute('hasYield', true); + if ($parent->getAttribute('hasReturn')) { + $parent->setAttribute(ReGenerator::SHOULD_ATTRIBUTE, true); + } + return; + } + } + } + public function enterReturn(Return_ $node, Context $ctx): void + { + if (!$node->expr) { + return; + } + foreach ($ctx->parents as $parent) { + if ($parent instanceof FunctionLike) { + $parent->setAttribute('hasReturn', true); + if ($parent->getAttribute('hasYield')) { + $parent->setAttribute(ReGenerator::SHOULD_ATTRIBUTE, true); + } + return; + } + } + } + public function runBefore(): array + { + return [ReGenerator::class]; + } + public function runAfter(): array + { + return [ArrowClosure::class]; + } +}