diff options
| author | bors <bors@rust-lang.org> | 2014-10-13 19:37:40 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2014-10-13 19:37:40 +0000 |
| commit | c7e072427469ef50880a722b7b6cd00b052939f5 (patch) | |
| tree | c87cb2f922c34bf1b6d9b6152ae466a31b817eff /src/libsyntax/ext | |
| parent | daa71e40a98f32084539e7cfe893a3e94f83fe69 (diff) | |
| parent | 16ccdba8512fc7ce397095cf5d62858ef2234c47 (diff) | |
| download | rust-c7e072427469ef50880a722b7b6cd00b052939f5.tar.gz rust-c7e072427469ef50880a722b7b6cd00b052939f5.zip | |
auto merge of #17733 : jgallagher/rust/while-let, r=alexcrichton
This is *heavily* based on `if let` (#17634) by @jakub- and @kballard This should close #17687
Diffstat (limited to 'src/libsyntax/ext')
| -rw-r--r-- | src/libsyntax/ext/build.rs | 8 | ||||
| -rw-r--r-- | src/libsyntax/ext/expand.rs | 36 |
2 files changed, 44 insertions, 0 deletions
diff --git a/src/libsyntax/ext/build.rs b/src/libsyntax/ext/build.rs index 87983e1aea3..98ac6fe6a6c 100644 --- a/src/libsyntax/ext/build.rs +++ b/src/libsyntax/ext/build.rs @@ -147,6 +147,8 @@ pub trait AstBuilder { fn expr_some(&self, sp: Span, expr: P<ast::Expr>) -> P<ast::Expr>; fn expr_none(&self, sp: Span) -> P<ast::Expr>; + fn expr_break(&self, sp: Span) -> P<ast::Expr>; + fn expr_tuple(&self, sp: Span, exprs: Vec<P<ast::Expr>>) -> P<ast::Expr>; fn expr_fail(&self, span: Span, msg: InternedString) -> P<ast::Expr>; @@ -688,6 +690,12 @@ impl<'a> AstBuilder for ExtCtxt<'a> { self.expr_path(none) } + + fn expr_break(&self, sp: Span) -> P<ast::Expr> { + self.expr(sp, ast::ExprBreak(None)) + } + + fn expr_tuple(&self, sp: Span, exprs: Vec<P<ast::Expr>>) -> P<ast::Expr> { self.expr(sp, ast::ExprTup(exprs)) } 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) => { |
