zephir-lang / zephir

Zephir is a compiled high-level language aimed to ease the creation of C-extensions for PHP
https://zephir-lang.com
MIT License
3.29k stars 466 forks source link

[NFR] Support coroutine or yield #1849

Open dreamsxin opened 5 years ago

dreamsxin commented 5 years ago

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

sergeyklay commented 5 years ago

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

niden commented 5 years ago

I will insert a picture of a dancing bear here!

dreamsxin commented 5 years ago
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 commented 5 years ago
<?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 commented 5 years ago

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);
}
/* }}} */
niden commented 4 years ago

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

sergeyklay commented 4 years ago

Not yet

JWprogrammer commented 3 years ago

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!

Jeckerson commented 3 years ago

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