diff options
Diffstat (limited to 'Zend')
-rw-r--r-- | Zend/zend_ast.h | 2 | ||||
-rw-r--r-- | Zend/zend_compile.c | 43 | ||||
-rw-r--r-- | Zend/zend_language_parser.y | 38 |
3 files changed, 64 insertions, 19 deletions
diff --git a/Zend/zend_ast.h b/Zend/zend_ast.h index 0f07b8983f..2f07cf3b42 100644 --- a/Zend/zend_ast.h +++ b/Zend/zend_ast.h @@ -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; diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c index 964b048c63..0556707ca8 100644 --- a/Zend/zend_compile.c +++ b/Zend/zend_compile.c @@ -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; diff --git a/Zend/zend_language_parser.y b/Zend/zend_language_parser.y index a3bae7f481..e561962fd6 100644 --- a/Zend/zend_language_parser.y +++ b/Zend/zend_language_parser.y @@ -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 |