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:
John Clements 2014-07-10 15:41:11 -07:00
parent 50d9965c25
commit f1ad425199
7 changed files with 34 additions and 35 deletions

View file

@ -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,

View file

@ -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();
}

View file

@ -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>;

View file

@ -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`,

View file

@ -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;
}

View file

@ -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(),
}
}

View file

@ -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(),
}
}