about summary refs log tree commit diff
path: root/src/libsyntax_ext/plugin_macro_defs.rs
diff options
context:
space:
mode:
authorVadim Petrochenkov <vadim.petrochenkov@gmail.com>2019-06-20 11:52:31 +0300
committerVadim Petrochenkov <vadim.petrochenkov@gmail.com>2019-07-26 13:09:54 +0300
commit8eaf17bca2674293eba0ea10056d5c77b6352086 (patch)
treea726739d50e26b0142be28425b154446f43e4fe5 /src/libsyntax_ext/plugin_macro_defs.rs
parent4268e7ee22935f086b856ef0063a9e22b49aeddb (diff)
downloadrust-8eaf17bca2674293eba0ea10056d5c77b6352086.tar.gz
rust-8eaf17bca2674293eba0ea10056d5c77b6352086.zip
Introduce built-in macros through libcore
Diffstat (limited to 'src/libsyntax_ext/plugin_macro_defs.rs')
-rw-r--r--src/libsyntax_ext/plugin_macro_defs.rs64
1 files changed, 64 insertions, 0 deletions
diff --git a/src/libsyntax_ext/plugin_macro_defs.rs b/src/libsyntax_ext/plugin_macro_defs.rs
new file mode 100644
index 00000000000..2fd1a42db95
--- /dev/null
+++ b/src/libsyntax_ext/plugin_macro_defs.rs
@@ -0,0 +1,64 @@
+//! Each macro must have a definition, so `#[plugin]` attributes
+//! inject a dummy `macro_rules` item for each macro they define.
+
+use syntax::ast::*;
+use syntax::attr;
+use syntax::edition::Edition;
+use syntax::ext::base::{Resolver, NamedSyntaxExtension};
+use syntax::parse::token;
+use syntax::ptr::P;
+use syntax::source_map::respan;
+use syntax::symbol::sym;
+use syntax::tokenstream::*;
+use syntax_pos::{Span, DUMMY_SP};
+use syntax_pos::hygiene::{ExpnId, ExpnInfo, ExpnKind, MacroKind};
+
+use std::mem;
+
+fn plugin_macro_def(name: Name, span: Span) -> P<Item> {
+    let rustc_builtin_macro = Attribute {
+        id: attr::mk_attr_id(),
+        style: AttrStyle::Outer,
+        path: Path::from_ident(Ident::new(sym::rustc_builtin_macro, span)),
+        tokens: TokenStream::empty(),
+        is_sugared_doc: false,
+        span,
+    };
+
+    let parens: TreeAndJoint = TokenTree::Delimited(
+        DelimSpan::from_single(span), token::Paren, TokenStream::empty()
+    ).into();
+    let trees = vec![parens.clone(), TokenTree::token(token::FatArrow, span).into(), parens];
+
+    P(Item {
+        ident: Ident::new(name, span),
+        attrs: vec![rustc_builtin_macro],
+        id: DUMMY_NODE_ID,
+        node: ItemKind::MacroDef(MacroDef { tokens: TokenStream::new(trees), legacy: true }),
+        vis: respan(span, VisibilityKind::Inherited),
+        span: span,
+        tokens: None,
+    })
+}
+
+pub fn inject(
+    krate: &mut Crate,
+    resolver: &mut dyn Resolver,
+    named_exts: Vec<NamedSyntaxExtension>,
+    edition: Edition,
+) {
+    if !named_exts.is_empty() {
+        let mut extra_items = Vec::new();
+        let span = DUMMY_SP.fresh_expansion(ExpnId::root(), ExpnInfo::allow_unstable(
+            ExpnKind::Macro(MacroKind::Attr, sym::plugin), DUMMY_SP, edition,
+            [sym::rustc_attrs][..].into(),
+        ));
+        for (name, ext) in named_exts {
+            resolver.register_builtin_macro(Ident::with_empty_ctxt(name), ext);
+            extra_items.push(plugin_macro_def(name, span));
+        }
+        // The `macro_rules` items must be inserted before any other items.
+        mem::swap(&mut extra_items, &mut krate.module.items);
+        krate.module.items.append(&mut extra_items);
+    }
+}