@@ -39,7 +39,7 @@ pub fn expand_expr(e: P<ast::Expr>, fld: &mut MacroExpander) -> P<ast::Expr> {
3939 e. and_then ( |ast:: Expr { id, node, span} | match node {
4040 // expr_mac should really be expr_ext or something; it's the
4141 // entry-point for all syntax extensions.
42- ExprMac ( mac) => {
42+ ast :: ExprMac ( mac) => {
4343 let expanded_expr = match expand_mac_invoc ( mac, span,
4444 |r| r. make_expr ( ) ,
4545 mark_expr, fld) {
@@ -67,6 +67,95 @@ pub fn expand_expr(e: P<ast::Expr>, fld: &mut MacroExpander) -> P<ast::Expr> {
6767 fld. cx . expr ( span, ast:: ExprWhile ( cond, body, opt_ident) )
6868 }
6969
70+ // Desugar ExprIfLet
71+ // From: `if let <pat> = <expr> <body> [<elseopt>]`
72+ ast:: ExprIfLet ( pat, expr, body, mut elseopt) => {
73+ let span = e. span ;
74+
75+ // to:
76+ //
77+ // match <expr> {
78+ // <pat> => <body>,
79+ // [_ if <elseopt_if_cond> => <elseopt_if_body>,]
80+ // _ => [<elseopt> | ()]
81+ // }
82+
83+ // `<pat> => <body>`
84+ let pat_arm = {
85+ let body_expr = fld. cx . expr_block ( body) ;
86+ fld. cx . arm ( pat. span , vec ! [ pat] , body_expr)
87+ } ;
88+
89+ // `[_ if <elseopt_if_cond> => <elseopt_if_body>,]`
90+ let else_if_arms = {
91+ let mut arms = vec ! [ ] ;
92+ loop {
93+ // NOTE: replace with 'if let' after snapshot
94+ match elseopt {
95+ Some ( els) => match els. node {
96+ // else if
97+ ast:: ExprIf ( cond, then, elseopt_) => {
98+ let pat_under = fld. cx . pat_wild ( span) ;
99+ elseopt = elseopt_;
100+ arms. push ( ast:: Arm {
101+ attrs : vec ! [ ] ,
102+ pats : vec ! [ pat_under] ,
103+ guard : Some ( cond) ,
104+ body : fld. cx . expr_block ( then)
105+ } ) ;
106+ }
107+ _ => break
108+ } ,
109+ None => break
110+ }
111+ }
112+ arms
113+ } ;
114+
115+ // `_ => [<elseopt> | ()]`
116+ let else_arm = {
117+ let pat_under = fld. cx . pat_wild ( span) ;
118+ let else_expr = match elseopt {
119+ Some ( els) => els,
120+ None => fld. cx . expr_lit ( span, ast:: LitNil )
121+ } ;
122+ fld. cx . arm ( span, vec ! [ pat_under] , else_expr)
123+ } ;
124+
125+ let mut arms = Vec :: with_capacity ( else_if_arms. len ( ) + 2 ) ;
126+ arms. push ( pat_arm) ;
127+ arms. push_all_move ( else_if_arms) ;
128+ arms. push ( else_arm) ;
129+
130+ let match_expr = fld. cx . expr_match ( span, expr, arms) ;
131+ fld. fold_expr ( match_expr)
132+ }
133+
134+ // Desugar support for ExprIfLet in the ExprIf else position
135+ ast:: ExprIf ( cond, blk, mut elseopt) => {
136+ // NOTE: replace with 'if let' after snapshot
137+ match elseopt {
138+ Some ( els) => match els. node {
139+ ast:: ExprIfLet ( ..) => {
140+ // wrap the if-let expr in a block
141+ let blk = P ( ast:: Block {
142+ view_items : vec ! [ ] ,
143+ stmts : vec ! [ ] ,
144+ expr : Some ( els) ,
145+ id : ast:: DUMMY_NODE_ID ,
146+ rules : ast:: DefaultBlock ,
147+ span : els. span
148+ } ) ;
149+ elseopt = Some ( fld. cx . expr_block ( blk) ) ;
150+ }
151+ _ => ( )
152+ } ,
153+ None => ( )
154+ } ;
155+ let if_expr = fld. cx . expr ( e. span , ast:: ExprIf ( cond, blk, elseopt) ) ;
156+ noop_fold_expr ( if_expr, fld)
157+ }
158+
70159 ast:: ExprLoop ( loop_block, opt_ident) => {
71160 let ( loop_block, opt_ident) = expand_loop_block ( loop_block, opt_ident, fld) ;
72161 fld. cx . expr ( span, ast:: ExprLoop ( loop_block, opt_ident) )
0 commit comments