@@ -41,6 +41,7 @@ use std::path::PathBuf;
4141use std:: rc:: Rc ;
4242use std:: { iter, mem} ;
4343
44+ #[ cfg( bootstrap) ]
4445macro_rules! ast_fragments {
4546 (
4647 $( $Kind: ident( $AstTy: ty) {
@@ -165,6 +166,131 @@ macro_rules! ast_fragments {
165166 }
166167}
167168
169+ #[ cfg( not( bootstrap) ) ]
170+ macro_rules! ast_fragments {
171+ (
172+ $( $Kind: ident( $AstTy: ty) {
173+ $kind_name: expr;
174+ $( one fn $mut_visit_ast: ident; fn $visit_ast: ident; ) ?
175+ $( many fn $flat_map_ast_elt: ident; fn $visit_ast_elt: ident( $( $args: tt) * ) ; ) ?
176+ fn $make_ast: ident;
177+ } ) *
178+ ) => {
179+ /// A fragment of AST that can be produced by a single macro expansion.
180+ /// Can also serve as an input and intermediate result for macro expansion operations.
181+ pub enum AstFragment {
182+ OptExpr ( Option <P <ast:: Expr >>) ,
183+ MethodReceiverExpr ( P <ast:: Expr >) ,
184+ $( $Kind( $AstTy) , ) *
185+ }
186+
187+ /// "Discriminant" of an AST fragment.
188+ #[ derive( Copy , Clone , PartialEq , Eq ) ]
189+ pub enum AstFragmentKind {
190+ OptExpr ,
191+ MethodReceiverExpr ,
192+ $( $Kind, ) *
193+ }
194+
195+ impl AstFragmentKind {
196+ pub fn name( self ) -> & ' static str {
197+ match self {
198+ AstFragmentKind :: OptExpr => "expression" ,
199+ AstFragmentKind :: MethodReceiverExpr => "expression" ,
200+ $( AstFragmentKind :: $Kind => $kind_name, ) *
201+ }
202+ }
203+
204+ fn make_from<' a>( self , result: Box <dyn MacResult + ' a>) -> Option <AstFragment > {
205+ match self {
206+ AstFragmentKind :: OptExpr =>
207+ result. make_expr( ) . map( Some ) . map( AstFragment :: OptExpr ) ,
208+ AstFragmentKind :: MethodReceiverExpr =>
209+ result. make_expr( ) . map( AstFragment :: MethodReceiverExpr ) ,
210+ $( AstFragmentKind :: $Kind => result. $make_ast( ) . map( AstFragment :: $Kind) , ) *
211+ }
212+ }
213+ }
214+
215+ impl AstFragment {
216+ pub fn add_placeholders( & mut self , placeholders: & [ NodeId ] ) {
217+ if placeholders. is_empty( ) {
218+ return ;
219+ }
220+ match self {
221+ $( $( AstFragment :: $Kind( ast) => ast. extend( placeholders. iter( ) . flat_map( |id| {
222+ ${ ignore( $flat_map_ast_elt) }
223+ placeholder( AstFragmentKind :: $Kind, * id, None ) . $make_ast( )
224+ } ) ) , ) ?) *
225+ _ => panic!( "unexpected AST fragment kind" )
226+ }
227+ }
228+
229+ pub fn make_opt_expr( self ) -> Option <P <ast:: Expr >> {
230+ match self {
231+ AstFragment :: OptExpr ( expr) => expr,
232+ _ => panic!( "AstFragment::make_* called on the wrong kind of fragment" ) ,
233+ }
234+ }
235+
236+ pub fn make_method_receiver_expr( self ) -> P <ast:: Expr > {
237+ match self {
238+ AstFragment :: MethodReceiverExpr ( expr) => expr,
239+ _ => panic!( "AstFragment::make_* called on the wrong kind of fragment" ) ,
240+ }
241+ }
242+
243+ $( pub fn $make_ast( self ) -> $AstTy {
244+ match self {
245+ AstFragment :: $Kind( ast) => ast,
246+ _ => panic!( "AstFragment::make_* called on the wrong kind of fragment" ) ,
247+ }
248+ } ) *
249+
250+ fn make_ast<T : InvocationCollectorNode >( self ) -> T :: OutputTy {
251+ T :: fragment_to_output( self )
252+ }
253+
254+ pub fn mut_visit_with<F : MutVisitor >( & mut self , vis: & mut F ) {
255+ match self {
256+ AstFragment :: OptExpr ( opt_expr) => {
257+ visit_clobber( opt_expr, |opt_expr| {
258+ if let Some ( expr) = opt_expr {
259+ vis. filter_map_expr( expr)
260+ } else {
261+ None
262+ }
263+ } ) ;
264+ }
265+ AstFragment :: MethodReceiverExpr ( expr) => vis. visit_method_receiver_expr( expr) ,
266+ $( $( AstFragment :: $Kind( ast) => vis. $mut_visit_ast( ast) , ) ?) *
267+ $( $( AstFragment :: $Kind( ast) =>
268+ ast. flat_map_in_place( |ast| vis. $flat_map_ast_elt( ast) ) , ) ?) *
269+ }
270+ }
271+
272+ pub fn visit_with<' a, V : Visitor <' a>>( & ' a self , visitor: & mut V ) {
273+ match self {
274+ AstFragment :: OptExpr ( Some ( expr) ) => visitor. visit_expr( expr) ,
275+ AstFragment :: OptExpr ( None ) => { }
276+ AstFragment :: MethodReceiverExpr ( expr) => visitor. visit_method_receiver_expr( expr) ,
277+ $( $( AstFragment :: $Kind( ast) => visitor. $visit_ast( ast) , ) ?) *
278+ $( $( AstFragment :: $Kind( ast) => for ast_elt in & ast[ ..] {
279+ visitor. $visit_ast_elt( ast_elt, $( $args) * ) ;
280+ } ) ?) *
281+ }
282+ }
283+ }
284+
285+ impl <' a> MacResult for crate :: mbe:: macro_rules:: ParserAnyMacro <' a> {
286+ $( fn $make_ast( self : Box <crate :: mbe:: macro_rules:: ParserAnyMacro <' a>>)
287+ -> Option <$AstTy> {
288+ Some ( self . make( AstFragmentKind :: $Kind) . $make_ast( ) )
289+ } ) *
290+ }
291+ }
292+ }
293+
168294ast_fragments ! {
169295 Expr ( P <ast:: Expr >) { "expression" ; one fn visit_expr; fn visit_expr; fn make_expr; }
170296 Pat ( P <ast:: Pat >) { "pattern" ; one fn visit_pat; fn visit_pat; fn make_pat; }
0 commit comments