Skip to content

Commit bdb206f

Browse files
committed
rustc: Parse labeled loop, break, and again
1 parent d54db12 commit bdb206f

19 files changed

+152
-53
lines changed

src/fuzzer/fuzzer.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,8 +41,8 @@ fn common_exprs() -> ~[ast::expr] {
4141
{ node: l, span: ast_util::dummy_sp() }
4242
}
4343

44-
~[dse(ast::expr_break),
45-
dse(ast::expr_again),
44+
~[dse(ast::expr_break(option::none)),
45+
dse(ast::expr_again(option::none)),
4646
dse(ast::expr_fail(option::none)),
4747
dse(ast::expr_fail(option::some(
4848
@dse(ast::expr_lit(@dsl(ast::lit_str(@~"boo"))))))),

src/libsyntax/ast.rs

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,8 @@ enum def {
8989
node_id /* expr node that creates the closure */),
9090
def_class(def_id, bool /* has constructor */),
9191
def_typaram_binder(node_id), /* class, impl or trait that has ty params */
92-
def_region(node_id)
92+
def_region(node_id),
93+
def_label(node_id)
9394
}
9495

9596
// The set of meta_items that define the compilation environment of the crate,
@@ -316,7 +317,7 @@ enum expr_ {
316317
/* Conditionless loop (can be exited with break, cont, ret, or fail)
317318
Same semantics as while(true) { body }, but typestate knows that the
318319
(implicit) condition is always true. */
319-
expr_loop(blk),
320+
expr_loop(blk, option<ident>),
320321
expr_match(@expr, ~[arm], alt_mode),
321322
expr_fn(proto, fn_decl, blk, capture_clause),
322323
expr_fn_block(fn_decl, blk, capture_clause),
@@ -339,8 +340,8 @@ enum expr_ {
339340
expr_path(@path),
340341
expr_addr_of(mutability, @expr),
341342
expr_fail(option<@expr>),
342-
expr_break,
343-
expr_again,
343+
expr_break(option<ident>),
344+
expr_again(option<ident>),
344345
expr_ret(option<@expr>),
345346
expr_log(int, @expr, @expr),
346347

src/libsyntax/ast_util.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ pure fn def_id_of_def(d: def) -> def_id {
6161
}
6262
def_arg(id, _) | def_local(id, _) | def_self(id) |
6363
def_upvar(id, _, _) | def_binding(id, _) | def_region(id)
64-
| def_typaram_binder(id) => {
64+
| def_typaram_binder(id) | def_label(id) => {
6565
local_def(id)
6666
}
6767

src/libsyntax/fold.rs

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -448,8 +448,9 @@ fn noop_fold_expr(e: expr_, fld: ast_fold) -> expr_ {
448448
expr_while(cond, body) => {
449449
expr_while(fld.fold_expr(cond), fld.fold_block(body))
450450
}
451-
expr_loop(body) => {
452-
expr_loop(fld.fold_block(body))
451+
expr_loop(body, opt_ident) => {
452+
expr_loop(fld.fold_block(body),
453+
option::map(opt_ident, |x| fld.fold_ident(x)))
453454
}
454455
expr_match(expr, arms, mode) => {
455456
expr_match(fld.fold_expr(expr),
@@ -492,7 +493,10 @@ fn noop_fold_expr(e: expr_, fld: ast_fold) -> expr_ {
492493
}
493494
expr_path(pth) => expr_path(fld.fold_path(pth)),
494495
expr_fail(e) => expr_fail(option::map(e, |x| fld.fold_expr(x))),
495-
expr_break | expr_again => copy e,
496+
expr_break(opt_ident) =>
497+
expr_break(option::map(opt_ident, |x| fld.fold_ident(x))),
498+
expr_again(opt_ident) =>
499+
expr_again(option::map(opt_ident, |x| fld.fold_ident(x))),
496500
expr_ret(e) => expr_ret(option::map(e, |x| fld.fold_expr(x))),
497501
expr_log(i, lv, e) => expr_log(i, fld.fold_expr(lv),
498502
fld.fold_expr(e)),

src/libsyntax/parse/classify.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import ast_util::operator_prec;
77
fn expr_requires_semi_to_be_stmt(e: @ast::expr) -> bool {
88
match e.node {
99
ast::expr_if(_, _, _) | ast::expr_match(_, _, _) | ast::expr_block(_)
10-
| ast::expr_while(_, _) | ast::expr_loop(_)
10+
| ast::expr_while(_, _) | ast::expr_loop(_, _)
1111
| ast::expr_call(_, _, true) => false,
1212
_ => true
1313
}

src/libsyntax/parse/parser.rs

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -939,10 +939,18 @@ class parser {
939939
ex = expr_ret(some(e));
940940
} else { ex = expr_ret(none); }
941941
} else if self.eat_keyword(~"break") {
942-
ex = expr_break;
942+
if is_ident(self.token) {
943+
ex = expr_break(some(self.parse_ident()));
944+
} else {
945+
ex = expr_break(none);
946+
}
943947
hi = self.span.hi;
944948
} else if self.eat_keyword(~"again") {
945-
ex = expr_again;
949+
if is_ident(self.token) {
950+
ex = expr_again(some(self.parse_ident()));
951+
} else {
952+
ex = expr_again(none);
953+
}
946954
hi = self.span.hi;
947955
} else if self.eat_keyword(~"copy") {
948956
let e = self.parse_expr();
@@ -1585,10 +1593,18 @@ class parser {
15851593
}
15861594

15871595
fn parse_loop_expr() -> @expr {
1596+
let opt_ident;
1597+
if is_ident(self.token) {
1598+
opt_ident = some(self.parse_ident());
1599+
self.expect(token::COLON);
1600+
} else {
1601+
opt_ident = none;
1602+
}
1603+
15881604
let lo = self.last_span.lo;
15891605
let body = self.parse_block_no_value();
15901606
let mut hi = body.span.hi;
1591-
return self.mk_expr(lo, hi, expr_loop(body));
1607+
return self.mk_expr(lo, hi, expr_loop(body, opt_ident));
15921608
}
15931609

15941610
// For distingishing between record literals and blocks

src/libsyntax/print/pprust.rs

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1142,9 +1142,10 @@ fn print_expr(s: ps, &&expr: @ast::expr) {
11421142
space(s.s);
11431143
print_block(s, blk);
11441144
}
1145-
ast::expr_loop(blk) => {
1145+
ast::expr_loop(blk, opt_ident) => {
11461146
head(s, ~"loop");
11471147
space(s.s);
1148+
option::iter(opt_ident, |ident| word_space(s, *ident));
11481149
print_block(s, blk);
11491150
}
11501151
ast::expr_match(expr, arms, mode) => {
@@ -1310,8 +1311,16 @@ fn print_expr(s: ps, &&expr: @ast::expr) {
13101311
_ => ()
13111312
}
13121313
}
1313-
ast::expr_break => word(s.s, ~"break"),
1314-
ast::expr_again => word(s.s, ~"again"),
1314+
ast::expr_break(opt_ident) => {
1315+
word(s.s, ~"break");
1316+
space(s.s);
1317+
option::iter(opt_ident, |ident| word_space(s, *ident));
1318+
}
1319+
ast::expr_again(opt_ident) => {
1320+
word(s.s, ~"again");
1321+
space(s.s);
1322+
option::iter(opt_ident, |ident| word_space(s, *ident));
1323+
}
13151324
ast::expr_ret(result) => {
13161325
word(s.s, ~"return");
13171326
match result {

src/libsyntax/visit.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -422,7 +422,7 @@ fn visit_expr<E>(ex: @expr, e: E, v: vt<E>) {
422422
visit_expr_opt(eo, e, v);
423423
}
424424
expr_while(x, b) => { v.visit_expr(x, e, v); v.visit_block(b, e, v); }
425-
expr_loop(b) => v.visit_block(b, e, v),
425+
expr_loop(b, _) => v.visit_block(b, e, v),
426426
expr_match(x, arms, _) => {
427427
v.visit_expr(x, e, v);
428428
for arms.each |a| { v.visit_arm(a, e, v); }
@@ -452,8 +452,8 @@ fn visit_expr<E>(ex: @expr, e: E, v: vt<E>) {
452452
expr_index(a, b) => { v.visit_expr(a, e, v); v.visit_expr(b, e, v); }
453453
expr_path(p) => visit_path(p, e, v),
454454
expr_fail(eo) => visit_expr_opt(eo, e, v),
455-
expr_break => (),
456-
expr_again => (),
455+
expr_break(_) => (),
456+
expr_again(_) => (),
457457
expr_ret(eo) => visit_expr_opt(eo, e, v),
458458
expr_log(_, lv, x) => {
459459
v.visit_expr(lv, e, v);

src/rustc/middle/astencode.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -374,6 +374,7 @@ impl ast::def: tr {
374374
ast::def_typaram_binder(nid) => {
375375
ast::def_typaram_binder(xcx.tr_id(nid))
376376
}
377+
ast::def_label(nid) => ast::def_label(xcx.tr_id(nid))
377378
}
378379
}
379380
}

src/rustc/middle/borrowck/gather_loans.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -227,7 +227,7 @@ fn req_loans_in_expr(ex: @ast::expr,
227227
}
228228

229229
// see explanation attached to the `root_ub` field:
230-
ast::expr_loop(body) => {
230+
ast::expr_loop(body, _) => {
231231
self.root_ub = body.node.id;
232232
visit::visit_expr(ex, self, vt);
233233
}

src/rustc/middle/check_loop.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ fn check_crate(tcx: ty::ctxt, crate: @crate) {
1515
v.visit_expr(e, cx, v);
1616
v.visit_block(b, {in_loop: true with cx}, v);
1717
}
18-
expr_loop(b) => {
18+
expr_loop(b, _) => {
1919
v.visit_block(b, {in_loop: true with cx}, v);
2020
}
2121
expr_fn(_, _, _, _) => {
@@ -29,12 +29,12 @@ fn check_crate(tcx: ty::ctxt, crate: @crate) {
2929
e)));
3030
v.visit_block(b, {in_loop: true, can_ret: blk}, v);
3131
}
32-
expr_break => {
32+
expr_break(_) => {
3333
if !cx.in_loop {
3434
tcx.sess.span_err(e.span, ~"`break` outside of loop");
3535
}
3636
}
37-
expr_again => {
37+
expr_again(_) => {
3838
if !cx.in_loop {
3939
tcx.sess.span_err(e.span, ~"`again` outside of loop");
4040
}

src/rustc/middle/liveness.rs

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -469,7 +469,7 @@ fn visit_expr(expr: @expr, &&self: @ir_maps, vt: vt<@ir_maps>) {
469469
expr_assert(*) | expr_addr_of(*) | expr_copy(*) |
470470
expr_loop_body(*) | expr_do_body(*) | expr_cast(*) |
471471
expr_unary(*) | expr_fail(*) |
472-
expr_break | expr_again | expr_lit(_) | expr_ret(*) |
472+
expr_break(_) | expr_again(_) | expr_lit(_) | expr_ret(*) |
473473
expr_block(*) | expr_move(*) | expr_unary_move(*) | expr_assign(*) |
474474
expr_swap(*) | expr_assign_op(*) | expr_mac(*) | expr_struct(*) |
475475
expr_repeat(*) => {
@@ -962,7 +962,7 @@ class liveness {
962962
self.propagate_through_loop(expr, some(cond), blk, succ)
963963
}
964964

965-
expr_loop(blk) => {
965+
expr_loop(blk, _) => {
966966
self.propagate_through_loop(expr, none, blk, succ)
967967
}
968968

@@ -1000,21 +1000,29 @@ class liveness {
10001000
self.propagate_through_opt_expr(o_e, self.s.exit_ln)
10011001
}
10021002

1003-
expr_break => {
1003+
expr_break(opt_label) => {
10041004
if !self.break_ln.is_valid() {
10051005
self.tcx.sess.span_bug(
10061006
expr.span, ~"break with invalid break_ln");
10071007
}
10081008

1009+
if opt_label.is_some() {
1010+
self.tcx.sess.span_unimpl(expr.span, ~"labeled break");
1011+
}
1012+
10091013
self.break_ln
10101014
}
10111015
1012-
expr_again => {
1016+
expr_again(opt_label) => {
10131017
if !self.cont_ln.is_valid() {
10141018
self.tcx.sess.span_bug(
10151019
expr.span, ~"cont with invalid cont_ln");
10161020
}
10171021

1022+
if opt_label.is_some() {
1023+
self.tcx.sess.span_unimpl(expr.span, ~"labeled again");
1024+
}
1025+
10181026
self.cont_ln
10191027
}
10201028

@@ -1457,7 +1465,7 @@ fn check_expr(expr: @expr, &&self: @liveness, vt: vt<@liveness>) {
14571465
expr_assert(*) | expr_copy(*) |
14581466
expr_loop_body(*) | expr_do_body(*) |
14591467
expr_cast(*) | expr_unary(*) | expr_fail(*) |
1460-
expr_ret(*) | expr_break | expr_again | expr_lit(_) |
1468+
expr_ret(*) | expr_break(*) | expr_again(*) | expr_lit(_) |
14611469
expr_block(*) | expr_swap(*) | expr_mac(*) | expr_addr_of(*) |
14621470
expr_struct(*) | expr_repeat(*) => {
14631471
visit::visit_expr(expr, self, vt);

src/rustc/middle/mem_categorization.rs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -317,8 +317,8 @@ impl &mem_categorization_ctxt {
317317
ast::expr_if(*) | ast::expr_log(*) |
318318
ast::expr_binary(*) | ast::expr_while(*) |
319319
ast::expr_block(*) | ast::expr_loop(*) | ast::expr_match(*) |
320-
ast::expr_lit(*) | ast::expr_break | ast::expr_mac(*) |
321-
ast::expr_again | ast::expr_rec(*) | ast::expr_struct(*) |
320+
ast::expr_lit(*) | ast::expr_break(*) | ast::expr_mac(*) |
321+
ast::expr_again(*) | ast::expr_rec(*) | ast::expr_struct(*) |
322322
ast::expr_unary_move(*) | ast::expr_repeat(*) => {
323323
return self.cat_rvalue(expr, expr_ty);
324324
}
@@ -335,7 +335,8 @@ impl &mem_categorization_ctxt {
335335
ast::def_use(_) | ast::def_variant(*) |
336336
ast::def_ty(_) | ast::def_prim_ty(_) |
337337
ast::def_ty_param(*) | ast::def_class(*) |
338-
ast::def_typaram_binder(*) | ast::def_region(_) => {
338+
ast::def_typaram_binder(*) | ast::def_region(_) |
339+
ast::def_label(_) => {
339340
@{id:id, span:span,
340341
cat:cat_special(sk_static_item), lp:none,
341342
mutbl:m_imm, ty:expr_ty}

0 commit comments

Comments
 (0)