Skip to content

Commit 4a34048

Browse files
tohavagraydon
authored andcommitted
implemented break for while-loop case
ast.ml - added break and cont statements item.ml - added break and cont statements lexer.mll - added break and cont statements token.ml - added break and cont statements trans.ml - implemented the break statement for the while-loop case - replaced hash table accesses with get_stmt_depth where needed type.ml = added break and cont statements typestate.ml - implemented the break statement for the while-loop case - added shorthand filter_live_block_slots walk.ml - added break and cont statements while-with-break.rs - code for testing while loops
1 parent 74cb950 commit 4a34048

File tree

10 files changed

+120
-36
lines changed

10 files changed

+120
-36
lines changed

src/Makefile

+1
Original file line numberDiff line numberDiff line change
@@ -579,6 +579,7 @@ TEST_XFAILS_LLVM := $(TASK_XFAILS) \
579579
vec-slice.rs \
580580
vec.rs \
581581
while-flow-graph.rs \
582+
while-with-break.rs \
582583
writealias.rs \
583584
yield.rs \
584585
yield2.rs \

src/boot/fe/ast.ml

+6
Original file line numberDiff line numberDiff line change
@@ -207,6 +207,8 @@ and stmt' =
207207
| STMT_put_each of (lval * (atom array))
208208
| STMT_ret of (atom option)
209209
| STMT_be of (lval * (atom array))
210+
| STMT_break
211+
| STMT_cont
210212
| STMT_alt_tag of stmt_alt_tag
211213
| STMT_alt_type of stmt_alt_type
212214
| STMT_alt_port of stmt_alt_port
@@ -1228,6 +1230,10 @@ and fmt_stmt_body (ff:Format.formatter) (s:stmt) : unit =
12281230
fmt_atoms ff az;
12291231
fmt ff ";";
12301232

1233+
| STMT_break -> fmt ff "break;";
1234+
1235+
| STMT_cont -> fmt ff "cont;";
1236+
12311237
| STMT_block b -> fmt_block ff b.node
12321238

12331239
| STMT_copy (lv, ex) ->

src/boot/fe/item.ml

+8-1
Original file line numberDiff line numberDiff line change
@@ -188,7 +188,14 @@ and parse_stmts_including_none (ps:pstate) : Ast.stmt array =
188188
let (stmts, atom) = ctxt "stmts: log value" parse_expr_atom ps in
189189
expect ps SEMI;
190190
spans ps stmts apos (Ast.STMT_log atom)
191-
191+
| BREAK ->
192+
bump ps;
193+
expect ps SEMI;
194+
[| span ps apos (lexpos ps) Ast.STMT_break |]
195+
| CONT ->
196+
bump ps;
197+
expect ps SEMI;
198+
[| span ps apos (lexpos ps) Ast.STMT_cont |]
192199
| CHECK ->
193200
bump ps;
194201
begin

src/boot/fe/lexer.mll

+2
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,8 @@
113113
("const", CONST);
114114

115115
("log", LOG);
116+
("break", BREAK);
117+
("cont", CONT);
116118
("spawn", SPAWN);
117119
("thread", THREAD);
118120
("yield", YIELD);

src/boot/fe/token.ml

+4
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,8 @@ type token =
7171
| PUT
7272
| RET
7373
| BE
74+
| BREAK
75+
| CONT
7476

7577
(* Type and type-state keywords *)
7678
| TYPE
@@ -226,6 +228,8 @@ let rec string_of_tok t =
226228
| PUT -> "put"
227229
| RET -> "ret"
228230
| BE -> "be"
231+
| BREAK -> "break"
232+
| CONT -> "cont"
229233

230234
(* Type and type-state keywords *)
231235
| TYPE -> "type"

src/boot/me/trans.ml

+15-3
Original file line numberDiff line numberDiff line change
@@ -234,6 +234,7 @@ let trans_visitor
234234
in
235235

236236
let epilogue_jumps = Stack.create() in
237+
let simple_break_jumps = Stack.create() in (* not used for for-each *)
237238

238239
let path_name (_:unit) : string =
239240
string_of_name (path_to_name path)
@@ -4717,7 +4718,7 @@ let trans_visitor
47174718
Some params -> params
47184719
| None -> [| |]
47194720
in
4720-
let depth = Hashtbl.find cx.ctxt_stmt_loop_depths stmt_id in
4721+
let depth = get_stmt_depth cx stmt_id in
47214722
let fc = { for_each_fixup = fix; for_each_depth = depth } in
47224723
iflog (fun _ ->
47234724
log cx "for-each at depth %d\n" depth);
@@ -5059,12 +5060,16 @@ let trans_visitor
50595060
let fwd_jmp = mark () in
50605061
emit (Il.jmp Il.JMP Il.CodeNone);
50615062
let block_begin = mark () in
5063+
Stack.push (Stack.create()) simple_break_jumps;
50625064
trans_block sw.Ast.while_body;
50635065
patch fwd_jmp;
50645066
Array.iter trans_stmt head_stmts;
50655067
check_interrupt_flag ();
5066-
let back_jmps = trans_cond false head_expr in
5067-
List.iter (fun j -> patch_existing j block_begin) back_jmps;
5068+
begin
5069+
let back_jmps = trans_cond false head_expr in
5070+
List.iter (fun j -> patch_existing j block_begin) back_jmps;
5071+
end;
5072+
Stack.iter patch (Stack.pop simple_break_jumps);
50685073

