public
Last active

Allow use As in closure declaration

  • Download Gist
fr61682.patch
Diff
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140
index 6f2ded3..67eeefd 100644
--- a/Zend/zend_closures.c
+++ b/Zend/zend_closures.c
@@ -291,6 +291,66 @@ static zend_object_value zend_closure_clone(zval *zobject TSRMLS_DC) /* {{{ */
}
/* }}} */
+static int zend_closure_copy_lexical_var(zval **p TSRMLS_DC, int num_args, va_list args, zend_hash_key *key) /* {{{ */
+{
+ zval *tmp;
+ zend_bool is_ref;
+ HashTable *target = va_arg(args, HashTable*);
+ zval *this_ptr = va_arg(args, zval *);
+ long h = key->h;
+ char *skey = (char *)key->arKey;
+ uint len = key->nKeyLength;
+
+ if (Z_TYPE_PP(p) & (IS_LEXICAL_VAR|IS_LEXICAL_REF)) {
+
+ is_ref = Z_TYPE_PP(p) & IS_LEXICAL_REF;
+ if ((Z_TYPE_PP(p) & IS_CONSTANT_TYPE_MASK) == IS_STRING) {
+ if (Z_STRLEN_PP(p) == sizeof("this") - 1 && this_ptr && memcmp(Z_STRVAL_PP(p), "this", sizeof("this") - 1) == 0) {
+ if (zend_hash_quick_add(target, key->arKey, key->nKeyLength, key->h, &this_ptr, sizeof(zval*), NULL) == SUCCESS) {
+ Z_ADDREF_P(this_ptr);
+ }
+ return ZEND_HASH_APPLY_KEEP;
+ }
+ skey = Z_STRVAL_PP(p);
+ len = Z_STRLEN_PP(p) + 1;
+ h = zend_inline_hash_func(skey, len);
+ }
+
+ if (!EG(active_symbol_table)) {
+ zend_rebuild_symbol_table(TSRMLS_C);
+ }
+ if (zend_hash_quick_find(EG(active_symbol_table), skey, len, h, (void **) &p) == FAILURE) {
+ if (is_ref) {
+ ALLOC_INIT_ZVAL(tmp);
+ Z_SET_ISREF_P(tmp);
+ zend_hash_quick_add(EG(active_symbol_table), skey, len, h, &tmp, sizeof(zval*), (void**)&p);
+ } else {
+ tmp = EG(uninitialized_zval_ptr);
+ zend_error(E_NOTICE,"Undefined variable: %s", key->arKey);
+ }
+ } else {
+ if (is_ref) {
+ SEPARATE_ZVAL_TO_MAKE_IS_REF(p);
+ tmp = *p;
+ } else if (Z_ISREF_PP(p)) {
+ ALLOC_INIT_ZVAL(tmp);
+ ZVAL_COPY_VALUE(tmp, *p);
+ zval_copy_ctor(tmp);
+ Z_SET_REFCOUNT_P(tmp, 0);
+ Z_UNSET_ISREF_P(tmp);
+ } else {
+ tmp = *p;
+ }
+ }
+ } else {
+ tmp = *p;
+ }
+ if (zend_hash_quick_add(target, key->arKey, key->nKeyLength, key->h, &tmp, sizeof(zval*), NULL) == SUCCESS) {
+ Z_ADDREF_P(tmp);
+ }
+ return ZEND_HASH_APPLY_KEEP;
+}
+/* }}} */
int zend_closure_get_closure(zval *obj, zend_class_entry **ce_ptr, zend_function **fptr_ptr, zval **zobj_ptr TSRMLS_DC) /* {{{ */
{
@@ -463,7 +523,7 @@ ZEND_API void zend_create_closure(zval *res, zend_function *func, zend_class_ent
ALLOC_HASHTABLE(closure->func.op_array.static_variables);
zend_hash_init(closure->func.op_array.static_variables, zend_hash_num_elements(static_variables), NULL, ZVAL_PTR_DTOR
, 0);
- zend_hash_apply_with_arguments(static_variables TSRMLS_CC, (apply_func_args_t)zval_copy_static_var, 1, closure->func.
op_array.static_variables);
+ zend_hash_apply_with_arguments(static_variables TSRMLS_CC, (apply_func_args_t)zend_closure_copy_lexical_var, 2, closu
re->func.op_array.static_variables, this_ptr);
}
closure->func.op_array.run_time_cache = NULL;
(*closure->func.op_array.refcount)++;
diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c
index c3c35eb..a6f5616 100644
--- a/Zend/zend_compile.c
+++ b/Zend/zend_compile.c
@@ -5964,6 +5964,25 @@ void zend_do_fetch_lexical_variable(znode *varname, zend_bool is_ref TSRMLS_DC)
}
/* }}} */
+void zend_do_fetch_lexical_variable_with_alias(znode *alias, znode *varname, zend_bool is_ref TSRMLS_DC) /* {{{ */
+{
+ znode value;
+ if (Z_STRLEN(alias->u.constant) == sizeof("this") - 1 &&
+ memcmp(Z_STRVAL(alias->u.constant), "this", sizeof("this") - 1) == 0) {
+ zend_error(E_COMPILE_ERROR, "Cannot use $this as lexical variable");
+ return;
+ }
+
+ value.op_type = IS_CONST;
+ ZVAL_STRINGL(&value.u.constant, Z_STRVAL(varname->u.constant), Z_STRLEN(varname->u.constant), 0);
+ Z_TYPE(value.u.constant) |= is_ref ? IS_LEXICAL_REF : IS_LEXICAL_VAR;
+ Z_SET_REFCOUNT_P(&value.u.constant, 1);
+ Z_UNSET_ISREF_P(&value.u.constant);
+
+ zend_do_fetch_static_variable(alias, &value, is_ref ? ZEND_FETCH_STATIC : ZEND_FETCH_LEXICAL TSRMLS_CC);
+}
+/* }}} */
+
void zend_do_fetch_global_variable(znode *varname, const znode *static_assignment, int fetch_type TSRMLS_DC) /* {{{ */
{
zend_op *opline;
diff --git a/Zend/zend_compile.h b/Zend/zend_compile.h
index 8a81a95..9341c05 100644
--- a/Zend/zend_compile.h
+++ b/Zend/zend_compile.h
@@ -437,6 +437,7 @@ void fetch_simple_variable_ex(znode *result, znode *varname, int bp, zend_uchar
void zend_do_indirect_references(znode *result, const znode *num_references, znode *variable TSRMLS_DC);
void zend_do_fetch_static_variable(znode *varname, const znode *static_assignment, int fetch_type TSRMLS_DC);
void zend_do_fetch_global_variable(znode *varname, const znode *static_assignment, int fetch_type TSRMLS_DC);
+void zend_do_fetch_lexical_variable_with_alias(znode *alias, znode *varname, zend_bool is_ref TSRMLS_DC);
void fetch_array_begin(znode *result, znode *varname, znode *first_dim TSRMLS_DC);
void fetch_array_dim(znode *result, const znode *parent, const znode *dim TSRMLS_DC);
diff --git a/Zend/zend_language_parser.y b/Zend/zend_language_parser.y
index d0730b7..efa2d8c 100644
--- a/Zend/zend_language_parser.y
+++ b/Zend/zend_language_parser.y
@@ -809,8 +809,9 @@ lexical_vars:
;
lexical_var_list:
- lexical_var_list ',' T_VARIABLE { zend_do_fetch_lexical_variable(&$3, 0 TSRMLS_CC); }
- | lexical_var_list ',' '&' T_VARIABLE { zend_do_fetch_lexical_variable(&$4, 1 TSRMLS_CC); }
+ lexical_var_list ',' lexical_var_list
+ | T_VARIABLE T_AS T_VARIABLE { zend_do_fetch_lexical_variable_with_alias(&$3, &$1, 0 TSRMLS_CC); }
+ | '&' T_VARIABLE T_AS T_VARIABLE { zend_do_fetch_lexical_variable_with_alias(&$4, &$2, 1 TSRMLS_CC); }
| T_VARIABLE { zend_do_fetch_lexical_variable(&$1, 0 TSRMLS_CC); }
| '&' T_VARIABLE { zend_do_fetch_lexical_variable(&$2, 1 TSRMLS_CC); }
;

Nice mix of tab and space indent.

Great patch! Hope it gets in.

Please sign in to comment on this gist.

Something went wrong with that request. Please try again.