Skip to content

Commit

Permalink
implemented break for while-loop case
Browse files Browse the repository at this point in the history
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
  • Loading branch information
tohava authored and graydon committed Sep 30, 2010
1 parent 74cb950 commit 4a34048
Show file tree
Hide file tree
Showing 10 changed files with 120 additions and 36 deletions.
1 change: 1 addition & 0 deletions src/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -579,6 +579,7 @@ TEST_XFAILS_LLVM := $(TASK_XFAILS) \
vec-slice.rs \
vec.rs \
while-flow-graph.rs \
while-with-break.rs \
writealias.rs \
yield.rs \
yield2.rs \
Expand Down
6 changes: 6 additions & 0 deletions src/boot/fe/ast.ml
Original file line number Diff line number Diff line change
Expand Up @@ -207,6 +207,8 @@ and stmt' =
| STMT_put_each of (lval * (atom array))
| STMT_ret of (atom option)
| STMT_be of (lval * (atom array))
| STMT_break
| STMT_cont
| STMT_alt_tag of stmt_alt_tag
| STMT_alt_type of stmt_alt_type
| STMT_alt_port of stmt_alt_port
Expand Down Expand Up @@ -1228,6 +1230,10 @@ and fmt_stmt_body (ff:Format.formatter) (s:stmt) : unit =
fmt_atoms ff az;
fmt ff ";";

| STMT_break -> fmt ff "break;";

| STMT_cont -> fmt ff "cont;";

| STMT_block b -> fmt_block ff b.node

| STMT_copy (lv, ex) ->
Expand Down
9 changes: 8 additions & 1 deletion src/boot/fe/item.ml
Original file line number Diff line number Diff line change
Expand Up @@ -188,7 +188,14 @@ and parse_stmts_including_none (ps:pstate) : Ast.stmt array =
let (stmts, atom) = ctxt "stmts: log value" parse_expr_atom ps in
expect ps SEMI;
spans ps stmts apos (Ast.STMT_log atom)

| BREAK ->
bump ps;
expect ps SEMI;
[| span ps apos (lexpos ps) Ast.STMT_break |]
| CONT ->
bump ps;
expect ps SEMI;
[| span ps apos (lexpos ps) Ast.STMT_cont |]
| CHECK ->
bump ps;
begin
Expand Down
2 changes: 2 additions & 0 deletions src/boot/fe/lexer.mll
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,8 @@
("const", CONST);

("log", LOG);
("break", BREAK);
("cont", CONT);
("spawn", SPAWN);
("thread", THREAD);
("yield", YIELD);
Expand Down
4 changes: 4 additions & 0 deletions src/boot/fe/token.ml
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,8 @@ type token =
| PUT
| RET
| BE
| BREAK
| CONT

(* Type and type-state keywords *)
| TYPE
Expand Down Expand Up @@ -226,6 +228,8 @@ let rec string_of_tok t =
| PUT -> "put"
| RET -> "ret"
| BE -> "be"
| BREAK -> "break"
| CONT -> "cont"

(* Type and type-state keywords *)
| TYPE -> "type"
Expand Down
18 changes: 15 additions & 3 deletions src/boot/me/trans.ml
Original file line number Diff line number Diff line change
Expand Up @@ -234,6 +234,7 @@ let trans_visitor
in

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

let path_name (_:unit) : string =
string_of_name (path_to_name path)
Expand Down Expand Up @@ -4717,7 +4718,7 @@ let trans_visitor
Some params -> params
| None -> [| |]
in
let depth = Hashtbl.find cx.ctxt_stmt_loop_depths stmt_id in
let depth = get_stmt_depth cx stmt_id in
let fc = { for_each_fixup = fix; for_each_depth = depth } in
iflog (fun _ ->
log cx "for-each at depth %d\n" depth);
Expand Down Expand Up @@ -5059,12 +5060,16 @@ let trans_visitor
let fwd_jmp = mark () in
emit (Il.jmp Il.JMP Il.CodeNone);
let block_begin = mark () in
Stack.push (Stack.create()) simple_break_jumps;
trans_block sw.Ast.while_body;
patch fwd_jmp;
Array.iter trans_stmt head_stmts;
check_interrupt_flag ();
let back_jmps = trans_cond false head_expr in
List.iter (fun j -> patch_existing j block_begin) back_jmps;
begin
let back_jmps = trans_cond false head_expr in
List.iter (fun j -> patch_existing j block_begin) back_jmps;
end;
Stack.iter patch (Stack.pop simple_break_jumps);

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

