about summary refs log tree commit diff
path: root/src/libsyntax/ext
diff options
context:
space:
mode:
authorJohn Gallagher <jgallagher@bignerdranch.com>2014-10-02 22:45:46 -0400
committerJohn Gallagher <jgallagher@bignerdranch.com>2014-10-10 20:30:31 -0400
commit0c2c8116a307e88f8327e0ea846d2c9c135193b7 (patch)
treeb9f17f6dc86f3e98b77b0eaf18a7d5ecb05bd7a4 /src/libsyntax/ext
parent78a7676898d9f80ab540c6df5d4c9ce35bb50463 (diff)
downloadrust-0c2c8116a307e88f8327e0ea846d2c9c135193b7.tar.gz
rust-0c2c8116a307e88f8327e0ea846d2c9c135193b7.zip
Teach libsyntax about `while let`
Diffstat (limited to 'src/libsyntax/ext')
-rw-r--r--src/libsyntax/ext/expand.rs36
1 files changed, 36 insertions, 0 deletions
diff --git a/src/libsyntax/ext/expand.rs b/src/libsyntax/ext/expand.rs
index efe4b76354f..575dcf32dd6 100644
--- a/src/libsyntax/ext/expand.rs
+++ b/src/libsyntax/ext/expand.rs
@@ -67,6 +67,42 @@ pub fn expand_expr(e: P<ast::Expr>, fld: &mut MacroExpander) -> P<ast::Expr> {
             fld.cx.expr(span, ast::ExprWhile(cond, body, opt_ident))
         }
 
+        // Desugar ExprWhileLet
+        // From: `[opt_ident]: while let <pat> = <expr> <body>`
+        ast::ExprWhileLet(pat, expr, body, opt_ident) => {
+            // to:
+            //
+            //   [opt_ident]: loop {
+            //     match <expr> {
+            //       <pat> => <body>,
+            //       _ => break
+            //     }
+            //   }
+
+            // `<pat> => <body>`
+            let pat_arm = {
+                let body_expr = fld.cx.expr_block(body);
+                fld.cx.arm(pat.span, vec![pat], body_expr)
+            };
+
+            // `_ => break`
+            let break_arm = {
+                let pat_under = fld.cx.pat_wild(span);
+                let break_expr = fld.cx.expr_break(span);
+                fld.cx.arm(span, vec![pat_under], break_expr)
+            };
+
+            // `match <expr> { ... }`
+            let arms = vec![pat_arm, break_arm];
+            let match_expr = fld.cx.expr(span,
+                                         ast::ExprMatch(expr, arms, ast::MatchWhileLetDesugar));
+
+            // `[opt_ident]: loop { ... }`
+            let loop_block = fld.cx.block_expr(match_expr);
+            let (loop_block, opt_ident) = expand_loop_block(loop_block, opt_ident, fld);
+            fld.cx.expr(span, ast::ExprLoop(loop_block, opt_ident))
+        }
+
         // Desugar ExprIfLet
         // From: `if let <pat> = <expr> <body> [<elseopt>]`
         ast::ExprIfLet(pat, expr, body, mut elseopt) => {