Skip to content

Remove do loops #2375

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
May 10, 2012
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 6 additions & 27 deletions doc/rust.md
Original file line number Diff line number Diff line change
Expand Up @@ -1991,28 +1991,19 @@ way.

*TODO*.

### While expressions
### While loops

~~~~~~~~{.ebnf .gram}
while_expr : "while" expr '{' block '}'
| "do" '{' block '}' "while" expr ;
~~~~~~~~

A `while` expression is a loop construct. A `while` loop may be either a
simple `while` or a `do`-`while` loop.
A `while` loop begins by evaluating the boolean loop conditional expression.
If the loop conditional expression evaluates to `true`, the loop body block
executes and control returns to the loop conditional expression. If the loop
conditional expression evaluates to `false`, the `while` expression completes.

In the case of a simple `while`, the loop begins by evaluating the boolean
loop conditional expression. If the loop conditional expression evaluates to
`true`, the loop body block executes and control returns to the loop
conditional expression. If the loop conditional expression evaluates to
`false`, the `while` expression completes.

In the case of a `do`-`while`, the loop begins with an execution of the loop
body. After the loop body executes, it evaluates the loop conditional
expression. If it evaluates to `true`, control returns to the beginning of the
loop body. If it evaluates to `false`, control exits the loop.

An example of a simple `while` expression:
An example:

~~~~
# let mut i = 0;
Expand All @@ -2024,18 +2015,6 @@ while i < 10 {
}
~~~~

An example of a `do`-`while` expression:

~~~~
# let mut i = 0;
# let println = io::println;

do {
println("hello\n");
i = i + 1;
} while i < 10;
~~~~

### Infinite loops

A `loop` expression denotes an infinite loop:
Expand Down
26 changes: 12 additions & 14 deletions doc/tutorial.md
Original file line number Diff line number Diff line change
Expand Up @@ -667,6 +667,15 @@ a specific value, are not allowed.
keyword `break` can be used to abort the loop, and `cont` can be used
to abort the current iteration and continue with the next.

~~~~
let mut cake_amount = 8;
while cake_amount > 0 {
cake_amount -= 1;
}
~~~~

`loop` is the preferred way of writing `while true`:

