Skip to content

Commit 7656c33

Browse files
committed
break/continue
1 parent 6097f69 commit 7656c33

File tree

2 files changed

+31
-19
lines changed

2 files changed

+31
-19
lines changed

Zend/zend_compile.c

Lines changed: 25 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -712,7 +712,7 @@ void zend_stop_lexing(void)
712712
}
713713

714714
static inline void zend_begin_loop(
715-
uint8_t free_opcode, const znode *loop_var, bool is_switch) /* {{{ */
715+
uint8_t free_opcode, const znode *loop_var, zend_brk_cont_kind kind) /* {{{ */
716716
{
717717
zend_brk_cont_element *brk_cont_element;
718718
int parent = CG(context).current_brk_cont;
@@ -721,7 +721,7 @@ static inline void zend_begin_loop(
721721
CG(context).current_brk_cont = CG(context).last_brk_cont;
722722
brk_cont_element = get_next_brk_cont_element();
723723
brk_cont_element->parent = parent;
724-
brk_cont_element->is_switch = is_switch;
724+
brk_cont_element->kind = kind;
725725

726726
if (loop_var && (loop_var->op_type & (IS_VAR|IS_TMP_VAR))) {
727727
uint32_t start = get_next_op_number();
@@ -5828,13 +5828,17 @@ static void zend_compile_with(zend_ast *ast)
58285828
}
58295829
zend_emit_op(&manager, ZEND_INIT_WITH, &manager, NULL);
58305830

5831+
58315832
/* $var = manager->enterContext() */
58325833
zend_emit_copy_tmp(&tmp, &manager);
58335834
zend_ast *enter_ast = zend_ast_create(ZEND_AST_METHOD_CALL,
58345835
zend_ast_create_znode(&tmp),
58355836
zend_ast_create_zval_from_str(ZSTR_KNOWN(ZEND_STR_ENTER_CONTEXT)),
58365837
zend_ast_create_list(0, ZEND_AST_ARG_LIST));
58375838
if (var_ast) {
5839+
if (var_ast->kind != ZEND_AST_VAR) {
5840+
zend_throw_error(NULL, "TODO: support non-var on right side of 'as'");
5841+
}
58385842
zend_compile_assign(&tmp, zend_ast_create(ZEND_AST_ASSIGN, var_ast, enter_ast));
58395843
} else {
58405844
zend_compile_method_call(&tmp, enter_ast, BP_VAR_R);
@@ -5883,9 +5887,7 @@ static void zend_compile_with(zend_ast *ast)
58835887
znode closed;
58845888
zend_emit_op_tmp(&closed, ZEND_QM_ASSIGN, &false_node, NULL);
58855889

5886-
if (var_ast && var_ast->kind != ZEND_AST_VAR) {
5887-
zend_throw_error(NULL, "TODO: support non-var on right side of 'as'");
5888-
}
5890+
zend_begin_loop(ZEND_NOP, NULL, ZEND_BRK_CONT_WITH);
58895891

58905892
zend_ast *catch_list = zend_ast_create_list(1, ZEND_AST_CATCH_LIST,
58915893
/* } catch (Exception exception) { */
@@ -5940,6 +5942,8 @@ static void zend_compile_with(zend_ast *ast)
59405942
}
59415943

59425944
zend_compile_try(zend_ast_create(ZEND_AST_TRY, stmts_ast, catch_list, finally_stmt));
5945+
5946+
zend_end_loop(get_next_op_number(), NULL);
59435947
}
59445948

59455949
static void zend_compile_echo(zend_ast *ast) /* {{{ */
@@ -6017,27 +6021,30 @@ static void zend_compile_break_continue(zend_ast *ast) /* {{{ */
60176021
ZEND_ASSERT(cur != -1);
60186022
}
60196023

6020-
if (CG(context).brk_cont_array[cur].is_switch) {
6024+
if (CG(context).brk_cont_array[cur].kind == ZEND_BRK_CONT_SWITCH
6025+
|| CG(context).brk_cont_array[cur].kind == ZEND_BRK_CONT_WITH) {
6026+
const char *keyword = CG(context).brk_cont_array[cur].kind == ZEND_BRK_CONT_SWITCH
6027+
? "switch" : "with";
60216028
if (depth == 1) {
60226029
if (CG(context).brk_cont_array[cur].parent == -1) {
60236030
zend_error(E_WARNING,
6024-
"\"continue\" targeting switch is equivalent to \"break\"");
6031+
"\"continue\" targeting %s is equivalent to \"break\"", keyword);
60256032
} else {
60266033
zend_error(E_WARNING,
6027-
"\"continue\" targeting switch is equivalent to \"break\". " \
6034+
"\"continue\" targeting %s is equivalent to \"break\". " \
60286035
"Did you mean to use \"continue " ZEND_LONG_FMT "\"?",
6029-
depth + 1);
6036+
keyword, depth + 1);
60306037
}
60316038
} else {
60326039
if (CG(context).brk_cont_array[cur].parent == -1) {
60336040
zend_error(E_WARNING,
6034-
"\"continue " ZEND_LONG_FMT "\" targeting switch is equivalent to \"break " ZEND_LONG_FMT "\"",
6035-
depth, depth);
6041+
"\"continue " ZEND_LONG_FMT "\" targeting %s is equivalent to \"break " ZEND_LONG_FMT "\"",
6042+
depth, keyword, depth);
60366043
} else {
60376044
zend_error(E_WARNING,
6038-
"\"continue " ZEND_LONG_FMT "\" targeting switch is equivalent to \"break " ZEND_LONG_FMT "\". " \
6045+
"\"continue " ZEND_LONG_FMT "\" targeting %s is equivalent to \"break " ZEND_LONG_FMT "\". " \
60396046
"Did you mean to use \"continue " ZEND_LONG_FMT "\"?",
6040-
depth, depth, depth + 1);
6047+
depth, keyword, depth, depth + 1);
60416048
}
60426049
}
60436050
}
@@ -6155,7 +6162,7 @@ static void zend_compile_while(zend_ast *ast) /* {{{ */
61556162

