Hey all, I know given all the discussion about this topic lately, this is a hot topic. But I whipped together a quick POC patch to implement scalar type casting for function parameters. Let me describe it:
Patch: https://gist.github.com/1947259 Example: function foo( (int) $bar ) { var_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? Well, there are really three main reasons. First off, to indicate that a cast may happen. Second, to prevent needing new tokens (and hence reserved words). And third to provide a distinction between a string class type hint and a string scalar type hint. Why did I only implement (int)? Well, because I just wanted to build a quick dirty POC that can be executed to see the semantics of operation. There are issues with it now, so rather than doing all the work to re-do it later, I just implemented int... Why implement (object)? Because right now, there's no way to say you want to accept a generic object without caring about type. So the (object) cast/hint would then provide that ability to accept a generic object. Why not implement (resource)? Because that would require a new parser token, as it's not available now... How does the casting work? Right now, it's using a copy of the same rules that internal functions use with zend_parse_parameters. That 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. So that means the cast effects the original zval AND the argument. Which is a no-go for a production patch. So that means that the cast logic would need to be put after the zval split. But we'd still want the checks first, so it's not too difficult to segregate, just requires deeper changes. It's not difficult (that I can see yet), just more work... Example of the problem: # sapi/cli/php -r 'function foo((int) $bar) { var_dump($bar); } $a = "1"; foo($a); var_dump($a);' int(1) int(1) 2. Right 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. So we'd be copying a lot of the code back and forth. In 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. That way, both systems would behave identical (or as close as possible). So, with that said, what do you think? Is this something worth pursuing? Are there any fundamental issues that I'm missing? What 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