Skip to content

Commit 07351b4

Browse files
committed
syntax: implement labelled breaks for for.
`for` desugars to `loop` so it is trivial to just desugar to `loop` while retaining any label.
1 parent b609d02 commit 07351b4

File tree

9 files changed

+32
-16
lines changed

9 files changed

+32
-16
lines changed

src/librustc/middle/trans/debuginfo.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2064,7 +2064,7 @@ fn populate_scope_map(cx: &mut CrateContext,
20642064
}
20652065
}
20662066

2067-
ast::ExprForLoop(_, _, _) => {
2067+
ast::ExprForLoop(_, _, _, _) => {
20682068
cx.sess.span_bug(exp.span, "debuginfo::populate_scope_map() - \
20692069
Found unexpanded for-loop.");
20702070
}

src/libsyntax/ast.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -528,7 +528,7 @@ pub enum Expr_ {
528528
ExprCast(@Expr, Ty),
529529
ExprIf(@Expr, Block, Option<@Expr>),
530530
ExprWhile(@Expr, Block),
531-
ExprForLoop(@Pat, @Expr, Block),
531+
ExprForLoop(@Pat, @Expr, Block, Option<Ident>),
532532
/* Conditionless loop (can be exited with break, cont, or ret)
533533
Same semantics as while(true) { body }, but typestate knows that the
534534
(implicit) condition is always true. */

src/libsyntax/ext/expand.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,7 @@ pub fn expand_expr(extsbox: @mut SyntaxEnv,
113113

114114
// Desugar expr_for_loop
115115
// From: `for <src_pat> in <src_expr> <src_loop_block>`
116-
ast::ExprForLoop(src_pat, src_expr, ref src_loop_block) => {
116+
ast::ExprForLoop(src_pat, src_expr, ref src_loop_block, opt_ident) => {
117117
let src_pat = src_pat.clone();
118118
let src_expr = src_expr.clone();
119119

@@ -257,7 +257,7 @@ pub fn expand_expr(extsbox: @mut SyntaxEnv,
257257
// `loop { ... }`
258258
let loop_block = {
259259
let loop_body_block = mk_block(cx, [match_stmt], None, span);
260-
let loop_body_expr = mk_expr(cx, span, ast::ExprLoop(loop_body_block, None));
260+
let loop_body_expr = mk_expr(cx, span, ast::ExprLoop(loop_body_block, opt_ident));
261261
let loop_body_stmt = @spanned(lo, hi, ast::StmtExpr(loop_body_expr, cx.next_id()));
262262
mk_block(cx, [iter_decl_stmt,
263263
loop_body_stmt],

src/libsyntax/fold.rs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -557,10 +557,11 @@ pub fn noop_fold_expr(e: &Expr_, fld: @ast_fold) -> Expr_ {
557557
ExprWhile(cond, ref body) => {
558558
ExprWhile(fld.fold_expr(cond), fld.fold_block(body))
559559
}
560-
ExprForLoop(pat, iter, ref body) => {
560+
ExprForLoop(pat, iter, ref body, opt_ident) => {
561561
ExprForLoop(fld.fold_pat(pat),
562-
fld.fold_expr(iter),
563-
fld.fold_block(body))
562+
fld.fold_expr(iter),
563+
fld.fold_block(body),
564+
opt_ident.map_move(|x| fld.fold_ident(x)))
564565
}
565566
ExprLoop(ref body, opt_ident) => {
566567
ExprLoop(

src/libsyntax/oldvisit.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -523,7 +523,7 @@ pub fn visit_expr<E:Clone>(ex: @Expr, (e, v): (E, vt<E>)) {
523523
(v.visit_expr)(x, (e.clone(), v));
524524
(v.visit_block)(b, (e.clone(), v));
525525
}
526-
ExprForLoop(pattern, subexpression, ref block) => {
526+
ExprForLoop(pattern, subexpression, ref block, _) => {
527527
(v.visit_pat)(pattern, (e.clone(), v));
528528
(v.visit_expr)(subexpression, (e.clone(), v));
529529
(v.visit_block)(block, (e.clone(), v))

src/libsyntax/parse/parser.rs

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1771,7 +1771,7 @@ impl Parser {
17711771
} else if self.eat_keyword(keywords::If) {
17721772
return self.parse_if_expr();
17731773
} else if self.eat_keyword(keywords::For) {
1774-
return self.parse_for_expr();
1774+
return self.parse_for_expr(None);
17751775
} else if self.eat_keyword(keywords::Do) {
17761776
return self.parse_sugary_call_expr(lo, ~"do", DoSugar,
17771777
ExprDoBody);
@@ -1781,8 +1781,13 @@ impl Parser {
17811781
let lifetime = self.get_lifetime(&*self.token);
17821782
self.bump();
17831783
self.expect(&token::COLON);
1784-
self.expect_keyword(keywords::Loop);
1785-
return self.parse_loop_expr(Some(lifetime));
1784+
if self.eat_keyword(keywords::For) {
1785+
return self.parse_for_expr(Some(lifetime))
1786+
} else if self.eat_keyword(keywords::Loop) {
1787+
return self.parse_loop_expr(Some(lifetime))
1788+
} else {
1789+
self.fatal("expected `for` or `loop` after a label")
1790+
}
17861791
} else if self.eat_keyword(keywords::Loop) {
17871792
return self.parse_loop_expr(None);
17881793
} else if self.eat_keyword(keywords::Match) {
@@ -2467,7 +2472,7 @@ impl Parser {
24672472
}
24682473

24692474
// parse a 'for' .. 'in' expression ('for' token already eaten)
2470-
pub fn parse_for_expr(&self) -> @Expr {
2475+
pub fn parse_for_expr(&self, opt_ident: Option<ast::Ident>) -> @Expr {
24712476
// Parse: `for <src_pat> in <src_expr> <src_loop_block>`
24722477

24732478
let lo = self.last_span.lo;
@@ -2477,7 +2482,7 @@ impl Parser {
24772482
let loop_block = self.parse_block();
24782483
let hi = self.span.hi;
24792484

2480-
self.mk_expr(lo, hi, ExprForLoop(pat, expr, loop_block))
2485+
self.mk_expr(lo, hi, ExprForLoop(pat, expr, loop_block, opt_ident))
24812486
}
24822487

24832488

src/libsyntax/print/pprust.rs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1232,7 +1232,12 @@ pub fn print_expr(s: @ps, expr: &ast::Expr) {
12321232
space(s.s);
12331233
print_block(s, blk);
12341234
}
1235-
ast::ExprForLoop(pat, iter, ref blk) => {
1235+
ast::ExprForLoop(pat, iter, ref blk, opt_ident) => {
1236+
for ident in opt_ident.iter() {
1237+
word(s.s, "'");
1238+
print_ident(s, *ident);
1239+
word_space(s, ":");
1240+
}
12361241
head(s, "for");
12371242
print_pat(s, pat);
12381243
space(s.s);

src/libsyntax/visit.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -599,7 +599,7 @@ pub fn walk_expr<E:Clone, V:Visitor<E>>(visitor: &mut V, expression: @Expr, env:
599599
visitor.visit_expr(subexpression, env.clone());
600600
visitor.visit_block(block, env.clone())
601601
}
602-
ExprForLoop(pattern, subexpression, ref block) => {
602+
ExprForLoop(pattern, subexpression, ref block, _) => {
603603
visitor.visit_pat(pattern, env.clone());
604604
visitor.visit_expr(subexpression, env.clone());
605605
visitor.visit_block(block, env.clone())
@@ -812,4 +812,3 @@ impl Visitor<()> for SimpleVisitorVisitor {
812812
walk_struct_field(self, struct_field, env)
813813
}
814814
}
815-

src/test/run-pass/labeled-break.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,4 +14,10 @@ pub fn main() {
1414
break 'foo;
1515
}
1616
}
17+
18+
'bar: for _ in range(0, 100) {
19+
loop {
20+
break 'bar;
21+
}
22+
}
1723
}

0 commit comments

Comments
 (0)