about summary refs log tree commit diff
path: root/src/libsyntax
diff options
context:
space:
mode:
authorHuon Wilson <dbau.pp+github@gmail.com>2013-09-08 22:08:01 +1000
committerHuon Wilson <dbau.pp+github@gmail.com>2013-09-08 22:08:01 +1000
commit07351b44c657225d45e2aa0a302ccd28f96839a8 (patch)
treee61809a471532d32ed51f9d72ea0536b9fef471c /src/libsyntax
parentb609d022c4df307e4d68499b063c81a9ecb1e9cf (diff)
downloadrust-07351b44c657225d45e2aa0a302ccd28f96839a8.tar.gz
rust-07351b44c657225d45e2aa0a302ccd28f96839a8.zip
syntax: implement labelled breaks for `for`.
`for` desugars to `loop` so it is trivial to just desugar to `loop` while
retaining any label.
Diffstat (limited to 'src/libsyntax')
-rw-r--r--src/libsyntax/ast.rs2
-rw-r--r--src/libsyntax/ext/expand.rs4
-rw-r--r--src/libsyntax/fold.rs7
-rw-r--r--src/libsyntax/oldvisit.rs2
-rw-r--r--src/libsyntax/parse/parser.rs15
-rw-r--r--src/libsyntax/print/pprust.rs7
-rw-r--r--src/libsyntax/visit.rs3
7 files changed, 25 insertions, 15 deletions
diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs
index b993f98ec82..6957f9ae351 100644
--- a/src/libsyntax/ast.rs
+++ b/src/libsyntax/ast.rs
@@ -528,7 +528,7 @@ pub enum Expr_ {
     ExprCast(@Expr, Ty),
     ExprIf(@Expr, Block, Option<@Expr>),
     ExprWhile(@Expr, Block),
-    ExprForLoop(@Pat, @Expr, Block),
+    ExprForLoop(@Pat, @Expr, Block, Option<Ident>),
     /* Conditionless loop (can be exited with break, cont, or ret)
        Same semantics as while(true) { body }, but typestate knows that the
        (implicit) condition is always true. */
diff --git a/src/libsyntax/ext/expand.rs b/src/libsyntax/ext/expand.rs
index cde418ca991..abade04fedf 100644
--- a/src/libsyntax/ext/expand.rs
+++ b/src/libsyntax/ext/expand.rs
@@ -113,7 +113,7 @@ pub fn expand_expr(extsbox: @mut SyntaxEnv,
 
         // Desugar expr_for_loop
         // From: `for <src_pat> in <src_expr> <src_loop_block>`
-        ast::ExprForLoop(src_pat, src_expr, ref src_loop_block) => {
+        ast::ExprForLoop(src_pat, src_expr, ref src_loop_block, opt_ident) => {
             let src_pat = src_pat.clone();
             let src_expr = src_expr.clone();
 
@@ -257,7 +257,7 @@ pub fn expand_expr(extsbox: @mut SyntaxEnv,
             // `loop { ... }`
             let loop_block = {
                 let loop_body_block = mk_block(cx, [match_stmt], None, span);
-                let loop_body_expr = mk_expr(cx, span, ast::ExprLoop(loop_body_block, None));
+                let loop_body_expr = mk_expr(cx, span, ast::ExprLoop(loop_body_block, opt_ident));
                 let loop_body_stmt = @spanned(lo, hi, ast::StmtExpr(loop_body_expr, cx.next_id()));
                 mk_block(cx, [iter_decl_stmt,
                               loop_body_stmt],
diff --git a/src/libsyntax/fold.rs b/src/libsyntax/fold.rs
index aad992706fd..11e39163992 100644
--- a/src/libsyntax/fold.rs
+++ b/src/libsyntax/fold.rs
@@ -557,10 +557,11 @@ pub fn noop_fold_expr(e: &Expr_, fld: @ast_fold) -> Expr_ {
         ExprWhile(cond, ref body) => {
             ExprWhile(fld.fold_expr(cond), fld.fold_block(body))
         }
-        ExprForLoop(pat, iter, ref body) => {
+        ExprForLoop(pat, iter, ref body, opt_ident) => {
             ExprForLoop(fld.fold_pat(pat),
-                          fld.fold_expr(iter),
-                          fld.fold_block(body))
+                        fld.fold_expr(iter),
+                        fld.fold_block(body),
+                        opt_ident.map_move(|x| fld.fold_ident(x)))
         }
         ExprLoop(ref body, opt_ident) => {
             ExprLoop(
diff --git a/src/libsyntax/oldvisit.rs b/src/libsyntax/oldvisit.rs
index e9d7b5c4a0d..850f73096ed 100644
--- a/src/libsyntax/oldvisit.rs
+++ b/src/libsyntax/oldvisit.rs
@@ -523,7 +523,7 @@ pub fn visit_expr<E:Clone>(ex: @Expr, (e, v): (E, vt<E>)) {
             (v.visit_expr)(x, (e.clone(), v));
             (v.visit_block)(b, (e.clone(), v));
         }
-        ExprForLoop(pattern, subexpression, ref block) => {
+        ExprForLoop(pattern, subexpression, ref block, _) => {
             (v.visit_pat)(pattern, (e.clone(), v));
             (v.visit_expr)(subexpression, (e.clone(), v));
             (v.visit_block)(block, (e.clone(), v))
diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs
index 8b11a25f13c..b8615352504 100644
--- a/src/libsyntax/parse/parser.rs
+++ b/src/libsyntax/parse/parser.rs
@@ -1771,7 +1771,7 @@ impl Parser {
         } else if self.eat_keyword(keywords::If) {
             return self.parse_if_expr();
         } else if self.eat_keyword(keywords::For) {
-            return self.parse_for_expr();
+            return self.parse_for_expr(None);
         } else if self.eat_keyword(keywords::Do) {
             return self.parse_sugary_call_expr(lo, ~"do", DoSugar,
                                                ExprDoBody);
@@ -1781,8 +1781,13 @@ impl Parser {
             let lifetime = self.get_lifetime(&*self.token);
             self.bump();
             self.expect(&token::COLON);
-            self.expect_keyword(keywords::Loop);
-            return self.parse_loop_expr(Some(lifetime));
+            if self.eat_keyword(keywords::For) {
+                return self.parse_for_expr(Some(lifetime))
+            } else if self.eat_keyword(keywords::Loop) {
+                return self.parse_loop_expr(Some(lifetime))
+            } else {
+                self.fatal("expected `for` or `loop` after a label")
+            }
         } else if self.eat_keyword(keywords::Loop) {
             return self.parse_loop_expr(None);
         } else if self.eat_keyword(keywords::Match) {
@@ -2467,7 +2472,7 @@ impl Parser {
     }
 
     // parse a 'for' .. 'in' expression ('for' token already eaten)
-    pub fn parse_for_expr(&self) -> @Expr {
+    pub fn parse_for_expr(&self, opt_ident: Option<ast::Ident>) -> @Expr {
         // Parse: `for <src_pat> in <src_expr> <src_loop_block>`
 
         let lo = self.last_span.lo;
@@ -2477,7 +2482,7 @@ impl Parser {
         let loop_block = self.parse_block();
         let hi = self.span.hi;
 
-        self.mk_expr(lo, hi, ExprForLoop(pat, expr, loop_block))
+        self.mk_expr(lo, hi, ExprForLoop(pat, expr, loop_block, opt_ident))
     }
 
 
diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs
index f440e0a1771..282b66b2c59 100644
--- a/src/libsyntax/print/pprust.rs
+++ b/src/libsyntax/print/pprust.rs
@@ -1232,7 +1232,12 @@ pub fn print_expr(s: @ps, expr: &ast::Expr) {
         space(s.s);
         print_block(s, blk);
       }
-      ast::ExprForLoop(pat, iter, ref blk) => {
+      ast::ExprForLoop(pat, iter, ref blk, opt_ident) => {
+        for ident in opt_ident.iter() {
+            word(s.s, "'");
+            print_ident(s, *ident);
+            word_space(s, ":");
+        }
         head(s, "for");
         print_pat(s, pat);
         space(s.s);
diff --git a/src/libsyntax/visit.rs b/src/libsyntax/visit.rs
index ae2044cb979..191b4509a80 100644
--- a/src/libsyntax/visit.rs
+++ b/src/libsyntax/visit.rs
@@ -599,7 +599,7 @@ pub fn walk_expr<E:Clone, V:Visitor<E>>(visitor: &mut V, expression: @Expr, env:
             visitor.visit_expr(subexpression, env.clone());
             visitor.visit_block(block, env.clone())
         }
-        ExprForLoop(pattern, subexpression, ref block) => {
+        ExprForLoop(pattern, subexpression, ref block, _) => {
             visitor.visit_pat(pattern, env.clone());
             visitor.visit_expr(subexpression, env.clone());
             visitor.visit_block(block, env.clone())
@@ -812,4 +812,3 @@ impl Visitor<()> for SimpleVisitorVisitor {
         walk_struct_field(self, struct_field, env)
     }
 }
-