]> granicus.if.org Git - php/commitdiff
Port if (partial)
authorNikita Popov <nikic@php.net>
Thu, 10 Jul 2014 14:38:04 +0000 (16:38 +0200)
committerNikita Popov <nikic@php.net>
Thu, 10 Jul 2014 14:38:04 +0000 (16:38 +0200)
Zend/zend_ast.h
Zend/zend_compile.c
Zend/zend_language_parser.y

index 0f07b8983f2d456147edcd9a747e673c4b4a171d..2f07cf3b426e19ce1718249ddb472f1cda766bf1 100644 (file)
@@ -80,6 +80,8 @@ enum _zend_ast_kind {
        ZEND_AST_WHILE,
        ZEND_AST_DO_WHILE,
        ZEND_AST_FOR,
+       ZEND_AST_IF,
+       ZEND_AST_IF_ELEM,
 };
 
 typedef unsigned short zend_ast_kind;
index 964b048c63760a1418c816e31bbca5adc92587ed..0556707ca8e516a70b1d3a9a48355cb971666595 100644 (file)
@@ -7164,6 +7164,46 @@ void zend_compile_for(zend_ast *ast TSRMLS_DC) {
        do_end_loop(opnum_loop, 0 TSRMLS_CC);
 }
 
+void zend_compile_if(zend_ast *ast TSRMLS_DC) {
+       zend_uint i;
+       zend_uint *jmp_opnums = safe_emalloc(sizeof(zend_uint), ast->children - 1, 0);
+       zend_uint opnum_last_jmpz = 0;
+               zend_op *opline;
+
+       for (i = 0; i < ast->children; ++i) {
+               zend_ast *elem_ast = ast->child[i];
+               zend_ast *cond_ast = elem_ast->child[0];
+               zend_ast *stmt_ast = elem_ast->child[1];
+
+               znode cond_node;
+               if (cond_ast) {
+                       zend_compile_expr(&cond_node, cond_ast TSRMLS_CC);
+
+                       opnum_last_jmpz = get_next_op_number(CG(active_op_array));
+                       emit_op(NULL, ZEND_JMPZ, &cond_node, NULL TSRMLS_CC);
+               }
+
+               zend_compile_stmt(stmt_ast TSRMLS_CC);
+
+               if (i != ast->children - 1) {
+                       jmp_opnums[i] = get_next_op_number(CG(active_op_array));
+                       emit_op(NULL, ZEND_JMP, NULL, NULL TSRMLS_CC);
+               }
+
+               if (cond_ast) {
+                       opline = &CG(active_op_array)->opcodes[opnum_last_jmpz];
+                       opline->op2.opline_num = get_next_op_number(CG(active_op_array));
+               }
+       }
+
+       for (i = 0; i < ast->children - 1; ++i) {
+               opline = &CG(active_op_array)->opcodes[jmp_opnums[i]];
+               opline->op1.opline_num = get_next_op_number(CG(active_op_array));
+       }
+
+       efree(jmp_opnums);
+}
+
 void zend_compile_stmt_list(zend_ast *ast TSRMLS_DC) {
        zend_uint i;
        for (i = 0; i < ast->children; ++i) {
@@ -7958,6 +7998,9 @@ void zend_compile_stmt(zend_ast *ast TSRMLS_DC) {
                case ZEND_AST_FOR:
                        zend_compile_for(ast TSRMLS_CC);
                        break;
+               case ZEND_AST_IF:
+                       zend_compile_if(ast TSRMLS_CC);
+                       break;
                default:
                {
                        znode result;
index a3bae7f48108811078649d1200b70aa740038d82..e561962fd61b384e0170c3dffd97fd83083200ee 100644 (file)
@@ -323,7 +323,8 @@ statement:
 
 unticked_statement:
                '{' inner_statement_list '}' { AN($$); }
-       |       T_IF parenthesis_expr { AC($2); zend_do_if_cond(&$2, &$1 TSRMLS_CC); } statement { AS($4); zend_do_if_after_statement(&$1, 1 TSRMLS_CC); } elseif_list else_single { zend_do_if_end(TSRMLS_C); AN($$); }
+       |       if_stmt
+       /*|     T_IF parenthesis_expr { AC($2); zend_do_if_cond(&$2, &$1 TSRMLS_CC); } statement { AS($4); zend_do_if_after_statement(&$1, 1 TSRMLS_CC); } elseif_list else_single { zend_do_if_end(TSRMLS_C); AN($$); }*/
        |       T_IF parenthesis_expr ':' { AC($2); zend_do_if_cond(&$2, &$1 TSRMLS_CC); } inner_statement_list { zend_do_if_after_statement(&$1, 1 TSRMLS_CC); } new_elseif_list new_else_single T_ENDIF ';' { zend_do_if_end(TSRMLS_C); AN($$); }
        |       T_WHILE parenthesis_expr while_statement
                        { $$.u.ast = zend_ast_create_binary(ZEND_AST_WHILE, $2.u.ast, $3.u.ast); }
@@ -331,15 +332,6 @@ unticked_statement:
                        { $$.u.ast = zend_ast_create_binary(ZEND_AST_DO_WHILE, $2.u.ast, $4.u.ast); }
        |       T_FOR '(' for_expr ';' for_expr ';' for_expr ')' for_statement
                        { $$.u.ast = zend_ast_create(4, ZEND_AST_FOR, $3.u.ast, $5.u.ast, $7.u.ast, $9.u.ast); }
-       /*|     T_FOR
-                       '('
-                               for_expr
-                       ';' { zend_do_free(&$3 TSRMLS_CC); $4.u.op.opline_num = get_next_op_number(CG(active_op_array)); }
-                               for_expr
-                       ';' { zend_do_extended_info(TSRMLS_C); zend_do_for_cond(&$6, &$7 TSRMLS_CC); }
-                               for_expr
-                       ')' { zend_do_free(&$9 TSRMLS_CC); zend_do_for_before_statement(&$4, &$7 TSRMLS_CC); }
-                       for_statement { zend_do_for_end(&$7 TSRMLS_CC); AN($$); }*/
        |       T_SWITCH parenthesis_expr       { AC($2); zend_do_switch_cond(&$2 TSRMLS_CC); } switch_case_list { zend_do_switch_end(&$4 TSRMLS_CC); AN($$); }
        |       T_BREAK ';'                     { $$.u.ast = zend_ast_create_unary(ZEND_BRK, NULL); }
        |       T_BREAK expr ';'        { $$.u.ast = zend_ast_create_unary(ZEND_BRK, $2.u.ast); }
@@ -541,12 +533,26 @@ while_statement:
 ;
 
 
+if_stmt_without_else:
+               T_IF parenthesis_expr statement
+                       { $$.u.ast = zend_ast_create_dynamic_and_add(ZEND_AST_IF,
+                             zend_ast_create_binary(ZEND_AST_IF_ELEM, $2.u.ast, $3.u.ast)); }
+       |       if_stmt_without_else T_ELSEIF parenthesis_expr statement
+                       { $$.u.ast = zend_ast_dynamic_add($1.u.ast,
+                             zend_ast_create_binary(ZEND_AST_IF_ELEM, $3.u.ast, $4.u.ast)); }
+;
 
-elseif_list:
-               /* empty */
-       |       elseif_list T_ELSEIF parenthesis_expr { AC($3); zend_do_if_cond(&$3, &$2 TSRMLS_CC); } statement { AS($5); zend_do_if_after_statement(&$2, 0 TSRMLS_CC); }
+if_stmt:
+               if_stmt_without_else { $$.u.ast = $1.u.ast; }
+       |       if_stmt_without_else T_ELSE statement
+                       { $$.u.ast = zend_ast_dynamic_add($1.u.ast,
+                             zend_ast_create_binary(ZEND_AST_IF_ELEM, NULL, $3.u.ast)); }
 ;
 
+/*elseif_list:
+               elseif_list T_ELSEIF parenthesis_expr { AC($3); zend_do_if_cond(&$3, &$2 TSRMLS_CC); } statement { AS($5); zend_do_if_after_statement(&$2, 0 TSRMLS_CC); }
+;*/
+
 
 new_elseif_list:
                /* empty */
@@ -554,12 +560,6 @@ new_elseif_list:
 ;
 
 
-else_single:
-               /* empty */
-       |       T_ELSE statement { AS($2); }
-;
-
-
 new_else_single:
                /* empty */
        |       T_ELSE ':' inner_statement_list