Port break/continue

This commit is contained in:
Nikita Popov 2014-07-09 23:05:21 +02:00
parent 5bf0c28fe3
commit cc8a6fa91e
2 changed files with 38 additions and 4 deletions

View file

@ -6995,6 +6995,36 @@ void zend_compile_throw(zend_ast *ast TSRMLS_DC) {
emit_op(NULL, ZEND_THROW, &expr_node, NULL TSRMLS_CC);
}
void zend_compile_break_continue(zend_ast *ast TSRMLS_DC) {
zend_ast *depth_ast = ast->child[0];
zend_uint opcode = ast->kind;
znode depth_node;
zend_op *opline;
ZEND_ASSERT(opcode == ZEND_BRK || opcode == ZEND_CONT);
if (depth_ast) {
if (depth_ast->kind != ZEND_AST_ZVAL) {
zend_error_noreturn(E_COMPILE_ERROR, "'%s' operator with non-constant operand "
"is no longer supported", opcode == ZEND_BRK ? "break" : "continue");
}
zend_compile_expr(&depth_node, depth_ast TSRMLS_CC);
if (Z_TYPE(depth_node.u.constant) != IS_LONG || Z_LVAL(depth_node.u.constant) < 1) {
zend_error_noreturn(E_COMPILE_ERROR, "'%s' operator accepts only positive numbers",
opcode == ZEND_BRK ? "break" : "continue");
}
} else {
depth_node.op_type = IS_CONST;
ZVAL_LONG(&depth_node.u.constant, 1);
}
opline = emit_op(NULL, opcode, NULL, &depth_node TSRMLS_CC);
opline->op1.opline_num = CG(context).current_brk_cont;
}
void zend_compile_binary_op(znode *result, zend_ast *ast TSRMLS_DC) {
zend_ast *left_ast = ast->child[0];
zend_ast *right_ast = ast->child[1];
@ -7756,6 +7786,10 @@ void zend_compile_stmt(zend_ast *ast TSRMLS_DC) {
case ZEND_THROW:
zend_compile_throw(ast TSRMLS_CC);
return;
case ZEND_BRK:
case ZEND_CONT:
zend_compile_break_continue(ast TSRMLS_CC);
return;
EMPTY_SWITCH_DEFAULT_CASE()
}
}

View file

@ -337,10 +337,10 @@ unticked_statement:
')' { zend_do_free(&$9 TSRMLS_CC); zend_do_for_before_statement(&$4, &$7 TSRMLS_CC); }
for_statement { zend_do_for_end(&$7 TSRMLS_CC); }
| T_SWITCH parenthesis_expr { AC($2); zend_do_switch_cond(&$2 TSRMLS_CC); } switch_case_list { zend_do_switch_end(&$4 TSRMLS_CC); }
| T_BREAK ';' { zend_do_brk_cont(ZEND_BRK, NULL TSRMLS_CC); }
| T_BREAK expr ';' { AC($2); zend_do_brk_cont(ZEND_BRK, &$2 TSRMLS_CC); }
| T_CONTINUE ';' { zend_do_brk_cont(ZEND_CONT, NULL TSRMLS_CC); }
| T_CONTINUE expr ';' { AC($2); zend_do_brk_cont(ZEND_CONT, &$2 TSRMLS_CC); }
| T_BREAK ';' { $$.u.ast = zend_ast_create_unary(ZEND_BRK, NULL); AS($$); }
| T_BREAK expr ';' { $$.u.ast = zend_ast_create_unary(ZEND_BRK, $2.u.ast); AS($$); }
| T_CONTINUE ';' { $$.u.ast = zend_ast_create_unary(ZEND_CONT, NULL); AS($$); }
| T_CONTINUE expr ';' { $$.u.ast = zend_ast_create_unary(ZEND_CONT, $2.u.ast); AS($$); }
| T_RETURN ';'
{ $$.u.ast = zend_ast_create_unary(ZEND_AST_RETURN, NULL); AS($$); }
| T_RETURN expr ';'