Skip to content

Commit 677b7ca

Browse files
author
Keegan McAllister
committed
Reformat metadata for exported macros
Instead of copy-pasting the whole macro_rules! item from the original .rs file, we serialize a separate name, attributes list, and body, the latter as pretty-printed TTs. The compilation of macro_rules! macros is decoupled somewhat from the expansion of macros in item position. This filters out comments, and facilitates selective imports.
1 parent 24aa7f0 commit 677b7ca

File tree

12 files changed

+143
-133
lines changed

12 files changed

+143
-133
lines changed

src/librustc/metadata/common.rs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -206,8 +206,8 @@ pub const tag_native_libraries_name: uint = 0x89;
206206
pub const tag_native_libraries_kind: uint = 0x8a;
207207

208208
pub const tag_plugin_registrar_fn: uint = 0x8b;
209-
pub const tag_exported_macros: uint = 0x8c;
210-
pub const tag_macro_def: uint = 0x8d;
209+
210+
// GAP 0x8c, 0x8d
211211

212212
pub const tag_method_argument_names: uint = 0x8e;
213213
pub const tag_method_argument_name: uint = 0x8f;
@@ -261,3 +261,7 @@ pub const tag_associated_type_names: uint = 0xb2;
261261
pub const tag_associated_type_name: uint = 0xb3;
262262

263263
pub const tag_polarity: uint = 0xb4;
264+
265+
pub const tag_macro_defs: uint = 0xb5;
266+
pub const tag_macro_def: uint = 0xb6;
267+
pub const tag_macro_def_body: uint = 0xb7;

src/librustc/metadata/creader.rs

