88// option. This file may not be copied, modified, or distributed
99// except according to those terms.
1010
11- pub use self :: SyntaxExtension :: * ;
11+ pub use self :: SyntaxExtension :: { MultiDecorator , MultiModifier , NormalTT , IdentTT } ;
1212
1313use ast:: { self , Attribute , Name , PatKind } ;
1414use attr:: HasAttrs ;
@@ -18,8 +18,9 @@ use errors::DiagnosticBuilder;
1818use ext:: expand:: { self , Invocation , Expansion } ;
1919use ext:: hygiene:: Mark ;
2020use ext:: tt:: macro_rules;
21+ use fold;
2122use parse;
22- use parse:: parser;
23+ use parse:: parser:: { self , Parser } ;
2324use parse:: token;
2425use parse:: token:: { InternedString , str_to_ident} ;
2526use ptr:: P ;
@@ -31,7 +32,8 @@ use feature_gate;
3132use std:: collections:: HashMap ;
3233use std:: path:: PathBuf ;
3334use std:: rc:: Rc ;
34- use tokenstream;
35+ use std:: default:: Default ;
36+ use tokenstream:: { self , TokenStream } ;
3537
3638
3739#[ derive( Debug , Clone ) ]
@@ -146,6 +148,190 @@ impl Into<Vec<Annotatable>> for Annotatable {
146148 }
147149}
148150
151+ pub trait ProcMacro {
152+ fn expand < ' cx > ( & self ,
153+ ecx : & ' cx mut ExtCtxt ,
154+ span : Span ,
155+ ts : TokenStream )
156+ -> TokenStream ;
157+ }
158+
159+ impl < F > ProcMacro for F
160+ where F : Fn ( TokenStream ) -> TokenStream
161+ {
162+ fn expand < ' cx > ( & self ,
163+ _ecx : & ' cx mut ExtCtxt ,
164+ _span : Span ,
165+ ts : TokenStream )
166+ -> TokenStream {
167+ // FIXME setup implicit context in TLS before calling self.
168+ ( * self ) ( ts)
169+ }
170+ }
171+
172+ pub trait AttrProcMacro {
173+ fn expand < ' cx > ( & self ,
174+ ecx : & ' cx mut ExtCtxt ,
175+ span : Span ,
176+ annotation : TokenStream ,
177+ annotated : TokenStream )
178+ -> TokenStream ;
179+ }
180+
181+ impl < F > AttrProcMacro for F
182+ where F : Fn ( TokenStream , TokenStream ) -> TokenStream
183+ {
184+ fn expand < ' cx > ( & self ,
185+ _ecx : & ' cx mut ExtCtxt ,
186+ _span : Span ,
187+ annotation : TokenStream ,
188+ annotated : TokenStream )
189+ -> TokenStream {
190+ // FIXME setup implicit context in TLS before calling self.
191+ ( * self ) ( annotation, annotated)
192+ }
193+ }
194+
195+ pub struct TokResult < ' a > {
196+ pub parser : Parser < ' a > ,
197+ pub span : Span ,
198+ }
199+
200+ impl < ' a > TokResult < ' a > {
201+ // There is quite a lot of overlap here with ParserAnyMacro in ext/tt/macro_rules.rs
202+ // We could probably share more code.
203+ // FIXME(#36641) Unify TokResult and ParserAnyMacro.
204+ fn ensure_complete_parse ( & mut self , allow_semi : bool ) {
205+ let macro_span = & self . span ;
206+ self . parser . ensure_complete_parse ( allow_semi, |parser| {
207+ let token_str = parser. this_token_to_string ( ) ;
208+ let msg = format ! ( "macro expansion ignores token `{}` and any following" , token_str) ;
209+ let span = parser. span ;
210+ parser. diagnostic ( )
211+ . struct_span_err ( span, & msg)
212+ . span_note ( * macro_span, "caused by the macro expansion here" )
213+ . emit ( ) ;
214+ } ) ;
215+ }
216+ }
217+
218+ impl < ' a > MacResult for TokResult < ' a > {
219+ fn make_items ( mut self : Box < Self > ) -> Option < SmallVector < P < ast:: Item > > > {
220+ if self . parser . sess . span_diagnostic . has_errors ( ) {
221+ return Some ( SmallVector :: zero ( ) ) ;
222+ }
223+
224+ let mut items = SmallVector :: zero ( ) ;
225+ loop {
226+ match self . parser . parse_item ( ) {
227+ Ok ( Some ( item) ) => items. push ( item) ,
228+ Ok ( None ) => {
229+ self . ensure_complete_parse ( false ) ;
230+ return Some ( items) ;
231+ }
232+ Err ( mut e) => {
233+ e. emit ( ) ;
234+ return Some ( SmallVector :: zero ( ) ) ;
235+ }
236+ }
237+ }
238+ }
239+
240+ fn make_impl_items ( mut self : Box < Self > ) -> Option < SmallVector < ast:: ImplItem > > {
241+ let mut items = SmallVector :: zero ( ) ;
242+ loop {
243+ if self . parser . token == token:: Eof {
244+ break ;
245+ }
246+ match self . parser . parse_impl_item ( ) {
247+ Ok ( item) => items. push ( item) ,
248+ Err ( mut e) => {
249+ e. emit ( ) ;
250+ return Some ( SmallVector :: zero ( ) ) ;
251+ }
252+ }
253+ }
254+ self . ensure_complete_parse ( false ) ;
255+ Some ( items)
256+ }
257+
258+ fn make_trait_items ( mut self : Box < Self > ) -> Option < SmallVector < ast:: TraitItem > > {
259+ let mut items = SmallVector :: zero ( ) ;
260+ loop {
261+ if self . parser . token == token:: Eof {
262+ break ;
263+ }
264+ match self . parser . parse_trait_item ( ) {
265+ Ok ( item) => items. push ( item) ,
266+ Err ( mut e) => {
267+ e. emit ( ) ;
268+ return Some ( SmallVector :: zero ( ) ) ;
269+ }
270+ }
271+ }
272+ self . ensure_complete_parse ( false ) ;
273+ Some ( items)
274+ }
275+
276+ fn make_expr ( mut self : Box < Self > ) -> Option < P < ast:: Expr > > {
277+ match self . parser . parse_expr ( ) {
278+ Ok ( e) => {
279+ self . ensure_complete_parse ( true ) ;
280+ Some ( e)
281+ }
282+ Err ( mut e) => {
283+ e. emit ( ) ;
284+ Some ( DummyResult :: raw_expr ( self . span ) )
285+ }
286+ }
287+ }
288+
289+ fn make_pat ( mut self : Box < Self > ) -> Option < P < ast:: Pat > > {
290+ match self . parser . parse_pat ( ) {
291+ Ok ( e) => {
292+ self . ensure_complete_parse ( false ) ;
293+ Some ( e)
294+ }
295+ Err ( mut e) => {
296+ e. emit ( ) ;
297+ Some ( P ( DummyResult :: raw_pat ( self . span ) ) )
298+ }
299+ }
300+ }
301+
302+ fn make_stmts ( mut self : Box < Self > ) -> Option < SmallVector < ast:: Stmt > > {
303+ let mut stmts = SmallVector :: zero ( ) ;
304+ loop {
305+ if self . parser . token == token:: Eof {
306+ break ;
307+ }
308+ match self . parser . parse_full_stmt ( false ) {
309+ Ok ( Some ( stmt) ) => stmts. push ( stmt) ,
310+ Ok ( None ) => { /* continue */ }
311+ Err ( mut e) => {
312+ e. emit ( ) ;
313+ return Some ( SmallVector :: zero ( ) ) ;
314+ }
315+ }
316+ }
317+ self . ensure_complete_parse ( false ) ;
318+ Some ( stmts)
319+ }
320+
321+ fn make_ty ( mut self : Box < Self > ) -> Option < P < ast:: Ty > > {
322+ match self . parser . parse_ty ( ) {
323+ Ok ( e) => {
324+ self . ensure_complete_parse ( false ) ;
325+ Some ( e)
326+ }
327+ Err ( mut e) => {
328+ e. emit ( ) ;
329+ Some ( DummyResult :: raw_ty ( self . span ) )
330+ }
331+ }
332+ }
333+ }
334+
149335/// Represents a thing that maps token trees to Macro Results
150336pub trait TTMacroExpander {
151337 fn expand < ' cx > ( & self ,
@@ -439,24 +625,35 @@ pub enum SyntaxExtension {
439625 /// based upon it.
440626 ///
441627 /// `#[derive(...)]` is a `MultiItemDecorator`.
442- MultiDecorator ( Box < MultiItemDecorator + ' static > ) ,
628+ ///
629+ /// Prefer ProcMacro or MultiModifier since they are more flexible.
630+ MultiDecorator ( Box < MultiItemDecorator > ) ,
443631
444632 /// A syntax extension that is attached to an item and modifies it
445- /// in-place. More flexible version than Modifier.
446- MultiModifier ( Box < MultiItemModifier + ' static > ) ,
633+ /// in-place. Also allows decoration, i.e., creating new items.
634+ MultiModifier ( Box < MultiItemModifier > ) ,
635+
636+ /// A function-like procedural macro. TokenStream -> TokenStream.
637+ ProcMacro ( Box < ProcMacro > ) ,
638+
639+ /// An attribute-like procedural macro. TokenStream, TokenStream -> TokenStream.
640+ /// The first TokenSteam is the attribute, the second is the annotated item.
641+ /// Allows modification of the input items and adding new items, similar to
642+ /// MultiModifier, but uses TokenStreams, rather than AST nodes.
643+ AttrProcMacro ( Box < AttrProcMacro > ) ,
447644
448645 /// A normal, function-like syntax extension.
449646 ///
450647 /// `bytes!` is a `NormalTT`.
451648 ///
452649 /// The `bool` dictates whether the contents of the macro can
453650 /// directly use `#[unstable]` things (true == yes).
454- NormalTT ( Box < TTMacroExpander + ' static > , Option < Span > , bool ) ,
651+ NormalTT ( Box < TTMacroExpander > , Option < Span > , bool ) ,
455652
456653 /// A function-like syntax extension that has an extra ident before
457654 /// the block.
458655 ///
459- IdentTT ( Box < IdentMacroExpander + ' static > , Option < Span > , bool ) ,
656+ IdentTT ( Box < IdentMacroExpander > , Option < Span > , bool ) ,
460657}
461658
462659pub type NamedSyntaxExtension = ( Name , SyntaxExtension ) ;
@@ -817,3 +1014,17 @@ pub fn get_exprs_from_tts(cx: &mut ExtCtxt,
8171014 }
8181015 Some ( es)
8191016}
1017+
1018+ pub struct ChangeSpan {
1019+ pub span : Span
1020+ }
1021+
1022+ impl Folder for ChangeSpan {
1023+ fn new_span ( & mut self , _sp : Span ) -> Span {
1024+ self . span
1025+ }
1026+
1027+ fn fold_mac ( & mut self , mac : ast:: Mac ) -> ast:: Mac {
1028+ fold:: noop_fold_mac ( mac, self )
1029+ }
1030+ }
0 commit comments