@@ -37,92 +37,28 @@ pub fn expand_expr(e: Gc<ast::Expr>, fld: &mut MacroExpander) -> Gc<ast::Expr> {
3737 // expr_mac should really be expr_ext or something; it's the
3838 // entry-point for all syntax extensions.
3939 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+ } ;
9949
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 ( ) ;
11157
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 ,
12662 }
12763 }
12864
@@ -246,6 +182,88 @@ pub fn expand_expr(e: Gc<ast::Expr>, fld: &mut MacroExpander) -> Gc<ast::Expr> {
246182 }
247183}
248184
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+
249267/// Rename loop label and expand its loop body
250268///
251269/// 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)
543561 return items;
544562}
545563
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.
547568fn 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) ,
558571 _ => return expand_non_macro_stmt ( s, fld)
559572 } ;
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,
567578 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 ( ) ) ;
609579 return SmallVector :: zero ( ) ;
610580 }
611581 } ;
612582
613583 // Keep going, outside-in.
614- let fully_expanded = fld. fold_stmt ( & * marked_after ) ;
584+ let fully_expanded = fld. fold_stmt ( & * expanded_stmt ) ;
615585 fld. cx . bt_pop ( ) ;
616586 let fully_expanded: SmallVector < Gc < Stmt > > = fully_expanded. move_iter ( )
617587 . map ( |s| box ( GC ) Spanned { span : s. span , node : s. node . clone ( ) } )
0 commit comments