50695074
| Ast.STMT_if si ->
50705075
let skip_thn_jmps = trans_cond true si.Ast.if_test in
@@ -5108,6 +5113,13 @@ let trans_visitor
51085113
let (dst_cell, _) = get_current_output_cell_and_slot () in
51095114
trans_be_fn cx dst_cell flv ty_params args
51105115

5116+
| Ast.STMT_break ->
5117+
if get_stmt_depth cx stmt.id > 0
5118+
then unimpl (Some stmt.id) "break within iterator-block";
5119+
drop_slots_at_curr_stmt();
5120+
Stack.push (mark()) (Stack.top simple_break_jumps);
5121+
emit (Il.jmp Il.JMP Il.CodeNone);
5122+
51115123
| Ast.STMT_put atom_opt ->
51125124
trans_put atom_opt
51135125

src/boot/me/type.ml

+3-1
Original file line numberDiff line numberDiff line change
@@ -945,7 +945,9 @@ let check_stmt (cx:Semant.ctxt) : (fn_ctx -> Ast.stmt -> unit) =
945945

946946
| Ast.STMT_alt_port _ -> () (* TODO *)
947947

948-
| Ast.STMT_fail | Ast.STMT_yield -> () (* always well-typed *)
948+
(* always well-typed *)
949+
| Ast.STMT_fail | Ast.STMT_yield
950+
| Ast.STMT_break | Ast.STMT_cont -> ()
949951

950952
| Ast.STMT_join lval -> infer_lval Ast.TY_task lval
951953

src/boot/me/typestate.ml

+65-29
Original file line numberDiff line numberDiff line change
@@ -445,6 +445,15 @@ let bitmap_assigning_visitor
445445
Walk.visit_block_pre = visit_block_pre }
446446
;;
447447

448+
type slots_stack = node_id Stack.t;;
449+
type block_slots_stack = slots_stack Stack.t;;
450+
type frame_block_slots_stack = block_slots_stack Stack.t;;
451+
type loop_block_slots_stack = block_slots_stack option Stack.t;;
452+
(* like ret drops slots from all blocks in the frame
453+
* break from a simple loo drops slots from all block in a loop *)
454+
let (loop_blocks:loop_block_slots_stack) =
455+
let s = Stack.create() in Stack.push None s; s
456+
448457
let condition_assigning_visitor
449458
(cx:ctxt)
450459
(tables_stack:typestate_tables Stack.t)
@@ -574,7 +583,7 @@ let condition_assigning_visitor
574583
let precond = slot_inits (lval_slots cx lval) in
575584
raise_precondition sid precond;
576585
in
577-
586+
578587
let visit_stmt_pre s =
579588
begin
580589
match s.node with
@@ -694,7 +703,6 @@ let condition_assigning_visitor
694703
| Ast.STMT_check_expr expr ->
695704
let precond = slot_inits (expr_slots cx expr) in
696705
raise_pre_post_cond s.id precond
697-
698706
| Ast.STMT_while sw ->
699707
let (_, expr) = sw.Ast.while_lval in
700708
let precond = slot_inits (expr_slots cx expr) in
@@ -1275,9 +1283,6 @@ let typestate_verify_visitor
12751283
Walk.visit_block_pre = visit_block_pre }
12761284
;;
12771285

1278-
type slots_stack = node_id Stack.t;;
1279-
type block_slots_stack = slots_stack Stack.t;;
1280-
type frame_block_slots_stack = block_slots_stack Stack.t;;
12811286

12821287
let lifecycle_visitor
12831288
(cx:ctxt)
@@ -1312,18 +1317,24 @@ let lifecycle_visitor
13121317

13131318

13141319
let visit_block_pre b =
1315-
Stack.push (Stack.create()) (Stack.top frame_blocks);
1316-
begin
1317-
match htab_search implicit_init_block_slots b.id with
1318-
None -> ()
1319-
| Some slots ->
1320+
1321+
let s = Stack.create() in
1322+
begin
1323+
match Stack.top loop_blocks with
1324+
Some loop -> Stack.push s loop | None -> ()
1325+
end;
1326+
Stack.push s (Stack.top frame_blocks);
1327+
begin
1328+
match htab_search implicit_init_block_slots b.id with
1329+
None -> ()
1330+
| Some slots ->
13201331
List.iter
13211332
(fun slot ->
13221333
push_slot slot;
13231334
mark_slot_live slot)
13241335
slots
1325-
end;
1326-
inner.Walk.visit_block_pre b
1336+
end;
1337+
inner.Walk.visit_block_pre b
13271338
in
13281339

13291340
let note_drops stmt slots =
@@ -1341,8 +1352,20 @@ let lifecycle_visitor
13411352
htab_put cx.ctxt_post_stmt_slot_drops stmt.id slots
13421353
in
13431354

