Re: import/use last call
| From: | Gregory Beaver | Date: | Tue, 23 Oct 2007 03:43:24 +0000 |
| Subject: | Re: import/use last call | ||
| References: | 1 2 3 | Groups: | php.internals |
| Request: | Send a blank email to internals+get-32924@lists.php.net to get a copy of this message | ||
Stanislav Malyshev wrote:
>> Hold off for a bit - I may have a simple solution that solves the
>> problem for class names, method names and functions, have to code the
>> patch tonight first to prove it works.
>
> OK, please send it as soon as you have it :)
Hi,
The attached patch is for PHP 5.3, if it is acceptable, I will port it
to PHP 6, which is not difficult, although it does involve a lot of
cut/pasting.
The patch does these things:
1) fixes an unrelated bug I found in implementation of LSB - "static" is
not checked for in zend_do_import()/zend_do_namespace() and other places
that we check for "self" and "parent"
2) fixes a rather serious error in the fix for Bug #42859 - missing
parens in zend_do_import()
3) adds "import" and "namespace" as valid function/class names
4) allows any string for method names, just as we allow any string for
variable names
5) fixes a bug in logic for $class->list where $class-> list (note the
whitespace between -> and list) returns a T_LIST instead of T_STRING
6) It allows "import ::Classname as Blah" which is currently a parse error
7) class constants are unchanged - reserved words still error out.
Note that the zend_compile.c fixes can all be committed directly as they
are all bugfixes and not related to the import/namespace/reserved words fix.
To implement this, I added several states to the lexer in order to
return T_STRING whenever possible, which is after T_NEW, T_INTERFACE,
T_CLASS, T_EXTENDS and in the T_IMPLEMENTS list. In addition, after
T_FUNCTION outside of a class, it returns T_STRING for "import" and
"namespace" but no other reserved words. After T_FUNCTION inside of a
class (method declaration), it returns T_STRING for all possible
strings. After :: or -> T_STRING is always returned. Also, rather than
take the approach LSB does with T_STATIC, I have the lexer initialize
the string value of T_IMPORT and T_NAMESPACE so we can preserve case for
autoloading needs. The parser frees the unused char * when normal
import/namespace declarations are called.
In the parser, I use fully_qualified_class_name instead of
namespace_name for both import syntaxes. This introduces a minor issue
in that this is no longer a parse error:
import static::oops as Classname;
However, if "Classname" is used, this will simply result in "Fatal
error: Class 'static::oops' not found in..." and shouldn't be too big of
a deal. Also in the parser, I inserted T_IMPORT and T_NAMESPACE as
aliases to T_STRING in global situations to allow for static method
calls, class constants, and fully-qualified namespace calls.
Basically this script is now possible with the patch:
<?php
namespace import;
import ::Exception as Test;
function import() {echo 'import function';}
interface import {}
interface fooey {}
class Exception extends ::Exception implements fooey, import {}
class namespace {
const HI = 3;
function list() {echo __METHOD__;}
}
import();
var_dump(namespace::HI);
namespace::list();
?>
and results in this output:
cellog@lot-49:~/workspace/php5$ sapi/cli/php -n testme.php
import functionint(3)
import::namespace::list
I have not performed profiling on the patch, instead focusing on
correctness for now.
The patch looks complicated because of the additional states, but is
really not that complicated, honest.
:)
Greg