Stanislav Malyshev wrote:
>> file1.php:
>> <?php
>> namespace foo;
>> class bar {}
>> ?>
>>
>> file2.php:
>> <?php
>> namespace gronk;
>> import foo::bar;
>> class bar {}
>> ?>
>
> The problem is not this code. The problem is this code:
>
> file1.php
> <?php
> namespace foo;
> import otherfoo::bar;
> ?>
>
> file2.php:
> <?php
> namespace gronk;
>
> class bar {}
> ?>
>
> Would start failing too once you merge them in one file, even though
> they worked just fine before.
Right, that's why I was saying expansion of imports would be necessary,
meaning that all references to "bar" would need to be translated to
"otherfoo::bar"
If this is a huge problem, it could be solved by having a separate
import scope within namespace brackets. This is accomplished easily by
storing the existing CG(current_import) in a temp variable,
CG(saved_import), resetting CG(current_import) to NULL to start over at
the namespace declaration, and then restoring the old import list via
CG(current_import) = CG(saved_import) and freeing CG(saved_import).
This would of course mean that top-level import is not the same as
import within a namespace, would that make sense?
I've attached an updated patch to reflect this (it adds 9 lines and a
new test for the approach, ns_046.phpt). Please note that I am not so
sure I like this approach, and I have not deleted the original patch (at
http://pear.php.net/~greg/namespaces.patch.txt). The new patch is also
at http://pear.php.net/~greg/namespaces_smartimport.patch.txt
Greg
? halt_compiler_php6.patch.txt
? namespace.patch.txt
? namespace_smartimport.patch.txt
Index: Zend/zend_compile.c
===================================================================
RCS file: /repository/ZendEngine2/zend_compile.c,v
retrieving revision 1.762
diff -u -r1.762 zend_compile.c
--- Zend/zend_compile.c 20 Aug 2007 09:48:41 -0000 1.762
+++ Zend/zend_compile.c 21 Aug 2007 23:08:35 -0000
@@ -4966,16 +4966,16 @@
}
/* }}} */
-void zend_do_namespace(znode *name TSRMLS_DC) /* {{{ */
+void zend_do_namespace(znode *name, int brackets TSRMLS_DC) /* {{{ */
{
unsigned int lcname_len;
zstr lcname;
- if (CG(active_op_array)->last > 0) {
+ if (!brackets && CG(active_op_array)->last > 0) {
zend_error(E_COMPILE_ERROR, "Namespace declaration statement
has to be the very first statement in the script");
}
if (CG(current_namespace)) {
- zend_error(E_COMPILE_ERROR, "Namespace cannot be declared
twice");
+ zend_error(E_COMPILE_ERROR, "Namespace cannot be declared twice
(without brackets) or nested within brackets");
}
lcname = zend_u_str_case_fold(Z_TYPE(name->u.constant),
Z_UNIVAL(name->u.constant), Z_UNILEN(name->u.constant), 0, &lcname_len);
if (((lcname_len == sizeof("self")-1) &&
@@ -4988,6 +4988,25 @@
ALLOC_ZVAL(CG(current_namespace));
*CG(current_namespace) = name->u.constant;
+ CG(saved_import) = CG(current_import);
+ CG(current_import) = NULL;
+}
+/* }}} */
+
+void zend_do_end_namespace(TSRMLS_D) /* {{{ */
+{
+ if (CG(current_namespace)) {
+ zval_dtor(CG(current_namespace));
+ efree(CG(current_namespace));
+ CG(current_namespace) = NULL;
+ }
+ if (CG(current_import)) {
+ zend_hash_destroy(CG(current_import));
+ efree(CG(current_import));
+ CG(current_import) = NULL;
+ }
+ CG(current_import) = CG(saved_import);
+ CG(saved_import) = NULL;
}
/* }}} */
@@ -5068,6 +5087,11 @@
efree(CG(current_import));
CG(current_import) = NULL;
}
+ if (CG(saved_import)) {
+ zend_hash_destroy(CG(saved_import));
+ efree(CG(saved_import));
+ CG(saved_import) = NULL;
+ }
}
/* }}} */
Index: Zend/zend_compile.h
===================================================================
RCS file: /repository/ZendEngine2/zend_compile.h,v
retrieving revision 1.363
diff -u -r1.363 zend_compile.h
--- Zend/zend_compile.h 20 Aug 2007 09:48:41 -0000 1.363
+++ Zend/zend_compile.h 21 Aug 2007 23:08:36 -0000
@@ -520,7 +520,8 @@
void zend_do_abstract_method(znode *function_name, znode *modifiers, znode
*body TSRMLS_DC);
void zend_do_build_namespace_name(znode *result, znode *prefix, znode *name
TSRMLS_DC);
-void zend_do_namespace(znode *name TSRMLS_DC);
+void zend_do_namespace(znode *name, int brackets TSRMLS_DC);
+void zend_do_end_namespace(TSRMLS_D);
void zend_do_import(znode *name, znode *new_name TSRMLS_DC);
void zend_do_end_compilation(TSRMLS_D);
Index: Zend/zend_globals.h
===================================================================
RCS file: /repository/ZendEngine2/zend_globals.h,v
retrieving revision 1.168
diff -u -r1.168 zend_globals.h
--- Zend/zend_globals.h 12 Jul 2007 09:23:48 -0000 1.168
+++ Zend/zend_globals.h 21 Aug 2007 23:08:36 -0000
@@ -140,6 +140,7 @@
zval *current_namespace;
HashTable *current_import;
+ HashTable *saved_import;
#ifdef ZTS
HashTable **static_members;
Index: Zend/zend_language_parser.y
===================================================================
RCS file: /repository/ZendEngine2/zend_language_parser.y,v
retrieving revision 1.188
diff -u -r1.188 zend_language_parser.y
--- Zend/zend_language_parser.y 20 Aug 2007 09:48:41 -0000 1.188
+++ Zend/zend_language_parser.y 21 Aug 2007 23:08:37 -0000
@@ -171,12 +171,12 @@
| function_declaration_statement {
zend_do_early_binding(TSRMLS_C); }
| class_declaration_statement {
zend_do_early_binding(TSRMLS_C); }
| T_HALT_COMPILER '(' ')' ';' {
zend_do_halt_compiler_register(TSRMLS_C); YYACCEPT; }
- | T_NAMESPACE namespace_name ';' { zend_do_namespace(&$2
TSRMLS_CC); }
+ | T_NAMESPACE namespace_name ';' { zend_do_namespace(&$2, 0
TSRMLS_CC); }
+ | T_NAMESPACE namespace_name '{' { zend_do_namespace(&$2, 1
TSRMLS_CC); } top_statement_list '}' { zend_do_end_namespace(TSRMLS_C); }
| T_IMPORT namespace_name ';' { zend_do_import(&$2,
NULL TSRMLS_CC); }
| T_IMPORT namespace_name T_AS T_STRING ';' {
zend_do_import(&$2, &$4 TSRMLS_CC); }
;
-
inner_statement_list:
inner_statement_list { zend_do_extended_info(TSRMLS_C); }
inner_statement { HANDLE_INTERACTIVE(); }
| /* empty */
Index: Zend/tests/ns_039.phpt
===================================================================
RCS file: Zend/tests/ns_039.phpt
diff -N Zend/tests/ns_039.phpt
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ Zend/tests/ns_039.phpt 21 Aug 2007 23:08:37 -0000
@@ -0,0 +1,14 @@
+--TEST--
+039: double namespace declaration
+--FILE--
+<?php
+namespace Exception;
+namespace Oops;
+function foo() {
+ echo "ok\n";
+}
+Exception::foo();
+Exception::bar();
+--EXPECTF--
+Fatal error: Namespace cannot be declared twice (without brackets) or nested
within brackets in %sns_039.php on line 3
+
Index: Zend/tests/ns_040.phpt
===================================================================
RCS file: Zend/tests/ns_040.phpt
diff -N Zend/tests/ns_040.phpt
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ Zend/tests/ns_040.phpt 21 Aug 2007 23:08:37 -0000
@@ -0,0 +1,14 @@
+--TEST--
+040: namespace not first declaration
+--FILE--
+<?php
+$a = oops;
+namespace Exception;
+function foo() {
+ echo "ok\n";
+}
+Exception::foo();
+Exception::bar();
+--EXPECTF--
+Fatal error: Namespace declaration statement has to be the very first
statement in the script in %sns_040.php on line 3
+
Index: Zend/tests/ns_041.phpt
===================================================================
RCS file: Zend/tests/ns_041.phpt
diff -N Zend/tests/ns_041.phpt
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ Zend/tests/ns_041.phpt 21 Aug 2007 23:08:37 -0000
@@ -0,0 +1,13 @@
+--TEST--
+041: namespace with brackets, function declaration
+--FILE--
+<?php
+namespace Exception {
+function foo() {
+ echo "ok\n";
+}
+}
+Exception::foo();
+--EXPECTF--
+ok
+
Index: Zend/tests/ns_042.phpt
===================================================================
RCS file: Zend/tests/ns_042.phpt
diff -N Zend/tests/ns_042.phpt
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ Zend/tests/ns_042.phpt 21 Aug 2007 23:08:37 -0000
@@ -0,0 +1,15 @@
+--TEST--
+042: namespace with brackets, class declaration
+--FILE--
+<?php
+namespace Exception {
+class test {
+static function foo() {
+ echo "ok\n";
+}
+}
+}
+Exception::test::foo();
+--EXPECTF--
+ok
+
Index: Zend/tests/ns_043.phpt
===================================================================
RCS file: Zend/tests/ns_043.phpt
diff -N Zend/tests/ns_043.phpt
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ Zend/tests/ns_043.phpt 21 Aug 2007 23:08:37 -0000
@@ -0,0 +1,20 @@
+--TEST--
+043: namespace with brackets, class declaration + function declaration
+--FILE--
+<?php
+namespace Exception {
+class test {
+static function foo() {
+ echo "ok\n";
+}
+}
+function foo() {
+ echo "ok\n";
+}
+}
+Exception::test::foo();
+Exception::foo();
+--EXPECTF--
+ok
+ok
+
Index: Zend/tests/ns_044.phpt
===================================================================
RCS file: Zend/tests/ns_044.phpt
diff -N Zend/tests/ns_044.phpt
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ Zend/tests/ns_044.phpt 21 Aug 2007 23:08:37 -0000
@@ -0,0 +1,34 @@
+--TEST--
+044: namespace with brackets, two namespace declarations
+--FILE--
+<?php
+namespace Exception {
+class test {
+static function foo() {
+ echo "ok\n";
+}
+}
+function foo() {
+ echo "ok\n";
+}
+}
+Exception::test::foo();
+Exception::foo();
+namespace Second {
+class test {
+static function foo() {
+ echo "ok\n";
+}
+}
+function foo() {
+ echo "ok\n";
+}
+}
+Second::test::foo();
+Second::foo();
+--EXPECTF--
+ok
+ok
+ok
+ok
+
Index: Zend/tests/ns_045.phpt
===================================================================
RCS file: Zend/tests/ns_045.phpt
diff -N Zend/tests/ns_045.phpt
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ Zend/tests/ns_045.phpt 21 Aug 2007 23:08:37 -0000
@@ -0,0 +1,30 @@
+--TEST--
+045: illegal nested namespace with brackets
+--FILE--
+<?php
+namespace Exception {
+class test {
+static function foo() {
+ echo "ok\n";
+}
+}
+function foo() {
+ echo "ok\n";
+}
+test::foo();
+foo();
+namespace Second {
+class test {
+static function foo() {
+ echo "ok\n";
+}
+}
+function foo() {
+ echo "ok\n";
+}
+}
+}
+Second::test::foo();
+Second::foo();
+--EXPECTF--
+Fatal error: Namespace cannot be declared twice (without brackets) or nested
within brackets in %sns_045.php on line 13
\ No newline at end of file
Index: Zend/tests/ns_046.phpt
===================================================================
RCS file: Zend/tests/ns_046.phpt
diff -N Zend/tests/ns_046.phpt
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ Zend/tests/ns_046.phpt 21 Aug 2007 23:08:37 -0000
@@ -0,0 +1,31 @@
+--TEST--
+046: smart import
+--FILE--
+<?php
+namespace foo {
+ class bar {
+ function __construct()
+ {
+ echo "foo::bar\n";
+ }
+ }
+ new bar;
+}
+import foo::bar;
+namespace gronk {
+ import foo::bar as gronk;
+ class bar {
+ function __construct()
+ {
+ echo "gronk::bar\n";
+ }
+ }
+ new bar;
+ new gronk;
+}
+new bar();
+--EXPECT--
+foo::bar
+gronk::bar
+foo::bar
+foo::bar
\ No newline at end of file
--
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php