From acfbbd059b2f653bb88c48763b65485b5dc75b54 Mon Sep 17 00:00:00 2001 From: Andres Gutierrez Date: Wed, 1 Apr 2015 11:00:36 -0500 Subject: [PATCH] Initiali support to call dynamic methods in static calls --- Library/Compiler.php | 2 +- ext/kernel/extended/fcall.c | 18 ++++++++++++------ parser/parser.lemon | 32 +++++++++++++++++++++----------- test/scalldynamic.zep | 29 +++++++++++++++++++++++++++++ 4 files changed, 63 insertions(+), 18 deletions(-) create mode 100644 test/scalldynamic.zep diff --git a/Library/Compiler.php b/Library/Compiler.php index c446965cee..9c62a12822 100755 --- a/Library/Compiler.php +++ b/Library/Compiler.php @@ -30,7 +30,7 @@ */ class Compiler { - const VERSION = '0.6.0a'; + const VERSION = '0.6.1a'; /** * @var CompilerFile[] diff --git a/ext/kernel/extended/fcall.c b/ext/kernel/extended/fcall.c index 41e408de8c..2c32baa575 100644 --- a/ext/kernel/extended/fcall.c +++ b/ext/kernel/extended/fcall.c @@ -583,6 +583,7 @@ static zend_bool zephir_is_callable_ex(zval *callable, zval *object_ptr, uint ch static zend_bool zephir_is_info_dynamic_callable(zephir_fcall_info *info, zend_fcall_info_cache *fcc, zend_class_entry *ce_org, int strict_class TSRMLS_DC) { int call_via_handler = 0; + char *lcname = zend_str_tolower_dup(info->func_name, info->func_length); if (fcc->object_ptr && fcc->calling_scope == ce_org) { if (strict_class && ce_org->__call) { @@ -594,11 +595,12 @@ static zend_bool zephir_is_info_dynamic_callable(zephir_fcall_info *info, zend_f fcc->function_handler->internal_function.num_args = 0; fcc->function_handler->internal_function.scope = ce_org; fcc->function_handler->internal_function.fn_flags = ZEND_ACC_CALL_VIA_HANDLER; - fcc->function_handler->internal_function.function_name = estrndup(info->func_name, info->func_length); + fcc->function_handler->internal_function.function_name = estrndup(lcname, info->func_length); call_via_handler = 1; + efree(lcname); return 1; } else if (Z_OBJ_HT_P(fcc->object_ptr)->get_method) { - fcc->function_handler = Z_OBJ_HT_P(fcc->object_ptr)->get_method(&fcc->object_ptr, (char *)info->func_name, info->func_length, NULL TSRMLS_CC); + fcc->function_handler = Z_OBJ_HT_P(fcc->object_ptr)->get_method(&fcc->object_ptr, lcname, info->func_length, NULL TSRMLS_CC); if (fcc->function_handler) { if (strict_class && (!fcc->function_handler->common.scope || @@ -611,15 +613,16 @@ static zend_bool zephir_is_info_dynamic_callable(zephir_fcall_info *info, zend_f } } else { call_via_handler = (fcc->function_handler->common.fn_flags & ZEND_ACC_CALL_VIA_HANDLER) != 0; + efree(lcname); return 1; } } } } else if (fcc->calling_scope) { if (fcc->calling_scope->get_static_method) { - fcc->function_handler = fcc->calling_scope->get_static_method(fcc->calling_scope, (char *)info->func_name, info->func_length TSRMLS_CC); + fcc->function_handler = fcc->calling_scope->get_static_method(fcc->calling_scope, lcname, info->func_length TSRMLS_CC); } else { - fcc->function_handler = zend_std_get_static_method(fcc->calling_scope, info->func_name, info->func_length, NULL TSRMLS_CC); + fcc->function_handler = zend_std_get_static_method(fcc->calling_scope, lcname, info->func_length, NULL TSRMLS_CC); } if (fcc->function_handler) { call_via_handler = (fcc->function_handler->common.fn_flags & ZEND_ACC_CALL_VIA_HANDLER) != 0; @@ -628,10 +631,12 @@ static zend_bool zephir_is_info_dynamic_callable(zephir_fcall_info *info, zend_f instanceof_function(Z_OBJCE_P(EG(This)), fcc->calling_scope TSRMLS_CC)) { fcc->object_ptr = EG(This); } + efree(lcname); return 1; } } + efree(lcname); return 0; } @@ -804,9 +809,10 @@ static zend_bool zephir_is_info_callable_ex(zephir_fcall_info *info, zend_fcall_ } return 1; } - } - return zephir_is_info_dynamic_callable(info, fcc, ce_org, 1 TSRMLS_DC); + return zephir_is_info_dynamic_callable(info, fcc, ce_org, 1 TSRMLS_DC); + } + break; } return 0; diff --git a/parser/parser.lemon b/parser/parser.lemon index 977c23d33b..69a2a29111 100644 --- a/parser/parser.lemon +++ b/parser/parser.lemon @@ -2956,16 +2956,16 @@ xx_fcall_expr(R) ::= BRACKET_OPEN IDENTIFIER(I) BRACKET_CLOSE PARENTHESES_OPEN P R = xx_ret_fcall(2, I, NULL, status->scanner_state); } -/* o::m(false, x) */ -xx_scall_expr(R) ::= IDENTIFIER(O) DOUBLECOLON IDENTIFIER(M) PARENTHESES_OPEN xx_call_parameters(P) PARENTHESES_CLOSE . { - R = xx_ret_scall(0, O->token, 0, M, P, status->scanner_state); -} - /* o::m() */ xx_scall_expr(R) ::= IDENTIFIER(O) DOUBLECOLON IDENTIFIER(M) PARENTHESES_OPEN PARENTHESES_CLOSE . { R = xx_ret_scall(0, O->token, 0, M, NULL, status->scanner_state); } +/* o::m(false, x) */ +xx_scall_expr(R) ::= IDENTIFIER(O) DOUBLECOLON IDENTIFIER(M) PARENTHESES_OPEN xx_call_parameters(P) PARENTHESES_CLOSE . { + R = xx_ret_scall(0, O->token, 0, M, P, status->scanner_state); +} + /* static::m(false, x) */ xx_scall_expr(R) ::= STATIC DOUBLECOLON IDENTIFIER(M) PARENTHESES_OPEN xx_call_parameters(P) PARENTHESES_CLOSE . { R = xx_ret_scall(0, "static", 0, M, P, status->scanner_state); @@ -2976,14 +2976,19 @@ xx_scall_expr(R) ::= STATIC DOUBLECOLON IDENTIFIER(M) PARENTHESES_OPEN PARENTHES R = xx_ret_scall(0, "static", 0, M, NULL, status->scanner_state); } +/* {o}::m() */ +xx_scall_expr(R) ::= BRACKET_OPEN IDENTIFIER(O) BRACKET_CLOSE DOUBLECOLON IDENTIFIER(M) PARENTHESES_OPEN PARENTHESES_CLOSE . { + R = xx_ret_scall(1, O->token, 0, M, NULL, status->scanner_state); +} + /* {o}::m(false, x) */ xx_scall_expr(R) ::= BRACKET_OPEN IDENTIFIER(O) BRACKET_CLOSE DOUBLECOLON IDENTIFIER(M) PARENTHESES_OPEN xx_call_parameters(P) PARENTHESES_CLOSE . { R = xx_ret_scall(1, O->token, 0, M, P, status->scanner_state); } -/* {o}::m() */ -xx_scall_expr(R) ::= BRACKET_OPEN IDENTIFIER(O) BRACKET_CLOSE DOUBLECOLON IDENTIFIER(M) PARENTHESES_OPEN PARENTHESES_CLOSE . { - R = xx_ret_scall(1, O->token, 0, M, NULL, status->scanner_state); +/* {o}::{m}() */ +xx_scall_expr(R) ::= BRACKET_OPEN IDENTIFIER(O) BRACKET_CLOSE DOUBLECOLON BRACKET_OPEN IDENTIFIER(M) BRACKET_CLOSE PARENTHESES_OPEN PARENTHESES_CLOSE . { + R = xx_ret_scall(1, O->token, 1, M, NULL, status->scanner_state); } /* {o}::{m}(false, x) */ @@ -2991,9 +2996,14 @@ xx_scall_expr(R) ::= BRACKET_OPEN IDENTIFIER(O) BRACKET_CLOSE DOUBLECOLON BRACKE R = xx_ret_scall(1, O->token, 1, M, P, status->scanner_state); } -/* {o}::{m}() */ -xx_scall_expr(R) ::= BRACKET_OPEN IDENTIFIER(O) BRACKET_CLOSE DOUBLECOLON BRACKET_OPEN IDENTIFIER(M) BRACKET_CLOSE PARENTHESES_OPEN PARENTHESES_CLOSE . { - R = xx_ret_scall(1, O->token, 1, M, NULL, status->scanner_state); +/* o::{m}() */ +xx_scall_expr(R) ::= IDENTIFIER(O) DOUBLECOLON BRACKET_OPEN IDENTIFIER(M) BRACKET_CLOSE PARENTHESES_OPEN PARENTHESES_CLOSE . { + R = xx_ret_scall(0, O, 1, M, NULL, status->scanner_state); +} + +/* o::{m}(false, x) */ +xx_scall_expr(R) ::= IDENTIFIER(O) DOUBLECOLON BRACKET_OPEN IDENTIFIER(M) BRACKET_CLOSE PARENTHESES_OPEN xx_call_parameters(P) PARENTHESES_CLOSE . { + R = xx_ret_scall(0, O, 1, M, P, status->scanner_state); } /* o->m(false, x) */ diff --git a/test/scalldynamic.zep b/test/scalldynamic.zep new file mode 100644 index 0000000000..490614071d --- /dev/null +++ b/test/scalldynamic.zep @@ -0,0 +1,29 @@ +/** + * Static Function calls + */ + +namespace Test; + +class ScallDynamic extends ScallParent +{ + + static public function testMethod1() + { + return "hello public"; + } + + static protected function testMethod2() + { + return "hello protected"; + } + + static private function testMethod3() + { + return "hello private"; + } + + static public function selfDynamicCall1(var methodName) + { + //return self::{methodName}(); + } +}