summaryrefslogtreecommitdiff
path: root/Zend/zend_generators.c
diff options
context:
space:
mode:
authorNikita Popov <nikic@php.net>2012-12-17 22:02:32 +0100
committerNikita Popov <nikic@php.net>2012-12-24 00:27:55 +0100
commitbe7b0bc3ec02e4f223920ee6397f9c4993eb7df5 (patch)
tree3d6f62821f0df9ca11147ce18652df7b2d109acb /Zend/zend_generators.c
parent24f1ef1b0254d4b8341aa9d74ca450e89c2a8683 (diff)
downloadphp-git-be7b0bc3ec02e4f223920ee6397f9c4993eb7df5.tar.gz
Implement Generator::throw() method
Generator::throw($exception) throws an exception into the generator. The exception is thrown at the current point of suspension within the generator. It basically behaves as if the current yield statement were replaced with a throw statement and the generator subsequently resumed.
Diffstat (limited to 'Zend/zend_generators.c')
-rw-r--r--Zend/zend_generators.c49
1 files changed, 44 insertions, 5 deletions
diff --git a/Zend/zend_generators.c b/Zend/zend_generators.c
index b16687c3d8..9c65c534bd 100644
--- a/Zend/zend_generators.c
+++ b/Zend/zend_generators.c
@@ -431,10 +431,6 @@ static zend_function *zend_generator_get_constructor(zval *object TSRMLS_DC) /*
ZEND_API void zend_generator_resume(zend_generator *generator TSRMLS_DC) /* {{{ */
{
- if (EG(exception)) {
- return;
- }
-
/* The generator is already closed, thus can't resume */
if (!generator->execute_data) {
return;
@@ -617,7 +613,7 @@ ZEND_METHOD(Generator, next)
}
/* }}} */
-/* {{{ proto mixed Generator::send()
+/* {{{ proto mixed Generator::send(mixed $value)
* Sends a value to the generator */
ZEND_METHOD(Generator, send)
{
@@ -648,6 +644,44 @@ ZEND_METHOD(Generator, send)
}
/* }}} */
+/* {{{ proto mixed Generator::throw(Exception $exception)
+ * Throws an exception into the generator */
+ZEND_METHOD(Generator, throw)
+{
+ zval *exception, *exception_copy;
+ zend_generator *generator;
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &exception) == FAILURE) {
+ return;
+ }
+
+ ALLOC_ZVAL(exception_copy);
+ MAKE_COPY_ZVAL(&exception, exception_copy);
+
+ generator = (zend_generator *) zend_object_store_get_object(getThis() TSRMLS_CC);
+
+ if (generator->execute_data) {
+ /* Throw the exception in the context of the generator */
+ zend_execute_data *current_execute_data = EG(current_execute_data);
+ EG(current_execute_data) = generator->execute_data;
+
+ zend_throw_exception_object(exception_copy TSRMLS_CC);
+
+ EG(current_execute_data) = current_execute_data;
+
+ zend_generator_resume(generator TSRMLS_CC);
+
+ if (generator->value) {
+ RETURN_ZVAL(generator->value, 1, 0);
+ }
+ } else {
+ /* If the generator is already closed throw the exception in the
+ * current context */
+ zend_throw_exception_object(exception_copy TSRMLS_CC);
+ }
+}
+/* }}} */
+
/* {{{ proto void Generator::__wakeup()
* Throws an Exception as generators can't be serialized */
ZEND_METHOD(Generator, __wakeup)
@@ -790,6 +824,10 @@ ZEND_BEGIN_ARG_INFO_EX(arginfo_generator_send, 0, 0, 1)
ZEND_ARG_INFO(0, value)
ZEND_END_ARG_INFO()
+ZEND_BEGIN_ARG_INFO_EX(arginfo_generator_throw, 0, 0, 1)
+ ZEND_ARG_INFO(0, exception)
+ZEND_END_ARG_INFO()
+
static const zend_function_entry generator_functions[] = {
ZEND_ME(Generator, rewind, arginfo_generator_void, ZEND_ACC_PUBLIC)
ZEND_ME(Generator, valid, arginfo_generator_void, ZEND_ACC_PUBLIC)
@@ -797,6 +835,7 @@ static const zend_function_entry generator_functions[] = {
ZEND_ME(Generator, key, arginfo_generator_void, ZEND_ACC_PUBLIC)
ZEND_ME(Generator, next, arginfo_generator_void, ZEND_ACC_PUBLIC)
ZEND_ME(Generator, send, arginfo_generator_send, ZEND_ACC_PUBLIC)
+ ZEND_ME(Generator, throw, arginfo_generator_throw, ZEND_ACC_PUBLIC)
ZEND_ME(Generator, __wakeup, arginfo_generator_void, ZEND_ACC_PUBLIC)
ZEND_FE_END
};