Hello all!

Attached is a patch (against 5_2) to allow scalar type hinting \o/

I realize that maaany will be against it so I won't be pushing it (a
lot), just wanted the patch archived somewhere :)

A .tar.bz2 archive can be found at
http://home.oslo.nith.no/~maghan/scalar.type.hint.tar.bz2 containing
the patch, phpt fixes and new phpt tests.

-Hannes
(maybe I should had said "if there are no objections I'll commit this
by the end of next week" hoping everyone were busy and wouldn't notice
this mail *evil wink*)
Index: Zend/zend_API.h
===================================================================
RCS file: /repository/ZendEngine2/zend_API.h,v
retrieving revision 1.207.2.8.2.5
diff -u -r1.207.2.8.2.5 zend_API.h
--- Zend/zend_API.h     18 Jul 2006 09:06:32 -0000      1.207.2.8.2.5
+++ Zend/zend_API.h     3 Nov 2006 13:28:51 -0000
@@ -62,8 +62,8 @@
 
 #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_OBJECT, 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)      \
        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.20
diff -u -r1.647.2.27.2.20 zend_compile.c
--- Zend/zend_compile.c 20 Oct 2006 02:44:02 -0000      1.647.2.27.2.20
+++ Zend/zend_compile.c 3 Nov 2006 13:28:51 -0000
@@ -1278,13 +1278,18 @@
        cur_arg_info = 
&CG(active_op_array)->arg_info[CG(active_op_array)->num_args-1];
        cur_arg_info->name = estrndup(varname->u.constant.value.str.val, 
varname->u.constant.value.str.len);
        cur_arg_info->name_len = varname->u.constant.value.str.len;
-       cur_arg_info->array_type_hint = 0;
+       cur_arg_info->class_name = NULL;
+       cur_arg_info->class_name_len = 0;
+       cur_arg_info->type_hint = 0;
        cur_arg_info->allow_null = 1;
        cur_arg_info->pass_by_reference = pass_by_reference;
 
        if (class_type->op_type != IS_UNUSED) {
                cur_arg_info->allow_null = 0;
-               if (class_type->u.constant.type == IS_STRING) {
+               cur_arg_info->type_hint = class_type->u.constant.type;
+
+               switch (class_type->u.constant.type) {
+               case IS_OBJECT:
                        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) {
@@ -1294,10 +1299,9 @@
                                        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;
@@ -1305,11 +1309,23 @@
                                        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:
+                       if (op == ZEND_RECV_INIT && 
Z_TYPE(initialization->u.constant) != class_type->u.constant.type) {
+                               zend_error(E_COMPILE_ERROR, "Default value for 
parameters with %s type hint can only be %s", 
zend_get_type_by_const(class_type->u.constant.type), 
zend_get_type_by_const(class_type->u.constant.type));
+                       }
+                       break;
+
+               default:
+                       zend_error(E_COMPILE_ERROR, "Unkown type hint");
                }
-       } else {
-               cur_arg_info->class_name = NULL;
-               cur_arg_info->class_name_len = 0;
        }
+       
        opline->result.u.EA.type |= EXT_TYPE_UNUSED;
 }
 
@@ -1950,8 +1966,8 @@
                        && strcmp(fe->common.arg_info[i].class_name, 
proto->common.arg_info[i].class_name)!=0) {
                        return 0;
                }
-               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 */
+               if (fe->common.arg_info[i].type_hint != 
proto->common.arg_info[i].type_hint) {
+                       /* 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_compile.h
===================================================================
RCS file: /repository/ZendEngine2/zend_compile.h,v
retrieving revision 1.316.2.8.2.7
diff -u -r1.316.2.8.2.7 zend_compile.h
--- Zend/zend_compile.h 26 Sep 2006 10:30:50 -0000      1.316.2.8.2.7
+++ Zend/zend_compile.h 3 Nov 2006 13:28:51 -0000
@@ -159,7 +159,7 @@
        zend_uint name_len;
        char *class_name;
        zend_uint class_name_len;
-       zend_bool array_type_hint;
+       zend_uint type_hint;
        zend_bool allow_null;
        zend_bool pass_by_reference;
        zend_bool return_reference;
Index: Zend/zend_execute.c
===================================================================
RCS file: /repository/ZendEngine2/zend_execute.c,v
retrieving revision 1.716.2.12.2.12
diff -u -r1.716.2.12.2.12 zend_execute.c
--- Zend/zend_execute.c 2 Oct 2006 11:09:52 -0000       1.716.2.12.2.12
+++ Zend/zend_execute.c 3 Nov 2006 13:28:52 -0000
@@ -513,12 +513,12 @@
                        need_msg = zend_verify_arg_class_kind(cur_arg_info, 
&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->array_type_hint) {
+       } else if (cur_arg_info->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 ", zend_get_type_by_const(cur_arg_info->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);
+               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 ", zend_get_type_by_const(cur_arg_info->type_hint), "", 
zend_zval_type_name(arg) TSRMLS_CC);
                }
        }
        return 1;
Index: Zend/zend_language_parser.y
===================================================================
RCS file: /repository/ZendEngine2/zend_language_parser.y,v
retrieving revision 1.160.2.4.2.1
diff -u -r1.160.2.4.2.1 zend_language_parser.y
--- Zend/zend_language_parser.y 11 May 2006 21:07:39 -0000      1.160.2.4.2.1
+++ Zend/zend_language_parser.y 3 Nov 2006 13:28:52 -0000
@@ -129,6 +129,10 @@
 %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_CLASS_C
 %token T_METHOD_C
 %token T_FUNC_C
@@ -438,8 +442,12 @@
 
 optional_class_type:
                /* empty */             { $$.op_type = IS_UNUSED; }
-       |       T_STRING                { $$ = $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_STRING                { $$.op_type = IS_CONST; 
Z_TYPE($$.u.constant)=IS_OBJECT;}
 ;
 
 
Index: Zend/zend_language_scanner.l
===================================================================
RCS file: /repository/ZendEngine2/zend_language_scanner.l,v
retrieving revision 1.131.2.11
diff -u -r1.131.2.11 zend_language_scanner.l
--- Zend/zend_language_scanner.l        13 Apr 2006 13:48:28 -0000      
1.131.2.11
+++ Zend/zend_language_scanner.l        3 Nov 2006 13:28:52 -0000
@@ -1079,6 +1079,22 @@
        return T_ARRAY;
 }
 
+<ST_IN_SCRIPTING>("bool"|"boolean") {
+       return T_BOOL_HINT;
+}
+
+<ST_IN_SCRIPTING>"string" {
+       return T_STRING_HINT;
+}
+
+<ST_IN_SCRIPTING>("int"|"integer") {
+       return T_INT_HINT;
+}
+
+<ST_IN_SCRIPTING>("real"|"double"|"float") {
+       return T_DOUBLE_HINT;
+}
+
 <ST_IN_SCRIPTING>"++" {
        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.31
diff -u -r1.164.2.33.2.31 php_reflection.c
--- ext/reflection/php_reflection.c     18 Oct 2006 16:35:15 -0000      
1.164.2.33.2.31
+++ ext/reflection/php_reflection.c     3 Nov 2006 13:28:52 -0000
@@ -610,7 +610,7 @@
                if (arg_info->allow_null) {
                        string_printf(str, "or NULL ");
                }
-       } else if (arg_info->array_type_hint) {
+       } else if (arg_info->type_hint == IS_ARRAY) {
                string_printf(str, "array ");
                if (arg_info->allow_null) {
                        string_printf(str, "or NULL ");
@@ -2015,7 +2015,7 @@
        METHOD_NOTSTATIC_NUMPARAMS(reflection_parameter_ptr, 0);
        GET_REFLECTION_OBJECT_PTR(param);
 
-       RETVAL_BOOL(param->arg_info->array_type_hint);
+       RETVAL_BOOL(param->arg_info->type_hint == IS_ARRAY);
 }
 /* }}} */
 
-- 
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php

Reply via email to