From 64e4c9eff16b082f87e94fc02ec620b85124197d Mon Sep 17 00:00:00 2001 From: Nikita Popov Date: Sat, 31 May 2014 17:18:37 +0200 Subject: [PATCH] Support directly calling closure --- Zend/tests/varSyntax/indirectFcall.phpt | 16 +++++++++++++++- Zend/zend_language_parser.y | 12 +++++++++--- Zend/zend_vm_def.h | 4 ++-- Zend/zend_vm_execute.h | 16 ++++++++-------- 4 files changed, 34 insertions(+), 14 deletions(-) diff --git a/Zend/tests/varSyntax/indirectFcall.phpt b/Zend/tests/varSyntax/indirectFcall.phpt index e42376a89b..4499f5ab64 100644 --- a/Zend/tests/varSyntax/indirectFcall.phpt +++ b/Zend/tests/varSyntax/indirectFcall.phpt @@ -13,7 +13,17 @@ id('id')('id')('var_dump')(3); id()()('var_dump')(4); id(['udef', 'id'])[1]()('var_dump')(5); -// (id((object) ['a' => 'id', 'b' => 'udef'])->a)(); +(id((object) ['a' => 'id', 'b' => 'udef'])->a)()()()()('var_dump')(6); + +$id = function($x) { return $x; }; + +$id($id)('var_dump')(7); + +(function($x) { return $x; })('id')('var_dump')(8); + +($f = function($x = null) use (&$f) { + return $x ?: $f; +})()()()('var_dump')(9); ?> --EXPECT-- @@ -23,3 +33,7 @@ int(2) int(3) int(4) int(5) +int(6) +int(7) +int(8) +int(9) diff --git a/Zend/zend_language_parser.y b/Zend/zend_language_parser.y index 4473e3771d..d6b0f874c3 100644 --- a/Zend/zend_language_parser.y +++ b/Zend/zend_language_parser.y @@ -870,7 +870,7 @@ function_call: function_call_parameter_list { zend_do_end_function_call(NULL, &$$, 1, 1 TSRMLS_CC); zend_do_extended_fcall_end(TSRMLS_C);} | variable_class_name T_PAAMAYIM_NEKUDOTAYIM simple_variable { fetch_simple_variable_ex(&$$, &$3, 0, ZEND_FETCH_R TSRMLS_CC); zend_do_begin_class_member_function_call(&$1, &$$ TSRMLS_CC); } function_call_parameter_list { zend_do_end_function_call(NULL, &$$, 1, 1 TSRMLS_CC); zend_do_extended_fcall_end(TSRMLS_C);} - | directly_callable_variable { zend_do_end_variable_parse(&$1, BP_VAR_R, 0 TSRMLS_CC); zend_do_begin_dynamic_function_call(&$1, 0 TSRMLS_CC); } + | callable_expr { zend_do_begin_dynamic_function_call(&$1, 0 TSRMLS_CC); } function_call_parameter_list { zend_do_end_function_call(&$1, &$$, 0, 1 TSRMLS_CC); zend_do_extended_fcall_end(TSRMLS_C);} ; @@ -1068,7 +1068,13 @@ dereferencable: | dereferencable_scalar { $$ = $1; zend_do_begin_variable_parse(TSRMLS_C); } ; -directly_callable_variable: +callable_expr: + callable_variable { zend_do_end_variable_parse(&$1, BP_VAR_R, 0 TSRMLS_CC); $$ = $1; } + | '(' expr ')' { $$ = $2; } + | dereferencable_scalar { $$ = $1; } +; + +callable_variable: simple_variable { zend_do_begin_variable_parse(TSRMLS_C); fetch_simple_variable(&$$, &$1, 1 TSRMLS_CC); @@ -1090,7 +1096,7 @@ directly_callable_variable: ; variable: - directly_callable_variable { $$ = $1; } + callable_variable { $$ = $1; } | static_member { $$ = $1; $$.EA = ZEND_PARSED_STATIC_MEMBER; } | dereferencable T_OBJECT_OPERATOR object_member { zend_do_fetch_property(&$$, &$1, &$3 TSRMLS_CC); $$.EA = ZEND_PARSED_MEMBER; } diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h index 0b5dde1599..20d350a892 100644 --- a/Zend/zend_vm_def.h +++ b/Zend/zend_vm_def.h @@ -2646,7 +2646,7 @@ ZEND_VM_HANDLER(59, ZEND_INIT_FCALL_BY_NAME, ANY, CONST|TMP|VAR|CV) CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); - } else if (OP2_TYPE != IS_CONST && OP2_TYPE != IS_TMP_VAR && + } else if (OP2_TYPE != IS_CONST && EXPECTED(Z_TYPE_P(function_name) == IS_OBJECT) && Z_OBJ_HANDLER_P(function_name, get_closure) && Z_OBJ_HANDLER_P(function_name, get_closure)(function_name, &call->called_scope, &call->fbc, &call->object TSRMLS_CC) == SUCCESS) { @@ -2657,7 +2657,7 @@ ZEND_VM_HANDLER(59, ZEND_INIT_FCALL_BY_NAME, ANY, CONST|TMP|VAR|CV) call->fbc->common.fn_flags & ZEND_ACC_CLOSURE) { /* Delay closure destruction until its invocation */ call->fbc->common.prototype = (zend_function*)function_name_ptr; - } else { + } else if (OP2_TYPE == IS_CV) { FREE_OP2(); } diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h index a5b678c9d2..c2e103965a 100644 --- a/Zend/zend_vm_execute.h +++ b/Zend/zend_vm_execute.h @@ -1515,7 +1515,7 @@ static int ZEND_FASTCALL ZEND_INIT_FCALL_BY_NAME_SPEC_CONST_HANDLER(ZEND_OPCODE CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); - } else if (IS_CONST != IS_CONST && IS_CONST != IS_TMP_VAR && + } else if (IS_CONST != IS_CONST && EXPECTED(Z_TYPE_P(function_name) == IS_OBJECT) && Z_OBJ_HANDLER_P(function_name, get_closure) && Z_OBJ_HANDLER_P(function_name, get_closure)(function_name, &call->called_scope, &call->fbc, &call->object TSRMLS_CC) == SUCCESS) { @@ -1526,7 +1526,7 @@ static int ZEND_FASTCALL ZEND_INIT_FCALL_BY_NAME_SPEC_CONST_HANDLER(ZEND_OPCODE call->fbc->common.fn_flags & ZEND_ACC_CLOSURE) { /* Delay closure destruction until its invocation */ call->fbc->common.prototype = (zend_function*)function_name_ptr; - } else { + } else if (IS_CONST == IS_CV) { } @@ -1846,7 +1846,7 @@ static int ZEND_FASTCALL ZEND_INIT_FCALL_BY_NAME_SPEC_TMP_HANDLER(ZEND_OPCODE_H CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); - } else if (IS_TMP_VAR != IS_CONST && IS_TMP_VAR != IS_TMP_VAR && + } else if (IS_TMP_VAR != IS_CONST && EXPECTED(Z_TYPE_P(function_name) == IS_OBJECT) && Z_OBJ_HANDLER_P(function_name, get_closure) && Z_OBJ_HANDLER_P(function_name, get_closure)(function_name, &call->called_scope, &call->fbc, &call->object TSRMLS_CC) == SUCCESS) { @@ -1857,7 +1857,7 @@ static int ZEND_FASTCALL ZEND_INIT_FCALL_BY_NAME_SPEC_TMP_HANDLER(ZEND_OPCODE_H call->fbc->common.fn_flags & ZEND_ACC_CLOSURE) { /* Delay closure destruction until its invocation */ call->fbc->common.prototype = (zend_function*)function_name_ptr; - } else { + } else if (IS_TMP_VAR == IS_CV) { zval_dtor(free_op2.var); } @@ -2035,7 +2035,7 @@ static int ZEND_FASTCALL ZEND_INIT_FCALL_BY_NAME_SPEC_VAR_HANDLER(ZEND_OPCODE_H CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); - } else if (IS_VAR != IS_CONST && IS_VAR != IS_TMP_VAR && + } else if (IS_VAR != IS_CONST && EXPECTED(Z_TYPE_P(function_name) == IS_OBJECT) && Z_OBJ_HANDLER_P(function_name, get_closure) && Z_OBJ_HANDLER_P(function_name, get_closure)(function_name, &call->called_scope, &call->fbc, &call->object TSRMLS_CC) == SUCCESS) { @@ -2046,7 +2046,7 @@ static int ZEND_FASTCALL ZEND_INIT_FCALL_BY_NAME_SPEC_VAR_HANDLER(ZEND_OPCODE_H call->fbc->common.fn_flags & ZEND_ACC_CLOSURE) { /* Delay closure destruction until its invocation */ call->fbc->common.prototype = (zend_function*)function_name_ptr; - } else { + } else if (IS_VAR == IS_CV) { zval_ptr_dtor_nogc(free_op2.var); } @@ -2261,7 +2261,7 @@ static int ZEND_FASTCALL ZEND_INIT_FCALL_BY_NAME_SPEC_CV_HANDLER(ZEND_OPCODE_HA CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); - } else if (IS_CV != IS_CONST && IS_CV != IS_TMP_VAR && + } else if (IS_CV != IS_CONST && EXPECTED(Z_TYPE_P(function_name) == IS_OBJECT) && Z_OBJ_HANDLER_P(function_name, get_closure) && Z_OBJ_HANDLER_P(function_name, get_closure)(function_name, &call->called_scope, &call->fbc, &call->object TSRMLS_CC) == SUCCESS) { @@ -2272,7 +2272,7 @@ static int ZEND_FASTCALL ZEND_INIT_FCALL_BY_NAME_SPEC_CV_HANDLER(ZEND_OPCODE_HA call->fbc->common.fn_flags & ZEND_ACC_CLOSURE) { /* Delay closure destruction until its invocation */ call->fbc->common.prototype = (zend_function*)function_name_ptr; - } else { + } else if (IS_CV == IS_CV) { } -- 2.50.1