Regenerator progress
This commit is contained in:
parent
49a12d79b3
commit
5228af041e
22
src/Plugin/ReGenerator.php
Normal file
22
src/Plugin/ReGenerator.php
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Phabel\Plugin;
|
||||||
|
|
||||||
|
use Phabel\Plugin;
|
||||||
|
use PhpParser\Builder\FunctionLike;
|
||||||
|
|
||||||
|
class ReGenerator extends Plugin
|
||||||
|
{
|
||||||
|
const SHOULD_ATTRIBUTE = 'shouldRegenerate';
|
||||||
|
public function enter(FunctionLike $function)
|
||||||
|
{
|
||||||
|
if (!$function->getAttribute(self::SHOULD_ATTRIBUTE, false)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
public function runAfter(): array
|
||||||
|
{
|
||||||
|
return [ArrowClosure::class];
|
||||||
|
}
|
||||||
|
}
|
@ -1,6 +1,6 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
namespace Phabel\Target\Php70\ReGenerator;
|
namespace Phabel\Plugin\ReGenerator;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Regenerator class.
|
* Regenerator class.
|
||||||
@ -65,7 +65,7 @@ class ReGenerator implements \Iterator
|
|||||||
/**
|
/**
|
||||||
* Yielded from (re)generator.
|
* Yielded from (re)generator.
|
||||||
*
|
*
|
||||||
* @var \Generator|self
|
* @var \Generator|self|null
|
||||||
*/
|
*/
|
||||||
private $yieldedFrom;
|
private $yieldedFrom;
|
||||||
|
|
||||||
@ -82,7 +82,7 @@ class ReGenerator implements \Iterator
|
|||||||
/**
|
/**
|
||||||
* Get return value.
|
* Get return value.
|
||||||
*
|
*
|
||||||
* @return void
|
* @return mixed
|
||||||
*/
|
*/
|
||||||
public function getReturn()
|
public function getReturn()
|
||||||
{
|
{
|
||||||
@ -97,7 +97,7 @@ class ReGenerator implements \Iterator
|
|||||||
private function start(): void
|
private function start(): void
|
||||||
{
|
{
|
||||||
if (!$this->started) {
|
if (!$this->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;
|
$this->started = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -112,9 +112,9 @@ class ReGenerator implements \Iterator
|
|||||||
$e = $exception;
|
$e = $exception;
|
||||||
}
|
}
|
||||||
if (!$this->yieldedFrom->valid()) { // Returned from yield from
|
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;
|
$this->yieldedFrom = null;
|
||||||
if ($e) {
|
if (isset($e)) {
|
||||||
return $this->throw($e);
|
return $this->throw($e);
|
||||||
}
|
}
|
||||||
return $this->send($returnValue);
|
return $this->send($returnValue);
|
||||||
@ -125,7 +125,7 @@ class ReGenerator implements \Iterator
|
|||||||
if (!$this->returned) {
|
if (!$this->returned) {
|
||||||
$this->sentValue = $value;
|
$this->sentValue = $value;
|
||||||
try {
|
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) {
|
} catch (\Throwable $e) {
|
||||||
$this->returned = true;
|
$this->returned = true;
|
||||||
throw $e;
|
throw $e;
|
||||||
@ -145,9 +145,9 @@ class ReGenerator implements \Iterator
|
|||||||
$e = $exception;
|
$e = $exception;
|
||||||
}
|
}
|
||||||
if (!$this->yieldedFrom->valid()) { // Returned from yield from
|
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;
|
$this->yieldedFrom = null;
|
||||||
if ($e) {
|
if (isset($e)) {
|
||||||
return $this->throw($e);
|
return $this->throw($e);
|
||||||
}
|
}
|
||||||
return $this->send($returnValue);
|
return $this->send($returnValue);
|
||||||
@ -158,7 +158,7 @@ class ReGenerator implements \Iterator
|
|||||||
if (!$this->returned) {
|
if (!$this->returned) {
|
||||||
$this->sentException = $value;
|
$this->sentException = $value;
|
||||||
try {
|
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) {
|
} catch (\Throwable $e) {
|
||||||
$this->returned = true;
|
$this->returned = true;
|
||||||
throw $e;
|
throw $e;
|
||||||
@ -171,18 +171,18 @@ class ReGenerator implements \Iterator
|
|||||||
|
|
||||||
public function current()
|
public function current()
|
||||||
{
|
{
|
||||||
$this->start();
|
|
||||||
if ($this->yieldedFrom) {
|
if ($this->yieldedFrom) {
|
||||||
return $this->yieldedFrom->current();
|
return $this->yieldedFrom->current();
|
||||||
}
|
}
|
||||||
|
$this->start();
|
||||||
return $this->yieldValue;
|
return $this->yieldValue;
|
||||||
}
|
}
|
||||||
public function key()
|
public function key()
|
||||||
{
|
{
|
||||||
$this->start();
|
|
||||||
if ($this->yieldedFrom) {
|
if ($this->yieldedFrom) {
|
||||||
return $this->yieldedFrom->key();
|
return $this->yieldedFrom->key();
|
||||||
}
|
}
|
||||||
|
$this->start();
|
||||||
return $this->yieldKey;
|
return $this->yieldKey;
|
||||||
}
|
}
|
||||||
public function next(): void
|
public function next(): void
|
30
src/Target/Php55/YieldDetector.php
Normal file
30
src/Target/Php55/YieldDetector.php
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Phabel\Target\Php55;
|
||||||
|
|
||||||
|
use Phabel\Context;
|
||||||
|
use Phabel\Plugin;
|
||||||
|
use Phabel\Plugin\ReGenerator;
|
||||||
|
use PhpParser\Node\Expr\Yield_;
|
||||||
|
use PhpParser\Node\FunctionLike;
|
||||||
|
|
||||||
|
class YieldDetector extends Plugin
|
||||||
|
{
|
||||||
|
public function enterYield(Yield_ $node, Context $ctx): void
|
||||||
|
{
|
||||||
|
foreach ($ctx->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];
|
||||||
|
}
|
||||||
|
}
|
@ -1,42 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
namespace Phabel\Target\Php70;
|
|
||||||
|
|
||||||
use Phabel\Context;
|
|
||||||
use Phabel\Plugin;
|
|
||||||
use PhpParser\Node;
|
|
||||||
use PhpParser\Node\Expr\Assign;
|
|
||||||
use PhpParser\Node\Expr\Instanceof_;
|
|
||||||
use PhpParser\Node\Expr\MethodCall;
|
|
||||||
use PhpParser\Node\Expr\Variable;
|
|
||||||
use PhpParser\Node\Expr\YieldFrom;
|
|
||||||
use PhpParser\Node\Identifier;
|
|
||||||
use PhpParser\Node\Name\FullyQualified;
|
|
||||||
use PhpParser\Node\Stmt\If_;
|
|
||||||
use PhpParser\Node\Stmt\While_;
|
|
||||||
|
|
||||||
class YieldFromReplacer extends Plugin
|
|
||||||
{
|
|
||||||
private string $phabelVar = '';
|
|
||||||
private int $phabelCount = 0;
|
|
||||||
public function shouldRunFile(string $file): bool
|
|
||||||
{
|
|
||||||
$this->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);
|
|
||||||
}
|
|
||||||
}
|
|
59
src/Target/Php70/YieldFromReturnDetector.php
Normal file
59
src/Target/Php70/YieldFromReturnDetector.php
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Phabel\Target\Php70;
|
||||||
|
|
||||||
|
use Phabel\Context;
|
||||||
|
use Phabel\Plugin;
|
||||||
|
use Phabel\Plugin\ReGenerator;
|
||||||
|
use PhpParser\Node\Expr\Yield_;
|
||||||
|
use PhpParser\Node\Expr\YieldFrom;
|
||||||
|
use PhpParser\Node\FunctionLike;
|
||||||
|
use PhpParser\Node\Stmt\Return_;
|
||||||
|
|
||||||
|
class YieldFromReturnDetector extends Plugin
|
||||||
|
{
|
||||||
|
public function enterYieldFrom(YieldFrom $node, Context $ctx): void
|
||||||
|
{
|
||||||
|
foreach ($ctx->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];
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user