about summary refs log tree commit diff
path: root/src/libsyntax
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2014-08-30 09:01:20 +0000
committerbors <bors@rust-lang.org>2014-08-30 09:01:20 +0000
commit43c26e6041b811b322f49933e8d0f9455cb7ea2b (patch)
tree1d6a7a8293538c92f5883659ab872d550a790690 /src/libsyntax
parentc8e86e977f5f95bd2f533c12ebf8107fb6f21a0f (diff)
parente76db8ebc2955ce19605a9c73d2b26b977406803 (diff)
downloadrust-43c26e6041b811b322f49933e8d0f9455cb7ea2b.tar.gz
rust-43c26e6041b811b322f49933e8d0f9455cb7ea2b.zip
auto merge of #16190 : Pythoner6/rust/labeled-while-loop, r=alexcrichton
Fixes #12643

> Say!
> I like labelled breaks/continues!

I will use them with a `for` loop.
And I will use with a `loop` loop.
Say! I will use them ANYWHERE!
… _even_ in a `while` loop.

Because they're now supported there.
Diffstat (limited to 'src/libsyntax')
-rw-r--r--src/libsyntax/ast.rs3
-rw-r--r--src/libsyntax/ext/expand.rs6
-rw-r--r--src/libsyntax/fold.rs14
-rw-r--r--src/libsyntax/parse/parser.rs11
-rw-r--r--src/libsyntax/print/pprust.rs8
-rw-r--r--src/libsyntax/visit.rs4
6 files changed, 31 insertions, 15 deletions
diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs
index 8df6b65cd16..68a1c521f19 100644
--- a/src/libsyntax/ast.rs
+++ b/src/libsyntax/ast.rs
@@ -524,7 +524,8 @@ pub enum Expr_ {
     ExprLit(Gc<Lit>),
     ExprCast(Gc<Expr>, P<Ty>),
     ExprIf(Gc<Expr>, P<Block>, Option<Gc<Expr>>),
-    ExprWhile(Gc<Expr>, P<Block>),
+    // FIXME #6993: change to Option<Name> ... or not, if these are hygienic.
+    ExprWhile(Gc<Expr>, P<Block>, Option<Ident>),
     // FIXME #6993: change to Option<Name> ... or not, if these are hygienic.
     ExprForLoop(Gc<Pat>, Gc<Expr>, P<Block>, Option<Ident>),
     // Conditionless loop (can be exited with break, cont, or ret)
diff --git a/src/libsyntax/ext/expand.rs b/src/libsyntax/ext/expand.rs
index 9dbea1c9ac2..d0f3cf6f9d7 100644
--- a/src/libsyntax/ext/expand.rs
+++ b/src/libsyntax/ext/expand.rs
@@ -66,6 +66,12 @@ fn expand_expr(e: Gc<ast::Expr>, fld: &mut MacroExpander) -> Gc<ast::Expr> {
             }
         }
 
+        ast::ExprWhile(cond, body, opt_ident) => {
+            let cond = fld.fold_expr(cond);
+            let (body, opt_ident) = expand_loop_block(body, opt_ident, fld);
+            fld.cx.expr(e.span, ast::ExprWhile(cond, body, opt_ident))
+        }
+
         ast::ExprLoop(loop_block, opt_ident) => {
             let (loop_block, opt_ident) = expand_loop_block(loop_block, opt_ident, fld);
             fld.cx.expr(e.span, ast::ExprLoop(loop_block, opt_ident))
diff --git a/src/libsyntax/fold.rs b/src/libsyntax/fold.rs
index be1c0d96711..7deabed04b8 100644
--- a/src/libsyntax/fold.rs
+++ b/src/libsyntax/fold.rs
@@ -1,4 +1,4 @@
-// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
+// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT
 // file at the top-level directory of this distribution and at
 // http://rust-lang.org/COPYRIGHT.
 //
@@ -1132,18 +1132,20 @@ pub fn noop_fold_expr<T: Folder>(e: Gc<Expr>, folder: &mut T) -> Gc<Expr> {
                    folder.fold_block(tr),
                    fl.map(|x| folder.fold_expr(x)))
         }
