From: Nikita Popov Date: Sat, 19 Jul 2014 12:54:56 +0000 (+0200) Subject: Port property declarations X-Git-Tag: POST_AST_MERGE^2~119 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=43d6e599cf96e1b056dbb4ed1ac35c9f7215521c;p=php Port property declarations --- diff --git a/Zend/zend_ast.h b/Zend/zend_ast.h index 1e942ece34..01f83d6694 100644 --- a/Zend/zend_ast.h +++ b/Zend/zend_ast.h @@ -103,6 +103,9 @@ enum _zend_ast_kind { ZEND_AST_CLOSURE, ZEND_AST_CLOSURE_USES, ZEND_AST_METHOD, + + ZEND_AST_PROP_DECL, + ZEND_AST_PROP_ELEM, }; typedef unsigned short zend_ast_kind; diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c index 50fa914c90..4697a4255d 100644 --- a/Zend/zend_compile.c +++ b/Zend/zend_compile.c @@ -6470,6 +6470,48 @@ void zend_compile_func_decl(znode *result, zend_ast *ast TSRMLS_DC) { CG(active_op_array) = orig_op_array; } +void zend_compile_prop_decl(zend_ast *ast TSRMLS_DC) { + zend_uint flags = ast->attr; + zend_class_entry *ce = CG(active_class_entry); + zend_uint i; + + if (ce->ce_flags & ZEND_ACC_INTERFACE) { + zend_error_noreturn(E_COMPILE_ERROR, "Interfaces may not include member variables"); + } + + if (flags & ZEND_ACC_ABSTRACT) { + zend_error_noreturn(E_COMPILE_ERROR, "Properties cannot be declared abstract"); + } + + for (i = 0; i < ast->children; ++i) { + zend_ast *prop_ast = ast->child[i]; + zend_ast *name_ast = prop_ast->child[0]; + zend_ast *value_ast = prop_ast->child[1]; + zend_string *name = Z_STR_P(zend_ast_get_zval(name_ast)); + zval value_zv; + + if (flags & ZEND_ACC_FINAL) { + zend_error_noreturn(E_COMPILE_ERROR, "Cannot declare property %s::$%s final, " + "the final modifier is allowed only for methods and classes", + ce->name->val, name->val); + } + + if (zend_hash_exists(&ce->properties_info, name)) { + zend_error_noreturn(E_COMPILE_ERROR, "Cannot redeclare %s::$%s", + ce->name->val, name->val); + } + + if (value_ast) { + _tmp_compile_const_expr(&value_zv, value_ast TSRMLS_CC); + } else { + ZVAL_NULL(&value_zv); + } + + name = zend_new_interned_string(name TSRMLS_CC); + zend_declare_property_ex(ce, name, &value_zv, flags, NULL /* TODO.AST doc comment */ TSRMLS_CC); + } +} + 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]; @@ -7307,6 +7349,9 @@ void zend_compile_stmt(zend_ast *ast TSRMLS_DC) { case ZEND_AST_METHOD: zend_compile_func_decl(NULL, ast TSRMLS_CC); break; + case ZEND_AST_PROP_DECL: + zend_compile_prop_decl(ast TSRMLS_CC); + break; default: { znode result; diff --git a/Zend/zend_language_parser.y b/Zend/zend_language_parser.y index 40c4061ec1..9febbc52a8 100644 --- a/Zend/zend_language_parser.y +++ b/Zend/zend_language_parser.y @@ -626,7 +626,8 @@ class_statement_list: class_statement: - variable_modifiers { CG(access_type) = Z_LVAL($1.u.constant); } class_variable_declaration ';' + variable_modifiers property_list ';' + { $$.u.ast = $2.u.ast; $$.u.ast->attr = Z_LVAL($1.u.constant); AS($$); } | class_constant_declaration ';' | trait_use_statement | method_modifiers function returns_ref T_STRING '(' parameter_list ')' method_body @@ -721,11 +722,15 @@ member_modifier: | T_FINAL { Z_LVAL($$.u.constant) = ZEND_ACC_FINAL; } ; -class_variable_declaration: - class_variable_declaration ',' T_VARIABLE { zend_do_declare_property(&$3, NULL, CG(access_type) TSRMLS_CC); } - | class_variable_declaration ',' T_VARIABLE '=' static_scalar { zend_do_declare_property(&$3, &$5, CG(access_type) TSRMLS_CC); } - | T_VARIABLE { zend_do_declare_property(&$1, NULL, CG(access_type) TSRMLS_CC); } - | T_VARIABLE '=' static_scalar { zend_do_declare_property(&$1, &$3, CG(access_type) TSRMLS_CC); } +property_list: + property_list ',' property { $$.u.ast = zend_ast_dynamic_add($1.u.ast, $3.u.ast); } + | property { $$.u.ast = zend_ast_create_dynamic_and_add(ZEND_AST_PROP_DECL, $1.u.ast); } +; + +property: + T_VARIABLE { $$.u.ast = zend_ast_create_binary(ZEND_AST_PROP_ELEM, AST_ZVAL(&$1), NULL); } + | T_VARIABLE '=' expr + { $$.u.ast = zend_ast_create_binary(ZEND_AST_PROP_ELEM, AST_ZVAL(&$1), $3.u.ast); } ; class_constant_declaration: