Newsgroups: php.internals Path: news.php.net Xref: news.php.net php.internals:34417 Return-Path: Mailing-List: contact internals-help@lists.php.net; run by ezmlm Delivered-To: mailing list internals@lists.php.net Received: (qmail 25321 invoked by uid 1010); 4 Jan 2008 17:13:19 -0000 Delivered-To: ezmlm-scan-internals@lists.php.net Delivered-To: ezmlm-internals@lists.php.net Received: (qmail 25306 invoked from network); 4 Jan 2008 17:13:19 -0000 Received: from unknown (HELO lists.php.net) (127.0.0.1) by localhost with SMTP; 4 Jan 2008 17:13:19 -0000 Authentication-Results: pb1.pair.com smtp.mail=sam@sambarrow.com; spf=permerror; sender-id=unknown Authentication-Results: pb1.pair.com header.from=sam@sambarrow.com; sender-id=unknown Received-SPF: error (pb1.pair.com: domain sambarrow.com from 205.234.132.11 cause and error) X-PHP-List-Original-Sender: sam@sambarrow.com X-Host-Fingerprint: 205.234.132.11 scottsdale.servershost.net Received: from [205.234.132.11] ([205.234.132.11:53630] helo=scottsdale.servershost.net) by pb1.pair.com (ecelerity 2.1.1.9-wez r(12769M)) with ESMTP id 01/8A-63281-E296E774 for ; Fri, 04 Jan 2008 12:13:19 -0500 Received: from [98.172.154.66] (port=31619 helo=[10.200.100.14]) by scottsdale.servershost.net with esmtpsa (SSLv3:RC4-MD5:128) (Exim 4.68) (envelope-from ) id 1JAq6d-0006dy-75; Fri, 04 Jan 2008 11:13:15 -0600 To: Pierre Cc: Gregory Beaver , Alain Williams , internals Mailing List In-Reply-To: References: <477DB7BF.10201@chiaraquartet.net> <20080104105558.GC7861@mint.phcomp.co.uk> <477E5649.2080104@chiaraquartet.net> <1199466070.15292.140.camel@sbarrow-desktop> Content-Type: multipart/mixed; boundary="=-Lpq1hDFvWimK1euvO0Ve" Date: Fri, 04 Jan 2008 12:11:41 -0500 Message-ID: <1199466701.15292.149.camel@sbarrow-desktop> Mime-Version: 1.0 X-Mailer: Evolution 2.10.1 X-Antivirus-Scanner: Clean mail though you should still use an Antivirus X-AntiAbuse: This header was added to track abuse, please include it with any abuse report X-AntiAbuse: Primary Hostname - scottsdale.servershost.net X-AntiAbuse: Original Domain - lists.php.net X-AntiAbuse: Originator/Caller UID/GID - [47 12] / [47 12] X-AntiAbuse: Sender Address Domain - sambarrow.com X-Source: X-Source-Args: X-Source-Dir: Subject: Re: [PHP-DEV] type hinting From: sam@sambarrow.com (Sam Barrow) --=-Lpq1hDFvWimK1euvO0Ve Content-Type: text/plain Content-Transfer-Encoding: 7bit On Fri, 2008-01-04 at 18:09 +0100, Pierre wrote: > On Jan 4, 2008 6:01 PM, Sam Barrow wrote: > > > > On Fri, 2008-01-04 at 17:53 +0100, Pierre wrote: > > > On Jan 4, 2008 5:53 PM, Pierre wrote: > > > > On Jan 4, 2008 4:52 PM, Gregory Beaver wrote: > > > > > > > > > But I *don't* want my functions to take an argument of arbitrary type - > > > > > it is in fact you who are missing the point. A type hint is a poor > > > > > solution to a real problem that is much more easily solved via simple > > > > > input validation and graceful error handling. The current situation in > > > > > PHP provides a much more flexible solution to the same problem. > > > > > > > > Unlike our OO strictness (E_FATAL!!), nothing will prevent you to use > > > > > > Read: othing will prevent you to >do not< use it :) > > > > > > > So you're saying if you don't like it just don't use it? > > Yes, that's the meaning of "optional" I suppose :) > > My idea about it (I did not test the patch, so correct me if I > misunderstood the proposal) was to leave the default as it is now: > > function($a) > what Greg likes to always use ;) > function(mixed $a) > little syntax sugar, same as the previous one > function(int $a) > etc. > Exactly. I just added the "mixed" type hint which is the same as using no type hint. The new patch is attached. Extra keywords (real, long, double, etc.) have been taken out. The available type hints are now mixed, int, float, bool, string, scalar, num, resource, and object. And of course array and class type hints still work. --=-Lpq1hDFvWimK1euvO0Ve Content-Disposition: attachment; filename=scalartypehinting.patch Content-Type: text/x-patch; name=scalartypehinting.patch; charset=utf-8 Content-Transfer-Encoding: 7bit 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); --=-Lpq1hDFvWimK1euvO0Ve--