| Ast.STMT_break ->
if get_stmt_depth cx stmt.id > 0
then unimpl (Some stmt.id) "break within iterator-block";
drop_slots_at_curr_stmt();
Stack.push (mark()) (Stack.top simple_break_jumps);
emit (Il.jmp Il.JMP Il.CodeNone);

| Ast.STMT_put atom_opt ->
trans_put atom_opt

Expand Down
4 changes: 3 additions & 1 deletion src/boot/me/type.ml
Original file line number Diff line number Diff line change
Expand Up @@ -945,7 +945,9 @@ let check_stmt (cx:Semant.ctxt) : (fn_ctx -> Ast.stmt -> unit) =

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

| Ast.STMT_fail | Ast.STMT_yield -> () (* always well-typed *)
(* always well-typed *)
| Ast.STMT_fail | Ast.STMT_yield
| Ast.STMT_break | Ast.STMT_cont -> ()

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

Expand Down
94 changes: 65 additions & 29 deletions src/boot/me/typestate.ml
Original file line number Diff line number Diff line change
Expand Up @@ -445,6 +445,15 @@ let bitmap_assigning_visitor
Walk.visit_block_pre = visit_block_pre }
;;

type slots_stack = node_id Stack.t;;
type block_slots_stack = slots_stack Stack.t;;
type frame_block_slots_stack = block_slots_stack Stack.t;;
type loop_block_slots_stack = block_slots_stack option Stack.t;;
(* like ret drops slots from all blocks in the frame
* break from a simple loo drops slots from all block in a loop *)
let (loop_blocks:loop_block_slots_stack) =
let s = Stack.create() in Stack.push None s; s

let condition_assigning_visitor
(cx:ctxt)
(tables_stack:typestate_tables Stack.t)
Expand Down Expand Up @@ -574,7 +583,7 @@ let condition_assigning_visitor
let precond = slot_inits (lval_slots cx lval) in
raise_precondition sid precond;
in

let visit_stmt_pre s =
begin
match s.node with
Expand Down Expand Up @@ -694,7 +703,6 @@ let condition_assigning_visitor
| Ast.STMT_check_expr expr ->
let precond = slot_inits (expr_slots cx expr) in
raise_pre_post_cond s.id precond

| Ast.STMT_while sw ->
let (_, expr) = sw.Ast.while_lval in
let precond = slot_inits (expr_slots cx expr) in
Expand Down Expand Up @@ -1275,9 +1283,6 @@ let typestate_verify_visitor
Walk.visit_block_pre = visit_block_pre }
;;

type slots_stack = node_id Stack.t;;
type block_slots_stack = slots_stack Stack.t;;
type frame_block_slots_stack = block_slots_stack Stack.t;;

let lifecycle_visitor
(cx:ctxt)
Expand Down Expand Up @@ -1312,18 +1317,24 @@ let lifecycle_visitor


let visit_block_pre b =
Stack.push (Stack.create()) (Stack.top frame_blocks);
begin
match htab_search implicit_init_block_slots b.id with
None -> ()
| Some slots ->

let s = Stack.create() in
begin
match Stack.top loop_blocks with
Some loop -> Stack.push s loop | None -> ()
end;
Stack.push s (Stack.top frame_blocks);
begin
match htab_search implicit_init_block_slots b.id with
None -> ()
| Some slots ->
List.iter
(fun slot ->
push_slot slot;
mark_slot_live slot)
slots
end;
inner.Walk.visit_block_pre b
end;
inner.Walk.visit_block_pre b
in

let note_drops stmt slots =
Expand All @@ -1341,8 +1352,20 @@ let lifecycle_visitor
htab_put cx.ctxt_post_stmt_slot_drops stmt.id slots
in

