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

Reply via email to