Support static closures

This commit is contained in:
Nikita Popov 2014-07-18 15:47:46 +02:00
parent 405b97e8a9
commit adbddf4e5b
4 changed files with 23 additions and 16 deletions

View file

@ -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_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, unsigned char *lex_pos, zend_string *doc_comment, zend_string *name,
zend_ast *params, zend_ast *uses, zend_ast *stmt zend_ast *params, zend_ast *uses, zend_ast *stmt
) { ) {
zend_ast_func_decl *ast = emalloc(sizeof(zend_ast_func_decl)); zend_ast_func_decl *ast = emalloc(sizeof(zend_ast_func_decl));
ast->kind = kind; ast->kind = kind;
ast->returns_ref = returns_ref; ast->attr = 0;
ast->start_lineno = start_lineno; ast->start_lineno = start_lineno;
ast->end_lineno = end_lineno; ast->end_lineno = end_lineno;
ast->flags = flags;
ast->lex_pos = lex_pos; ast->lex_pos = lex_pos;
ast->doc_comment = doc_comment; ast->doc_comment = doc_comment;
ast->name = name; ast->name = name;

View file

@ -125,9 +125,10 @@ typedef struct _zend_ast_zval {
/* Using a separate structure as it needs a bunch of extra information. */ /* Using a separate structure as it needs a bunch of extra information. */
typedef struct _zend_ast_func_decl { typedef struct _zend_ast_func_decl {
zend_ast_kind kind; zend_ast_kind kind;
zend_bool returns_ref; zend_ast_attr attr; /* Unused - for structure compatibility */
zend_uint start_lineno; zend_uint start_lineno;
zend_uint end_lineno; zend_uint end_lineno;
zend_uint flags;
unsigned char *lex_pos; unsigned char *lex_pos;
zend_string *doc_comment; zend_string *doc_comment;
zend_string *name; zend_string *name;
@ -148,7 +149,7 @@ ZEND_API zend_ast *zend_ast_create(
zend_uint children, zend_ast_kind kind, ...); zend_uint children, zend_ast_kind kind, ...);
ZEND_API zend_ast *zend_ast_create_func_decl( 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, unsigned char *lex_pos, zend_string *doc_comment, zend_string *name,
zend_ast *params, zend_ast *uses, zend_ast *stmt zend_ast *params, zend_ast *uses, zend_ast *stmt
); );

View file

@ -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->function_name = STR_COPY(name);
} }
op_array->fn_flags |= fn->flags;
op_array->line_start = fn->start_lineno; op_array->line_start = fn->start_lineno;
op_array->line_end = fn->end_lineno; op_array->line_end = fn->end_lineno;
if (fn->doc_comment) { if (fn->doc_comment) {
op_array->doc_comment = STR_COPY(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) { if (is_closure) {
op_array->fn_flags |= ZEND_ACC_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); zend_release_labels(0 TSRMLS_CC);
// TODO.AST __autoload // TODO.AST __autoload
// TODO.AST doc comment
/* Pop the switch and foreach separators */ /* Pop the switch and foreach separators */
zend_stack_del_top(&CG(switch_cond_stack)); zend_stack_del_top(&CG(switch_cond_stack));

View file

@ -388,8 +388,8 @@ unset_variable:
; ;
function_declaration_statement: function_declaration_statement:
function is_reference T_STRING '(' parameter_list ')' '{' inner_statement_list '}' function returns_ref T_STRING '(' parameter_list ')' '{' inner_statement_list '}'
{ $$.u.ast = zend_ast_create_func_decl(ZEND_AST_FUNC_DECL, $2.op_type, { $$.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, $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); } 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 { $$.u.ast = zend_ast_create_binary(ZEND_YIELD, $2.u.ast, NULL); }
| T_YIELD expr T_DOUBLE_ARROW expr | T_YIELD expr T_DOUBLE_ARROW expr
{ $$.u.ast = zend_ast_create_binary(ZEND_YIELD, $4.u.ast, $2.u.ast); } { $$.u.ast = zend_ast_create_binary(ZEND_YIELD, $4.u.ast, $2.u.ast); }
| function is_reference '(' parameter_list ')' lexical_vars '{' inner_statement_list '}' | function returns_ref '(' parameter_list ')' lexical_vars '{' inner_statement_list '}'
{ $$.u.ast = zend_ast_create_func_decl(ZEND_AST_CLOSURE, $2.op_type, { $$.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, $1.EA, CG(zend_lineno), LANG_SCNG(yy_text), $1.u.op.ptr,
STR_INIT("{closure}", sizeof("{closure}") - 1, 0), STR_INIT("{closure}", sizeof("{closure}") - 1, 0),
$4.u.ast, $6.u.ast, $8.u.ast); } $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); } | T_STATIC function returns_ref '(' parameter_list ')' lexical_vars
'(' 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 '}'
'{' inner_statement_list '}' { AS($12); zend_do_end_function_declaration(&$2 TSRMLS_CC); $$.u.ast = AST_ZNODE(&$4); } { $$.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: function:
@ -885,6 +888,11 @@ function:
{ $$.EA = CG(zend_lineno); $$.u.op.ptr = CG(doc_comment); CG(doc_comment) = NULL; } { $$.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: function2:
T_FUNCTION { $$.EA = CG(zend_lineno); } T_FUNCTION { $$.EA = CG(zend_lineno); }
; ;