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

Reply via email to