]> granicus.if.org Git - php/commitdiff
Support directly calling closure
authorNikita Popov <nikic@php.net>
Sat, 31 May 2014 15:18:37 +0000 (17:18 +0200)
committerNikita Popov <nikic@php.net>
Sat, 31 May 2014 15:18:37 +0000 (17:18 +0200)
Zend/tests/varSyntax/indirectFcall.phpt
Zend/zend_language_parser.y
Zend/zend_vm_def.h
Zend/zend_vm_execute.h

index e42376a89b7051cce143293374411b0c9229c74c..4499f5ab641d1dff3c8716acd1ef82be1cf6fc46 100644 (file)
@@ -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)
index 4473e3771d37a1e878c86b25ef51fb15fcd1793e..d6b0f874c3588abfb9146c70fdff05c2cb828820 100644 (file)
@@ -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; }
index 0b5dde159922ae2bb5163ad2bec355f65587d621..20d350a892387e4d5f832a2d601f9dfdcfaa5d90 100644 (file)
@@ -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();
                        }
 
index a5b678c9d247bcfe886a34922a4bd215b15bad8f..c2e103965a48efb7de3a700b4b6460861428020b 100644 (file)
@@ -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) {
 
                        }