diff options
| author | Jeffrey Seyfried <jeffrey.seyfried@gmail.com> | 2016-06-26 03:32:45 +0000 |
|---|---|---|
| committer | Jeffrey Seyfried <jeffrey.seyfried@gmail.com> | 2016-07-14 01:34:37 +0000 |
| commit | 0701571fe741866b4d0d9ad34b6c99717d1e1893 (patch) | |
| tree | d8008de798ec028f2bc5781fa3bf38a6629c729d /src/libsyntax | |
| parent | a15dfca54f1b6e54226797fa12fe0d7a2bf9252e (diff) | |
| download | rust-0701571fe741866b4d0d9ad34b6c99717d1e1893.tar.gz rust-0701571fe741866b4d0d9ad34b6c99717d1e1893.zip | |
Implement `macro_rules!` placeholders and the macro scope map
Diffstat (limited to 'src/libsyntax')
| -rw-r--r-- | src/libsyntax/ext/expand.rs | 33 | ||||
| -rw-r--r-- | src/libsyntax/ext/mtwt.rs | 16 | ||||
| -rw-r--r-- | src/libsyntax/test.rs | 4 |
3 files changed, 46 insertions, 7 deletions
diff --git a/src/libsyntax/ext/expand.rs b/src/libsyntax/ext/expand.rs index 5b5a5d0e531..10b66d08955 100644 --- a/src/libsyntax/ext/expand.rs +++ b/src/libsyntax/ext/expand.rs @@ -15,7 +15,7 @@ use attr::HasAttrs; use ext::mtwt; use attr; use attr::AttrMetaMethods; -use codemap::{Spanned, ExpnInfo, NameAndSpan, MacroBang, MacroAttribute}; +use codemap::{dummy_spanned, Spanned, ExpnInfo, NameAndSpan, MacroBang, MacroAttribute}; use syntax_pos::{self, Span, ExpnId}; use config::StripUnconfigured; use ext::base::*; @@ -105,6 +105,23 @@ pub fn expand_expr(expr: ast::Expr, fld: &mut MacroExpander) -> P<ast::Expr> { } } +struct MacroScopePlaceholder; +impl MacResult for MacroScopePlaceholder { + fn make_items(self: Box<Self>) -> Option<SmallVector<P<ast::Item>>> { + Some(SmallVector::one(P(ast::Item { + ident: keywords::Invalid.ident(), + attrs: Vec::new(), + id: ast::DUMMY_NODE_ID, + node: ast::ItemKind::Mac(dummy_spanned(ast::Mac_ { + path: ast::Path { span: syntax_pos::DUMMY_SP, global: false, segments: Vec::new() }, + tts: Vec::new(), + })), + vis: ast::Visibility::Inherited, + span: syntax_pos::DUMMY_SP, + }))) + } +} + /// Expand a macro invocation. Returns the result of expansion. fn expand_mac_invoc<T>(mac: ast::Mac, ident: Option<Ident>, attrs: Vec<ast::Attribute>, span: Span, fld: &mut MacroExpander) -> T @@ -143,6 +160,7 @@ fn expand_mac_invoc<T>(mac: ast::Mac, ident: Option<Ident>, attrs: Vec<ast::Attr }; let ident = ident.unwrap_or(keywords::Invalid.ident()); + let marked_tts = mark_tts(&tts, mark); match *extension { NormalTT(ref expandfun, exp_span, allow_internal_unstable) => { if ident.name != keywords::Invalid.name() { @@ -161,7 +179,6 @@ fn expand_mac_invoc<T>(mac: ast::Mac, ident: Option<Ident>, attrs: Vec<ast::Attr }, }); - let marked_tts = mark_tts(&tts, mark); Some(expandfun.expand(fld.cx, call_site, &marked_tts)) } @@ -181,7 +198,6 @@ fn expand_mac_invoc<T>(mac: ast::Mac, ident: Option<Ident>, attrs: Vec<ast::Attr } }); - let marked_tts = mark_tts(&tts, mark); Some(expander.expand(fld.cx, call_site, ident, marked_tts)) } @@ -210,15 +226,14 @@ fn expand_mac_invoc<T>(mac: ast::Mac, ident: Option<Ident>, attrs: Vec<ast::Attr span: call_site, imported_from: None, use_locally: true, - body: tts, + body: marked_tts, export: attr::contains_name(&attrs, "macro_export"), allow_internal_unstable: attr::contains_name(&attrs, "allow_internal_unstable"), attrs: attrs, }); // macro_rules! has a side effect but expands to nothing. - fld.cx.bt_pop(); - None + Some(Box::new(MacroScopePlaceholder)) } MultiDecorator(..) | MultiModifier(..) => { @@ -343,6 +358,12 @@ fn expand_multi_modified(a: Annotatable, fld: &mut MacroExpander) -> SmallVector match a { Annotatable::Item(it) => match it.node { ast::ItemKind::Mac(..) => { + if match it.node { + ItemKind::Mac(ref mac) => mac.node.path.segments.is_empty(), + _ => unreachable!(), + } { + return SmallVector::one(Annotatable::Item(it)); + } it.and_then(|it| match it.node { ItemKind::Mac(mac) => expand_mac_invoc(mac, Some(it.ident), it.attrs, it.span, fld), diff --git a/src/libsyntax/ext/mtwt.rs b/src/libsyntax/ext/mtwt.rs index a4c698a9226..ac5bac58d2a 100644 --- a/src/libsyntax/ext/mtwt.rs +++ b/src/libsyntax/ext/mtwt.rs @@ -17,7 +17,7 @@ pub use self::SyntaxContext_::*; -use ast::{Mrk, SyntaxContext}; +use ast::{Ident, Mrk, SyntaxContext}; use std::cell::RefCell; use std::collections::HashMap; @@ -112,6 +112,20 @@ pub fn outer_mark(ctxt: SyntaxContext) -> Mrk { }) } +/// If `ident` is macro expanded, return the source ident from the macro definition +/// and the mark of the expansion that created the macro definition. +pub fn source(ident: Ident) -> Option<(Ident /* source ident */, Mrk /* source macro */)> { + with_sctable(|sctable| { + let ctxts = sctable.table.borrow(); + if let Mark(_expansion_mark, macro_ctxt) = ctxts[ident.ctxt.0 as usize] { + if let Mark(definition_mark, orig_ctxt) = ctxts[macro_ctxt.0 as usize] { + return Some((Ident::new(ident.name, orig_ctxt), definition_mark)); + } + } + None + }) +} + #[cfg(test)] mod tests { use ast::{EMPTY_CTXT, Ident, Mrk, Name, SyntaxContext}; diff --git a/src/libsyntax/test.rs b/src/libsyntax/test.rs index 0a60b7fd430..327696e87b0 100644 --- a/src/libsyntax/test.rs +++ b/src/libsyntax/test.rs @@ -185,6 +185,8 @@ impl<'a> fold::Folder for TestHarnessGenerator<'a> { mod_folded } + + fn fold_mac(&mut self, mac: ast::Mac) -> ast::Mac { mac } } struct EntryPointCleaner { @@ -234,6 +236,8 @@ impl fold::Folder for EntryPointCleaner { SmallVector::one(folded) } + + fn fold_mac(&mut self, mac: ast::Mac) -> ast::Mac { mac } } fn mk_reexport_mod(cx: &mut TestCtxt, tests: Vec<ast::Ident>, |
