From: Nikita Popov Date: Fri, 18 Jul 2014 12:57:00 +0000 (+0200) Subject: Use dedicated func_decl ast node X-Git-Tag: POST_AST_MERGE^2~134 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=359f99fe4850c1338b1b52b5e98705da4de6debd;p=php Use dedicated func_decl ast node Functions need a bunch of extra info, that becomes inconvenient to handle using the normal ast structure. --- diff --git a/Zend/zend_ast.c b/Zend/zend_ast.c index 85b6448908..3edc1f9fda 100644 --- a/Zend/zend_ast.c +++ b/Zend/zend_ast.c @@ -45,6 +45,24 @@ ZEND_API zend_ast *zend_ast_create_zval_ex(zval *zv, zend_ast_attr attr) return (zend_ast *) ast; } +ZEND_API zend_ast *zend_ast_create_func_decl( + zend_ast_kind kind, zend_bool returns_ref, zend_uint start_lineno, zend_uint end_lineno, + zend_string *name, zend_ast *params, zend_ast *uses, zend_ast *stmt +) { + zend_ast_func_decl *ast = emalloc(sizeof(zend_ast_func_decl)); + + ast->kind = kind; + ast->returns_ref = returns_ref; + ast->start_lineno = start_lineno; + ast->end_lineno = end_lineno; + ast->name = name; + ast->params = params; + ast->uses = uses; + ast->stmt = stmt; + + return (zend_ast *) ast; +} + static zend_ast *zend_ast_create_from_va_list( zend_uint children, zend_ast_kind kind, zend_ast_attr attr, va_list va ) { @@ -315,16 +333,34 @@ ZEND_API zend_ast *zend_ast_copy(zend_ast *ast) ZEND_API void zend_ast_destroy(zend_ast *ast) { - int i; + if (!ast) { + return; + } - if (ast->kind == ZEND_AST_ZVAL) { - zval_ptr_dtor(zend_ast_get_zval(ast)); - } else if (ast->kind != ZEND_AST_ZNODE) { - for (i = 0; i < ast->children; i++) { - if (ast->child[i]) { + switch (ast->kind) { + case ZEND_AST_ZVAL: + zval_ptr_dtor(zend_ast_get_zval(ast)); + break; + case ZEND_AST_ZNODE: + break; + case ZEND_AST_FUNC_DECL: + case ZEND_AST_CLOSURE: + { + zend_ast_func_decl *fn = (zend_ast_func_decl *) ast; + STR_RELEASE(fn->name); + zend_ast_destroy(fn->params); + zend_ast_destroy(fn->uses); + zend_ast_destroy(fn->stmt); + break; + } + default: + { + zend_uint i; + for (i = 0; i < ast->children; i++) { zend_ast_destroy(ast->child[i]); } } } + efree(ast); } diff --git a/Zend/zend_ast.h b/Zend/zend_ast.h index 3c22fda349..490046d057 100644 --- a/Zend/zend_ast.h +++ b/Zend/zend_ast.h @@ -100,7 +100,6 @@ enum _zend_ast_kind { ZEND_AST_TYPE, ZEND_AST_FUNC_DECL, - ZEND_AST_CLOSURE, ZEND_AST_CLOSURE_USES, }; @@ -123,6 +122,18 @@ typedef struct _zend_ast_zval { zval val; } zend_ast_zval; +/* Using a separate structure as it needs a bunch of extra information. */ +typedef struct _zend_ast_func_decl { + zend_ast_kind kind; + zend_bool returns_ref; + zend_uint start_lineno; + zend_uint end_lineno; + zend_string *name; + zend_ast *params; + zend_ast *uses; + zend_ast *stmt; +} zend_ast_func_decl; + static inline zval *zend_ast_get_zval(zend_ast *ast) { return &((zend_ast_zval *) ast)->val; } @@ -134,6 +145,11 @@ ZEND_API zend_ast *zend_ast_create_ex( ZEND_API zend_ast *zend_ast_create( zend_uint children, zend_ast_kind kind, ...); +ZEND_API zend_ast *zend_ast_create_func_decl( + zend_ast_kind kind, zend_bool by_ref, zend_uint start_lineno, zend_uint end_lineno, + zend_string *name, zend_ast *params, zend_ast *uses, zend_ast *stmt +); + ZEND_API zend_ast *zend_ast_create_dynamic(zend_ast_kind kind); ZEND_API zend_ast *zend_ast_dynamic_add(zend_ast *ast, zend_ast *op); ZEND_API void zend_ast_dynamic_shrink(zend_ast **ast); diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c index 17013401f3..5278abaed0 100644 --- a/Zend/zend_compile.c +++ b/Zend/zend_compile.c @@ -7004,13 +7004,13 @@ void zend_compile_closure_uses(zend_ast *ast TSRMLS_DC) { } } -static void zend_begin_func_decl( - znode *result, zend_string *name, zend_uint start_lineno, zend_bool returns_ref TSRMLS_DC -) { +void zend_compile_func_decl(znode *result, zend_ast *ast TSRMLS_DC) { + zend_ast_func_decl *fn = (zend_ast_func_decl *) ast; + zend_op_array *orig_op_array = CG(active_op_array); zend_op_array *op_array = emalloc(sizeof(zend_op_array)); - zend_string *lcname; + zend_string *name = fn->name, *lcname; zend_op *opline; - zend_bool is_closure = result != NULL; + zend_bool is_closure = ast->kind == ZEND_AST_CLOSURE; // TODO.AST interactive (not just here - also bpc etc!) @@ -7023,8 +7023,9 @@ static void zend_begin_func_decl( op_array->function_name = STR_COPY(name); } - op_array->line_start = start_lineno; - if (returns_ref) { + op_array->line_start = fn->start_lineno; + op_array->line_end = fn->end_lineno; + if (fn->returns_ref) { op_array->fn_flags |= ZEND_ACC_RETURN_REFERENCE; } if (is_closure) { @@ -7078,7 +7079,7 @@ static void zend_begin_func_decl( if (CG(compiler_options) & ZEND_COMPILE_EXTENDED_INFO) { zend_op *opline_ext = emit_op(NULL, ZEND_EXT_NOP, NULL, NULL TSRMLS_CC); - opline_ext->lineno = start_lineno; + opline_ext->lineno = fn->start_lineno; } { @@ -7100,9 +7101,11 @@ static void zend_begin_func_decl( zend_stack_push(&CG(foreach_copy_stack), (void *) &dummy_opline); } -} -static void zend_end_func_decl(TSRMLS_D) { + zend_compile_params(fn->params TSRMLS_CC); + zend_compile_closure_uses(fn->uses TSRMLS_CC); + zend_compile_stmt(fn->stmt TSRMLS_CC); + zend_do_extended_info(TSRMLS_C); zend_do_return(NULL, 0 TSRMLS_CC); @@ -7110,49 +7113,13 @@ static void zend_end_func_decl(TSRMLS_D) { zend_release_labels(0 TSRMLS_CC); // TODO.AST __autoload - // TODO.AST end line // TODO.AST doc comment /* Pop the switch and foreach separators */ zend_stack_del_top(&CG(switch_cond_stack)); zend_stack_del_top(&CG(foreach_copy_stack)); -} -void zend_compile_func_decl(zend_ast *ast TSRMLS_DC) { - zend_ast *name_ast = ast->child[0]; - zend_ast *params_ast = ast->child[1]; - zend_ast *stmt_ast = ast->child[2]; - zend_bool returns_ref = ast->attr; - zend_string *name = Z_STR_P(zend_ast_get_zval(name_ast)); - - zend_op_array *orig_op_array = CG(active_op_array); - zend_begin_func_decl(NULL, name, ast->lineno, returns_ref TSRMLS_CC); - - zend_compile_params(params_ast TSRMLS_CC); - zend_compile_stmt(stmt_ast TSRMLS_CC); - - zend_end_func_decl(TSRMLS_C); - CG(active_op_array) = orig_op_array; -} - -void zend_compile_closure(znode *result, zend_ast *ast TSRMLS_DC) { - zend_ast *params_ast = ast->child[0]; - zend_ast *uses_ast = ast->child[1]; - zend_ast *stmt_ast = ast->child[2]; - zend_bool returns_ref = ast->attr; - zend_string *name = STR_INIT("{closure}", sizeof("{closure}") - 1, 0); - - zend_op_array *orig_op_array = CG(active_op_array); - zend_begin_func_decl(result, name, ast->lineno, returns_ref TSRMLS_CC); - - zend_compile_closure_uses(uses_ast TSRMLS_CC); - zend_compile_params(params_ast TSRMLS_CC); - zend_compile_stmt(stmt_ast TSRMLS_CC); - - zend_end_func_decl(TSRMLS_C); CG(active_op_array) = orig_op_array; - - STR_RELEASE(name); } void zend_compile_binary_op(znode *result, zend_ast *ast TSRMLS_DC) { @@ -7994,7 +7961,7 @@ void zend_compile_stmt(zend_ast *ast TSRMLS_DC) { zend_compile_try(ast TSRMLS_CC); break; case ZEND_AST_FUNC_DECL: - zend_compile_func_decl(ast TSRMLS_CC); + zend_compile_func_decl(NULL, ast TSRMLS_CC); break; default: { @@ -8121,7 +8088,7 @@ void zend_compile_expr(znode *result, zend_ast *ast TSRMLS_DC) { zend_compile_magic_const(result, ast TSRMLS_CC); return; case ZEND_AST_CLOSURE: - zend_compile_closure(result, ast TSRMLS_CC); + zend_compile_func_decl(result, ast TSRMLS_CC); return; default: ZEND_ASSERT(0 /* not supported */); diff --git a/Zend/zend_language_parser.y b/Zend/zend_language_parser.y index 7fdf5eb8e6..6798b5ac07 100644 --- a/Zend/zend_language_parser.y +++ b/Zend/zend_language_parser.y @@ -389,8 +389,9 @@ unset_variable: function_declaration_statement: function is_reference T_STRING '(' parameter_list ')' '{' inner_statement_list '}' - { $$.u.ast = zend_ast_create_ex(3, ZEND_AST_FUNC_DECL, - $2.op_type, AST_ZVAL(&$3), $5.u.ast, $8.u.ast); } + { $$.u.ast = zend_ast_create_func_decl(ZEND_AST_FUNC_DECL, $2.op_type, + $1.u.op.opline_num, CG(zend_lineno), Z_STR($3.u.constant), + $5.u.ast, NULL, $8.u.ast); } ; class_declaration_statement: @@ -870,8 +871,10 @@ expr_without_variable: | T_YIELD expr T_DOUBLE_ARROW expr { $$.u.ast = zend_ast_create_binary(ZEND_YIELD, $4.u.ast, $2.u.ast); } | function is_reference '(' parameter_list ')' lexical_vars '{' inner_statement_list '}' - { $$.u.ast = zend_ast_create_ex(3, ZEND_AST_CLOSURE, - $2.op_type, $4.u.ast, $6.u.ast, $8.u.ast); } + { $$.u.ast = zend_ast_create_func_decl(ZEND_AST_CLOSURE, $2.op_type, + $1.u.op.opline_num, CG(zend_lineno), + STR_INIT("{closure}", sizeof("{closure}") - 1, 0), + $4.u.ast, $6.u.ast, $8.u.ast); } | T_STATIC function is_reference { zend_do_begin_lambda_function_declaration(&$$, &$2, $3.op_type, 1 TSRMLS_CC); } '(' parameter_list ')' { zend_compile_params($6.u.ast TSRMLS_CC); zend_ast_destroy($6.u.ast); } lexical_vars { zend_compile_closure_uses($9.u.ast TSRMLS_CC); if ($9.u.ast) zend_ast_destroy($9.u.ast); } '{' inner_statement_list '}' { AS($12); zend_do_end_function_declaration(&$2 TSRMLS_CC); $$.u.ast = AST_ZNODE(&$4); }