Just so anyone who wants it has it, I have attached the last version of
my patch.

Note that it still issues a fatal error but this can be changed very
easily, would take me about 2 minutes.

Full specs:
Type hinting patch allows for 8 new type hints, in addition to array and
class type hinting.

- Integers (specified by "int", "integer", or "long")
- Floats (specified by "float", "double", or "real")
- Numbers (matches integers and floats, specified by "num" or "number")
- Strings (specified by "string")
- Booleans (specified by "bool" or "boolean")
- Scalars (matches strings, booleans, and numbers; specified by
"scalar")
- Resources (specified by "resource")
- Objects (matches any object, specified by "object")

The patch specifies a constant, PATCH_SCALAR_TYPE_HINTING, just there to
indicate that the patch is installed.

On Thu, 2008-01-03 at 20:23 +0100, Derick Rethans wrote:
> On Thu, 3 Jan 2008, Stanislav Malyshev wrote:
> 
> > > When the type hint says I want an integer, then only integer should be
> > > accepted; no casting should be done. It may give predictable results
> > 
> > Why people that want Java just don't use Java I wonder? PHP never was a 
> > strict
> > static typed language.
> 
> Broken record perhaps? I am getting a bit tired of this "just use Java 
> argument", it's perhaps even a bit arrogant. From what I read there is 
> plenty of people that want type hints for static types - there's a few 
> patches out there, it doesn't slow down the general case. So why should 
> we *not* add it? (And yes, I changed my mind)
> 
> regards,
> Derick
> 
> -- 
> Derick Rethans
> http://derickrethans.nl | http://ezcomponents.org | http://xdebug.org
> 
Index: Zend/zend_API.h
===================================================================
RCS file: /repository/ZendEngine2/zend_API.h,v
retrieving revision 1.207.2.8.2.8.2.5
diff -u -r1.207.2.8.2.8.2.5 zend_API.h
--- Zend/zend_API.h	2 Nov 2007 19:40:37 -0000	1.207.2.8.2.8.2.5
+++ Zend/zend_API.h	21 Dec 2007 20:56:40 -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.31
diff -u -r1.647.2.27.2.41.2.31 zend_compile.c
--- Zend/zend_compile.c	13 Dec 2007 10:02:03 -0000	1.647.2.27.2.41.2.31
+++ Zend/zend_compile.c	21 Dec 2007 20:56:41 -0000
@@ -1341,26 +1341,54 @@
 	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("number", 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("integer", class_type->u.constant.value.str.val) == 0) {
+ 				cur_arg_info->type_hint = IS_LONG;
+ 			} else if (strcasecmp("long", 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("double", class_type->u.constant.value.str.val) == 0) {
+ 				cur_arg_info->type_hint = IS_DOUBLE;
+ 			} else if (strcasecmp("real", 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("boolean", 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 {
+ 				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;
@@ -2278,6 +2306,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.11
diff -u -r1.316.2.8.2.12.2.11 zend_compile.h
--- Zend/zend_compile.h	13 Dec 2007 10:02:03 -0000	1.316.2.8.2.12.2.11
+++ Zend/zend_compile.h	21 Dec 2007 20:56:41 -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.6
diff -u -r1.71.2.5.2.7.2.6 zend_constants.c
--- Zend/zend_constants.c	20 Nov 2007 16:34:25 -0000	1.71.2.5.2.7.2.6
+++ Zend/zend_constants.c	21 Dec 2007 20:56:41 -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.9
diff -u -r1.716.2.12.2.24.2.9 zend_execute.c
--- Zend/zend_execute.c	14 Dec 2007 14:14:50 -0000	1.716.2.12.2.24.2.9
+++ Zend/zend_execute.c	21 Dec 2007 20:56:41 -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);

-- 
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php

Reply via email to