Lines changed: 36 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,9 @@ use syntax::ast;
2929
use syntax::abi;
3030
use syntax::attr;
3131
use syntax::attr::AttrMetaMethods;
32-
use syntax::codemap::{Span};
32+
use syntax::codemap::{Span, mk_sp};
3333
use syntax::diagnostic::SpanHandler;
34+
use syntax::parse;
3435
use syntax::parse::token::InternedString;
3536
use syntax::parse::token;
3637
use syntax::visit;
@@ -491,7 +492,36 @@ impl<'a> CrateReader<'a> {
491492
}
492493
None => { load_ctxt.report_load_errs(); unreachable!() },
493494
};
494-
let macros = decoder::get_exported_macros(library.metadata.as_slice());
495+
496+
// Read exported macros
497+
let imported_from = Some(token::intern(info.ident[]).ident());
498+
let source_name = format!("<{} macros>", info.ident[]);
499+
let mut macros = vec![];
500+
decoder::each_exported_macro(library.metadata.as_slice(), &*self.sess.cstore.intr,
501+
|name, attrs, body| {
502+
// NB: Don't use parse::parse_tts_from_source_str because it parses with
503+
// quote_depth > 0.
504+
let mut p = parse::new_parser_from_source_str(&self.sess.parse_sess,
505+
self.sess.opts.cfg.clone(),
506+
source_name.clone(),
507+
body);
508+
let lo = p.span.lo;
509+
let body = p.parse_all_token_trees();
510+
let span = mk_sp(lo, p.last_span.hi);
511+
p.abort_if_errors();
512+
macros.push(ast::MacroDef {
513+
ident: name.ident(),
514+
attrs: attrs,
515+
id: ast::DUMMY_NODE_ID,
516+
span: span,
517+
imported_from: imported_from,
518+
body: body,
519+
});
520+
true
521+
}
522+
);
523+
524+
// Look for a plugin registrar
495525
let registrar = decoder::get_plugin_registrar_fn(library.metadata.as_slice()).map(|id| {
496526
decoder::get_symbol(library.metadata.as_slice(), id)
497527
});
@@ -504,9 +534,11 @@ impl<'a> CrateReader<'a> {
504534
// empty dylib.
505535
}
506536
let pc = PluginMetadata {
507-
lib: library.dylib.clone(),
508537
macros: macros,
509-
registrar_symbol: registrar,
538+
registrar: match (library.dylib.as_ref(), registrar) {
539+
(Some(dylib), Some(reg)) => Some((dylib.clone(), reg)),
540+
_ => None,
541+
},
510542
};
511543
if should_link && self.existing_match(info.name[], None).is_none() {
512544
// register crate now to avoid double-reading metadata

src/librustc/metadata/decoder.rs

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1353,15 +1353,16 @@ pub fn get_plugin_registrar_fn(data: &[u8]) -> Option<ast::NodeId> {
13531353
.map(|doc| FromPrimitive::from_u32(reader::doc_as_u32(doc)).unwrap())
13541354
}
13551355

1356-
pub fn get_exported_macros(data: &[u8]) -> Vec<String> {
1357-
let macros = reader::get_doc(rbml::Doc::new(data),
1358-
tag_exported_macros);
1359-
let mut result = Vec::new();
1356+
pub fn each_exported_macro<F>(data: &[u8], intr: &IdentInterner, mut f: F) where
1357+
F: FnMut(ast::Name, Vec<ast::Attribute>, String) -> bool,
1358+
{
1359+
let macros = reader::get_doc(rbml::Doc::new(data), tag_macro_defs);
13601360
reader::tagged_docs(macros, tag_macro_def, |macro_doc| {
1361-
result.push(macro_doc.as_str().to_string());
1362-
true
1361+
let name = item_name(intr, macro_doc);
1362+
let attrs = get_attributes(macro_doc);
1363+
let body = reader::get_doc(macro_doc, tag_macro_def_body);
1364+
f(name, attrs, body.as_str().to_string())
13631365
});
1364-
result
13651366
}
13661367

13671368
pub fn get_dylib_dependency_formats(cdata: Cmd)

src/librustc/metadata/encoder.rs

Lines changed: 16 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ use syntax::attr::AttrMetaMethods;
4242
use syntax::diagnostic::SpanHandler;
4343
use syntax::parse::token::special_idents;
4444
use syntax::parse::token;
45+
use syntax::print::pprust;
4546
use syntax::ptr::P;
4647
use syntax::visit::Visitor;
4748
use syntax::visit;
@@ -1818,25 +1819,21 @@ fn encode_plugin_registrar_fn(ecx: &EncodeContext, rbml_w: &mut Encoder) {
18181819
}
18191820
}
18201821

1821-
/// Given a span, write the text of that span into the output stream
1822-
/// as an exported macro
1823-
fn encode_macro_def(ecx: &EncodeContext,
1824-
rbml_w: &mut Encoder,
1825-
span: &syntax::codemap::Span) {
1826-
let def = ecx.tcx.sess.codemap().span_to_snippet(*span)
1827-
.expect("Unable to find source for macro");
1828-
rbml_w.start_tag(tag_macro_def);
1829-
rbml_w.wr_str(def[]);
1830-
rbml_w.end_tag();
1831-
}
1832-
18331822
/// Serialize the text of the exported macros
1834-
fn encode_macro_defs(ecx: &EncodeContext,
1835-
krate: &ast::Crate,
1836-
rbml_w: &mut Encoder) {
1837-
rbml_w.start_tag(tag_exported_macros);
1838-
for item in krate.exported_macros.iter() {
1839-
encode_macro_def(ecx, rbml_w, &item.span);
1823+
fn encode_macro_defs(rbml_w: &mut Encoder,
1824+
krate: &ast::Crate) {
1825+
rbml_w.start_tag(tag_macro_defs);
1826+
for def in krate.exported_macros.iter() {
1827+
rbml_w.start_tag(tag_macro_def);
1828+
1829+
encode_name(rbml_w, def.ident.name);
1830+
encode_attributes(rbml_w, def.attrs[]);
1831+
1832+
rbml_w.start_tag(tag_macro_def_body);
1833+
rbml_w.wr_str(pprust::tts_to_string(def.body[])[]);
1834+
rbml_w.end_tag();
1835+
1836+
rbml_w.end_tag();
18401837
}
18411838
rbml_w.end_tag();
18421839
}
@@ -2154,7 +2151,7 @@ fn encode_metadata_inner(wr: &mut SeekableMemWriter,
21542151

21552152
// Encode macro definitions
21562153
i = rbml_w.writer.tell().unwrap();
2157-
encode_macro_defs(&ecx, krate, &mut rbml_w);
2154+
encode_macro_defs(&mut rbml_w, krate);
21582155
stats.macro_defs_bytes = rbml_w.writer.tell().unwrap() - i;
21592156

21602157
// Encode the types of all unboxed closures in this crate.

src/librustc/plugin/load.rs

Lines changed: 13 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
// option. This file may not be copied, modified, or distributed
99
// except according to those terms.
1010

11-
//! Used by `rustc` when loading a plugin.
11+
//! Used by `rustc` when loading a plugin, or a crate with exported macros.
1212
1313
use session::Session;
1414
use metadata::creader::CrateReader;
@@ -21,17 +21,14 @@ use syntax::ast;
2121
use syntax::attr;
2222
use syntax::visit;
2323
use syntax::visit::Visitor;
24-
use syntax::ext::expand::ExportedMacros;
2524
use syntax::attr::AttrMetaMethods;
2625

27-
/// Plugin-related crate metadata.
26+
/// Metadata for a single plugin crate.
2827
pub struct PluginMetadata {
29-
/// Source code of macros exported by the crate.
30-
pub macros: Vec<String>,
31-
/// Path to the shared library file.
32-
pub lib: Option<Path>,
33-
/// Symbol name of the plugin registrar function.
34-
pub registrar_symbol: Option<String>,
28+
/// Macros exported by the crate.
29+
pub macros: Vec<ast::MacroDef>,
30+
/// Path to the shared library file, and registrar function symbol.
31+
pub registrar: Option<(Path, String)>,
3532
}
3633

3734
/// Pointer to a registrar function.
@@ -40,8 +37,8 @@ pub type PluginRegistrarFun =
4037

4138
/// Information about loaded plugins.
4239
pub struct Plugins {
43-
/// Source code of exported macros.
44-
pub macros: Vec<ExportedMacros>,
40+
/// Imported macros.
41+
pub macros: Vec<ast::MacroDef>,
4542
/// Registrars, as function pointers.
4643
pub registrars: Vec<PluginRegistrarFun>,
4744
}
@@ -90,7 +87,7 @@ pub fn load_plugins(sess: &Session, krate: &ast::Crate,
9087
impl<'a, 'v> Visitor<'v> for PluginLoader<'a> {
9188
fn visit_view_item(&mut self, vi: &ast::ViewItem) {
9289
match vi.node {
93-
ast::ViewItemExternCrate(name, _, _) => {
90+
ast::ViewItemExternCrate(_, _, _) => {
9491
let mut plugin_phase = false;
9592

9693
for attr in vi.attrs.iter().filter(|a| a.check_name("phase")) {
@@ -107,17 +104,13 @@ impl<'a, 'v> Visitor<'v> for PluginLoader<'a> {
107104

108105
if !plugin_phase { return; }
109106

110-
let PluginMetadata { macros, lib, registrar_symbol } =
107+
let PluginMetadata { macros, registrar } =
111108
self.reader.read_plugin_metadata(vi);
112109

113-
self.plugins.macros.push(ExportedMacros {
114-
crate_name: name,
115-
macros: macros,
116-
});
110+
self.plugins.macros.extend(macros.into_iter());
117111

118-
match (lib, registrar_symbol) {
119-
(Some(lib), Some(symbol))
120-
=> self.dylink_registrar(vi, lib, symbol),
112+
match registrar {
113+
Some((lib, symbol)) => self.dylink_registrar(vi, lib, symbol),
121114
_ => (),
122115
}
123116
}

src/librustdoc/visit_ast.rs

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
7373
None);
7474
// attach the crate's exported macros to the top-level module:
7575
self.module.macros = krate.exported_macros.iter()
76-
.map(|it| self.visit_macro(&**it)).collect();
76+
.map(|def| self.visit_macro(def)).collect();
7777
self.module.is_crate = true;
7878
}
7979

@@ -363,13 +363,13 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
363363
}
364364

365365
// convert each exported_macro into a doc item
366-
fn visit_macro(&self, item: &ast::Item) -> Macro {
366+
fn visit_macro(&self, def: &ast::MacroDef) -> Macro {
367367
Macro {
368-
id: item.id,
369-
attrs: item.attrs.clone(),
370-
name: item.ident,
371-
whence: item.span,
372-
stab: self.stability(item.id),
368+
id: def.id,
369+
attrs: def.attrs.clone(),
370+
name: def.ident,
371+
whence: def.span,
372+
stab: self.stability(def.id),
373373
}
374374
}
375375
}

src/libsyntax/ast.rs

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -476,7 +476,7 @@ pub struct Crate {
476476
pub attrs: Vec<Attribute>,
477477
pub config: CrateConfig,
478478
pub span: Span,
479-
pub exported_macros: Vec<P<Item>>
479+
pub exported_macros: Vec<MacroDef>,
480480
}
481481

482482
pub type MetaItem = Spanned<MetaItem_>;
@@ -1698,6 +1698,19 @@ pub enum InlinedItem {
16981698
IIForeign(P<ForeignItem>),
16991699
}
17001700

1701+
/// A macro definition, in this crate or imported from another.
1702+
///
1703+
/// Not parsed directly, but created on macro import or `macro_rules!` expansion.
1704+
#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Show)]
1705+
pub struct MacroDef {
1706+
pub ident: Ident,
1707+
pub attrs: Vec<Attribute>,
1708+
pub id: NodeId,
1709+
pub span: Span,
1710+
pub imported_from: Option<Ident>,
1711+
pub body: Vec<TokenTree>,
1712+
}
1713+
17011714
#[cfg(test)]
17021715
mod test {
17031716
use serialize::json;

src/libsyntax/ext/base.rs

Lines changed: 1 addition & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -28,19 +28,6 @@ use fold::Folder;
2828
use std::collections::HashMap;
2929
use std::rc::Rc;
3030

31-
// new-style macro! tt code:
32-
//
33-
// MacResult, NormalTT, IdentTT
34-
//
35-
// also note that ast::Mac used to have a bunch of extraneous cases and
36-
// is now probably a redundant AST node, can be merged with
37-
// ast::MacInvocTT.
38-
39-
pub struct MacroDef {
40-
pub name: String,
41-
pub ext: SyntaxExtension
42-
}
43-
4431
pub trait ItemDecorator {
4532
fn expand(&self,
4633
ecx: &mut ExtCtxt,
@@ -140,13 +127,6 @@ impl<F> IdentMacroExpander for F
140127
/// methods are spliced into the AST at the callsite of the macro (or
141128
/// just into the compiler's internal macro table, for `make_def`).
142129
pub trait MacResult {
143-
/// Attempt to define a new macro.
144-
// this should go away; the idea that a macro might expand into
145-
// either a macro definition or an expression, depending on what
146-
// the context wants, is kind of silly.
147-
fn make_def(&mut self) -> Option<MacroDef> {
148-
None
149-
}
150130
/// Create an expression.
151131
fn make_expr(self: Box<Self>) -> Option<P<ast::Expr>> {
152132
None
@@ -469,7 +449,7 @@ pub struct ExtCtxt<'a> {
469449

470450
pub mod_path: Vec<ast::Ident> ,
471451
pub trace_mac: bool,
472-
pub exported_macros: Vec<P<ast::Item>>,
452+
pub exported_macros: Vec<ast::MacroDef>,
473453

474454
pub syntax_env: SyntaxEnv,
475455
pub recursion_count: uint,

0 commit comments

Comments
 (0)