diff options
| author | Igor Wiedler <igor@wiedler.ch> | 2013-07-23 20:21:48 +0200 |
|---|---|---|
| committer | Igor Wiedler <igor@wiedler.ch> | 2013-08-22 15:51:26 +0200 |
| commit | 4adf49eeaffc23cc6f4be53c2d89c720bd96d0c3 (patch) | |
| tree | 57373a102eb74080663a346dc985fa7b00acf267 | |
| parent | e1125a6a894a8b005aaea6b8ce2e0ea6bf39e483 (diff) | |
| download | php-git-4adf49eeaffc23cc6f4be53c2d89c720bd96d0c3.tar.gz | |
Import namespaced constants via new 'use const' sequence
| -rw-r--r-- | Zend/tests/use_const/alias.phpt | 26 | ||||
| -rw-r--r-- | Zend/tests/use_const/basic.phpt | 22 | ||||
| -rw-r--r-- | Zend/tests/use_const/conflicting_use.phpt | 21 | ||||
| -rw-r--r-- | Zend/tests/use_const/function_and_cons.phpt | 25 | ||||
| -rw-r--r-- | Zend/tests/use_const/no_global_fallback.phpt | 18 | ||||
| -rw-r--r-- | Zend/tests/use_const/shadow_core.phpt | 24 | ||||
| -rw-r--r-- | Zend/tests/use_const/shadow_core_null.phpt | 12 | ||||
| -rw-r--r-- | Zend/tests/use_const/shadow_global.phpt | 28 | ||||
| -rw-r--r-- | Zend/tests/use_const/shadow_global_same_ns.phpt | 21 | ||||
| -rw-r--r-- | Zend/zend_compile.c | 47 | ||||
| -rw-r--r-- | Zend/zend_compile.h | 2 | ||||
| -rw-r--r-- | Zend/zend_globals.h | 1 | ||||
| -rw-r--r-- | Zend/zend_language_parser.y | 13 |
13 files changed, 251 insertions, 9 deletions
diff --git a/Zend/tests/use_const/alias.phpt b/Zend/tests/use_const/alias.phpt new file mode 100644 index 0000000000..f179393006 --- /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 0000000000..6eaed7f27d --- /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 0000000000..f873fdcc65 --- /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 0000000000..6c975ba923 --- /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 0000000000..fad18797ba --- /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 0000000000..8052baebc6 --- /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 0000000000..5bbc9329df --- /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 0000000000..ddd47a264c --- /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 0000000000..7e8a871027 --- /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 8013a1e5d1..2660781e60 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 066c517089..3c944e45a6 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 2a1194affc..ddb5fc5df7 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 df3e55f95f..7cfab914de 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); } |
