]> granicus.if.org Git - php/commitdiff
Use dedicated func_decl ast node
authorNikita Popov <nikic@php.net>
Fri, 18 Jul 2014 12:57:00 +0000 (14:57 +0200)
committerNikita Popov <nikic@php.net>
Fri, 18 Jul 2014 12:57:00 +0000 (14:57 +0200)
Functions need a bunch of extra info, that becomes inconvenient
to handle using the normal ast structure.

Zend/zend_ast.c
Zend/zend_ast.h
Zend/zend_compile.c
Zend/zend_language_parser.y

index 85b644890810cebebf80dcf40fb37bccc8aa4092..3edc1f9fdae0542da7ee603f5c42366400d36462 100644 (file)
@@ -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);
 }
index 3c22fda3493d224bf83ea1b7daa9e2490757618b..490046d057e4bab823925a083d15e1175095fef7 100644 (file)
@@ -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);
index 17013401f33de79311b1f3b24accebc1490fb3da..5278abaed06615b7839b5f244b8a924106bd1463 100644 (file)
@@ -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 */);
index 7fdf5eb8e625778ae0ef3904ffe062fb8c86b7c8..6798b5ac0713efffb5bdbffe90db03e308572d36 100644 (file)
@@ -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); }