Index: Zend/zend_API.h =================================================================== RCS file: /repository/ZendEngine2/zend_API.h,v retrieving revision 1.207.2.8.2.8.2.6 diff -u -r1.207.2.8.2.8.2.6 zend_API.h --- Zend/zend_API.h 31 Dec 2007 07:17:04 -0000 1.207.2.8.2.8.2.6 +++ Zend/zend_API.h 4 Jan 2008 15:22:11 -0000 @@ -69,7 +69,7 @@ #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_BEGIN_ARG_INFO_EX(name, pass_rest_by_reference, return_reference, required_num_args) \ const zend_arg_info name[] = { \ - { NULL, 0, NULL, 0, 0, 0, pass_rest_by_reference, return_reference, required_num_args }, + { NULL, 0, NULL, 0, 0, 0, pass_rest_by_reference, return_reference, required_num_args, 0, 0, 0 }, #define ZEND_BEGIN_ARG_INFO(name, pass_rest_by_reference) \ ZEND_BEGIN_ARG_INFO_EX(name, pass_rest_by_reference, ZEND_RETURN_VALUE, -1) #define ZEND_END_ARG_INFO() }; Index: Zend/zend_compile.c =================================================================== RCS file: /repository/ZendEngine2/zend_compile.c,v retrieving revision 1.647.2.27.2.41.2.35 diff -u -r1.647.2.27.2.41.2.35 zend_compile.c --- Zend/zend_compile.c 31 Dec 2007 07:17:04 -0000 1.647.2.27.2.41.2.35 +++ Zend/zend_compile.c 4 Jan 2008 15:22:11 -0000 @@ -1372,26 +1372,42 @@ cur_arg_info->pass_by_reference = pass_by_reference; cur_arg_info->class_name = NULL; cur_arg_info->class_name_len = 0; + cur_arg_info->scalar_type_hint = 0; + cur_arg_info->number_type_hint = 0; + cur_arg_info->type_hint = 0; if (class_type->op_type != IS_UNUSED) { - cur_arg_info->allow_null = 0; if (class_type->u.constant.type == IS_STRING) { - 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); - } - cur_arg_info->class_name = class_type->u.constant.value.str.val; - cur_arg_info->class_name_len = class_type->u.constant.value.str.len; - 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; - } else { - zend_error(E_COMPILE_ERROR, "Default value for parameters with a class type hint can only be NULL"); + if (strcasecmp("scalar", class_type->u.constant.value.str.val) == 0) { + cur_arg_info->scalar_type_hint = 1; + } else if (strcasecmp("num", class_type->u.constant.value.str.val) == 0) { + cur_arg_info->number_type_hint = 1; + } else if (strcasecmp("int", class_type->u.constant.value.str.val) == 0) { + cur_arg_info->type_hint = IS_LONG; + } else if (strcasecmp("float", class_type->u.constant.value.str.val) == 0) { + cur_arg_info->type_hint = IS_DOUBLE; + } else if (strcasecmp("string", class_type->u.constant.value.str.val) == 0) { + cur_arg_info->type_hint = IS_STRING; + } else if (strcasecmp("bool", class_type->u.constant.value.str.val) == 0) { + cur_arg_info->type_hint = IS_BOOL; + } else if (strcasecmp("object", class_type->u.constant.value.str.val) == 0) { + cur_arg_info->type_hint = IS_OBJECT; + } else if (strcasecmp("resource", class_type->u.constant.value.str.val) == 0) { + cur_arg_info->type_hint = IS_RESOURCE; + } else if (strcasecmp("mixed", class_type->u.constant.value.str.val) != 0) { + zend_resolve_class_name(class_type, &opline->extended_value, 1 TSRMLS_CC); + cur_arg_info->class_name = class_type->u.constant.value.str.val; + cur_arg_info->class_name_len = class_type->u.constant.value.str.len; + 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; + } else { + 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; 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; @@ -2311,6 +2327,16 @@ /* Only one has an array type hint and the other one doesn't */ return 0; } + if (fe->common.arg_info[i].scalar_type_hint != proto->common.arg_info[i].scalar_type_hint) { + return 0; + } + if (fe->common.arg_info[i].number_type_hint != proto->common.arg_info[i].number_type_hint) { + return 0; + } + if (fe->common.arg_info[i].type_hint != proto->common.arg_info[i].type_hint) { + return 0; + } + if (fe->common.arg_info[i].pass_by_reference != proto->common.arg_info[i].pass_by_reference) { return 0; } Index: Zend/zend_compile.h =================================================================== RCS file: /repository/ZendEngine2/zend_compile.h,v retrieving revision 1.316.2.8.2.12.2.12 diff -u -r1.316.2.8.2.12.2.12 zend_compile.h --- Zend/zend_compile.h 31 Dec 2007 07:17:04 -0000 1.316.2.8.2.12.2.12 +++ Zend/zend_compile.h 4 Jan 2008 15:22:11 -0000 @@ -167,6 +167,9 @@ zend_bool pass_by_reference; zend_bool return_reference; int required_num_args; + zend_bool scalar_type_hint; + zend_bool number_type_hint; + zend_uint type_hint; } zend_arg_info; typedef struct _zend_compiled_variable { Index: Zend/zend_constants.c =================================================================== RCS file: /repository/ZendEngine2/zend_constants.c,v retrieving revision 1.71.2.5.2.7.2.7 diff -u -r1.71.2.5.2.7.2.7 zend_constants.c --- Zend/zend_constants.c 31 Dec 2007 07:17:04 -0000 1.71.2.5.2.7.2.7 +++ Zend/zend_constants.c 4 Jan 2008 15:22:11 -0000 @@ -148,6 +148,14 @@ c.value.value.lval = ZEND_DEBUG; c.value.type = IS_BOOL; zend_register_constant(&c TSRMLS_CC); + + c.flags = CONST_PERSISTENT | CONST_CS; + + c.name = zend_strndup(ZEND_STRL("PATCH_SCALAR_TYPE_HINTING")); + c.name_len = sizeof("PATCH_SCALAR_TYPE_HINTING"); + c.value.value.lval = ZTS_V; + c.value.type = IS_BOOL; + zend_register_constant(&c TSRMLS_CC); } } Index: Zend/zend_execute.c =================================================================== RCS file: /repository/ZendEngine2/zend_execute.c,v retrieving revision 1.716.2.12.2.24.2.11 diff -u -r1.716.2.12.2.24.2.11 zend_execute.c --- Zend/zend_execute.c 31 Dec 2007 07:17:04 -0000 1.716.2.12.2.24.2.11 +++ Zend/zend_execute.c 4 Jan 2008 15:22:12 -0000 @@ -517,6 +517,27 @@ need_msg = zend_verify_arg_class_kind(cur_arg_info, fetch_type, &class_name, &ce TSRMLS_CC); return zend_verify_arg_error(zf, arg_num, cur_arg_info, need_msg, class_name, zend_zval_type_name(arg), "" TSRMLS_CC); } + } else if (cur_arg_info->type_hint != 0) { + if (!arg) { + return zend_verify_arg_error(zf, arg_num, cur_arg_info, "be of type ", zend_get_type_by_const(cur_arg_info->type_hint), "none", "" TSRMLS_CC); + } + if (Z_TYPE_P(arg) != cur_arg_info->type_hint && (Z_TYPE_P(arg) != IS_NULL || !cur_arg_info->allow_null)) { + return zend_verify_arg_error(zf, arg_num, cur_arg_info, "be of type ", zend_get_type_by_const(cur_arg_info->type_hint), zend_zval_type_name(arg), "" TSRMLS_CC); + } + } else if (cur_arg_info->scalar_type_hint) { + if (!arg) { + return zend_verify_arg_error(zf, arg_num, cur_arg_info, "be a scalar", "", "none", "" TSRMLS_CC); + } + if (Z_TYPE_P(arg) != IS_LONG && Z_TYPE_P(arg) != IS_DOUBLE && Z_TYPE_P(arg) != IS_BOOL && Z_TYPE_P(arg) != IS_STRING && (Z_TYPE_P(arg) != IS_NULL || !cur_arg_info->allow_null)) { + return zend_verify_arg_error(zf, arg_num, cur_arg_info, "be a scalar", "", zend_zval_type_name(arg), "" TSRMLS_CC); + } + } else if (cur_arg_info->number_type_hint) { + if (!arg) { + return zend_verify_arg_error(zf, arg_num, cur_arg_info, "be a number", "", "none", "" TSRMLS_CC); + } + if (Z_TYPE_P(arg) != IS_LONG && Z_TYPE_P(arg) != IS_DOUBLE && (Z_TYPE_P(arg) != IS_NULL || !cur_arg_info->allow_null)) { + return zend_verify_arg_error(zf, arg_num, cur_arg_info, "be a number", "", zend_zval_type_name(arg), "" TSRMLS_CC); + } } 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);