Index: Zend/zend_API.c =================================================================== RCS file: /repository/ZendEngine2/zend_API.c,v retrieving revision 1.296.2.27.2.34.2.64 diff -u -p -a -d -u -r1.296.2.27.2.34.2.64 zend_API.c --- Zend/zend_API.c 4 Jun 2009 18:20:42 -0000 1.296.2.27.2.34.2.64 +++ Zend/zend_API.c 4 Jul 2009 17:20:50 -0000 @@ -198,10 +198,13 @@ ZEND_API char *zend_get_type_by_const(in { switch(type) { case IS_BOOL: + case FORCE_BOOL: return "boolean"; case IS_LONG: + case FORCE_LONG: return "integer"; case IS_DOUBLE: + case FORCE_DOUBLE: return "double"; case IS_STRING: return "string"; @@ -212,7 +215,12 @@ ZEND_API char *zend_get_type_by_const(in case IS_NULL: return "null"; case IS_ARRAY: + case FORCE_ARRAY: return "array"; + case IS_SCALAR: + return "scalar"; + case IS_NUMERIC: + return "numeric"; default: return "unknown"; } Index: Zend/zend_API.h =================================================================== RCS file: /repository/ZendEngine2/zend_API.h,v retrieving revision 1.207.2.8.2.8.2.24 diff -u -p -a -d -u -r1.207.2.8.2.8.2.24 zend_API.h --- Zend/zend_API.h 31 Dec 2008 11:15:31 -0000 1.207.2.8.2.8.2.24 +++ Zend/zend_API.h 4 Jul 2009 17:20:50 -0000 @@ -98,8 +98,8 @@ typedef struct _zend_fcall_info_cache { #define ZEND_ARG_INFO(pass_by_ref, name) { #name, sizeof(#name)-1, NULL, 0, 0, 0, pass_by_ref, 0, 0 }, #define ZEND_ARG_PASS_INFO(pass_by_ref) { NULL, 0, NULL, 0, 0, 0, pass_by_ref, 0, 0 }, -#define ZEND_ARG_OBJ_INFO(pass_by_ref, name, classname, allow_null) { #name, sizeof(#name)-1, #classname, sizeof(#classname)-1, 0, allow_null, pass_by_ref, 0, 0 }, -#define ZEND_ARG_ARRAY_INFO(pass_by_ref, name, allow_null) { #name, sizeof(#name)-1, NULL, 0, 1, allow_null, pass_by_ref, 0, 0 }, +#define ZEND_ARG_OBJ_INFO(pass_by_ref, name, classname, allow_null) { #name, sizeof(#name)-1, #classname, sizeof(#classname)-1, IS_CLASS, allow_null, pass_by_ref, 0, 0 }, +#define ZEND_ARG_ARRAY_INFO(pass_by_ref, name, allow_null) { #name, sizeof(#name)-1, NULL, 0, IS_ARRAY, allow_null, pass_by_ref, 0, 0 }, #define ZEND_BEGIN_ARG_INFO_EX(name, pass_rest_by_reference, return_reference, required_num_args) \ static const zend_arg_info name[] = { \ { NULL, 0, NULL, 0, 0, 0, pass_rest_by_reference, return_reference, required_num_args }, Index: Zend/zend_compile.c =================================================================== RCS file: /repository/ZendEngine2/zend_compile.c,v retrieving revision 1.647.2.27.2.41.2.109 diff -u -p -a -d -u -r1.647.2.27.2.41.2.109 zend_compile.c --- Zend/zend_compile.c 7 Jun 2009 15:46:51 -0000 1.647.2.27.2.41.2.109 +++ Zend/zend_compile.c 4 Jul 2009 17:20:50 -0000 @@ -1498,7 +1498,10 @@ void zend_do_receive_arg(zend_uchar op, if (class_type->op_type != IS_UNUSED) { cur_arg_info->allow_null = 0; - if (class_type->u.constant.type == IS_STRING) { + cur_arg_info->array_type_hint = class_type->u.constant.type; + + switch (class_type->u.constant.type) { + case IS_CLASS: if (ZEND_FETCH_CLASS_DEFAULT == zend_get_class_fetch_type(Z_STRVAL(class_type->u.constant), Z_STRLEN(class_type->u.constant))) { zend_resolve_class_name(class_type, &opline->extended_value, 1 TSRMLS_CC); } @@ -1511,10 +1514,9 @@ void zend_do_receive_arg(zend_uchar op, zend_error(E_COMPILE_ERROR, "Default value for parameters with a class type hint can only be NULL"); } } - } else { - cur_arg_info->array_type_hint = 1; - cur_arg_info->class_name = NULL; - cur_arg_info->class_name_len = 0; + break; + + case IS_ARRAY: if (op == ZEND_RECV_INIT) { if (Z_TYPE(initialization->u.constant) == IS_NULL || (Z_TYPE(initialization->u.constant) == IS_CONSTANT && !strcasecmp(Z_STRVAL(initialization->u.constant), "NULL"))) { cur_arg_info->allow_null = 1; @@ -1522,6 +1524,56 @@ void zend_do_receive_arg(zend_uchar op, zend_error(E_COMPILE_ERROR, "Default value for parameters with array type hint can only be an array or NULL"); } } + break; + + /* scalar type hinting */ + case IS_BOOL: + case IS_STRING: + case IS_LONG: + case IS_DOUBLE: + case IS_RESOURCE: + case IS_NUMERIC: + case IS_SCALAR: + case IS_OBJECT: + if (op == ZEND_RECV_INIT) { + if (Z_TYPE(initialization->u.constant) != class_type->u.constant.type && Z_TYPE(initialization->u.constant) != IS_NULL) { + zend_error(E_COMPILE_ERROR, "Default value for parameters with %s type hint can only be %s or NULL", zend_get_type_by_const(class_type->u.constant.type), zend_get_type_by_const(class_type->u.constant.type)); + } else if (Z_TYPE(initialization->u.constant) == IS_NULL) { + cur_arg_info->allow_null = 1; + } + } + break; + + /* type forcing via cast */ + case FORCE_BOOL: + case FORCE_STRING: + case FORCE_LONG: + case FORCE_DOUBLE: + if (op == ZEND_RECV_INIT) { + switch (Z_TYPE(initialization->u.constant)) { + case IS_ARRAY: + case IS_OBJECT: + case IS_RESOURCE: + zend_error(E_COMPILE_ERROR, "Default value for parameters with a forced type of %s can only be a scalar", zend_get_type_by_const(class_type->u.constant.type)); + break; + case IS_NULL: + cur_arg_info->allow_null = 1; + break; + } + } + break; + case FORCE_ARRAY: + if (op == ZEND_RECV_INIT) { + if (Z_TYPE(initialization->u.constant) == IS_NULL) { + cur_arg_info->allow_null = 1; + } else if (Z_TYPE(initialization->u.constant) != IS_ARRAY && Z_TYPE(initialization->u.constant) != IS_CONSTANT_ARRAY) { + zend_error(E_COMPILE_ERROR, "Default value for parameters with a forced array type can only be of type array"); + } + } + break; + + default: + zend_error(E_COMPILE_ERROR, "Unkown type hint"); } } opline->result.u.EA.type |= EXT_TYPE_UNUSED; @@ -2542,7 +2594,7 @@ static zend_bool zend_do_perform_impleme } } if (fe->common.arg_info[i].array_type_hint != proto->common.arg_info[i].array_type_hint) { - /* Only one has an array type hint and the other one doesn't */ + /* Incompatible type hint */ return 0; } if (fe->common.arg_info[i].pass_by_reference != proto->common.arg_info[i].pass_by_reference) { Index: Zend/zend_execute.c =================================================================== RCS file: /repository/ZendEngine2/zend_execute.c,v retrieving revision 1.716.2.12.2.24.2.44 diff -u -p -a -d -u -r1.716.2.12.2.24.2.44 zend_execute.c --- Zend/zend_execute.c 4 Jun 2009 18:20:42 -0000 1.716.2.12.2.24.2.44 +++ Zend/zend_execute.c 4 Jul 2009 17:20:50 -0000 @@ -506,13 +506,82 @@ static inline int zend_verify_arg_type(z } } else if (cur_arg_info->array_type_hint) { if (!arg) { - return zend_verify_arg_error(zf, arg_num, cur_arg_info, "be an array", "", "none", "" TSRMLS_CC); + return zend_verify_arg_error(zf, arg_num, cur_arg_info, "be of the type ", zend_get_type_by_const(cur_arg_info->array_type_hint), "none", "" TSRMLS_CC); } - if (Z_TYPE_P(arg) != IS_ARRAY && (Z_TYPE_P(arg) != IS_NULL || !cur_arg_info->allow_null)) { - return zend_verify_arg_error(zf, arg_num, cur_arg_info, "be an array", "", zend_zval_type_name(arg), "" TSRMLS_CC); + + /* existing type already matches the hint or forced type */ + if (Z_TYPE_P(arg) == cur_arg_info->array_type_hint || Z_TYPE_P(arg) == (cur_arg_info->array_type_hint ^ (1<<7))) { + return 1; + } + + /* NULL type give, check if parameter is optional */ + if (Z_TYPE_P(arg) == IS_NULL) { + if (!cur_arg_info->allow_null) { + goto type_error; + } else { + return 1; + } + } + + switch (cur_arg_info->array_type_hint) { + case IS_SCALAR: + switch (Z_TYPE_P(arg)) { + case IS_STRING: + case IS_BOOL: + case IS_LONG: + case IS_DOUBLE: + return 1; + default: + goto type_error; + } + break; + + case IS_NUMERIC: + switch (Z_TYPE_P(arg)) { + case IS_STRING: + if (is_numeric_string(Z_STRVAL_P(arg), Z_STRLEN_P(arg), NULL, NULL, 0)) { + return 1; + } else { + goto type_error; + } + break; + case IS_BOOL: + case IS_LONG: + case IS_DOUBLE: + return 1; + default: + goto type_error; + } + break; + + case FORCE_BOOL: + convert_to_boolean(arg); + break; + + case FORCE_STRING: + convert_to_string(arg); + break; + + case FORCE_LONG: + convert_to_long(arg); + break; + + case FORCE_DOUBLE: + convert_to_double(arg); + break; + + case FORCE_ARRAY: + convert_to_array(arg); + break; + + default: + goto type_error; } } return 1; + +type_error: + return zend_verify_arg_error(zf, arg_num, cur_arg_info, "be of the type ", zend_get_type_by_const(cur_arg_info->array_type_hint), "", zend_zval_type_name(arg) TSRMLS_CC); } static inline void zend_assign_to_object(znode *result, zval **object_ptr, zval *property_name, znode *value_op, const temp_variable *Ts, int opcode TSRMLS_DC) Index: Zend/zend.h =================================================================== RCS file: /repository/ZendEngine2/zend.h,v retrieving revision 1.293.2.11.2.9.2.37 diff -u -p -a -d -u -r1.293.2.11.2.9.2.37 zend.h --- Zend/zend.h 17 Jun 2009 08:55:23 -0000 1.293.2.11.2.9.2.37 +++ Zend/zend.h 4 Jul 2009 17:20:50 -0000 @@ -536,6 +536,16 @@ typedef int (*zend_write_func_t)(const c #define IS_RESOURCE 7 #define IS_CONSTANT 8 #define IS_CONSTANT_ARRAY 9 +/* used for type-hinting only */ +#define IS_NUMERIC 10 +#define IS_SCALAR 11 +#define IS_CLASS 12 +/* used for forcing method/function parameter type */ +#define FORCE_BOOL (IS_BOOL | (1<<7)) +#define FORCE_STRING (IS_STRING | (1<<7)) +#define FORCE_LONG (IS_LONG | (1<<7)) +#define FORCE_DOUBLE (IS_DOUBLE | (1<<7)) +#define FORCE_ARRAY (IS_ARRAY | (1<<7)) /* Ugly hack to support constants as static array indices */ #define IS_CONSTANT_TYPE_MASK 0x0f Index: Zend/zend_language_parser.y =================================================================== RCS file: /repository/ZendEngine2/zend_language_parser.y,v retrieving revision 1.160.2.4.2.8.2.35 diff -u -p -a -d -u -r1.160.2.4.2.8.2.35 zend_language_parser.y --- Zend/zend_language_parser.y 26 Mar 2009 12:37:17 -0000 1.160.2.4.2.8.2.35 +++ Zend/zend_language_parser.y 4 Jul 2009 17:20:50 -0000 @@ -128,6 +128,14 @@ %token T_DOUBLE_ARROW %token T_LIST %token T_ARRAY +%token T_BOOL_HINT +%token T_STRING_HINT +%token T_INT_HINT +%token T_DOUBLE_HINT +%token T_RESOURCE_HINT +%token T_NUMERIC_HINT +%token T_SCALAR_HINT +%token T_OBJECT_HINT %token T_CLASS_C %token T_METHOD_C %token T_FUNC_C @@ -463,8 +471,21 @@ non_empty_parameter_list: optional_class_type: /* empty */ { $$.op_type = IS_UNUSED; } - | fully_qualified_class_name { $$ = $1; } - | T_ARRAY { $$.op_type = IS_CONST; Z_TYPE($$.u.constant)=IS_NULL;} + | T_ARRAY { $$.op_type = IS_CONST; Z_TYPE($$.u.constant)=IS_ARRAY; } + | T_BOOL_HINT { $$.op_type = IS_CONST; Z_TYPE($$.u.constant)=IS_BOOL; } + | T_STRING_HINT { $$.op_type = IS_CONST; Z_TYPE($$.u.constant)=IS_STRING; } + | T_INT_HINT { $$.op_type = IS_CONST; Z_TYPE($$.u.constant)=IS_LONG; } + | T_DOUBLE_HINT { $$.op_type = IS_CONST; Z_TYPE($$.u.constant)=IS_DOUBLE; } + | T_RESOURCE_HINT { $$.op_type = IS_CONST; Z_TYPE($$.u.constant)=IS_RESOURCE; } + | T_NUMERIC_HINT { $$.op_type = IS_CONST; Z_TYPE($$.u.constant)=IS_NUMERIC; } + | T_SCALAR_HINT { $$.op_type = IS_CONST; Z_TYPE($$.u.constant)=IS_SCALAR; } + | T_OBJECT_HINT { $$.op_type = IS_CONST; Z_TYPE($$.u.constant)=IS_OBJECT; } + | T_BOOL_CAST { $$.op_type = IS_CONST; Z_TYPE($$.u.constant)=FORCE_BOOL; } + | T_STRING_CAST { $$.op_type = IS_CONST; Z_TYPE($$.u.constant)=FORCE_STRING; } + | T_INT_CAST { $$.op_type = IS_CONST; Z_TYPE($$.u.constant)=FORCE_LONG; } + | T_DOUBLE_CAST { $$.op_type = IS_CONST; Z_TYPE($$.u.constant)=FORCE_DOUBLE; } + | T_ARRAY_CAST { $$.op_type = IS_CONST; Z_TYPE($$.u.constant)=FORCE_ARRAY; } + | fully_qualified_class_name { $$.op_type = IS_CONST; Z_TYPE($$.u.constant)=IS_CLASS; } ; @@ -661,10 +682,10 @@ 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); } - | T_VARIABLE { zend_do_fetch_lexical_variable(&$1, 0 TSRMLS_CC); } - | '&' T_VARIABLE { zend_do_fetch_lexical_variable(&$2, 1 TSRMLS_CC); } + 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); } + | T_VARIABLE { zend_do_fetch_lexical_variable(&$1, 0 TSRMLS_CC); } + | '&' T_VARIABLE { zend_do_fetch_lexical_variable(&$2, 1 TSRMLS_CC); } ; function_call: Index: Zend/zend_language_scanner.l =================================================================== RCS file: /repository/ZendEngine2/zend_language_scanner.l,v retrieving revision 1.131.2.11.2.13.2.40 diff -u -p -a -d -u -r1.131.2.11.2.13.2.40 zend_language_scanner.l --- Zend/zend_language_scanner.l 5 May 2009 01:35:44 -0000 1.131.2.11.2.13.2.40 +++ Zend/zend_language_scanner.l 4 Jul 2009 17:20:50 -0000 @@ -1158,6 +1158,38 @@ NEWLINE ("\r"|"\n"|"\r\n") return T_ARRAY; } +("bool"|"boolean") { + return T_BOOL_HINT; +} + +("string"|"binary"|"unicode") { + return T_STRING_HINT; +} + +("int"|"integer"|"long") { + return T_INT_HINT; +} + +("real"|"double"|"float") { + return T_DOUBLE_HINT; +} + +"resource" { + return T_RESOURCE_HINT; +} + +"numeric" { + return T_NUMERIC_HINT; +} + +"scalar" { + return T_SCALAR_HINT; +} + +"object" { + return T_OBJECT_HINT; +} + "++" { return T_INC; } Index: ext/reflection/php_reflection.c =================================================================== RCS file: /repository/php-src/ext/reflection/php_reflection.c,v retrieving revision 1.164.2.33.2.45.2.61 diff -u -p -a -d -r1.164.2.33.2.45.2.61 php_reflection.c --- ext/reflection/php_reflection.c 1 Jul 2009 18:44:56 -0000 1.164.2.33.2.45.2.61 +++ ext/reflection/php_reflection.c 4 Jul 2009 18:05:50 -0000 @@ -679,7 +679,11 @@ static void _parameter_string(string *st string_printf(str, "or NULL "); } } else if (arg_info->array_type_hint) { - string_printf(str, "array "); + if (arg_info->array_type_hint & (1<<7)) { + string_printf(str, "forced to %s ", zend_get_type_by_const(arg_info->array_type_hint ^ (1<<7))); + } else { + string_printf(str, "%s ", zend_get_type_by_const(arg_info->array_type_hint)); + } if (arg_info->allow_null) { string_printf(str, "or NULL "); } @@ -2274,7 +2278,153 @@ ZEND_METHOD(reflection_parameter, isArra } GET_REFLECTION_OBJECT_PTR(param); - RETVAL_BOOL(param->arg_info->array_type_hint); + RETVAL_BOOL(param->arg_info->array_type_hint == IS_ARRAY); +} +/* }}} */ + +/* {{{ proto public bool ReflectionParameter::isInt() + Returns whether parameter MUST be a long */ +ZEND_METHOD(reflection_parameter, isInt) +{ + reflection_object *intern; + parameter_reference *param; + + GET_REFLECTION_OBJECT_PTR(param); + + RETVAL_BOOL(param->arg_info->array_type_hint == IS_LONG); +} +/* }}} */ + +/* {{{ proto public bool ReflectionParameter::isDouble() + Returns whether parameter MUST be a double */ +ZEND_METHOD(reflection_parameter, isDouble) +{ + reflection_object *intern; + parameter_reference *param; + + GET_REFLECTION_OBJECT_PTR(param); + + RETVAL_BOOL(param->arg_info->array_type_hint == IS_DOUBLE); +} +/* }}} */ + +/* {{{ proto public bool ReflectionParameter::isBool() + Returns whether parameter MUST be a boolean */ +ZEND_METHOD(reflection_parameter, isBool) +{ + reflection_object *intern; + parameter_reference *param; + + GET_REFLECTION_OBJECT_PTR(param); + + RETVAL_BOOL(param->arg_info->array_type_hint == IS_BOOL); +} +/* }}} */ + +/* {{{ proto public bool ReflectionParameter::isObject() + Returns whether parameter MUST be a boolean */ +ZEND_METHOD(reflection_parameter, isObject) +{ + reflection_object *intern; + parameter_reference *param; + + GET_REFLECTION_OBJECT_PTR(param); + + RETVAL_BOOL(param->arg_info->array_type_hint == IS_OBJECT); +} +/* }}} */ + +/* {{{ proto public bool ReflectionParameter::isString() + Returns whether parameter MUST be a string */ +ZEND_METHOD(reflection_parameter, isString) +{ + reflection_object *intern; + parameter_reference *param; + + GET_REFLECTION_OBJECT_PTR(param); + + RETVAL_BOOL(param->arg_info->array_type_hint == IS_STRING); +} +/* }}} */ + +/* {{{ proto public bool ReflectionParameter::isResource() + Returns whether parameter MUST be a resource */ +ZEND_METHOD(reflection_parameter, isResource) +{ + reflection_object *intern; + parameter_reference *param; + + GET_REFLECTION_OBJECT_PTR(param); + + RETVAL_BOOL(param->arg_info->array_type_hint == IS_RESOURCE); +} +/* }}} */ + +/* {{{ proto public bool ReflectionParameter::isForcedToString() + Returns whether parameter will be cast to a string */ +ZEND_METHOD(reflection_parameter, isForcedToString) +{ + reflection_object *intern; + parameter_reference *param; + + GET_REFLECTION_OBJECT_PTR(param); + + RETVAL_BOOL(param->arg_info->array_type_hint == FORCE_STRING); +} +/* }}} */ + +/* {{{ proto public bool ReflectionParameter::isForcedToArray() + Returns whether parameter will be cast to an array */ +ZEND_METHOD(reflection_parameter, isForcedToArray) +{ + reflection_object *intern; + parameter_reference *param; + + if (zend_parse_parameters_none() == FAILURE) { + return; + } + GET_REFLECTION_OBJECT_PTR(param); + + RETVAL_BOOL(param->arg_info->array_type_hint == FORCE_ARRAY); +} +/* }}} */ + +/* {{{ proto public bool ReflectionParameter::isForcedToInt() + Returns whether parameter will be cast to a long */ +ZEND_METHOD(reflection_parameter, isForcedToInt) +{ + reflection_object *intern; + parameter_reference *param; + + GET_REFLECTION_OBJECT_PTR(param); + + RETVAL_BOOL(param->arg_info->array_type_hint == FORCE_LONG); +} +/* }}} */ + +/* {{{ proto public bool ReflectionParameter::isForcedToDouble() + Returns whether parameter will be cast to a double */ +ZEND_METHOD(reflection_parameter, isForcedToDouble) +{ + reflection_object *intern; + parameter_reference *param; + + GET_REFLECTION_OBJECT_PTR(param); + + RETVAL_BOOL(param->arg_info->array_type_hint == FORCE_DOUBLE); +} +/* }}} */ + +/* {{{ proto public bool ReflectionParameter::isForcedToBool() + Returns whether parameter will be cast to a boolean */ +ZEND_METHOD(reflection_parameter, isForcedToBool) +{ + reflection_object *intern; + parameter_reference *param; + + GET_REFLECTION_OBJECT_PTR(param); + + RETVAL_BOOL(param->arg_info->array_type_hint == FORCE_BOOL); } /* }}} */ @@ -4500,7 +4650,7 @@ ZEND_METHOD(reflection_property, getValu *return_value= *member_p; zval_copy_ctor(return_value); INIT_PZVAL(return_value); - if (member_p != EG(uninitialized_zval_ptr)) { + if (member_p == EG(uninitialized_zval_ptr)) { zval_add_ref(&member_p); zval_ptr_dtor(&member_p); } @@ -4960,7 +5110,7 @@ ZEND_METHOD(reflection_extension, getDep } /* }}} */ -/* {{{ proto public void ReflectionExtension::info() U +/* {{{ proto public void ReflectionExtension::info() Prints phpinfo block for the extension */ ZEND_METHOD(reflection_extension, info) { @@ -5297,6 +5447,17 @@ static const zend_function_entry reflect ZEND_ME(reflection_parameter, getDeclaringClass, NULL, 0) ZEND_ME(reflection_parameter, getClass, NULL, 0) ZEND_ME(reflection_parameter, isArray, NULL, 0) + ZEND_ME(reflection_parameter, isInt, NULL, 0) + ZEND_ME(reflection_parameter, isDouble, NULL, 0) + ZEND_ME(reflection_parameter, isBool, NULL, 0) + ZEND_ME(reflection_parameter, isString, NULL, 0) + ZEND_ME(reflection_parameter, isObject, NULL, 0) + ZEND_ME(reflection_parameter, isResource, NULL, 0) + ZEND_ME(reflection_parameter, isForcedToArray, NULL, 0) + ZEND_ME(reflection_parameter, isForcedToInt, NULL, 0) + ZEND_ME(reflection_parameter, isForcedToDouble, NULL, 0) + ZEND_ME(reflection_parameter, isForcedToBool, NULL, 0) + ZEND_ME(reflection_parameter, isForcedToString, NULL, 0) ZEND_ME(reflection_parameter, allowsNull, NULL, 0) ZEND_ME(reflection_parameter, getPosition, NULL, 0) ZEND_ME(reflection_parameter, isOptional, NULL, 0)