From: Nikita Popov Date: Fri, 18 Jul 2014 13:47:46 +0000 (+0200) Subject: Support static closures X-Git-Tag: POST_AST_MERGE^2~131 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=adbddf4e5b6ae33c758d239a25488eb692777a0c;p=php Support static closures --- diff --git a/Zend/zend_ast.c b/Zend/zend_ast.c index 891b36d9af..69321e044d 100644 --- a/Zend/zend_ast.c +++ b/Zend/zend_ast.c @@ -46,16 +46,17 @@ ZEND_API zend_ast *zend_ast_create_zval_ex(zval *zv, zend_ast_attr attr) } 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_ast_kind kind, zend_uint flags, zend_uint start_lineno, zend_uint end_lineno, unsigned char *lex_pos, zend_string *doc_comment, 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->attr = 0; ast->start_lineno = start_lineno; ast->end_lineno = end_lineno; + ast->flags = flags; ast->lex_pos = lex_pos; ast->doc_comment = doc_comment; ast->name = name; diff --git a/Zend/zend_ast.h b/Zend/zend_ast.h index d3eca8117c..f20446fd22 100644 --- a/Zend/zend_ast.h +++ b/Zend/zend_ast.h @@ -125,9 +125,10 @@ typedef struct _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_ast_attr attr; /* Unused - for structure compatibility */ zend_uint start_lineno; zend_uint end_lineno; + zend_uint flags; unsigned char *lex_pos; zend_string *doc_comment; zend_string *name; @@ -148,7 +149,7 @@ 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_ast_kind kind, zend_uint flags, zend_uint start_lineno, zend_uint end_lineno, unsigned char *lex_pos, zend_string *doc_comment, zend_string *name, zend_ast *params, zend_ast *uses, zend_ast *stmt ); diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c index e6e641abf0..1d16b9b3d3 100644 --- a/Zend/zend_compile.c +++ b/Zend/zend_compile.c @@ -7023,14 +7023,12 @@ void zend_compile_func_decl(znode *result, zend_ast *ast TSRMLS_DC) { op_array->function_name = STR_COPY(name); } + op_array->fn_flags |= fn->flags; op_array->line_start = fn->start_lineno; op_array->line_end = fn->end_lineno; if (fn->doc_comment) { op_array->doc_comment = STR_COPY(fn->doc_comment); } - if (fn->returns_ref) { - op_array->fn_flags |= ZEND_ACC_RETURN_REFERENCE; - } if (is_closure) { op_array->fn_flags |= ZEND_ACC_CLOSURE; } @@ -7116,7 +7114,6 @@ void zend_compile_func_decl(znode *result, zend_ast *ast TSRMLS_DC) { zend_release_labels(0 TSRMLS_CC); // TODO.AST __autoload - // TODO.AST doc comment /* Pop the switch and foreach separators */ zend_stack_del_top(&CG(switch_cond_stack)); diff --git a/Zend/zend_language_parser.y b/Zend/zend_language_parser.y index 68049e098f..1dd800e6e4 100644 --- a/Zend/zend_language_parser.y +++ b/Zend/zend_language_parser.y @@ -388,8 +388,8 @@ unset_variable: ; function_declaration_statement: - function is_reference T_STRING '(' parameter_list ')' '{' inner_statement_list '}' - { $$.u.ast = zend_ast_create_func_decl(ZEND_AST_FUNC_DECL, $2.op_type, + function returns_ref T_STRING '(' parameter_list ')' '{' inner_statement_list '}' + { $$.u.ast = zend_ast_create_func_decl(ZEND_AST_FUNC_DECL, $2.EA, $1.EA, CG(zend_lineno), LANG_SCNG(yy_text), $1.u.op.ptr, Z_STR($3.u.constant), $5.u.ast, NULL, $8.u.ast); } ; @@ -870,14 +870,17 @@ expr_without_variable: | T_YIELD expr { $$.u.ast = zend_ast_create_binary(ZEND_YIELD, $2.u.ast, NULL); } | 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_func_decl(ZEND_AST_CLOSURE, $2.op_type, + | function returns_ref '(' parameter_list ')' lexical_vars '{' inner_statement_list '}' + { $$.u.ast = zend_ast_create_func_decl(ZEND_AST_CLOSURE, $2.EA, $1.EA, CG(zend_lineno), LANG_SCNG(yy_text), $1.u.op.ptr, STR_INIT("{closure}", sizeof("{closure}") - 1, 0), - $4.u.ast, $6.u.ast, $8.u.ast); } - | T_STATIC function2 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); } + $4.u.ast, $6.u.ast, $8.u.ast); } + | T_STATIC function returns_ref '(' parameter_list ')' lexical_vars + '{' inner_statement_list '}' + { $$.u.ast = zend_ast_create_func_decl(ZEND_AST_CLOSURE, + $3.EA | ZEND_ACC_STATIC, $2.EA, CG(zend_lineno), LANG_SCNG(yy_text), + $2.u.op.ptr, STR_INIT("{closure}", sizeof("{closure}") - 1, 0), + $5.u.ast, $7.u.ast, $9.u.ast); } ; function: @@ -885,6 +888,11 @@ function: { $$.EA = CG(zend_lineno); $$.u.op.ptr = CG(doc_comment); CG(doc_comment) = NULL; } ; +returns_ref: + /* empty */ { $$.EA = 0; } + | '&' { $$.EA = ZEND_ACC_RETURN_REFERENCE; } +; + function2: T_FUNCTION { $$.EA = CG(zend_lineno); } ;