From: Nikita Popov Date: Sat, 19 Jul 2014 13:13:50 +0000 (+0200) Subject: Port class const decl X-Git-Tag: POST_AST_MERGE^2~118 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=222430d99cd6dc8e31228a9c91e615a2c2987b6d;p=php Port class const decl --- diff --git a/Zend/zend_ast.h b/Zend/zend_ast.h index 01f83d6694..bb184cd9a8 100644 --- a/Zend/zend_ast.h +++ b/Zend/zend_ast.h @@ -106,6 +106,9 @@ enum _zend_ast_kind { ZEND_AST_PROP_DECL, ZEND_AST_PROP_ELEM, + + ZEND_AST_CLASS_CONST_DECL, + ZEND_AST_CONST_ELEM, }; typedef unsigned short zend_ast_kind; diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c index 4697a4255d..66eb470100 100644 --- a/Zend/zend_compile.c +++ b/Zend/zend_compile.c @@ -6512,6 +6512,44 @@ void zend_compile_prop_decl(zend_ast *ast TSRMLS_DC) { } } +void zend_compile_class_const_decl(zend_ast *ast TSRMLS_DC) { + zend_class_entry *ce = CG(active_class_entry); + zend_uint i; + + for (i = 0; i < ast->children; ++i) { + zend_ast *const_ast = ast->child[i]; + zend_ast *name_ast = const_ast->child[0]; + zend_ast *value_ast = const_ast->child[1]; + zend_string *name = Z_STR_P(zend_ast_get_zval(name_ast)); + zval value_zv; + + if (ce->ce_flags & ZEND_ACC_TRAIT) { + zend_error_noreturn(E_COMPILE_ERROR, "Traits cannot have constants"); + return; + } + + if (value_ast) { + _tmp_compile_const_expr(&value_zv, value_ast TSRMLS_CC); + } else { + ZVAL_NULL(&value_zv); + } + + if (Z_TYPE(value_zv) == IS_ARRAY + || (Z_TYPE(value_zv) == IS_CONSTANT_AST && Z_ASTVAL(value_zv)->kind == ZEND_AST_ARRAY) + ) { + zend_error_noreturn(E_COMPILE_ERROR, "Arrays are not allowed in class constants"); + } + + name = zend_new_interned_string(name TSRMLS_CC); + if (zend_hash_add(&ce->constants_table, name, &value_zv) == NULL) { + zend_error_noreturn(E_COMPILE_ERROR, "Cannot redefine class constant %s::%s", + ce->name->val, name); + } + + // TODO.AST doc comment + } +} + void zend_compile_binary_op(znode *result, zend_ast *ast TSRMLS_DC) { zend_ast *left_ast = ast->child[0]; zend_ast *right_ast = ast->child[1]; @@ -7352,6 +7390,9 @@ void zend_compile_stmt(zend_ast *ast TSRMLS_DC) { case ZEND_AST_PROP_DECL: zend_compile_prop_decl(ast TSRMLS_CC); break; + case ZEND_AST_CLASS_CONST_DECL: + zend_compile_class_const_decl(ast TSRMLS_CC); + break; default: { znode result; diff --git a/Zend/zend_language_parser.y b/Zend/zend_language_parser.y index 9febbc52a8..e2018e517a 100644 --- a/Zend/zend_language_parser.y +++ b/Zend/zend_language_parser.y @@ -628,7 +628,7 @@ class_statement_list: class_statement: variable_modifiers property_list ';' { $$.u.ast = $2.u.ast; $$.u.ast->attr = Z_LVAL($1.u.constant); AS($$); } - | class_constant_declaration ';' + | class_const_list ';' { $$.u.ast = $1.u.ast; AS($$); } | trait_use_statement | method_modifiers function returns_ref T_STRING '(' parameter_list ')' method_body { $$.u.ast = zend_ast_create_func_decl(ZEND_AST_METHOD, $3.EA | Z_LVAL($1.u.constant), @@ -733,9 +733,15 @@ property: { $$.u.ast = zend_ast_create_binary(ZEND_AST_PROP_ELEM, AST_ZVAL(&$1), $3.u.ast); } ; -class_constant_declaration: - class_constant_declaration ',' T_STRING '=' static_scalar { zend_do_declare_class_constant(&$3, &$5 TSRMLS_CC); } - | T_CONST T_STRING '=' static_scalar { zend_do_declare_class_constant(&$2, &$4 TSRMLS_CC); } +class_const_list: + class_const_list ',' class_const { $$.u.ast = zend_ast_dynamic_add($1.u.ast, $3.u.ast); } + | class_const + { $$.u.ast = zend_ast_create_dynamic_and_add(ZEND_AST_CLASS_CONST_DECL, $1.u.ast); } +; + +class_const: + T_CONST T_STRING '=' expr + { $$.u.ast = zend_ast_create_binary(ZEND_AST_CONST_ELEM, AST_ZVAL(&$2), $4.u.ast); } ; echo_expr_list: