1
0
mirror of https://github.com/danog/amp.git synced 2024-11-27 04:24:42 +01:00

Minor coroutine refactoring/optimization; add makeGeneratorError()

This commit is contained in:
Daniel Lowrey 2015-06-16 10:59:44 -04:00
parent 1d777c7e3e
commit 40fbb6e16d

View File

@ -527,7 +527,7 @@ function wait(Promise $promise, Reactor $reactor = null) {
*/
function coroutine(callable $func, Reactor $reactor = null) {
return function() use ($func, $reactor) {
$result = \call_user_func_array($func, func_get_args());
$result = \call_user_func_array($func, \func_get_args());
return ($result instanceof \Generator)
? resolve($result, $reactor)
: $result;
@ -550,7 +550,6 @@ function resolve(\Generator $generator, Reactor $reactor = null) {
$cs->generator = $generator;
$cs->returnValue = null;
$cs->currentPromise = null;
$cs->isResolved = false;
__coroutineAdvance($cs);
@ -572,28 +571,30 @@ function __coroutineAdvance($cs) {
}
} elseif (($key = $cs->generator->key()) === "return") {
$cs->returnValue = $yielded;
$cs->reactor->immediately("Amp\__coroutineNextTick", ["cb_data" => $cs]);
__coroutineSend(null, null, $cs);
} elseif ($yielded instanceof Promise) {
$cs->currentPromise = $yielded;
$cs->reactor->immediately("Amp\__coroutineNextTick", ["cb_data" => $cs]);
} else {
$cs->isResolved = true;
$cs->promisor->fail(new \DomainException(
__coroutineYieldError($cs->generator, $key, $yielded)
$error = makeGeneratorError($cs->generator, sprintf(
'Unexpected yield (Promise|null|"return" expected); %s yielded at key %s',
is_object($yielded) ? get_class($yielded) : gettype($yielded),
$key
));
$cs->reactor->immediately(function() use ($cs, $error) {
$cs->promisor->fail(new \DomainException($error));
});
}
} catch (\Exception $uncaught) {
if ($cs->isResolved) {
throw new \RuntimeException("", 0, $uncaught);
} else {
$cs->isResolved = true;
$cs->reactor->immediately(function() use ($cs, $uncaught) {
$cs->promisor->fail($uncaught);
}
});
}
}
function __coroutineNextTick($reactor, $watcherId, $cs) {
if ($promise = $cs->currentPromise) {
if ($cs->currentPromise) {
$promise = $cs->currentPromise;
$cs->currentPromise = null;
$promise->when("Amp\__coroutineSend", $cs);
} else {
@ -610,32 +611,32 @@ function __coroutineSend($error, $result, $cs) {
}
__coroutineAdvance($cs);
} catch (\Exception $uncaught) {
if ($cs->isResolved) {
throw new \RuntimeException("", 0, $uncaught);
} else {
$cs->isResolved = true;
$cs->reactor->immediately(function() use ($cs, $uncaught) {
$cs->promisor->fail($uncaught);
}
});
}
}
function __coroutineYieldError($generator, $key, $yielded) {
$type = is_object($yielded) ? get_class($yielded) : gettype($yielded);
$msg = "Unexpected Generator yield (Promise|\"return\"|null expected); {$type} yielded at key {$key}";
if (PHP_MAJOR_VERSION < 7) {
return $msg;
/**
* 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 ($exeGen !== $generator) {
// We're executing a subgenerator; use the correct reflection
if ($isSubgenerator = ($exeGen !== $generator)) {
$reflGen = new \ReflectionGenerator($exeGen);
}
return sprintf(
"%s on line %s in %s",
$msg,
"{$prefix} on line %s in %s",
$reflGen->getExecutingLine(),
$reflGen->getExecutingFile()
);