zephir icon indicating copy to clipboard operation
zephir copied to clipboard

[NFR] Support coroutine or yield

Open dreamsxin opened this issue 5 years ago • 9 comments

I don't think it's very meaningful to implement yield because curl and the IO wait of PDO can't be solved. We can add libuv and boost.context implementation a lower level symmetric coroutine.

@sergeyklay

dreamsxin avatar Apr 21 '19 03:04 dreamsxin

Yes, it seems so. Good idea, thank you!

sergeyklay avatar Apr 21 '19 14:04 sergeyklay

I will insert a picture of a dancing bear here!

niden avatar Apr 21 '19 14:04 niden

class AsyncTest {

    async plubic function test() {
        sleep(10);
        return 1;
    }
}
test = new AsyncTest;
test->test(); // nonblock
wait test->test(); // block
let ret = test->test(); // block

dreamsxin avatar Apr 22 '19 08:04 dreamsxin

<?php

Generator implements Iterator {

	public current() {
	}

	public key() {
	
	}

	public next() {
	}

	public rewind() {
	}

	public send(mixed $value) {
	}

	public throw(Exception $exception) {
	}

	public valid () {
	}

	public __wakeup () {
	
	}
}

dreamsxin avatar Jun 25 '19 09:06 dreamsxin

Reference zend source code

void zend_compile_yield(znode *result, zend_ast *ast) /* {{{ */
{
	zend_ast *value_ast = ast->child[0];
	zend_ast *key_ast = ast->child[1];

	znode value_node, key_node;
	znode *value_node_ptr = NULL, *key_node_ptr = NULL;
	zend_op *opline;
	zend_bool returns_by_ref = (CG(active_op_array)->fn_flags & ZEND_ACC_RETURN_REFERENCE) != 0;

	zend_mark_function_as_generator();

	if (key_ast) {
		zend_compile_expr(&key_node, key_ast);
		key_node_ptr = &key_node;
	}

	if (value_ast) {
		if (returns_by_ref && zend_is_variable(value_ast) && !zend_is_call(value_ast)) {
			zend_compile_var(&value_node, value_ast, BP_VAR_W);
		} else {
			zend_compile_expr(&value_node, value_ast);
		}
		value_node_ptr = &value_node;
	}

	opline = zend_emit_op(result, ZEND_YIELD, value_node_ptr, key_node_ptr);

	if (value_ast && returns_by_ref && zend_is_call(value_ast)) {
		opline->extended_value = ZEND_RETURNS_FUNCTION;
	}
}
/* }}} */

void zend_compile_yield_from(znode *result, zend_ast *ast) /* {{{ */
{
	zend_ast *expr_ast = ast->child[0];
	znode expr_node;

	zend_mark_function_as_generator();

	if (CG(active_op_array)->fn_flags & ZEND_ACC_RETURN_REFERENCE) {
		zend_error_noreturn(E_COMPILE_ERROR,
			"Cannot use \"yield from\" inside a by-reference generator");
	}

	zend_compile_expr(&expr_node, expr_ast);
	zend_emit_op_tmp(result, ZEND_YIELD_FROM, &expr_node, NULL);
}
/* }}} */

dreamsxin avatar Jun 27 '19 03:06 dreamsxin

Any updates on this boys or we are doing other stuff?

niden avatar Dec 10 '19 20:12 niden

Not yet

sergeyklay avatar Dec 10 '19 20:12 sergeyklay

Generators (using yield) are a very important feature to convert PHP projects to Zephir. Thank you for developing a good tool and trying to make it as similar to PHP as possible!

JWprogrammer avatar Jun 11 '21 18:06 JWprogrammer

~Blocked by https://github.com/zephir-lang/php-zephir-parser/issues/118~

Jeckerson avatar Sep 11 '21 10:09 Jeckerson