Hi,

These 2 scripts demonstrate the problem:

foo.php:
<?php
namespace foo;
const one = 1;
function what()
{
echo __FUNCTION__,"\n";
}
?>

bar.php:
<?php
include 'foo.php';
class foo {
const one = 1;
static function what()
{
echo __FUNCTION__,"\n";
}
}
foo::what(); // is this static method ::foo::what() or namespace
function ::foo::what()?
var_dump(foo::one); // is this class constant ::foo::one or namespace
constant ::foo::one?
?>

The logical solution for functions would be to allow something to
disambiguate.  I would suggest allowing function:: to differentiate
between a method and a function:

bar_func.php:
<?php
include 'foo.php';
use function foo::what; // this should inform PHP to alias namespace
function foo::what to "what"

class foo {
const one = 1;
static function what()
{
echo __FUNCTION__,"\n";
}
}
foo::what(); // this is static method ::foo::what();
function::foo::what(); // this is namespace function ::foo::what();
what(); // this is namespace function ::foo::what();
?>

The solution for constants can be similar:

bar_const.php:
<?php
include 'foo.php';
use const foo::one; // this should inform PHP to alias namespace
constant foo::one to "one"

class foo {
const one = 1;
static function what()
{
echo __FUNCTION__,"\n";
}
}
echo foo::one; // this is class constant ::foo::one;
echo const::foo::one; // this is namespace constant ::foo::one;
echo one; // this is namespace constant ::foo::one;
?>

To implement this technically, we would need to create two new import
hashes, one for functions, and one for constants.  For this to be
technically possible, we would need to ensure this is illegal:

<?php
use foo::name, function foo::name; // conflict between "name" and "name"
even though context would differentiate
use foo::name, const foo::name; // same conflict
?>

Fortunately, it is easy to test, as zend_do_use() could simply check the
other hashes for existence of the name in question.

Then, the implementation of unqualified name resolution would consist of
doing resolution like so:

resolving name::foo():
1) is there a use blah::name; or use something::else as name;? =>
resolve "name::foo()" as class blah::name/something::else, method foo
2) is there a class in the current namespace called "name"? => resolve
"name::foo()" as class name method foo
3) is there a namespace in the current namespace called "name" and a
function in it called "foo"? => resolve to namespace function "name::foo()"
4) resolve name::foo() at runtime using current resolution rules

resolving foo();
1) is there a use function name::foo; or use function something::else as
foo;? => resolve "foo()" as namespace function
"name::foo()/something::else()"
2) is there a foo() function in the current namespace? => resolve
"foo()" as namespace function in the current namespace "foo()"
if we are in a namespace:
3a) is there an internal function named foo()? => resolve "foo()" as
internal function foo.
and if we're in the top-level unnamespace:
3b) is there any global function named foo()? => resolve "foo()" as
global function foo.

resolving foo [in const context such as "$a = foo;"]:
1) is there a use const name::foo; or use const something::else as foo;?
=> resolve "foo" as namespace constant name::foo/something::else at
compile time
2) is there a const in the current namespace "foo"? => resolve "foo" as
namespace constant in current namespace at compile time
3) resolve "foo" as define()d at runtime

It must be noted that because functions/constants cannot be autoloaded,
we can safely assume that if a namespace function or constant does not
exist at runtime, then we can error out immediately.  This simplifies
resolution slightly over class resolution.

If this looks good, I may be able to try my hand at a patch, but I only
have time today or tomorrow to do so.

Greg

-- 
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php

Reply via email to