-        ExprWhile(cond, body) => {
-            ExprWhile(folder.fold_expr(cond), folder.fold_block(body))
+        ExprWhile(cond, body, opt_ident) => {
+            ExprWhile(folder.fold_expr(cond),
+                      folder.fold_block(body),
+                      opt_ident.map(|i| folder.fold_ident(i)))
         }
-        ExprForLoop(pat, iter, body, ref maybe_ident) => {
+        ExprForLoop(pat, iter, body, ref opt_ident) => {
             ExprForLoop(folder.fold_pat(pat),
                         folder.fold_expr(iter),
                         folder.fold_block(body),
-                        maybe_ident.map(|i| folder.fold_ident(i)))
+                        opt_ident.map(|i| folder.fold_ident(i)))
         }
         ExprLoop(body, opt_ident) => {
             ExprLoop(folder.fold_block(body),
-                     opt_ident.map(|x| folder.fold_ident(x)))
+                     opt_ident.map(|i| folder.fold_ident(i)))
         }
         ExprMatch(expr, ref arms) => {
             ExprMatch(folder.fold_expr(expr),
diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs
index 37bda15ac2c..60f24401152 100644
--- a/src/libsyntax/parse/parser.rs
+++ b/src/libsyntax/parse/parser.rs
@@ -2094,19 +2094,22 @@ impl<'a> Parser<'a> {
                     return self.parse_for_expr(None);
                 }
                 if self.eat_keyword(keywords::While) {
-                    return self.parse_while_expr();
+                    return self.parse_while_expr(None);
                 }
                 if Parser::token_is_lifetime(&self.token) {
                     let lifetime = self.get_lifetime();
                     self.bump();
                     self.expect(&token::COLON);
+                    if self.eat_keyword(keywords::While) {
+                        return self.parse_while_expr(Some(lifetime))
+                    }
                     if self.eat_keyword(keywords::For) {
                         return self.parse_for_expr(Some(lifetime))
                     }
                     if self.eat_keyword(keywords::Loop) {
                         return self.parse_loop_expr(Some(lifetime))
                     }
-                    self.fatal("expected `for` or `loop` after a label")
+                    self.fatal("expected `while`, `for`, or `loop` after a label")
                 }
                 if self.eat_keyword(keywords::Loop) {
                     return self.parse_loop_expr(None);
@@ -2762,12 +2765,12 @@ impl<'a> Parser<'a> {
         self.mk_expr(lo, hi, ExprForLoop(pat, expr, loop_block, opt_ident))
     }
 
-    pub fn parse_while_expr(&mut self) -> Gc<Expr> {
+    pub fn parse_while_expr(&mut self, opt_ident: Option<ast::Ident>) -> Gc<Expr> {
         let lo = self.last_span.lo;
         let cond = self.parse_expr_res(RESTRICT_NO_STRUCT_LITERAL);
         let body = self.parse_block();
         let hi = body.span.hi;
-        return self.mk_expr(lo, hi, ExprWhile(cond, body));
+        return self.mk_expr(lo, hi, ExprWhile(cond, body, opt_ident));
     }
 
     pub fn parse_loop_expr(&mut self, opt_ident: Option<ast::Ident>) -> Gc<Expr> {
diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs
index da265d81250..6b94048eab7 100644
--- a/src/libsyntax/print/pprust.rs
+++ b/src/libsyntax/print/pprust.rs
@@ -1,4 +1,4 @@
-// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
+// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT
 // file at the top-level directory of this distribution and at
 // http://rust-lang.org/COPYRIGHT.
 //
@@ -1438,7 +1438,11 @@ impl<'a> State<'a> {
             ast::ExprIf(ref test, ref blk, elseopt) => {
                 try!(self.print_if(&**test, &**blk, elseopt, false));
             }
-            ast::ExprWhile(ref test, ref blk) => {
+            ast::ExprWhile(ref test, ref blk, opt_ident) => {
+                for ident in opt_ident.iter() {
+                    try!(self.print_ident(*ident));
+                    try!(self.word_space(":"));
+                }
                 try!(self.head("while"));
                 try!(self.print_expr(&**test));
                 try!(space(&mut self.s));
diff --git a/src/libsyntax/visit.rs b/src/libsyntax/visit.rs
index 7a35d82b0e4..65e192e8437 100644
--- a/src/libsyntax/visit.rs
+++ b/src/libsyntax/visit.rs
@@ -1,4 +1,4 @@
-// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT
+// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT
 // file at the top-level directory of this distribution and at
 // http://rust-lang.org/COPYRIGHT.
 //
@@ -775,7 +775,7 @@ pub fn walk_expr<E: Clone, V: Visitor<E>>(visitor: &mut V, expression: &Expr, en
             visitor.visit_block(&**if_block, env.clone());
             walk_expr_opt(visitor, optional_else, env.clone())
         }
-        ExprWhile(ref subexpression, ref block) => {
+        ExprWhile(ref subexpression, ref block, _) => {
             visitor.visit_expr(&**subexpression, env.clone());
             visitor.visit_block(&**block, env.clone())
         }