Commit:    4adf49eeaffc23cc6f4be53c2d89c720bd96d0c3
Author:    Igor Wiedler <i...@wiedler.ch>         Tue, 23 Jul 2013 20:21:48 
+0200
Parents:   e1125a6a894a8b005aaea6b8ce2e0ea6bf39e483
Branches:  PHP-5.6 master

Link:       
http://git.php.net/?p=php-src.git;a=commitdiff;h=4adf49eeaffc23cc6f4be53c2d89c720bd96d0c3

Log:
Import namespaced constants via new 'use const' sequence

Changed paths:
  A  Zend/tests/use_const/alias.phpt
  A  Zend/tests/use_const/basic.phpt
  A  Zend/tests/use_const/conflicting_use.phpt
  A  Zend/tests/use_const/function_and_cons.phpt
  A  Zend/tests/use_const/no_global_fallback.phpt
  A  Zend/tests/use_const/shadow_core.phpt
  A  Zend/tests/use_const/shadow_core_null.phpt
  A  Zend/tests/use_const/shadow_global.phpt
  A  Zend/tests/use_const/shadow_global_same_ns.phpt
  M  Zend/zend_compile.c
  M  Zend/zend_compile.h
  M  Zend/zend_globals.h
  M  Zend/zend_language_parser.y