let filter_live_block_slots slots =
List.filter (fun i -> Hashtbl.mem live_block_slots i) slots
in

let visit_block_post b =
inner.Walk.visit_block_post b;
begin
match Stack.top loop_blocks with
Some loop ->
ignore(Stack.pop loop);
if Stack.is_empty loop then
ignore(Stack.pop loop_blocks);
| None -> ()
end;
let block_slots = Stack.pop (Stack.top frame_blocks) in
let stmts = b.node in
let len = Array.length stmts in
Expand All @@ -1352,7 +1375,8 @@ let lifecycle_visitor
let s = stmts.(len-1) in
match s.node with
Ast.STMT_ret _
| Ast.STMT_be _ ->
| Ast.STMT_be _
| Ast.STMT_break ->
() (* Taken care of in visit_stmt_post below. *)
| _ ->
(* The blk_slots stack we have has accumulated slots in
Expand All @@ -1364,11 +1388,7 @@ let lifecycle_visitor
* point in the block.
*)
let slots = stk_elts_from_top block_slots in
let live =
List.filter
(fun i -> Hashtbl.mem live_block_slots i)
slots
in
let live = filter_live_block_slots slots in
note_drops s live
end;
in
Expand Down Expand Up @@ -1440,6 +1460,10 @@ let lifecycle_visitor
f.Ast.for_each_body.id
[ (fst f.Ast.for_each_slot).id ]

| Ast.STMT_while _ ->
iflog cx (fun _ -> log cx "entering a loop");
Stack.push (Some (Stack.create ())) loop_blocks;

| Ast.STMT_alt_tag { Ast.alt_tag_arms = arms } ->
let note_slot block slot_id =
log cx
Expand Down Expand Up @@ -1475,26 +1499,38 @@ let lifecycle_visitor

let visit_stmt_post s =
inner.Walk.visit_stmt_post s;
let handle_ret_like_stmt block_stack =
let blocks = stk_elts_from_top block_stack in
let slots = List.concat (List.map stk_elts_from_top blocks) in
let live = filter_live_block_slots slots in
note_drops s live
in
match s.node with
Ast.STMT_ret _
| Ast.STMT_be _ ->
let blocks = stk_elts_from_top (Stack.top frame_blocks) in
let slots = List.concat (List.map stk_elts_from_top blocks) in
let live =
List.filter
(fun i -> Hashtbl.mem live_block_slots i)
slots
in
note_drops s live
handle_ret_like_stmt (Stack.top frame_blocks)
| Ast.STMT_break ->
begin
match (Stack.top loop_blocks) with
Some loop -> handle_ret_like_stmt loop
| None ->
iflog cx (fun _ ->
log cx "break statement outside of a loop");
err (Some s.id) "break statement outside of a loop"
end
| _ -> ()
in

let enter_frame _ =
Stack.push (Stack.create()) frame_blocks
Stack.push (Stack.create()) frame_blocks;
Stack.push None loop_blocks
in

let leave_frame _ =
ignore (Stack.pop frame_blocks)
ignore (Stack.pop frame_blocks);
match Stack.pop loop_blocks with
Some _ -> bug () "leave_frame should not end a loop"
| None -> ()
in

let visit_mod_item_pre n p i =
Expand Down
3 changes: 1 addition & 2 deletions src/boot/me/walk.ml
Original file line number Diff line number Diff line change
Expand Up @@ -481,8 +481,7 @@ and walk_stmt
| Ast.STMT_decl (Ast.DECL_slot (_, slot)) ->
walk_slot_identified v slot

| Ast.STMT_yield
| Ast.STMT_fail ->
| Ast.STMT_break | Ast.STMT_cont | Ast.STMT_yield | Ast.STMT_fail ->
()

| Ast.STMT_join task ->
Expand Down
15 changes: 15 additions & 0 deletions src/test/run-pass/while-with-break.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
// -*- rust -*-

fn main() {
let int i = 90;
while (i < 100) {
log i;
i = i + 1;
if (i == 95) {
let vec[int] v = vec(1,2,3,4,5); // we check that it is freed by break
log "breaking";
break;
}
}
check(i == 95);
}

0 comments on commit 4a34048

Please sign in to comment.