diff --git a/.gitignore b/.gitignore index bef310b..10c9815 100644 --- a/.gitignore +++ b/.gitignore @@ -5,3 +5,4 @@ phpunit.xml vendor .php_cs.cache coverage +a.php diff --git a/src/Target/Php70/ReGenerator/ReGenerator.php b/src/Target/Php70/ReGenerator/ReGenerator.php new file mode 100644 index 0000000..8b16ecb --- /dev/null +++ b/src/Target/Php70/ReGenerator/ReGenerator.php @@ -0,0 +1,212 @@ +generator = $function; + } + + /** + * Get return value. + * + * @return void + */ + public function getReturn() + { + return $this->returnValue; + } + + /** + * Start generator. + * + * @return void + */ + private function start(): void + { + if (!$this->started) { + ($this->generator)($this->state, $this->variables, $this->yieldKey, $this->yieldValue, $this->sentValue, $this->sentException, $this->returnValue, $this->returned); + $this->started = true; + } + } + + public function send($value) + { + $this->start(); + if ($this->yieldedFrom) { + try { + $result = $this->yieldedFrom->send($value); + } catch (\Throwable $exception) { + $e = $exception; + } + if (!$this->yieldedFrom->valid()) { // Returned from yield from + $returnValue = $this->yieldedFrom->getReturn(); + $this->yieldedFrom = null; + if ($e) { + return $this->throw($e); + } + return $this->send($returnValue); + } + return $result; + } + $value = $this->yieldValue; + 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); + } catch (\Throwable $e) { + $this->returned = true; + throw $e; + } finally { + $this->sentValue = null; + } + } + return $value; + } + public function throw(\Throwable $throwable) + { + $this->start(); + if ($this->yieldedFrom) { + try { + $result = $this->yieldedFrom->throw($throwable); + } catch (\Throwable $exception) { + $e = $exception; + } + if (!$this->yieldedFrom->valid()) { // Returned from yield from + $returnValue = $this->yieldedFrom->getReturn(); + $this->yieldedFrom = null; + if ($e) { + return $this->throw($e); + } + return $this->send($returnValue); + } + return $result; + } + $value = $this->yieldValue; + if (!$this->returned) { + $this->sentException = $value; + try { + ($this->generator)($this->variables, $this->yieldKey, $this->yieldValue, $this->sentValue, $this->sentException, $this->returnValue, $this->returned); + } catch (\Throwable $e) { + $this->returned = true; + throw $e; + } finally { + $this->sentException = null; + } + } + return $value; + } + + public function current() + { + $this->start(); + if ($this->yieldedFrom) { + return $this->yieldedFrom->current(); + } + return $this->yieldValue; + } + public function key() + { + $this->start(); + if ($this->yieldedFrom) { + return $this->yieldedFrom->key(); + } + return $this->yieldKey; + } + public function next(): void + { + $this->send(null); + } + public function rewind(): void + { + if ($this->started && !$this->returned) { + throw new \Exception('Cannot rewind a generator that was already run'); + } + $this->started = false; + $this->returned = false; + $this->returnValue = null; + $this->yieldKey = null; + $this->yieldValue = null; + $this->sentValue = null; + $this->sentException = null; + $this->yieldedFrom = null; + $this->variables = []; + $this->start(); + } + public function valid(): bool + { + return !$this->returned; + } +}