1355+
let filter_live_block_slots slots =
1356+
List.filter (fun i -> Hashtbl.mem live_block_slots i) slots
1357+
in
1358+
13441359
let visit_block_post b =
13451360
inner.Walk.visit_block_post b;
1361+
begin
1362+
match Stack.top loop_blocks with
1363+
Some loop ->
1364+
ignore(Stack.pop loop);
1365+
if Stack.is_empty loop then
1366+
ignore(Stack.pop loop_blocks);
1367+
| None -> ()
1368+
end;
13461369
let block_slots = Stack.pop (Stack.top frame_blocks) in
13471370
let stmts = b.node in
13481371
let len = Array.length stmts in
@@ -1352,7 +1375,8 @@ let lifecycle_visitor
13521375
let s = stmts.(len-1) in
13531376
match s.node with
13541377
Ast.STMT_ret _
1355-
| Ast.STMT_be _ ->
1378+
| Ast.STMT_be _
1379+
| Ast.STMT_break ->
13561380
() (* Taken care of in visit_stmt_post below. *)
13571381
| _ ->
13581382
(* The blk_slots stack we have has accumulated slots in
@@ -1364,11 +1388,7 @@ let lifecycle_visitor
13641388
* point in the block.
13651389
*)
13661390
let slots = stk_elts_from_top block_slots in
1367-
let live =
1368-
List.filter
1369-
(fun i -> Hashtbl.mem live_block_slots i)
1370-
slots
1371-
in
1391+
let live = filter_live_block_slots slots in
13721392
note_drops s live
13731393
end;
13741394
in
@@ -1440,6 +1460,10 @@ let lifecycle_visitor
14401460
f.Ast.for_each_body.id
14411461
[ (fst f.Ast.for_each_slot).id ]
14421462

1463+
| Ast.STMT_while _ ->
1464+
iflog cx (fun _ -> log cx "entering a loop");
1465+
Stack.push (Some (Stack.create ())) loop_blocks;
1466+
14431467
| Ast.STMT_alt_tag { Ast.alt_tag_arms = arms } ->
14441468
let note_slot block slot_id =
14451469
log cx
@@ -1475,26 +1499,38 @@ let lifecycle_visitor
14751499

14761500
let visit_stmt_post s =
14771501
inner.Walk.visit_stmt_post s;
1502+
let handle_ret_like_stmt block_stack =
1503+
let blocks = stk_elts_from_top block_stack in
1504+
let slots = List.concat (List.map stk_elts_from_top blocks) in
1505+
let live = filter_live_block_slots slots in
1506+
note_drops s live
1507+
in
14781508
match s.node with
14791509
Ast.STMT_ret _
14801510
| Ast.STMT_be _ ->
1481-
let blocks = stk_elts_from_top (Stack.top frame_blocks) in
1482-
let slots = List.concat (List.map stk_elts_from_top blocks) in
1483-
let live =
1484-
List.filter
1485-
(fun i -> Hashtbl.mem live_block_slots i)
1486-
slots
1487-
in
1488-
note_drops s live
1511+
handle_ret_like_stmt (Stack.top frame_blocks)
1512+
| Ast.STMT_break ->
1513+
begin
1514+
match (Stack.top loop_blocks) with
1515+
Some loop -> handle_ret_like_stmt loop
1516+
| None ->
1517+
iflog cx (fun _ ->
1518+
log cx "break statement outside of a loop");
1519+
err (Some s.id) "break statement outside of a loop"
1520+
end
14891521
| _ -> ()
14901522
in
14911523

14921524
let enter_frame _ =
1493-
Stack.push (Stack.create()) frame_blocks
1525+
Stack.push (Stack.create()) frame_blocks;
1526+
Stack.push None loop_blocks
14941527
in
1495-
1528+
14961529
let leave_frame _ =
1497-
ignore (Stack.pop frame_blocks)
1530+
ignore (Stack.pop frame_blocks);
1531+
match Stack.pop loop_blocks with
1532+
Some _ -> bug () "leave_frame should not end a loop"
1533+
| None -> ()
14981534
in
14991535

15001536
let visit_mod_item_pre n p i =

src/boot/me/walk.ml

+1-2
Original file line numberDiff line numberDiff line change
@@ -481,8 +481,7 @@ and walk_stmt
481481
| Ast.STMT_decl (Ast.DECL_slot (_, slot)) ->
482482
walk_slot_identified v slot
483483

484-
| Ast.STMT_yield
485-
| Ast.STMT_fail ->
484+
| Ast.STMT_break | Ast.STMT_cont | Ast.STMT_yield | Ast.STMT_fail ->
486485
()
487486

488487
| Ast.STMT_join task ->

src/test/run-pass/while-with-break.rs

+15
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
// -*- rust -*-
2+
3+
fn main() {
4+
let int i = 90;
5+
while (i < 100) {
6+
log i;
7+
i = i + 1;
8+
if (i == 95) {
9+
let vec[int] v = vec(1,2,3,4,5); // we check that it is freed by break
10+
log "breaking";
11+
break;
12+
}
13+
}
14+
check(i == 95);
15+
}

0 commit comments

Comments
 (0)