diff --git a/Zend/tests/use_const/alias.phpt b/Zend/tests/use_const/alias.phpt
new file mode 100644
index 0000000..f179393
--- /dev/null
+++ b/Zend/tests/use_const/alias.phpt
@@ -0,0 +1,26 @@
+--TEST--
+aliasing imported constants to resolve naming conflicts
+--FILE--
+<?php
+
+namespace foo {
+    const baz = 42;
+}
+
+namespace bar {
+    const baz = 43;
+}
+
+namespace {
+    use const foo\baz as foo_baz,
+              bar\baz as bar_baz;
+    var_dump(foo_baz);
+    var_dump(bar_baz);
+    echo "Done\n";
+}
+
+?>
+--EXPECT--
+int(42)
+int(43)
+Done
diff --git a/Zend/tests/use_const/basic.phpt b/Zend/tests/use_const/basic.phpt
new file mode 100644
index 0000000..6eaed7f
--- /dev/null
+++ b/Zend/tests/use_const/basic.phpt
@@ -0,0 +1,22 @@
+--TEST--
+import namespaced constant
+--FILE--
+<?php
+
+namespace foo\bar {
+    const baz = 42;
+    const qux = 43;
+}
+
+namespace {
+    use const foo\bar\baz, foo\bar\qux;
+    var_dump(baz);
+    var_dump(qux);
+    echo "Done\n";
+}
+
+?>
+--EXPECT--
+int(42)
+int(43)
+Done
diff --git a/Zend/tests/use_const/conflicting_use.phpt 
b/Zend/tests/use_const/conflicting_use.phpt
new file mode 100644
index 0000000..f873fdc
--- /dev/null
+++ b/Zend/tests/use_const/conflicting_use.phpt
@@ -0,0 +1,21 @@
+--TEST--
+use const statements with conflicting names
+--FILE--
+<?php
+
+namespace foo {
+    const baz = 42;
+}
+
+namespace bar {
+    const baz = 42;
+}
+
+namespace {
+    use const foo\baz, bar\baz;
+    echo "Done\n";
+}
+
+?>
+--EXPECTF--
+Fatal error: Cannot use bar\baz as baz because the name is already in use in 
%s on line %d
diff --git a/Zend/tests/use_const/function_and_cons.phpt 
b/Zend/tests/use_const/function_and_cons.phpt
new file mode 100644
index 0000000..6c975ba
--- /dev/null
+++ b/Zend/tests/use_const/function_and_cons.phpt
@@ -0,0 +1,25 @@
+--TEST--
+use function and use const in the same block
+--FILE--
+<?php
+
+namespace foo {
+    const bar = 'local const';
+    function bar() {
+        return 'local function';
+    }
+}
+
+namespace {
+    use const foo\bar;
+    use function foo\bar;
+    var_dump(bar);
+    var_dump(bar());
+    echo "Done\n";
+}
+
+?>
+--EXPECT--
+string(11) "local const"
+string(14) "local function"
+Done
diff --git a/Zend/tests/use_const/no_global_fallback.phpt 
b/Zend/tests/use_const/no_global_fallback.phpt
new file mode 100644
index 0000000..fad1879
--- /dev/null
+++ b/Zend/tests/use_const/no_global_fallback.phpt
@@ -0,0 +1,18 @@
+--TEST--
+non-existent imported constants should not be looked up in the global table
+--FILE--
+<?php
+
+namespace {
+    const baz = NULL;
+}
+
+namespace {
+    use const foo\bar\baz;
+    var_dump(baz);
+}
+
+?>
+--EXPECTF--
+Notice: Use of undefined constant baz - assumed 'baz' in %s on line %d
+string(3) "baz"
diff --git a/Zend/tests/use_const/shadow_core.phpt 
b/Zend/tests/use_const/shadow_core.phpt
new file mode 100644
index 0000000..8052bae
--- /dev/null
+++ b/Zend/tests/use_const/shadow_core.phpt
@@ -0,0 +1,24 @@
+--TEST--
+shadowing a global core constant with a local version
+--FILE--
+<?php
+
+namespace foo {
+    const PHP_VERSION = 42;
+}
+
+namespace {
+    var_dump(PHP_VERSION);
+}
+
+namespace {
+    use const foo\PHP_VERSION;
+    var_dump(PHP_VERSION);
+    echo "Done\n";
+}
+
+?>
+--EXPECTF--
+string(%d) "%s"
+int(42)
+Done
diff --git a/Zend/tests/use_const/shadow_core_null.phpt 
b/Zend/tests/use_const/shadow_core_null.phpt
new file mode 100644
index 0000000..5bbc932
--- /dev/null
+++ b/Zend/tests/use_const/shadow_core_null.phpt
@@ -0,0 +1,12 @@
+--TEST--
+shadowing null with a local version
+--FILE--
+<?php
+
+namespace foo {
+    const null = 42;
+}
+
+?>
+--EXPECTF--
+Fatal error: Cannot redeclare constant 'null' in %s on line %d
diff --git a/Zend/tests/use_const/shadow_global.phpt 
b/Zend/tests/use_const/shadow_global.phpt
new file mode 100644
index 0000000..ddd47a2
--- /dev/null
+++ b/Zend/tests/use_const/shadow_global.phpt
@@ -0,0 +1,28 @@
+--TEST--
+shadowing a global constant with a local version
+--FILE--
+<?php
+
+namespace {
+    const bar = 'global bar';
+}
+
+namespace foo {
+    const bar = 'local bar';
+}
+
+namespace {
+    var_dump(bar);
+}
+
+namespace {
+    use const foo\bar;
+    var_dump(bar);
+    echo "Done\n";
+}
+
+?>
+--EXPECT--
+string(10) "global bar"
+string(9) "local bar"
+Done
diff --git a/Zend/tests/use_const/shadow_global_same_ns.phpt 
b/Zend/tests/use_const/shadow_global_same_ns.phpt
new file mode 100644
index 0000000..7e8a871
--- /dev/null
+++ b/Zend/tests/use_const/shadow_global_same_ns.phpt
@@ -0,0 +1,21 @@
+--TEST--
+shadowing global constants defined in the same namespace as use
+--FILE--
+<?php
+
+namespace foo {
+    const bar = 'local';
+}
+
+namespace {
+    const bar = 'global';
+
+    use const foo\bar;
+    var_dump(bar);
+    echo "Done\n";
+}
+
+?>
+--EXPECT--
+string(5) "local"
+Done
diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c
index 8013a1e..2660781 100644
--- a/Zend/zend_compile.c
+++ b/Zend/zend_compile.c
@@ -205,6 +205,7 @@ void zend_init_compiler_data_structures(TSRMLS_D) /* {{{ */
        CG(has_bracketed_namespaces) = 0;
        CG(current_import) = NULL;
        CG(current_import_function) = NULL;
+       CG(current_import_const) = NULL;
        init_compiler_declarables(TSRMLS_C);
        zend_stack_init(&CG(context_stack));
 
