Newsgroups: php.internals Path: news.php.net Xref: news.php.net php.internals:58473 Return-Path: Mailing-List: contact internals-help@lists.php.net; run by ezmlm Delivered-To: mailing list internals@lists.php.net Received: (qmail 45954 invoked from network); 2 Mar 2012 12:51:27 -0000 Received: from unknown (HELO lists.php.net) (127.0.0.1) by localhost with SMTP; 2 Mar 2012 12:51:27 -0000 Authentication-Results: pb1.pair.com smtp.mail=ircmaxell@gmail.com; spf=pass; sender-id=pass Authentication-Results: pb1.pair.com header.from=ircmaxell@gmail.com; sender-id=pass Received-SPF: pass (pb1.pair.com: domain gmail.com designates 209.85.216.173 as permitted sender) X-PHP-List-Original-Sender: ircmaxell@gmail.com X-Host-Fingerprint: 209.85.216.173 mail-qy0-f173.google.com Received: from [209.85.216.173] ([209.85.216.173:48249] helo=mail-qy0-f173.google.com) by pb1.pair.com (ecelerity 2.1.1.9-wez r(12769M)) with ESMTP id A4/EC-11220-E42C05F4 for ; Fri, 02 Mar 2012 07:51:26 -0500 Received: by qcsc20 with SMTP id c20so803465qcs.18 for ; Fri, 02 Mar 2012 04:51:23 -0800 (PST) Received-SPF: pass (google.com: domain of ircmaxell@gmail.com designates 10.229.76.149 as permitted sender) client-ip=10.229.76.149; Authentication-Results: mr.google.com; spf=pass (google.com: domain of ircmaxell@gmail.com designates 10.229.76.149 as permitted sender) smtp.mail=ircmaxell@gmail.com; dkim=pass header.i=ircmaxell@gmail.com Received: from mr.google.com ([10.229.76.149]) by 10.229.76.149 with SMTP id c21mr1438106qck.5.1330692683731 (num_hops = 1); Fri, 02 Mar 2012 04:51:23 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=mime-version:in-reply-to:references:date:message-id:subject:from:to :cc:content-type:content-transfer-encoding; bh=8CShIvQs2Np+UShlfj8KW+VPaT7XCGIz8gFzJ0sIeog=; b=0XMac+RvHAegK8RDeS2AjL13Aamnn9g6LLraS8butvXF4frGJLqvyKiLSUYSEq3NGj NY99crdBYFawJhypvHLcRXmbGz9RDp/m1H7Ep/rweU2ChnYf0khHhF1Z6WcbWa4M1LtN 6kbZtQUj9nToon+CjqgbmqBowfUkK9MC4wsDCjD9IY2XX7iymC59qVRYGCaMWTAyWkUR I8jiScl2lFIg4rE9DOFMuCggZSVEbVb9uEc05aW89wrlYtSenn0Awxd1XWnjzAurOcaz Lg+GnM54FBuDXlPVR9WUdpDJ1aC6gnbQLCrVOOrYsNJC5+iEYoXpAdPsCeTz3j5DPsP7 WTIQ== MIME-Version: 1.0 Received: by 10.229.76.149 with SMTP id c21mr1217969qck.5.1330692683661; Fri, 02 Mar 2012 04:51:23 -0800 (PST) Received: by 10.229.49.74 with HTTP; Fri, 2 Mar 2012 04:51:23 -0800 (PST) In-Reply-To: References: Date: Fri, 2 Mar 2012 07:51:23 -0500 Message-ID: To: Lazare Inepologlou Cc: internals@lists.php.net Content-Type: text/plain; charset=ISO-8859-1 Content-Transfer-Encoding: quoted-printable Subject: Re: [PHP-DEV] [POC Patch] Scalar Type Hinting/Casting - Proof Of Concept From: ircmaxell@gmail.com (Anthony Ferrara) Well, there are a few questions about the implementation: 1. *Which* type casting rules should it follow? a. Regular cast rules (like $foo =3D (int) $foo), where it converts always without error? b. Internal function cast rules, where it warnings on error and prevents execution of the function. c. Current type hinting rules, where if it can't convert cleanly it E_RECOVERABLE_ERRORS Personally, I like C the best. Where if it is passed an invalid value, it attempts to cleanly convert, but errors out if it can't... But I can see other arguments being made... 2. Should (array) be supported? Perhaps. So at that point, foo(array $bar) would do a "strict" check, and foo((array) $bar) would attempt to cast. But my question would be: what would attempt to cast mean? Should it error out if you pass foo(1)? That's what the internal function cast rules do. And to me that's more obvious than silently converting it to foo(array(1))... 3. Should references be supported? My feeling is yes, they should. So if you do foo((array) &$bar), it would cast the original value (if possible) as well. 4. What about consistency? Well, there currently is no consistency. Internal function parameters behave one way, and explicit casts behave another. And even more confusing implicit casts behave yet another way ($a + $b). So to implement this, we'd need to be consistent with one of them. Frankly, I would only want to add consistency to internal function parameters, since the explicit cast is not useful IMHO (it's identical to $bar =3D (int) $bar), at which point it's not worth adding to save only that one line. But if we're consistent with internal function parameter checking, then it becomes quite useful. We can throw warnings on unclean conversion and prevent execution of the function... That way, all function calls behave the same (as much as I hate the concept of warnings on type hint failure)... So, in that case, function calls become an implicit cast to the type, which is then why the stricter error handling (without breaking the spirit or consistency). 5. What about BC breaks? Well, this entire patch (up to this point) wouldn't require one. it's only adding the casting functionality (which is not implemented today), so no problem. Existing code would still function fine. Thoughts? Should I update the patch to be more inline with what I said above (the implicit hints that are offered by the current internal function argument mechanism: # sapi/cli/php -r 'function foo((int) $bar) { return $bar; } $a =3D "1"; var_dump(foo($a));' int(1) # sapi/cli/php -r 'function foo((int) $bar) { return $bar; } $a =3D "foo"; var_dump(foo($a));' Warning: Argument 1 passed to foo() must be of the type integer, string given, called in Command line code on line 1 and defined in Command line code on line 1 However, since it's not raising a terminating error, more changes would need to be made to the VM to check the return status of the argument check (which is currently ignored) to determine if to proceed with the function call, or just return null imediately... Thoughts? Anthony On Fri, Mar 2, 2012 at 5:27 AM, Lazare Inepologlou wro= te: > +1 for the syntax. There are two nice side effects I would like to > underline. > > > 1. > Error-raising can be clearly delegated to the type juggling mechanism. Th= ere > will be no need to implement anything new here but reuse the existing typ= e > juggling system of PHP. That would be very consistent. At the end of the > day, these two syntaxes are completely equivalent: > > function foo((int) $bar) { ... } > function foo($bar) { $bar =3D (int)$bar; ... } > > > 2. > If we put passing by reference into the picture, it is easy to see why th= e > following syntax should be a parsing error: > > function foo((int) & $bar) { =A0} =A0 =A0// parsing error > > On the contrary, were there no brackets, the resemblance to the syntax of= C > would be confusing. > > > > > Lazare INEPOLOGLOU > Ing=E9nieur Logiciel > > > 2012/3/2 Anthony Ferrara >> >> Hey all, >> >> I know given all the discussion about this topic lately, this is a hot >> topic. =A0But I whipped together a quick POC patch to implement scalar >> type casting for function parameters. =A0Let me describe it: >> >> Patch: https://gist.github.com/1947259 >> >> Example: >> >> function foo( (int) $bar ) { >> =A0 =A0var_dump($bar); >> } >> >> foo(1); // int(1) >> foo("1"); // int(1) >> foo(1.5); // int(1) >> foo("foo"); // E_RECOVERABLE_ERROR - Expected integer >> foo(array()); // E_RECOVERABLE_ERROR >> >> Right now, I only implemented the checks for (int), but I add the >> parser constructs for (int), (float), (bool), (string) and (object)... >> >> Now, let's talk why I did what I did: >> >> Why did I use cast syntax? =A0Well, there are really three main reasons. >> =A0First off, to indicate that a cast may happen. =A0Second, to prevent >> needing new tokens (and hence reserved words). =A0And third to provide a >> distinction between a string class type hint and a string scalar type >> hint. >> >> Why did I only implement (int)? =A0Well, because I just wanted to build >> a quick dirty POC that can be executed to see the semantics of >> operation. =A0There are issues with it now, so rather than doing all the >> work to re-do it later, I just implemented int... >> >> Why implement (object)? =A0Because right now, there's no way to say you >> want to accept a generic object without caring about type. =A0So the >> (object) cast/hint would then provide that ability to accept a generic >> object. >> >> Why not implement (resource)? =A0Because that would require a new parser >> token, as it's not available now... >> >> How does the casting work? =A0Right now, it's using a copy of the same >> rules that internal functions use with zend_parse_parameters. =A0That >> way, it brings the operating semantics of internal functions and >> userland functions more inline with each other. >> >> >> >> So with that said, there are some (significant) issues with the patch: >> >> 1. First off, the arg checks happen before separation of the zval on >> non-referenced calls. =A0So that means the cast effects the original >> zval AND the argument. =A0Which is a no-go for a production patch. =A0So >> that means that the cast logic would need to be put after the zval >> split. =A0But we'd still want the checks first, so it's not too >> difficult to segregate, just requires deeper changes. =A0It's not >> difficult (that I can see yet), just more work... =A0Example of the >> problem: >> >> # sapi/cli/php -r 'function foo((int) $bar) { var_dump($bar); } $a =3D >> "1"; foo($a); var_dump($a);' >> int(1) >> int(1) >> >> 2. =A0Right now, the zend_aprse_arg_impl ( >> http://lxr.php.net/xref/PHP_5_4/Zend/zend_API.c#zend_parse_arg_impl ) >> that's used by internal functions is defined as static. =A0So we'd be >> copying a lot of the code back and forth. =A0In the production patch, >> I'd also want to re-factor that out a bit into either functions or >> macros to handle the type conversion and casting in both places. =A0That >> way, both systems would behave identical (or as close as possible). >> >> >> So, with that said, what do you think? =A0Is this something worth >> pursuing? =A0Are there any fundamental issues that I'm missing? =A0What >> else would we need to cover in a production patch and RFC? >> >> Thanks, >> >> Anthony >> >> -- >> PHP Internals - PHP Runtime Development Mailing List >> To unsubscribe, visit: http://www.php.net/unsub.php >> >