public function resume($params = null) { $this->generator->send($params); if (!$this->generator->valid()) { $this->closed = true; } return $this->generator->current(); }
/** * {@inheritdoc} */ public function tick() { if ($this->firstTick) { $this->firstTick = false; $this->deferred->notify(new MessageEvent($this, $this->generator->current())); } else { $this->deferred->notify(new MessageEvent($this, $this->generator->send(null))); } if (!$this->generator->valid()) { $this->deferred->resolve(new Event($this)); } }
/** * When you need to return Result from your function, and it also depends on another * functions returning Results, you can make it a generator function and yield * values from dependant functions, this pattern makes code less bloated with * statements like this: * $res = something(); * if ($res instanceof Ok) { * $something = $res->unwrap(); * } else { * return $res; * } * * Instead you can write: * $something = (yield something()); * * @see /example.php * * @param \Generator $resultsGenerator Generator that produces Result instances * @return Result */ public static function reduce(\Generator $resultsGenerator) { /** @var Result $result */ $result = $resultsGenerator->current(); while ($resultsGenerator->valid()) { if ($result instanceof Err) { return $result; } $tmpResult = $resultsGenerator->send($result->unwrap()); if ($resultsGenerator->valid()) { $result = $tmpResult; } } return $result; }
public function valid() { if ($this->_currentGen) { return $this->_currentGen->valid(); } return !!$this->current(); }
/** * Examines the value yielded from the generator and prepares the next step in interation. * * @param mixed $yielded */ private function next($yielded) { if (!$this->generator->valid()) { $result = $this->generator->getReturn(); if ($result instanceof Awaitable) { $this->reject(new AwaitableReturnedError($result)); return; } if ($result instanceof Generator) { $this->reject(new GeneratorReturnedError($result)); return; } $this->resolve($result); return; } $this->busy = true; if ($yielded instanceof Generator) { $yielded = new self($yielded); } $this->current = $yielded; if ($yielded instanceof Awaitable) { $yielded->done($this->send, $this->capture); } else { Loop\queue($this->send, $yielded); } $this->busy = false; }
/** * Return value that generator has returned or thrown. * @return mixed */ public function getReturnOrThrown() { $this->validateInvalidity(); if ($this->e === null && $this->g->valid() && !$this->valid()) { return $this->g->current(); } if ($this->e) { return $this->e; } return method_exists($this->g, 'getReturn') ? $this->g->getReturn() : null; }
private function checkResult(\Generator $generator, Channel $channel) { if (!$generator->valid()) { foreach ($this->actions as list(, $gen, , $undo)) { if ($gen && $gen !== $generator) { $undo($gen->current()); } } return [$generator->getReturn(), $channel]; } return false; }
/** * @param \Generator $generator * @param string $prefix */ public function __construct(\Generator $generator, string $prefix) { $yielded = $generator->current(); $prefix .= \sprintf("; %s yielded at key %s", \is_object($yielded) ? \get_class($yielded) : \gettype($yielded), $generator->key()); if (!$generator->valid()) { parent::__construct($prefix); return; } $reflGen = new \ReflectionGenerator($generator); $exeGen = $reflGen->getExecutingGenerator(); if ($isSubgenerator = $exeGen !== $generator) { $reflGen = new \ReflectionGenerator($exeGen); } parent::__construct(\sprintf("%s on line %s in %s", $prefix, $reflGen->getExecutingLine(), $reflGen->getExecutingFile())); }
/** * Examines the value yielded from the generator and prepares the next step in interation. * * @param mixed $yielded */ private function next($yielded) { if (!$this->generator->valid()) { $this->resolve($this->generator->getReturn()); $this->close(); return; } if ($yielded instanceof Generator) { $yielded = new self($yielded); } if ($yielded instanceof Awaitable) { $yielded->done($this->send, $this->capture); } else { Loop\queue($this->send, $yielded); } }
/** * {@inheritdoc} */ public function read($length) { $this->initializeBeforeRead(); if (!$this->generator->valid()) { return ''; } if ($this->resource->eof()) { $this->generator->next(); if (!$this->generator->valid()) { return ''; } $this->resource = $this->generator->current(); $this->resource->rewind(); } return $this->resource->fread($length); }
/** * Runs the generator to completion then fails the coroutine with the given exception. * * @param \Throwable $exception */ private function dispose(\Throwable $exception) { if ($this->generator->valid()) { try { try { // Ensure generator has run to completion to avoid throws from finally blocks on destruction. do { $this->generator->throw($exception); } while ($this->generator->valid()); } finally { // Throw from finally to attach any exception thrown from generator as previous exception. throw $exception; } } catch (\Throwable $exception) { // $exception will be used to fail the coroutine. } } $this->fail($exception); }
/** * {@inheritdoc} */ public function cancel(Throwable $reason = null) { if (null === $reason) { $reason = new TerminatedException(); } if (null !== $this->generator) { try { do { if ($this->current instanceof Awaitable) { $this->current->cancel($reason); } $this->current = $this->generator->throw($reason); } while ($this->generator->valid()); } catch (Throwable $exception) { $reason = $exception; } } parent::cancel($reason); }
/** * * @param int $n * @param \Generator $gen * * @return \Generator */ function take($n, Generator $gen) { while ($n-- > 0 && $gen->valid()) { (yield $gen->current()); $gen->next(); } }
private function responseCodec(\Generator $filter, InternalRequest $ireq) : \Generator { while ($filter->valid()) { $cur = $filter->send(yield); if ($cur !== null) { $ireq->responseWriter->send($cur); } } $cur = $filter->getReturn(); if ($cur !== null) { $ireq->responseWriter->send($cur); } $ireq->responseWriter->send(null); }
/** * Returns true, if there are still tokens left to be generated. * * If the lexer-generator still has tokens to generate, * this returns true and false, if it doesn't * * @see \Generator->valid * * @return bool */ protected function hasTokens() { return $this->tokens->valid(); }
private function responseCodec(\Generator $filter, InternalRequest $ireq) : \Generator { while (($yield = yield) !== null) { $cur = $filter->send($yield); if ($yield === false) { if ($cur !== null) { $ireq->responseWriter->send($cur); if (\is_array($cur)) { // in case of headers, to flush a maybe started body too, we need to send false twice $cur = $filter->send(false); if ($cur !== null) { $ireq->responseWriter->send($cur); } } } $ireq->responseWriter->send(false); } elseif ($cur !== null) { $ireq->responseWriter->send($cur); } } $cur = $filter->send(null); if (\is_array($cur)) { $ireq->responseWriter->send($cur); $filter->send(null); } \assert($filter->valid() === false); $cur = $filter->getReturn(); if ($cur !== null) { $ireq->responseWriter->send($cur); } $ireq->responseWriter->send(null); }
/** * Checks if current position is valid * @see Iterator::rewind * @link http://php.net/manual/en/iterator.valid.php * @return boolean */ public function valid() { return $this->generator->valid(); }
/** * For a callable, it's always valid to iterate * * @return bool */ public function valid() { return $this->generator ? $this->generator->valid() : true; }
/** * @param \Generator $generator */ public function __construct(Generator $generator) { $this->generator = $generator; parent::__construct(function (callable $resolve, callable $reject) { $yielded = $this->generator->current(); if (!$this->generator->valid()) { $resolve($this->generator->getReturn()); $this->close(); return; } /** * @param mixed $value The value to send to the generator. */ $this->send = function ($value = null) use($resolve, $reject) { if ($this->paused) { // If paused, save callable and value for resuming. $this->next = [$this->send, $value]; return; } try { // Send the new value and execute to next yield statement. $yielded = $this->generator->send($value); if (!$this->generator->valid()) { $resolve($this->generator->getReturn()); $this->close(); return; } $this->next($yielded); } catch (Throwable $exception) { $reject($exception); $this->close(); } }; /** * @param \Throwable $exception Exception to be thrown into the generator. */ $this->capture = function (Throwable $exception) use($resolve, $reject) { if ($this->paused) { // If paused, save callable and exception for resuming. $this->next = [$this->capture, $exception]; return; } try { // Throw exception at current execution point. $yielded = $this->generator->throw($exception); if (!$this->generator->valid()) { $resolve($this->generator->getReturn()); $this->close(); return; } $this->next($yielded); } catch (Throwable $exception) { $reject($exception); $this->close(); } }; $this->next($yielded); return function (Throwable $exception) { try { $current = $this->generator->current(); // Get last yielded value. if ($current instanceof PromiseInterface) { $current->cancel($exception); } } finally { $this->close(); } }; }); }
/** * A general purpose function for creating error messages from generator yields * * @param \Generator $generator * @param string $prefix * @return string */ function makeGeneratorError(\Generator $generator, $prefix = "Generator error") { if (PHP_MAJOR_VERSION < 7 || !$generator->valid()) { return $prefix; } $reflGen = new \ReflectionGenerator($generator); $exeGen = $reflGen->getExecutingGenerator(); if ($isSubgenerator = $exeGen !== $generator) { $reflGen = new \ReflectionGenerator($exeGen); } return sprintf("{$prefix} on line %s in %s", $reflGen->getExecutingLine(), $reflGen->getExecutingFile()); }
/** * @param \Generator $logs * * @return int */ protected function cntGeneratorLogs($logs) { $cnt = 0; while ($logs->valid()) { $cnt++; $logs->next(); } return $cnt; }
/** * checks whether a coroutine is empty * @return bool */ public function isFinished() { return !$this->coroutine->valid(); }
/** * @param \Generator $generator */ public function __construct(Generator $generator) { $this->generator = $generator; parent::__construct(function (callable $resolve, callable $reject) { /** * @param mixed $value The value to send to the generator. * @param \Throwable|null $exception Exception object to be thrown into the generator if not null. */ $this->worker = function ($value = null, Throwable $exception = null) use($resolve, $reject) { if ($this->paused) { // If paused, mark coroutine as ready to resume. $this->ready = true; return; } try { if ($this->initial) { // Get result of first yield statement. $this->initial = false; $this->current = $this->generator->current(); } elseif (null !== $exception) { // Throw exception at current execution point. $this->current = $this->generator->throw($exception); } else { // Send the new value and execute to next yield statement. $this->current = $this->generator->send($value); } if (!$this->generator->valid()) { $resolve($this->generator->getReturn()); $this->close(); return; } if ($this->current instanceof Generator) { $this->current = new self($this->current); } if ($this->current instanceof PromiseInterface) { $this->current->done($this->worker, $this->capture); } else { Loop\queue($this->worker, $this->current); } } catch (Throwable $exception) { $reject($exception); $this->close(); } }; /** * @param \Throwable $exception Exception to be thrown into the generator. */ $this->capture = function (Throwable $exception) { if (null !== $this->worker) { // Coroutine may have been closed. ($this->worker)(null, $exception); } }; Loop\queue($this->worker); return function (Throwable $exception) { try { $current = $this->generator->current(); // Get last yielded value. while ($this->generator->valid()) { if ($current instanceof PromiseInterface) { $current->cancel($exception); } $current = $this->generator->throw($exception); } } finally { $this->close(); } }; }); }
public function valid() { if (!$this->generator) { $this->rewind(); } return $this->generator->valid(); }
/** @internal */ function __next_coroutine($yielded, \Generator $generator) { return promise_for($yielded)->then(function ($value) use($generator) { $nextYield = $generator->send($value); return $generator->valid() ? __next_coroutine($nextYield, $generator) : $value; }, function ($reason) use($generator) { $nextYield = $generator->throw(exception_for($reason)); // The throw was caught, so keep iterating on the coroutine return __next_coroutine($nextYield, $generator); }); }
/** * Returns true if the task is finished. * * @return boolean */ public function isFinished() { return $this->started && !($this->generator && $this->generator->valid()); }