]> granicus.if.org Git - php/commitdiff
Port property declarations
authorNikita Popov <nikic@php.net>
Sat, 19 Jul 2014 12:54:56 +0000 (14:54 +0200)
committerNikita Popov <nikic@php.net>
Sat, 19 Jul 2014 12:54:56 +0000 (14:54 +0200)
Zend/zend_ast.h
Zend/zend_compile.c
Zend/zend_language_parser.y

index 1e942ece34828c7d38210d77834beb30a46d9596..01f83d6694da5383dfc96ec12e9e51e68bd2f999 100644 (file)
@@ -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;
index 50fa914c903c85324833576349e7821458d68785..4697a4255d84ea93f76e0745363f27f03ba61397 100644 (file)
@@ -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;
index 40c4061ec1ef9843452c1b6153487fe7081b1b20..9febbc52a8acf2afb657ebb12d8ebc39b3b56818 100644 (file)
@@ -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: