From: Nikita Popov Date: Sat, 12 Jul 2014 15:00:53 +0000 (+0200) Subject: Port static vars X-Git-Tag: POST_AST_MERGE^2~149 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=c58079b4fda6c23f112347ab208038480cfd6704;p=php Port static vars Need to figure out the constant expr stuff --- diff --git a/Zend/zend_ast.h b/Zend/zend_ast.h index 59d383a64e..0769bfa61b 100644 --- a/Zend/zend_ast.h +++ b/Zend/zend_ast.h @@ -73,6 +73,7 @@ enum _zend_ast_kind { ZEND_AST_STMT_LIST, ZEND_AST_GLOBAL, + ZEND_AST_STATIC, ZEND_AST_UNSET, ZEND_AST_RETURN, ZEND_AST_LABEL, diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c index 933ac8ffe8..4f190d764a 100644 --- a/Zend/zend_compile.c +++ b/Zend/zend_compile.c @@ -5878,6 +5878,22 @@ void zend_do_constant_expression(znode *result, zend_ast *ast TSRMLS_DC) /* {{{ } /* }}} */ +// TODO.AST Sort out the whole constant folding issue +static void _tmp_compile_const_expr(zval *result, zend_ast *ast TSRMLS_DC) { + ast = zend_ast_copy(ast); + zend_eval_const_expr(&ast TSRMLS_CC); + zend_compile_const_expr(&ast TSRMLS_CC); + if (ast->kind == ZEND_AST_ZVAL) { + ZVAL_COPY_VALUE(result, zend_ast_get_zval(ast)); + if (Z_TYPE_P(result) == IS_ARRAY) { + zend_make_immutable_array_r(result TSRMLS_CC); + } + efree(ast); + } else { + ZVAL_NEW_AST(result, ast); + } +} + /* {{{ zend_dirname Returns directory name component of path */ ZEND_API size_t zend_dirname(char *path, size_t len) @@ -6913,6 +6929,46 @@ void zend_compile_global_var(zend_ast *ast TSRMLS_DC) { efree(fetch_ast); } +void zend_compile_static_var(zend_ast *ast TSRMLS_DC) { + zend_ast *var_ast = ast->child[0]; + zend_ast *value_ast = ast->child[1]; + + znode var_node, result; + zval value_zv; + zend_op *opline; + + zend_compile_expr(&var_node, var_ast TSRMLS_CC); + if (var_node.op_type == IS_CONST) { + if (Z_TYPE(var_node.u.constant) != IS_STRING) { + convert_to_string(&var_node.u.constant); + } + } + + if (value_ast) { + _tmp_compile_const_expr(&value_zv, value_ast TSRMLS_CC); + } else { + ZVAL_NULL(&value_zv); + } + + if (!CG(active_op_array)->static_variables) { + if (CG(active_op_array)->scope) { + CG(active_op_array)->scope->ce_flags |= ZEND_HAS_STATIC_IN_METHODS; + } + ALLOC_HASHTABLE(CG(active_op_array)->static_variables); + zend_hash_init(CG(active_op_array)->static_variables, 8, NULL, ZVAL_PTR_DTOR, 0); + } + + zend_hash_update(CG(active_op_array)->static_variables, + Z_STR(var_node.u.constant), &value_zv); + + opline = emit_op(&result, ZEND_FETCH_W, &var_node, NULL TSRMLS_CC); + opline->extended_value = ZEND_FETCH_STATIC; + + zend_ast *fetch_ast = zend_ast_create_unary(ZEND_AST_VAR, var_ast); + zend_compile_assign_ref_common(NULL, fetch_ast, &result TSRMLS_CC); + efree(fetch_ast); +} + void zend_compile_unset(zend_ast *ast TSRMLS_DC) { zend_ast *var_ast = ast->child[0]; @@ -8263,6 +8319,9 @@ void zend_compile_stmt(zend_ast *ast TSRMLS_DC) { case ZEND_AST_GLOBAL: zend_compile_global_var(ast TSRMLS_CC); break; + case ZEND_AST_STATIC: + zend_compile_static_var(ast TSRMLS_CC); + break; case ZEND_AST_UNSET: zend_compile_unset(ast TSRMLS_CC); break; diff --git a/Zend/zend_language_parser.y b/Zend/zend_language_parser.y index 6170e9aa12..7cfcb70d62 100644 --- a/Zend/zend_language_parser.y +++ b/Zend/zend_language_parser.y @@ -345,7 +345,7 @@ unticked_statement: | T_RETURN expr ';' { $$.u.ast = zend_ast_create_unary(ZEND_AST_RETURN, $2.u.ast); } | T_GLOBAL global_var_list ';' { $$.u.ast = $2.u.ast; } - | T_STATIC static_var_list ';' { AN($$); } + | T_STATIC static_var_list ';' { $$.u.ast = $2.u.ast; } | T_ECHO echo_expr_list ';' { $$.u.ast = $2.u.ast; } | T_INLINE_HTML { $$.u.ast = zend_ast_create_unary(ZEND_ECHO, AST_ZVAL(&$1)); } | expr ';' { $$.u.ast = $1.u.ast; } @@ -361,9 +361,6 @@ unticked_statement: | ';' /* empty statement */ { $$.u.ast = NULL; } | T_TRY '{' inner_statement_list '}' catch_list finally_statement { $$.u.ast = zend_ast_create_ternary(ZEND_AST_TRY, $3.u.ast, $5.u.ast, $6.u.ast); } - /*| T_TRY { zend_do_try(&$1 TSRMLS_CC); } '{' inner_statement_list '}' { AS($4); } - catch_statement { zend_do_bind_catch(&$1, &$7 TSRMLS_CC); } - finally_statement { zend_do_end_finally(&$1, &$6, &$8 TSRMLS_CC); AN($$); }*/ | T_THROW expr ';' { $$.u.ast = zend_ast_create_unary(ZEND_THROW, $2.u.ast); } | T_GOTO T_STRING ';' { $$.u.ast = zend_ast_create_unary(ZEND_GOTO, AST_ZVAL(&$2)); } ; @@ -374,17 +371,11 @@ catch_list: | catch_list T_CATCH '(' name T_VARIABLE ')' '{' inner_statement_list '}' { $$.u.ast = zend_ast_dynamic_add($1.u.ast, zend_ast_create_ternary(ZEND_AST_CATCH, $4.u.ast, AST_ZVAL(&$5), $8.u.ast)); } - /*| T_CATCH '(' { zend_initialize_try_catch_element(&$1 TSRMLS_CC); } - fully_qualified_class_name { zend_do_first_catch(&$2 TSRMLS_CC); } - T_VARIABLE ')' { zend_do_begin_catch(&$1, &$4, &$6, &$2 TSRMLS_CC); } - '{' inner_statement_list '}' { AS($10); zend_do_end_catch(&$1 TSRMLS_CC); } - additional_catches { zend_do_mark_last_catch(&$2, &$13 TSRMLS_CC); $$ = $1;}*/ ; finally_statement: /* empty */ { $$.u.ast = NULL; } | T_FINALLY '{' inner_statement_list '}' { $$.u.ast = $3.u.ast; } - /*| T_FINALLY { zend_do_finally(&$1 TSRMLS_CC); } '{' inner_statement_list '}' { AS($4); $$ = $1; }*/ ; unset_variables: @@ -615,11 +606,15 @@ global_var: static_var_list: - static_var_list ',' T_VARIABLE { zend_do_fetch_static_variable(&$3, NULL, ZEND_FETCH_STATIC TSRMLS_CC); } - | static_var_list ',' T_VARIABLE '=' static_scalar { Z_CONST_FLAGS($5.u.constant) = 0; zend_do_fetch_static_variable(&$3, &$5, ZEND_FETCH_STATIC TSRMLS_CC); } - | T_VARIABLE { zend_do_fetch_static_variable(&$1, NULL, ZEND_FETCH_STATIC TSRMLS_CC); } - | T_VARIABLE '=' static_scalar { Z_CONST_FLAGS($3.u.constant) = 0; zend_do_fetch_static_variable(&$1, &$3, ZEND_FETCH_STATIC TSRMLS_CC); } + static_var_list ',' static_var { $$.u.ast = zend_ast_dynamic_add($1.u.ast, $3.u.ast); } + | static_var { $$.u.ast = zend_ast_create_dynamic_and_add(ZEND_AST_STMT_LIST, $1.u.ast); } +; +static_var: + T_VARIABLE + { $$.u.ast = zend_ast_create_binary(ZEND_AST_STATIC, AST_ZVAL(&$1), NULL); } + | T_VARIABLE '=' expr + { $$.u.ast = zend_ast_create_binary(ZEND_AST_STATIC, AST_ZVAL(&$1), $3.u.ast); } ;