@@ -37,92 +37,28 @@ pub fn expand_expr(e: Gc<ast::Expr>, fld: &mut MacroExpander) -> Gc<ast::Expr> {
37
37
// expr_mac should really be expr_ext or something; it's the
38
38
// entry-point for all syntax extensions.
39
39
ExprMac ( ref mac) => {
40
- match ( * mac) . node {
41
- // it would almost certainly be cleaner to pass the whole
42
- // macro invocation in, rather than pulling it apart and
43
- // marking the tts and the ctxt separately. This also goes
44
- // for the other three macro invocation chunks of code
45
- // in this file.
46
- // Token-tree macros:
47
- MacInvocTT ( ref pth, ref tts, _) => {
48
- if pth. segments . len ( ) > 1 u {
49
- fld. cx . span_err ( pth. span ,
50
- "expected macro name without module \
51
- separators") ;
52
- // let compilation continue
53
- return DummyResult :: raw_expr ( e. span ) ;
54
- }
55
- let extname = pth. segments . get ( 0 ) . identifier ;
56
- let extnamestr = token:: get_ident ( extname) ;
57
- let marked_after = match fld. extsbox . find ( & extname. name ) {
58
- None => {
59
- fld. cx . span_err (
60
- pth. span ,
61
- format ! ( "macro undefined: '{}!'" ,
62
- extnamestr. get( ) ) . as_slice ( ) ) ;
63
-
64
- // let compilation continue
65
- return DummyResult :: raw_expr ( e. span ) ;
66
- }
67
- Some ( & NormalTT ( ref expandfun, exp_span) ) => {
68
- fld. cx . bt_push ( ExpnInfo {
69
- call_site : e. span ,
70
- callee : NameAndSpan {
71
- name : extnamestr. get ( ) . to_string ( ) ,
72
- format : MacroBang ,
73
- span : exp_span,
74
- } ,
75
- } ) ;
76
- let fm = fresh_mark ( ) ;
77
- // mark before:
78
- let marked_before = mark_tts ( tts. as_slice ( ) , fm) ;
79
-
80
- // The span that we pass to the expanders we want to
81
- // be the root of the call stack. That's the most
82
- // relevant span and it's the actual invocation of
83
- // the macro.
84
- let mac_span = original_span ( fld. cx ) ;
85
-
86
- let expanded = match expandfun. expand ( fld. cx ,
87
- mac_span. call_site ,
88
- marked_before. as_slice ( ) ) . make_expr ( ) {
89
- Some ( e) => e,
90
- None => {
91
- fld. cx . span_err (
92
- pth. span ,
93
- format ! ( "non-expression macro in expression position: {}" ,
94
- extnamestr. get( ) . as_slice( )
95
- ) . as_slice ( ) ) ;
96
- return DummyResult :: raw_expr ( e. span ) ;
97
- }
98
- } ;
40
+ let expanded_expr = match expand_mac_invoc ( mac, & e. span ,
41
+ |r|{ r. make_expr ( ) } ,
42
+ |expr, fm|{ mark_expr ( expr, fm) } ,
43
+ fld) {
44
+ Some ( expr) => expr,
45
+ None => {
46
+ return DummyResult :: raw_expr ( e. span ) ;
47
+ }
48
+ } ;
99
49
100
- // mark after:
101
- mark_expr ( expanded, fm)
102
- }
103
- _ => {
104
- fld. cx . span_err (
105
- pth. span ,
106
- format ! ( "'{}' is not a tt-style macro" ,
107
- extnamestr. get( ) ) . as_slice ( ) ) ;
108
- return DummyResult :: raw_expr ( e. span ) ;
109
- }
110
- } ;
50
+ // Keep going, outside-in.
51
+ //
52
+ // FIXME(pcwalton): Is it necessary to clone the
53
+ // node here?
54
+ let fully_expanded =
55
+ fld. fold_expr ( expanded_expr) . node . clone ( ) ;
56
+ fld. cx . bt_pop ( ) ;
111
57
112
- // Keep going, outside-in.
113
- //
114
- // FIXME(pcwalton): Is it necessary to clone the
115
- // node here?
116
- let fully_expanded =
117
- fld. fold_expr ( marked_after) . node . clone ( ) ;
118
- fld. cx . bt_pop ( ) ;
119
-
120
- box ( GC ) ast:: Expr {
121
- id : ast:: DUMMY_NODE_ID ,
122
- node : fully_expanded,
123
- span : e. span ,
124
- }
125
- }
58
+ box ( GC ) ast:: Expr {
59
+ id : ast:: DUMMY_NODE_ID ,
60
+ node : fully_expanded,
61
+ span : e. span ,
126
62
}
127
63
}
128
64
@@ -246,6 +182,88 @@ pub fn expand_expr(e: Gc<ast::Expr>, fld: &mut MacroExpander) -> Gc<ast::Expr> {
246
182
}
247
183
}
248
184
185
+ /// Expand a (not-ident-style) macro invocation. Returns the result
186
+ /// of expansion and the mark which must be applied to the result.
187
+ /// Our current interface doesn't allow us to apply the mark to the
188
+ /// result until after calling make_expr, make_items, etc.
189
+ fn expand_mac_invoc < T > ( mac : & ast:: Mac , span : & codemap:: Span ,
190
+ parse_thunk: |Box < MacResult > |->Option < T > ,
191
+ mark_thunk: |T , Mrk |->T ,
192
+ fld: & mut MacroExpander )
193
+ -> Option < T > {
194
+ match ( * mac) . node {
195
+ // it would almost certainly be cleaner to pass the whole
196
+ // macro invocation in, rather than pulling it apart and
197
+ // marking the tts and the ctxt separately. This also goes
198
+ // for the other three macro invocation chunks of code
199
+ // in this file.
200
+ // Token-tree macros:
201
+ MacInvocTT ( ref pth, ref tts, _) => {
202
+ if pth. segments . len ( ) > 1 u {
203
+ fld. cx . span_err ( pth. span ,
204
+ "expected macro name without module \
205
+ separators") ;
206
+ // let compilation continue
207
+ return None ;
208
+ }
209
+ let extname = pth. segments . get ( 0 ) . identifier ;
210
+ let extnamestr = token:: get_ident ( extname) ;
211
+ match fld. extsbox . find ( & extname. name ) {
212
+ None => {
213
+ fld. cx . span_err (
214
+ pth. span ,
215
+ format ! ( "macro undefined: '{}!'" ,
216
+ extnamestr. get( ) ) . as_slice ( ) ) ;
217
+
218
+ // let compilation continue
219
+ None
220
+ }
221
+ Some ( & NormalTT ( ref expandfun, exp_span) ) => {
222
+ fld. cx . bt_push ( ExpnInfo {
223
+ call_site : * span,
224
+ callee : NameAndSpan {
225
+ name : extnamestr. get ( ) . to_string ( ) ,
226
+ format : MacroBang ,
227
+ span : exp_span,
228
+ } ,
229
+ } ) ;
230
+ let fm = fresh_mark ( ) ;
231
+ let marked_before = mark_tts ( tts. as_slice ( ) , fm) ;
232
+
233
+ // The span that we pass to the expanders we want to
234
+ // be the root of the call stack. That's the most
235
+ // relevant span and it's the actual invocation of
236
+ // the macro.
237
+ let mac_span = original_span ( fld. cx ) ;
238
+
239
+ let expanded = expandfun. expand ( fld. cx ,
240
+ mac_span. call_site ,
241
+ marked_before. as_slice ( ) ) ;
242
+ let parsed = match parse_thunk ( expanded) {
243
+ Some ( e) => e,
244
+ None => {
245
+ fld. cx . span_err (
246
+ pth. span ,
247
+ format ! ( "non-expression macro in expression position: {}" ,
248
+ extnamestr. get( ) . as_slice( )
249
+ ) . as_slice ( ) ) ;
250
+ return None ;
251
+ }
252
+ } ;
253
+ Some ( mark_thunk ( parsed, fm) )
254
+ }
255
+ _ => {
256
+ fld. cx . span_err (
257
+ pth. span ,
258
+ format ! ( "'{}' is not a tt-style macro" ,
259
+ extnamestr. get( ) ) . as_slice ( ) ) ;
260
+ None
261
+ }
262
+ }
263
+ }
264
+ }
265
+ }
266
+
249
267
/// Rename loop label and expand its loop body
250
268
///
251
269
/// The renaming procedure for loop is different in the sense that the loop
@@ -543,75 +561,27 @@ fn expand_item_mac(it: Gc<ast::Item>, fld: &mut MacroExpander)
543
561
return items;
544
562
}
545
563
546
- // expand a stmt
564
+ /// Expand a stmt
565
+ //
566
+ // I don't understand why this returns a vector... it looks like someone got
567
+ // half done adding machinery to allow macros to expand into multiple statements.
547
568
fn expand_stmt ( s : & Stmt , fld : & mut MacroExpander ) -> SmallVector < Gc < Stmt > > {
548
- // why the copying here and not in expand_expr?
549
- // looks like classic changed-in-only-one-place
550
- let ( pth, tts, semi) = match s. node {
551
- StmtMac ( ref mac, semi) => {
552
- match mac. node {
553
- MacInvocTT ( ref pth, ref tts, _) => {
554
- ( pth, ( * tts) . clone ( ) , semi)
555
- }
556
- }
557
- }
569
+ let ( mac, semi) = match s. node {
570
+ StmtMac ( ref mac, semi) => ( mac, semi) ,
558
571
_ => return expand_non_macro_stmt ( s, fld)
559
572
} ;
560
- if pth. segments . len ( ) > 1 u {
561
- fld. cx . span_err ( pth. span , "expected macro name without module separators" ) ;
562
- return SmallVector :: zero ( ) ;
563
- }
564
- let extname = pth. segments . get ( 0 ) . identifier ;
565
- let extnamestr = token:: get_ident ( extname) ;
566
- let marked_after = match fld. extsbox . find ( & extname. name ) {
573
+ let expanded_stmt = match expand_mac_invoc ( mac, s. span ,
574
+ |r|{ r. make_stmt ( ) } ,
575
+ |sts, mrk|{ mark_stmt ( sts, mrk) } ,
576
+ fld) {
577
+ Some ( stmt) => stmt,
567
578
None => {
568
- fld. cx . span_err ( pth. span ,
569
- format ! ( "macro undefined: '{}!'" ,
570
- extnamestr) . as_slice ( ) ) ;
571
- return SmallVector :: zero ( ) ;
572
- }
573
-
574
- Some ( & NormalTT ( ref expandfun, exp_span) ) => {
575
- fld. cx . bt_push ( ExpnInfo {
576
- call_site : s. span ,
577
- callee : NameAndSpan {
578
- name : extnamestr. get ( ) . to_string ( ) ,
579
- format : MacroBang ,
580
- span : exp_span,
581
- }
582
- } ) ;
583
- let fm = fresh_mark ( ) ;
584
- // mark before expansion:
585
- let marked_tts = mark_tts ( tts. as_slice ( ) , fm) ;
586
-
587
- // See the comment in expand_expr for why we want the original span,
588
- // not the current mac.span.
589
- let mac_span = original_span ( fld. cx ) ;
590
-
591
- let expanded = match expandfun. expand ( fld. cx ,
592
- mac_span. call_site ,
593
- marked_tts. as_slice ( ) ) . make_stmt ( ) {
594
- Some ( stmt) => stmt,
595
- None => {
596
- fld. cx . span_err ( pth. span ,
597
- format ! ( "non-statement macro in statement position: {}" ,
598
- extnamestr) . as_slice ( ) ) ;
599
- return SmallVector :: zero ( ) ;
600
- }
601
- } ;
602
-
603
- mark_stmt ( & * expanded, fm)
604
- }
605
-
606
- _ => {
607
- fld. cx . span_err ( pth. span , format ! ( "'{}' is not a tt-style macro" ,
608
- extnamestr) . as_slice ( ) ) ;
609
579
return SmallVector :: zero ( ) ;
610
580
}
611
581
} ;
612
582
613
583
// Keep going, outside-in.
614
- let fully_expanded = fld. fold_stmt ( & * marked_after ) ;
584
+ let fully_expanded = fld. fold_stmt ( & * expanded_stmt ) ;
615
585
fld. cx . bt_pop ( ) ;
616
586
let fully_expanded: SmallVector < Gc < Stmt > > = fully_expanded. move_iter ( )
617
587
. map ( |s| box ( GC ) Spanned { span : s. span , node : s. node . clone ( ) } )
0 commit comments