Skip to content

Commit 600ae73

Browse files
committed
py: Implement break and continue byte codes, and add tests.
Also fixes a bug in the for-in-range optimiser. I hope to remove break and continue byte codes in the future and just use jump (if possible).
1 parent 2c30256 commit 600ae73

4 files changed

Lines changed: 47 additions & 3 deletions

File tree

py/compile.c

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1442,24 +1442,27 @@ void compile_for_stmt_optimised_range(compiler_t *comp, mp_parse_node_t pn_var,
14421442
comp->continue_label = continue_label;
14431443

14441444
int top_label = comp_next_label(comp);
1445+
int entry_label = comp_next_label(comp);
14451446

14461447
// compile: var = start
14471448
compile_node(comp, pn_start);
14481449
c_assign(comp, pn_var, ASSIGN_STORE);
14491450

1450-
EMIT(jump, continue_label);
1451+
EMIT(jump, entry_label);
14511452
EMIT(label_assign, top_label);
14521453

14531454
// compile body
14541455
compile_node(comp, pn_body);
14551456

1457+
EMIT(label_assign, continue_label);
1458+
14561459
// compile: var += step
14571460
c_assign(comp, pn_var, ASSIGN_AUG_LOAD);
14581461
compile_node(comp, pn_step);
14591462
EMIT(binary_op, RT_BINARY_OP_INPLACE_ADD);
14601463
c_assign(comp, pn_var, ASSIGN_AUG_STORE);
14611464

1462-
EMIT(label_assign, continue_label);
1465+
EMIT(label_assign, entry_label);
14631466

14641467
// compile: if var <cond> end: goto top
14651468
compile_node(comp, pn_var);

py/vm.c

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -326,6 +326,18 @@ bool mp_execute_byte_code_2(const byte *code_info, const byte **ip_in_out, mp_ob
326326
break;
327327
*/
328328

329+
// TODO this might need more sophisticated handling when breaking from within an except
330+
case MP_BC_BREAK_LOOP:
331+
DECODE_ULABEL;
332+
ip += unum;
333+
break;
334+
335+
// TODO this might need more sophisticated handling when breaking from within an except
336+
case MP_BC_CONTINUE_LOOP:
337+
DECODE_ULABEL;
338+
ip += unum;
339+
break;
340+
329341
// matched against: POP_BLOCK or POP_EXCEPT (anything else?)
330342
case MP_BC_SETUP_EXCEPT:
331343
DECODE_ULABEL; // except labels are always forward
@@ -366,7 +378,7 @@ bool mp_execute_byte_code_2(const byte *code_info, const byte **ip_in_out, mp_ob
366378
exc_sp -= 2; // pop back to previous exception handler
367379
break;
368380

369-
// matched againts: SETUP_EXCEPT
381+
// matched against: SETUP_EXCEPT
370382
case MP_BC_POP_EXCEPT:
371383
// TODO need to work out how blocks work etc
372384
// pops block, checks it's an exception block, and restores the stack, saving the 3 exception values to local threadstate

tests/basics/break.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
while True:
2+
break
3+
4+
for i in range(4):
5+
print('one', i)
6+
if i > 2:
7+
break
8+
print('two', i)
9+
10+
for i in [1, 2, 3, 4]:
11+
if i == 3:
12+
break
13+
print(i)

tests/basics/continue.py

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
for i in range(4):
2+
print('one', i)
3+
if i > 2:
4+
continue
5+
print('two', i)
6+
7+
for i in range(4):
8+
print('one', i)
9+
if i < 2:
10+
continue
11+
print('two', i)
12+
13+
for i in [1, 2, 3, 4]:
14+
if i == 3:
15+
continue
16+
print(i)

0 commit comments

Comments
 (0)