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

More Intelligent Variable Type Inference #1878

Open dreamsxin opened 5 years ago

dreamsxin commented 5 years ago

@sergeyklay

Example

namespace Test;

class ArrayIteratorTest
{
    public static function test()
    {
        var arr, k, v;
        let arr = new ArrayIterator();
        for k, v in arr {
            return k . v;
        } 
    }
}

Now, the generate code:

    ZEPHIR_INIT_VAR(&arr);
    object_init_ex(&arr, test_arrayiterator_ce);
    ZEPHIR_CALL_METHOD(NULL, &arr, "__construct", NULL, 4);
    zephir_check_call_status();
    zephir_is_iterable(&arr, 0, "test/arrayiteratortest.zep", 12);
    if (Z_TYPE_P(&arr) == IS_ARRAY) {
            // ...
    } else {
        ZEPHIR_CALL_METHOD(NULL, &arr, "rewind", NULL, 0);
        zephir_check_call_status();
        while (1) {
            ZEPHIR_CALL_METHOD(&_1, &arr, "valid", NULL, 0);
            zephir_check_call_status();
            if (!zend_is_true(&_1)) {
                break;
            }
            ZEPHIR_CALL_METHOD(&k, &arr, "key", NULL, 0);
            zephir_check_call_status();
            ZEPHIR_CALL_METHOD(&v, &arr, "current", NULL, 0);
            zephir_check_call_status();
                ZEPHIR_CONCAT_VV(return_value, &k, &v);
                RETURN_MM();
            ZEPHIR_CALL_METHOD(NULL, &arr, "next", NULL, 0);
            zephir_check_call_status();
        }
    }

Expect:

    ZEPHIR_INIT_VAR(&arr);
    object_init_ex(&arr, test_arrayiterator_ce);
    ZEPHIR_CALL_METHOD(NULL, &arr, "__construct", NULL, 4);
    zephir_check_call_status();
    zephir_is_iterable(&arr, 0, "test/arrayiteratortest.zep", 12);

    ZEPHIR_CALL_METHOD(NULL, &arr, "rewind", NULL, 0);
    zephir_check_call_status();
    while (1) {
        ZEPHIR_CALL_METHOD(&_1, &arr, "valid", NULL, 0);
        zephir_check_call_status();
        if (!zend_is_true(&_1)) {
            break;
        }
        ZEPHIR_CALL_METHOD(&k, &arr, "key", NULL, 0);
        zephir_check_call_status();
        ZEPHIR_CALL_METHOD(&v, &arr, "current", NULL, 0);
        zephir_check_call_status();
            ZEPHIR_CONCAT_VV(return_value, &k, &v);
            RETURN_MM();
        ZEPHIR_CALL_METHOD(NULL, &arr, "next", NULL, 0);
        zephir_check_call_status();
    }

And https://github.com/phalcon/zephir/issues/1875 Can record whether the current context variable is assigned


        let included = this->getOption("included"); // assigned 

       // maybe assigned
        if typeof included == "array" {
            let included = (bool) included[field]; // possible
        } else {
            let included = (bool) included; // possible
        }
}
sergeyklay commented 5 years ago

Yeah, type check Z_TYPE_P(&arr) == IS_ARRAY is redundant here