]> git.lizzy.rs Git - rust.git/commitdiff
Refactor MultiModifier expansion
authorJeffrey Seyfried <jeffrey.seyfried@gmail.com>
Sun, 12 Jun 2016 13:38:39 +0000 (13:38 +0000)
committerJeffrey Seyfried <jeffrey.seyfried@gmail.com>
Thu, 16 Jun 2016 03:55:53 +0000 (03:55 +0000)
src/libsyntax/ext/expand.rs

index 83ddc79af84747ce9b71c2471aa2d957a3e416b9..e7d7b0a6aef06401e4531324c55a8c2d8b45f77d 100644 (file)
@@ -13,6 +13,7 @@
 use ast::{MacStmtStyle, Mrk, Stmt, StmtKind, ItemKind};
 use ast::TokenTree;
 use ast;
+use attr::HasAttrs;
 use ext::mtwt;
 use ext::build::AstBuilder;
 use attr;
@@ -712,11 +713,7 @@ fn fold_mac(&mut self, mac: ast::Mac) -> ast::Mac {
     }
 }
 
-fn expand_annotatable(a: Annotatable,
-                      fld: &mut MacroExpander)
-                      -> SmallVector<Annotatable> {
-    let a = expand_item_multi_modifier(a, fld);
-
+fn expand_multi_modified(a: Annotatable, fld: &mut MacroExpander) -> SmallVector<Annotatable> {
     let new_items: SmallVector<Annotatable> = match a {
         Annotatable::Item(it) => match it.node {
             ast::ItemKind::Mac(..) => {
@@ -795,29 +792,6 @@ fn decorate(a: Annotatable, fld: &mut MacroExpander) -> SmallVector<Annotatable>
     new_items
 }
 
-// Partition a set of attributes into one kind of attribute, and other kinds.
-macro_rules! partition {
-    ($fn_name: ident, $variant: ident) => {
-        #[allow(deprecated)] // The `allow` is needed because the `Modifier` variant might be used.
-        fn $fn_name(attrs: &[ast::Attribute],
-                    fld: &MacroExpander)
-                     -> (Vec<ast::Attribute>, Vec<ast::Attribute>) {
-            attrs.iter().cloned().partition(|attr| {
-                match fld.cx.syntax_env.find(intern(&attr.name())) {
-                    Some(rc) => match *rc {
-                        $variant(..) => true,
-                        _ => false
-                    },
-                    _ => false
-                }
-            })
-        }
-    }
-}
-
-partition!(multi_modifiers, MultiModifier);
-
-
 fn expand_decorators(a: Annotatable,
                      fld: &mut MacroExpander,
                      decorator_items: &mut SmallVector<Annotatable>,
@@ -861,46 +835,41 @@ fn expand_decorators(a: Annotatable,
     }
 }
 
-fn expand_item_multi_modifier(mut it: Annotatable,
-                              fld: &mut MacroExpander)
-                              -> Annotatable {
-    let (modifiers, other_attrs) = multi_modifiers(it.attrs(), fld);
-
-    // Update the attrs, leave everything else alone. Is this mutation really a good idea?
-    it = it.fold_attrs(other_attrs);
-
-    if modifiers.is_empty() {
-        return it
-    }
-
-    for attr in &modifiers {
-        let mname = intern(&attr.name());
-
-        match fld.cx.syntax_env.find(mname) {
-            Some(rc) => match *rc {
-                MultiModifier(ref mac) => {
-                    attr::mark_used(attr);
-                    fld.cx.bt_push(ExpnInfo {
-                        call_site: attr.span,
-                        callee: NameAndSpan {
-                            format: MacroAttribute(mname),
-                            span: Some(attr.span),
-                            // attributes can do whatever they like,
-                            // for now
-                            allow_internal_unstable: true,
-                        }
-                    });
-                    it = mac.expand(fld.cx, attr.span, &attr.node.value, it);
-                    fld.cx.bt_pop();
+fn expand_annotatable(mut item: Annotatable, fld: &mut MacroExpander) -> SmallVector<Annotatable> {
+    let mut multi_modifier = None;
+    item = item.map_attrs(|mut attrs| {
+        for i in 0..attrs.len() {
+            if let Some(extension) = fld.cx.syntax_env.find(intern(&attrs[i].name())) {
+                if let MultiModifier(..) = *extension {
+                    multi_modifier = Some((attrs.remove(i), extension));
+                    break;
                 }
-                _ => unreachable!()
-            },
-            _ => unreachable!()
+            }
         }
-    }
+        attrs
+    });
 
-    // Expansion may have added new ItemKind::Modifiers.
-    expand_item_multi_modifier(it, fld)
+    match multi_modifier {
+        None => expand_multi_modified(item, fld),
+        Some((attr, extension)) => match *extension {
+            MultiModifier(ref mac) => {
+                attr::mark_used(&attr);
+                fld.cx.bt_push(ExpnInfo {
+                    call_site: attr.span,
+                    callee: NameAndSpan {
+                        format: MacroAttribute(intern(&attr.name())),
+                        span: Some(attr.span),
+                        // attributes can do whatever they like, for now
+                        allow_internal_unstable: true,
+                    }
+                });
+                let modified = mac.expand(fld.cx, attr.span, &attr.node.value, item);
+                fld.cx.bt_pop();
+                expand_annotatable(modified, fld)
+            }
+            _ => unreachable!(),
+        }
+    }
 }
 
 fn expand_impl_item(ii: ast::ImplItem, fld: &mut MacroExpander)