61566163
opnum_jmp = zend_emit_jump(0);
61576164

6158-
zend_begin_loop(ZEND_NOP, NULL, false);
6165+
zend_begin_loop(ZEND_NOP, NULL, ZEND_BRK_CONT_DEFAULT);
61596166

61606167
opnum_start = get_next_op_number();
61616168
zend_compile_stmt(stmt_ast);
@@ -6178,7 +6185,7 @@ static void zend_compile_do_while(zend_ast *ast) /* {{{ */
61786185
znode cond_node;
61796186
uint32_t opnum_start, opnum_cond;
61806187

6181-
zend_begin_loop(ZEND_NOP, NULL, false);
6188+
zend_begin_loop(ZEND_NOP, NULL, ZEND_BRK_CONT_DEFAULT);
61826189

61836190
opnum_start = get_next_op_number();
61846191
zend_compile_stmt(stmt_ast);
@@ -6235,7 +6242,7 @@ static void zend_compile_for(zend_ast *ast) /* {{{ */
62356242

62366243
opnum_jmp = zend_emit_jump(0);
62376244

6238-
zend_begin_loop(ZEND_NOP, NULL, false);
6245+
zend_begin_loop(ZEND_NOP, NULL, ZEND_BRK_CONT_DEFAULT);
62396246

62406247
opnum_start = get_next_op_number();
62416248
zend_compile_stmt(stmt_ast);
@@ -6297,7 +6304,7 @@ static void zend_compile_foreach(zend_ast *ast) /* {{{ */
62976304
opnum_reset = get_next_op_number();
62986305
opline = zend_emit_op(&reset_node, by_ref ? ZEND_FE_RESET_RW : ZEND_FE_RESET_R, &expr_node, NULL);
62996306

6300-
zend_begin_loop(ZEND_FE_FREE, &reset_node, false);
6307+
zend_begin_loop(ZEND_FE_FREE, &reset_node, ZEND_BRK_CONT_DEFAULT);
63016308

63026309
opnum_fetch = get_next_op_number();
63036310
opline = zend_emit_op(NULL, by_ref ? ZEND_FE_FETCH_RW : ZEND_FE_FETCH_R, &reset_node, NULL);
@@ -6470,7 +6477,7 @@ static void zend_compile_switch(zend_ast *ast) /* {{{ */
64706477

64716478
zend_compile_expr(&expr_node, expr_ast);
64726479

6473-
zend_begin_loop(ZEND_FREE, &expr_node, true);
6480+
zend_begin_loop(ZEND_FREE, &expr_node, ZEND_BRK_CONT_SWITCH);
64746481

64756482
case_node.op_type = IS_TMP_VAR;
64766483
case_node.u.op.var = get_temporary_variable();

Zend/zend_compile.h

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -156,13 +156,18 @@ struct _zend_op {
156156
#endif
157157
};
158158

159+
typedef enum _zend_brk_cont_kind {
160+
ZEND_BRK_CONT_DEFAULT,
161+
ZEND_BRK_CONT_SWITCH,
162+
ZEND_BRK_CONT_WITH,
163+
} zend_brk_cont_kind;
159164

160165
typedef struct _zend_brk_cont_element {
161166
int start;
162167
int cont;
163168
int brk;
164169
int parent;
165-
bool is_switch;
170+
zend_brk_cont_kind kind;
166171
} zend_brk_cont_element;
167172

168173
typedef struct _zend_label {

0 commit comments

Comments
 (0)