diff options
Diffstat (limited to 'Zend/zend_compile.c')
-rw-r--r-- | Zend/zend_compile.c | 60 |
1 files changed, 57 insertions, 3 deletions
diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c index 723191cf56..5546e2a0da 100644 --- a/Zend/zend_compile.c +++ b/Zend/zend_compile.c @@ -1401,6 +1401,33 @@ void zend_do_begin_function_declaration(znode *function_token, znode *function_n CG(labels) = NULL; } +void zend_do_begin_lambda_function_declaration(znode *result, znode *function_token, int return_reference, int is_static TSRMLS_DC) +{ + znode function_name; + zend_op_array *current_op_array = CG(active_op_array); + int current_op_number = get_next_op_number(CG(active_op_array)); + zend_op *current_op; + + function_name.op_type = IS_CONST; + ZVAL_STRINGL(&function_name.u.constant, "lambda", sizeof("lambda")-1, 1); + + zend_do_begin_function_declaration(function_token, &function_name, 0, return_reference, NULL TSRMLS_CC); + + result->op_type = IS_TMP_VAR; + result->u.var = get_temporary_variable(current_op_array);; + + current_op = ¤t_op_array->opcodes[current_op_number]; + current_op->opcode = ZEND_DECLARE_LAMBDA_FUNCTION; + zval_dtor(¤t_op->op2.u.constant); + ZVAL_LONG(¤t_op->op2.u.constant, zend_hash_func(Z_STRVAL(current_op->op1.u.constant), Z_STRLEN(current_op->op1.u.constant))); + current_op->result = *result; + if (is_static) { + CG(active_op_array)->fn_flags |= ZEND_ACC_STATIC; + } + CG(active_op_array)->fn_flags |= ZEND_ACC_CLOSURE; +} + + void zend_do_handle_exception(TSRMLS_D) { zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC); @@ -4155,13 +4182,13 @@ void zend_do_fetch_static_variable(znode *varname, znode *static_assignment, int } opline = get_next_op(CG(active_op_array) TSRMLS_CC); - opline->opcode = ZEND_FETCH_W; /* the default mode must be Write, since fetch_simple_variable() is used to define function arguments */ + opline->opcode = (fetch_type == ZEND_FETCH_LEXICAL) ? ZEND_FETCH_R : ZEND_FETCH_W; /* the default mode must be Write, since fetch_simple_variable() is used to define function arguments */ opline->result.op_type = IS_VAR; opline->result.u.EA.type = 0; opline->result.u.var = get_temporary_variable(CG(active_op_array)); opline->op1 = *varname; SET_UNUSED(opline->op2); - opline->op2.u.EA.type = fetch_type; + opline->op2.u.EA.type = ZEND_FETCH_STATIC; result = opline->result; if (varname->op_type == IS_CONST) { @@ -4169,12 +4196,39 @@ void zend_do_fetch_static_variable(znode *varname, znode *static_assignment, int } fetch_simple_variable(&lval, varname, 0 TSRMLS_CC); /* Relies on the fact that the default fetch is BP_VAR_W */ - zend_do_assign_ref(NULL, &lval, &result TSRMLS_CC); + if (fetch_type == ZEND_FETCH_LEXICAL) { + znode dummy; + + zend_do_begin_variable_parse(TSRMLS_C); + zend_do_assign(&dummy, &lval, &result TSRMLS_CC); + zend_do_free(&dummy TSRMLS_CC); + } else { + zend_do_assign_ref(NULL, &lval, &result TSRMLS_CC); + } CG(active_op_array)->opcodes[CG(active_op_array)->last-1].result.u.EA.type |= EXT_TYPE_UNUSED; /* zval_dtor(&varname->u.constant); */ } +void zend_do_fetch_lexical_variable(znode *varname, zend_bool is_ref TSRMLS_DC) +{ + znode value; + + if (Z_STRLEN(varname->u.constant) == sizeof("this") - 1 && + memcmp(Z_STRVAL(varname->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_NULL(&value.u.constant); + 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(varname, &value, is_ref ? ZEND_FETCH_STATIC : ZEND_FETCH_LEXICAL TSRMLS_CC); +} + void zend_do_fetch_global_variable(znode *varname, znode *static_assignment, int fetch_type TSRMLS_DC) { zend_op *opline; |