diff options
| author | Nick Cameron <ncameron@mozilla.com> | 2015-09-28 17:24:42 +1300 |
|---|---|---|
| committer | Nick Cameron <ncameron@mozilla.com> | 2015-10-09 11:53:41 +1300 |
| commit | bc364b4a0d678b29cba92ce948d948aee9d76b25 (patch) | |
| tree | dd7ae97421e42072e69df6ca867c9d64b68b0a6b /src/libsyntax | |
| parent | 04a7675d222bcba021886bd5f21d7c6b33273811 (diff) | |
| download | rust-bc364b4a0d678b29cba92ce948d948aee9d76b25.tar.gz rust-bc364b4a0d678b29cba92ce948d948aee9d76b25.zip | |
if let and while let
Diffstat (limited to 'src/libsyntax')
| -rw-r--r-- | src/libsyntax/ext/expand.rs | 144 |
1 files changed, 4 insertions, 140 deletions
diff --git a/src/libsyntax/ext/expand.rs b/src/libsyntax/ext/expand.rs index 8cfad6341de..f6767bc4e47 100644 --- a/src/libsyntax/ext/expand.rs +++ b/src/libsyntax/ext/expand.rs @@ -212,147 +212,11 @@ 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 - // } - // } - - push_compiler_expansion(fld, span, CompilerExpansionFormat::WhileLet); - - // `<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::MatchSource::WhileLetDesugar)); - - // `[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); - let result = fld.cx.expr(span, ast::ExprLoop(loop_block, opt_ident)); - fld.cx.bt_pop(); - result - } - - // Desugar ExprIfLet - // From: `if let <pat> = <expr> <body> [<elseopt>]` - ast::ExprIfLet(pat, expr, body, mut elseopt) => { - // to: - // - // match <expr> { - // <pat> => <body>, - // [_ if <elseopt_if_cond> => <elseopt_if_body>,] - // _ => [<elseopt> | ()] - // } - - push_compiler_expansion(fld, span, CompilerExpansionFormat::IfLet); - - // `<pat> => <body>` - let pat_arm = { - let body_expr = fld.cx.expr_block(body); - fld.cx.arm(pat.span, vec![pat], body_expr) - }; - - // `[_ if <elseopt_if_cond> => <elseopt_if_body>,]` - let else_if_arms = { - let mut arms = vec![]; - loop { - let elseopt_continue = elseopt - .and_then(|els| els.and_then(|els| match els.node { - // else if - ast::ExprIf(cond, then, elseopt) => { - let pat_under = fld.cx.pat_wild(span); - arms.push(ast::Arm { - attrs: vec![], - pats: vec![pat_under], - guard: Some(cond), - body: fld.cx.expr_block(then) - }); - elseopt.map(|elseopt| (elseopt, true)) - } - _ => Some((P(els), false)) - })); - match elseopt_continue { - Some((e, true)) => { - elseopt = Some(e); - } - Some((e, false)) => { - elseopt = Some(e); - break; - } - None => { - elseopt = None; - break; - } - } - } - arms - }; - - let contains_else_clause = elseopt.is_some(); - - // `_ => [<elseopt> | ()]` - let else_arm = { - let pat_under = fld.cx.pat_wild(span); - let else_expr = elseopt.unwrap_or_else(|| fld.cx.expr_tuple(span, vec![])); - fld.cx.arm(span, vec![pat_under], else_expr) - }; - - let mut arms = Vec::with_capacity(else_if_arms.len() + 2); - arms.push(pat_arm); - arms.extend(else_if_arms); - arms.push(else_arm); - - let match_expr = fld.cx.expr(span, - ast::ExprMatch(expr, arms, - ast::MatchSource::IfLetDesugar { - contains_else_clause: contains_else_clause, - })); - let result = fld.fold_expr(match_expr); - fld.cx.bt_pop(); - result - } - - // Desugar support for ExprIfLet in the ExprIf else position - ast::ExprIf(cond, blk, elseopt) => { - let elseopt = elseopt.map(|els| els.and_then(|els| match els.node { - ast::ExprIfLet(..) => { - push_compiler_expansion(fld, span, CompilerExpansionFormat::IfLet); - // wrap the if-let expr in a block - let span = els.span; - let blk = P(ast::Block { - stmts: vec![], - expr: Some(P(els)), - id: ast::DUMMY_NODE_ID, - rules: ast::DefaultBlock, - span: span - }); - let result = fld.cx.expr_block(blk); - fld.cx.bt_pop(); - result - } - _ => P(els) - })); - let if_expr = fld.cx.expr(span, ast::ExprIf(cond, blk, elseopt)); - if_expr.map(|e| noop_fold_expr(e, fld)) + let pat = fld.fold_pat(pat); + let expr = fld.fold_expr(expr); + let (body, opt_ident) = expand_loop_block(body, opt_ident, fld); + fld.cx.expr(span, ast::ExprWhileLet(pat, expr, body, opt_ident)) } ast::ExprLoop(loop_block, opt_ident) => { |