~~~~
let mut x = 5;
while true {
Expand All @@ -679,17 +688,6 @@ while true {
This code prints out a weird sequence of numbers and stops as soon as
it finds one that can be divided by five.

There's also `while`'s ugly cousin, `do`/`while`, which does not check
its condition on the first iteration, using traditional syntax:

~~~~
# fn eat_cake() {}
# fn any_cake_left() -> bool { false }
do {
eat_cake();
} while any_cake_left();
~~~~

For more involved iteration, such as going over the elements of a
collection, Rust uses higher-order functions. We'll come back to those
in a moment.
Expand Down Expand Up @@ -2496,12 +2494,12 @@ Here is the function which implements the child task:
fn stringifier(from_parent: comm::port<uint>,
to_parent: comm::chan<str>) {
let mut value: uint;
do {
loop {
value = comm::recv(from_parent);
comm::send(to_parent, uint::to_str(value, 10u));
} while value != 0u;
if value == 0u { break; }
}
}

~~~~

You can see that the function takes two parameters. The first is a
Expand Down
3 changes: 0 additions & 3 deletions src/fuzzer/fuzzer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -74,9 +74,6 @@ pure fn safe_to_use_expr(e: ast::expr, tm: test_mode) -> bool {
ast::expr_alt(_, _, _) { false }
ast::expr_while(_, _) { false }

// https://github.com/mozilla/rust/issues/955
ast::expr_do_while(_, _) { false }

// https://github.com/mozilla/rust/issues/929
ast::expr_cast(_, _) { false }
ast::expr_assert(_) { false }
Expand Down
4 changes: 2 additions & 2 deletions src/libcore/path.rs
Original file line number Diff line number Diff line change
Expand Up @@ -251,7 +251,7 @@ fn normalize(p: path) -> path {
let mut t = [];
let mut i = vec::len(s);
let mut skip = 0;
do {
while i != 0u {
i -= 1u;
if s[i] == ".." {
skip += 1;
Expand All @@ -262,7 +262,7 @@ fn normalize(p: path) -> path {
skip -= 1;
}
}
} while i != 0u;
}
let mut t = vec::reversed(t);
while skip > 0 {
t += [".."];
Expand Down
1 change: 0 additions & 1 deletion src/librustsyntax/ast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -305,7 +305,6 @@ enum expr_ {
expr_cast(@expr, @ty),
expr_if(@expr, blk, option<@expr>),
expr_while(@expr, blk),
expr_do_while(blk, @expr),
/* Conditionless loop (can be exited with break, cont, ret, or fail)
Same semantics as while(true) { body }, but typestate knows that the
(implicit) condition is always true. */
Expand Down
3 changes: 0 additions & 3 deletions src/librustsyntax/fold.rs
Original file line number Diff line number Diff line change
Expand Up @@ -444,9 +444,6 @@ fn noop_fold_expr(e: expr_, fld: ast_fold) -> expr_ {
expr_while(cond, body) {
expr_while(fld.fold_expr(cond), fld.fold_block(body))
}
expr_do_while(blk, expr) {
expr_do_while(fld.fold_block(blk), fld.fold_expr(expr))
}
expr_loop(body) {
expr_loop(fld.fold_block(body))
}
Expand Down
4 changes: 2 additions & 2 deletions src/librustsyntax/parse/classify.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ fn expr_requires_semi_to_be_stmt(e: @ast::expr) -> bool {
alt e.node {
ast::expr_if(_, _, _) | ast::expr_if_check(_, _, _)
| ast::expr_alt(_, _, _) | ast::expr_block(_)
| ast::expr_do_while(_, _) | ast::expr_while(_, _)
| ast::expr_loop(_) | ast::expr_call(_, _, true) {
| ast::expr_while(_, _) | ast::expr_loop(_)
| ast::expr_call(_, _, true) {
false
}
_ { true }
Expand Down
11 changes: 0 additions & 11 deletions src/librustsyntax/parse/parser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -727,8 +727,6 @@ fn parse_bottom_expr(p: parser) -> pexpr {
ret pexpr(parse_for_expr(p));
} else if eat_keyword(p, "while") {
ret pexpr(parse_while_expr(p));
} else if eat_keyword(p, "do") {
ret pexpr(parse_do_while_expr(p));
} else if eat_keyword(p, "loop") {
ret pexpr(parse_loop_expr(p));
} else if eat_keyword(p, "alt") {
Expand Down Expand Up @@ -1233,15 +1231,6 @@ fn parse_while_expr(p: parser) -> @expr {
ret mk_expr(p, lo, hi, expr_while(cond, body));
}

fn parse_do_while_expr(p: parser) -> @expr {
let lo = p.last_span.lo;
let body = parse_block_no_value(p);
expect_keyword(p, "while");
let cond = parse_expr(p);
let mut hi = cond.span.hi;
ret mk_expr(p, lo, hi, expr_do_while(body, cond));
}

fn parse_loop_expr(p: parser) -> @expr {
let lo = p.last_span.lo;
let body = parse_block_no_value(p);
Expand Down
8 changes: 0 additions & 8 deletions src/librustsyntax/print/pprust.rs
Original file line number Diff line number Diff line change
Expand Up @@ -975,14 +975,6 @@ fn print_expr(s: ps, &&expr: @ast::expr) {
space(s.s);
print_block(s, blk);
}
ast::expr_do_while(blk, expr) {
head(s, "do");
space(s.s);
print_block(s, blk);
space(s.s);
word_space(s, "while");
print_expr(s, expr);
}
ast::expr_alt(expr, arms, mode) {
cbox(s, alt_indent_unit);
ibox(s, 4u);
Expand Down
1 change: 0 additions & 1 deletion src/librustsyntax/visit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -376,7 +376,6 @@ fn visit_expr<E>(ex: @expr, e: E, v: vt<E>) {
}
expr_while(x, b) { v.visit_expr(x, e, v); v.visit_block(b, e, v); }
expr_loop(b) { v.visit_block(b, e, v); }
expr_do_while(b, x) { v.visit_block(b, e, v); v.visit_expr(x, e, v); }
expr_alt(x, arms, _) {
v.visit_expr(x, e, v);
for arms.each {|a| v.visit_arm(a, e, v); }
Expand Down
15 changes: 9 additions & 6 deletions src/rustc/metadata/tydecode.rs
Original file line number Diff line number Diff line change
Expand Up @@ -69,10 +69,11 @@ fn parse_constrs(st: @pstate, conv: conv_did) -> [@ty::constr] {
let mut rslt: [@ty::constr] = [];
alt peek(st) {
':' {
do {
loop {
next(st);
rslt += [parse_constr(st, conv, parse_constr_arg)];
} while peek(st) == ';'
if peek(st) != ';' { break; }
}
}
_ { }
}
Expand All @@ -84,10 +85,11 @@ fn parse_ty_constrs(st: @pstate, conv: conv_did) -> [@ty::type_constr] {
let mut rslt: [@ty::type_constr] = [];
alt peek(st) {
':' {
do {
loop {
next(st);
rslt += [parse_constr(st, conv, parse_ty_constr_arg)];
} while peek(st) == ';'
if peek(st) != ';' { break; }
}
}
_ { }
}
Expand Down Expand Up @@ -154,12 +156,13 @@ fn parse_constr<T: copy>(st: @pstate, conv: conv_did,
assert (ignore == '(');
let def = parse_def(st, conv);
let mut an_arg: constr_arg_general_<T>;
do {
loop {
an_arg = pser(st);
// FIXME use a real span
args += [@respan(sp, an_arg)];
ignore = next(st);
} while ignore == ';'
if ignore != ';' { break; }
}
assert (ignore == ')');
ret @respan(sp, {path: pth, args: args, id: def});
}
Expand Down
2 changes: 1 addition & 1 deletion src/rustc/middle/alias.rs
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,7 @@ fn visit_expr(cx: @ctx, ex: @ast::expr, sc: scope, v: vt<scope>) {
check_lval(cx, dest, sc, v);
}
ast::expr_if(c, then, els) { check_if(c, then, els, sc, v); }
ast::expr_while(_, _) | ast::expr_do_while(_, _) {
ast::expr_while(_, _) {
check_loop(*cx, sc) {|| visit::visit_expr(ex, sc, v); }
}
_ { handled = false; }
Expand Down
6 changes: 3 additions & 3 deletions src/rustc/middle/borrowck.rs
Original file line number Diff line number Diff line change
Expand Up @@ -761,9 +761,9 @@ impl categorize_methods for borrowck_ctxt {
ast::expr_vstore(*) | ast::expr_vec(*) | ast::expr_tup(*) |
ast::expr_if_check(*) | ast::expr_if(*) | ast::expr_log(*) |
ast::expr_new(*) | ast::expr_binary(*) | ast::expr_while(*) |
ast::expr_do_while(*) | ast::expr_block(*) | ast::expr_loop(*) |
ast::expr_alt(*) | ast::expr_lit(*) | ast::expr_break |
ast::expr_mac(*) | ast::expr_cont | ast::expr_rec(*) {
ast::expr_block(*) | ast::expr_loop(*) | ast::expr_alt(*) |
ast::expr_lit(*) | ast::expr_break | ast::expr_mac(*) |
ast::expr_cont | ast::expr_rec(*) {
@{id:expr.id, span:expr.span,
cat:cat_rvalue(rv_misc), lp:none,
mutbl:m_imm, ty:expr_ty}
Expand Down
2 changes: 1 addition & 1 deletion src/rustc/middle/check_loop.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ fn check_crate(tcx: ty::ctxt, crate: @crate) {
},
visit_expr: {|e: @expr, cx: ctx, v: visit::vt<ctx>|
alt e.node {
expr_while(e, b) | expr_do_while(b, e) {
expr_while(e, b) {
v.visit_expr(e, cx, v);
v.visit_block(b, {in_loop: true with cx}, v);
}
Expand Down
2 changes: 1 addition & 1 deletion src/rustc/middle/last_use.rs
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ fn visit_expr(ex: @expr, cx: ctx, v: visit::vt<ctx>) {
leave_fn(cx);
}
expr_break { add_block_exit(cx, lp); }
expr_while(_, _) | expr_do_while(_, _) | expr_loop(_) {
expr_while(_, _) | expr_loop(_) {
visit_block(lp, cx) {|| visit::visit_expr(ex, cx, v);}
}
expr_alt(input, arms, _) {
Expand Down
21 changes: 0 additions & 21 deletions src/rustc/middle/trans/base.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1761,23 +1761,6 @@ fn trans_while(cx: block, cond: @ast::expr, body: ast::blk)
ret next_cx;
}

fn trans_do_while(cx: block, body: ast::blk, cond: @ast::expr) ->
block {
let _icx = cx.insn_ctxt("trans_do_while");
let next_cx = sub_block(cx, "next");
let body_cx =
loop_scope_block(cx, cont_self, next_cx,
"do-while loop body", body.span);
let body_end = trans_block(body_cx, body, ignore);
let cond_cx = scope_block(body_cx, "do-while cond");
cleanup_and_Br(body_end, body_cx, cond_cx.llbb);
let cond_res = trans_temp_expr(cond_cx, cond);
let cond_bcx = trans_block_cleanups(cond_res.bcx, cond_cx);
CondBr(cond_bcx, cond_res.val, body_cx.llbb, next_cx.llbb);
Br(cx, body_cx.llbb);
ret next_cx;
}

fn trans_loop(cx:block, body: ast::blk) -> block {
let _icx = cx.insn_ctxt("trans_loop");
let next_cx = sub_block(cx, "next");
Expand Down Expand Up @@ -3285,10 +3268,6 @@ fn trans_expr(bcx: block, e: @ast::expr, dest: dest) -> block {
assert dest == ignore;
ret trans_loop(bcx, body);
}
ast::expr_do_while(body, cond) {
assert dest == ignore;
ret trans_do_while(bcx, body, cond);
}
ast::expr_assign(dst, src) {
assert dest == ignore;
let src_r = trans_temp_lval(bcx, src);
Expand Down
7 changes: 3 additions & 4 deletions src/rustc/middle/trans/type_use.rs
Original file line number Diff line number Diff line change
Expand Up @@ -212,10 +212,9 @@ fn mark_for_expr(cx: ctx, e: @expr) {
}
}
}
expr_do_while(_, _) | expr_alt(_, _, _) |
expr_block(_) | expr_if(_, _, _) | expr_while(_, _) |
expr_fail(_) | expr_break | expr_cont | expr_unary(_, _) |
expr_lit(_) | expr_assert(_) | expr_check(_, _) |
expr_alt(_, _, _) | expr_block(_) | expr_if(_, _, _) |
expr_while(_, _) | expr_fail(_) | expr_break | expr_cont |
expr_unary(_, _) | expr_lit(_) | expr_assert(_) | expr_check(_, _) |
expr_if_check(_, _, _) | expr_mac(_) | expr_addr_of(_, _) |
expr_ret(_) | expr_loop(_) | expr_bind(_, _) | expr_loop_body(_) {}
}
Expand Down
19 changes: 0 additions & 19 deletions src/rustc/middle/tstate/pre_post_conditions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -425,25 +425,6 @@ fn find_pre_post_expr(fcx: fn_ctxt, e: @expr) {
intersect_states(expr_postcond(fcx.ccx, test),
block_postcond(fcx.ccx, body)));
}
expr_do_while(body, test) {
find_pre_post_block(fcx, body);
find_pre_post_expr(fcx, test);
let mut loop_postcond =
seq_postconds(fcx,
[block_postcond(fcx.ccx, body),
expr_postcond(fcx.ccx, test)]);
/* conservative approximation: if the body
could break or cont, the test may never be executed */

if has_nonlocal_exits(body) {
loop_postcond = empty_poststate(num_local_vars);
}
set_pre_and_post(fcx.ccx, e.id,
seq_preconds(fcx,
[block_pp(fcx.ccx, body),
expr_pp(fcx.ccx, test)]),
loop_postcond);
}
expr_loop(body) {
find_pre_post_block(fcx, body);
/* Infinite loop: if control passes it, everything is true. */
Expand Down
Loading