@@ -2098,7 +2099,7 @@ void zend_resolve_non_class_name(znode *element_name, 
zend_bool check_namespace,
        if (current_import_sub) {
                len = Z_STRLEN(element_name->u.constant)+1;
                lcname = 
zend_str_tolower_dup(Z_STRVAL(element_name->u.constant), len);
-               /* Check if function matches imported name */
+               /* Check if function/const matches imported name */
                if (zend_hash_find(current_import_sub, lcname, len, 
(void**)&ns) == SUCCESS) {
                        zval_dtor(&element_name->u.constant);
                        element_name->u.constant = **ns;
@@ -2150,7 +2151,7 @@ void zend_resolve_function_name(znode *element_name, 
zend_bool check_namespace T
 
 void zend_resolve_const_name(znode *element_name, zend_bool check_namespace 
TSRMLS_DC) /* {{{ */
 {
-       zend_resolve_non_class_name(element_name, check_namespace, NULL 
TSRMLS_CC);
+       zend_resolve_non_class_name(element_name, check_namespace, 
CG(current_import_const) TSRMLS_CC);
 }
 /* }}} */
 
@@ -7030,6 +7031,12 @@ void zend_do_begin_namespace(const znode *name, 
zend_bool with_bracket TSRMLS_DC
                CG(current_import_function) = NULL;
        }
 
+       if (CG(current_import_const)) {
+               zend_hash_destroy(CG(current_import_const));
+               efree(CG(current_import_const));
+               CG(current_import_const) = NULL;
+       }
+
        if (CG(doc_comment)) {
                efree(CG(doc_comment));
                CG(doc_comment) = NULL;
@@ -7122,17 +7129,12 @@ void zend_do_use(znode *ns_name, znode *new_name, int 
is_global TSRMLS_DC) /* {{
 }
 /* }}} */
 
-void zend_do_use_function(znode *ns_name, znode *new_name, int is_global 
TSRMLS_DC) /* {{{ */
+void zend_do_use_non_class(znode *ns_name, znode *new_name, int is_global, 
HashTable *current_import_sub TSRMLS_DC) /* {{{ */
 {
        char *lcname;
        zval *name, *ns, tmp;
        zend_bool warn = 0;
 
-       if (!CG(current_import_function)) {
-               CG(current_import_function) = emalloc(sizeof(HashTable));
-               zend_hash_init(CG(current_import_function), 0, NULL, 
ZVAL_PTR_DTOR, 0);
-       }
-
        ALLOC_ZVAL(ns);
        *ns = ns_name->u.constant;
        if (new_name) {
@@ -7162,7 +7164,7 @@ void zend_do_use_function(znode *ns_name, znode 
*new_name, int is_global TSRMLS_
                zend_error(E_COMPILE_ERROR, "Cannot use %s as %s because '%s' 
is a special class name", Z_STRVAL_P(ns), Z_STRVAL_P(name), Z_STRVAL_P(name));
        }
 
-       if (zend_hash_add(CG(current_import_function), lcname, 
Z_STRLEN_P(name)+1, &ns, sizeof(zval*), NULL) != SUCCESS) {
+       if (zend_hash_add(current_import_sub, lcname, Z_STRLEN_P(name)+1, &ns, 
sizeof(zval*), NULL) != SUCCESS) {
                zend_error(E_COMPILE_ERROR, "Cannot use %s as %s because the 
name is already in use", Z_STRVAL_P(ns), Z_STRVAL_P(name));
        }
        if (warn) {
@@ -7173,6 +7175,28 @@ void zend_do_use_function(znode *ns_name, znode 
*new_name, int is_global TSRMLS_
 }
 /* }}} */
 
+void zend_do_use_function(znode *ns_name, znode *new_name, int is_global 
TSRMLS_DC) /* {{{ */
+{
+       if (!CG(current_import_function)) {
+               CG(current_import_function) = emalloc(sizeof(HashTable));
+               zend_hash_init(CG(current_import_function), 0, NULL, 
ZVAL_PTR_DTOR, 0);
+       }
+
+       zend_do_use_non_class(ns_name, new_name, is_global, 
CG(current_import_function) TSRMLS_CC);
+}
+/* }}} */
+
+void zend_do_use_const(znode *ns_name, znode *new_name, int is_global 
TSRMLS_DC) /* {{{ */
+{
+       if (!CG(current_import_const)) {
+               CG(current_import_const) = emalloc(sizeof(HashTable));
+               zend_hash_init(CG(current_import_const), 0, NULL, 
ZVAL_PTR_DTOR, 0);
+       }
+
+       zend_do_use_non_class(ns_name, new_name, is_global, 
CG(current_import_const) TSRMLS_CC);
+}
+/* }}} */
+
 void zend_do_declare_constant(znode *name, znode *value TSRMLS_DC) /* {{{ */
 {
        zend_op *opline;
@@ -7230,6 +7254,11 @@ void zend_do_end_namespace(TSRMLS_D) /* {{{ */
                efree(CG(current_import_function));
                CG(current_import_function) = NULL;
        }
+       if (CG(current_import_const)) {
+               zend_hash_destroy(CG(current_import_const));
+               efree(CG(current_import_const));
+               CG(current_import_const) = NULL;
+       }
 }
 /* }}} */
 
diff --git a/Zend/zend_compile.h b/Zend/zend_compile.h
index 066c517..3c944e4 100644
--- a/Zend/zend_compile.h
+++ b/Zend/zend_compile.h
@@ -638,7 +638,9 @@ void zend_do_begin_namespace(const znode *name, zend_bool 
with_brackets TSRMLS_D
 void zend_do_end_namespace(TSRMLS_D);
 void zend_verify_namespace(TSRMLS_D);
 void zend_do_use(znode *name, znode *new_name, int is_global TSRMLS_DC);
+void zend_do_use_non_class(znode *ns_name, znode *new_name, int is_global, 
HashTable *current_import_sub TSRMLS_DC);
 void zend_do_use_function(znode *name, znode *new_name, int is_global 
TSRMLS_DC);
+void zend_do_use_const(znode *name, znode *new_name, int is_global TSRMLS_DC);
 void zend_do_end_compilation(TSRMLS_D);
 
 void zend_do_resolve_class_name(znode *result, znode *class_name, int 
is_static TSRMLS_DC);
diff --git a/Zend/zend_globals.h b/Zend/zend_globals.h
index 2a1194a..ddb5fc5 100644
--- a/Zend/zend_globals.h
+++ b/Zend/zend_globals.h
@@ -132,6 +132,7 @@ struct _zend_compiler_globals {
        zval      *current_namespace;
        HashTable *current_import;
        HashTable *current_import_function;
+       HashTable *current_import_const;
        zend_bool  in_namespace;
        zend_bool  has_bracketed_namespaces;
 
diff --git a/Zend/zend_language_parser.y b/Zend/zend_language_parser.y
index df3e55f..7cfab91 100644
--- a/Zend/zend_language_parser.y
+++ b/Zend/zend_language_parser.y
@@ -241,6 +241,7 @@ top_statement:
                top_statement_list '}'                  { 
zend_do_end_namespace(TSRMLS_C); }
        |       T_USE use_declarations ';'      { 
zend_verify_namespace(TSRMLS_C); }
        |       T_USE T_FUNCTION use_function_declarations ';' { 
zend_verify_namespace(TSRMLS_C); }
+       |       T_USE T_CONST use_const_declarations ';'       { 
zend_verify_namespace(TSRMLS_C); }
        |       constant_declaration ';'                { 
zend_verify_namespace(TSRMLS_C); }
 ;
 
@@ -268,6 +269,18 @@ use_function_declaration:
        |       T_NS_SEPARATOR namespace_name T_AS T_STRING { 
zend_do_use_function(&$2, &$4, 1 TSRMLS_CC); }
 ;
 
+use_const_declarations:
+               use_const_declarations ',' use_const_declaration
+       |       use_const_declaration
+;
+
+use_const_declaration:
+               namespace_name                  { zend_do_use_const(&$1, NULL, 
0 TSRMLS_CC); }
+       |       namespace_name T_AS T_STRING    { zend_do_use_const(&$1, &$3, 0 
TSRMLS_CC); }
+       |       T_NS_SEPARATOR namespace_name { zend_do_use_const(&$2, NULL, 1 
TSRMLS_CC); }
+       |       T_NS_SEPARATOR namespace_name T_AS T_STRING { 
zend_do_use_const(&$2, &$4, 1 TSRMLS_CC); }
+;
+
 constant_declaration:
                constant_declaration ',' T_STRING '=' static_scalar     { 
zend_do_declare_constant(&$3, &$5 TSRMLS_CC); }
        |       T_CONST T_STRING '=' static_scalar { 
zend_do_declare_constant(&$2, &$4 TSRMLS_CC); }
-- 
PHP CVS Mailing List (http://www.php.net/)
To unsubscribe, visit: http://www.php.net/unsub.php

Reply via email to