diff options
| author | Vadim Petrochenkov <vadim.petrochenkov@gmail.com> | 2019-06-20 11:52:31 +0300 |
|---|---|---|
| committer | Vadim Petrochenkov <vadim.petrochenkov@gmail.com> | 2019-07-26 13:09:54 +0300 |
| commit | 8eaf17bca2674293eba0ea10056d5c77b6352086 (patch) | |
| tree | a726739d50e26b0142be28425b154446f43e4fe5 /src/libsyntax_ext/plugin_macro_defs.rs | |
| parent | 4268e7ee22935f086b856ef0063a9e22b49aeddb (diff) | |
| download | rust-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.rs | 64 |
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); + } +} |
