use side table to store exported macros
Per discussion with @sfackler, refactored the expander to change the way that exported macros are collected. Specifically, a crate now contains a side table of spans that exported macros go into. This has two benefits. First, the encoder doesn't need to scan through the expanded crate in order to discover exported macros. Second, the expander can drop all expanded macros from the crate, with the pleasant result that a fully expanded crate contains no macro invocations (which include macro definitions).
This commit is contained in:
parent
50d9965c25
commit
f1ad425199
@ -28,7 +28,8 @@ use syntax::{ast, codemap};
|
||||
use std::os;
|
||||
use std::cell::{Cell, RefCell};
|
||||
|
||||
|
||||
// Represents the data associated with a compilation
|
||||
// session for a single crate.
|
||||
pub struct Session {
|
||||
pub targ_cfg: config::Config,
|
||||
pub opts: config::Options,
|
||||
|
@ -1584,37 +1584,25 @@ fn encode_plugin_registrar_fn(ecx: &EncodeContext, ebml_w: &mut Encoder) {
|
||||
}
|
||||
}
|
||||
|
||||
struct MacroDefVisitor<'a, 'b, 'c> {
|
||||
ecx: &'a EncodeContext<'b>,
|
||||
ebml_w: &'a mut Encoder<'c>
|
||||
/// Given a span, write the text of that span into the output stream
|
||||
/// as an exported macro
|
||||
fn encode_macro_def(ecx: &EncodeContext,
|
||||
ebml_w: &mut Encoder,
|
||||
span: &syntax::codemap::Span) {
|
||||
let def = ecx.tcx.sess.codemap().span_to_snippet(*span)
|
||||
.expect("Unable to find source for macro");
|
||||
ebml_w.start_tag(tag_macro_def);
|
||||
ebml_w.wr_str(def.as_slice());
|
||||
ebml_w.end_tag();
|
||||
}
|
||||
|
||||
impl<'a, 'b, 'c> Visitor<()> for MacroDefVisitor<'a, 'b, 'c> {
|
||||
fn visit_item(&mut self, item: &Item, _: ()) {
|
||||
match item.node {
|
||||
ItemMac(..) => {
|
||||
let def = self.ecx.tcx.sess.codemap().span_to_snippet(item.span)
|
||||
.expect("Unable to find source for macro");
|
||||
self.ebml_w.start_tag(tag_macro_def);
|
||||
self.ebml_w.wr_str(def.as_slice());
|
||||
self.ebml_w.end_tag();
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
visit::walk_item(self, item, ());
|
||||
}
|
||||
}
|
||||
|
||||
fn encode_macro_defs<'a>(ecx: &'a EncodeContext,
|
||||
krate: &Crate,
|
||||
ebml_w: &'a mut Encoder) {
|
||||
/// Serialize the text of the exported macros
|
||||
fn encode_macro_defs(ecx: &EncodeContext,
|
||||
krate: &Crate,
|
||||
ebml_w: &mut Encoder) {
|
||||
ebml_w.start_tag(tag_exported_macros);
|
||||
{
|
||||
let mut visitor = MacroDefVisitor {
|
||||
ecx: ecx,
|
||||
ebml_w: ebml_w,
|
||||
};
|
||||
visit::walk_crate(&mut visitor, krate, ());
|
||||
for span in krate.exported_macros.iter() {
|
||||
encode_macro_def(ecx, ebml_w, span);
|
||||
}
|
||||
ebml_w.end_tag();
|
||||
}
|
||||
|
@ -249,6 +249,7 @@ pub struct Crate {
|
||||
pub attrs: Vec<Attribute>,
|
||||
pub config: CrateConfig,
|
||||
pub span: Span,
|
||||
pub exported_macros: Vec<Span>
|
||||
}
|
||||
|
||||
pub type MetaItem = Spanned<MetaItem_>;
|
||||
@ -1245,6 +1246,7 @@ mod test {
|
||||
hi: BytePos(20),
|
||||
expn_info: None,
|
||||
},
|
||||
exported_macros: Vec::new(),
|
||||
};
|
||||
// doesn't matter which encoder we use....
|
||||
let _f = &e as &serialize::Encodable<json::Encoder, io::IoError>;
|
||||
|
@ -410,6 +410,7 @@ pub struct ExtCtxt<'a> {
|
||||
|
||||
pub mod_path: Vec<ast::Ident> ,
|
||||
pub trace_mac: bool,
|
||||
pub exported_macros: Vec<codemap::Span>
|
||||
}
|
||||
|
||||
impl<'a> ExtCtxt<'a> {
|
||||
@ -421,7 +422,8 @@ impl<'a> ExtCtxt<'a> {
|
||||
backtrace: None,
|
||||
mod_path: Vec::new(),
|
||||
ecfg: ecfg,
|
||||
trace_mac: false
|
||||
trace_mac: false,
|
||||
exported_macros: Vec::new(),
|
||||
}
|
||||
}
|
||||
|
||||
@ -539,6 +541,9 @@ impl<'a> ExtCtxt<'a> {
|
||||
pub fn name_of(&self, st: &str) -> ast::Name {
|
||||
token::intern(st)
|
||||
}
|
||||
pub fn push_exported_macro(&mut self, span: codemap::Span) {
|
||||
self.exported_macros.push(span);
|
||||
}
|
||||
}
|
||||
|
||||
/// Extract a string literal from the macro expanded version of `expr`,
|
||||
|
@ -518,10 +518,9 @@ fn expand_item_mac(it: Gc<ast::Item>, fld: &mut MacroExpander)
|
||||
// create issue to recommend refactoring here?
|
||||
fld.extsbox.insert(intern(name.as_slice()), ext);
|
||||
if attr::contains_name(it.attrs.as_slice(), "macro_export") {
|
||||
SmallVector::one(it)
|
||||
} else {
|
||||
SmallVector::zero()
|
||||
fld.cx.push_exported_macro(it.span);
|
||||
}
|
||||
SmallVector::zero()
|
||||
}
|
||||
None => {
|
||||
match expanded.make_items() {
|
||||
@ -1039,6 +1038,7 @@ pub struct ExportedMacros {
|
||||
|
||||
pub fn expand_crate(parse_sess: &parse::ParseSess,
|
||||
cfg: ExpansionConfig,
|
||||
// these are the macros being imported to this crate:
|
||||
macros: Vec<ExportedMacros>,
|
||||
user_exts: Vec<NamedSyntaxExtension>,
|
||||
c: Crate) -> Crate {
|
||||
@ -1066,7 +1066,8 @@ pub fn expand_crate(parse_sess: &parse::ParseSess,
|
||||
expander.extsbox.insert(name, extension);
|
||||
}
|
||||
|
||||
let ret = expander.fold_crate(c);
|
||||
let mut ret = expander.fold_crate(c);
|
||||
ret.exported_macros = expander.cx.exported_macros.clone();
|
||||
parse_sess.span_diagnostic.handler().abort_if_errors();
|
||||
return ret;
|
||||
}
|
||||
|
@ -713,6 +713,7 @@ pub fn noop_fold_crate<T: Folder>(c: Crate, folder: &mut T) -> Crate {
|
||||
attrs: c.attrs.iter().map(|x| folder.fold_attribute(*x)).collect(),
|
||||
config: c.config.iter().map(|x| fold_meta_item_(*x, folder)).collect(),
|
||||
span: folder.new_span(c.span),
|
||||
exported_macros: c.exported_macros.iter().map(|sp| folder.new_span(*sp)).collect(),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -5386,7 +5386,8 @@ impl<'a> Parser<'a> {
|
||||
module: m,
|
||||
attrs: inner,
|
||||
config: self.cfg.clone(),
|
||||
span: mk_sp(lo, self.span.lo)
|
||||
span: mk_sp(lo, self.span.lo),
|
||||
exported_macros: Vec::new(),
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user