Skip to content

Commit

Permalink
Load macros from external modules
Browse files Browse the repository at this point in the history
  • Loading branch information
sfackler committed Jan 16, 2014
1 parent a5ed0c5 commit 328b47d
Show file tree
Hide file tree
Showing 39 changed files with 873 additions and 205 deletions.
4 changes: 4 additions & 0 deletions src/compiletest/header.rs
Original file line number Diff line number Diff line change
Expand Up @@ -90,10 +90,14 @@ pub fn is_test_ignored(config: &config, testfile: &Path) -> bool {
fn xfail_target(config: &config) -> ~str {
~"xfail-" + util::get_os(config.target)
}
fn xfail_stage(config: &config) -> ~str {
~"xfail-" + config.stage_id.split('-').next().unwrap()
}
let val = iter_header(testfile, |ln| {
if parse_name_directive(ln, "xfail-test") { false }
else if parse_name_directive(ln, xfail_target(config)) { false }
else if parse_name_directive(ln, xfail_stage(config)) { false }
else if config.mode == common::mode_pretty &&
parse_name_directive(ln, "xfail-pretty") { false }
else { true }
Expand Down
26 changes: 21 additions & 5 deletions src/librustc/driver/driver.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ use lib::llvm::{ContextRef, ModuleRef};
use metadata::common::LinkMeta;
use metadata::{creader, filesearch};
use metadata::cstore::CStore;
use metadata::creader::Loader;
use metadata;
use middle::{trans, freevars, kind, ty, typeck, lint, astencode, reachable};
use middle;
Expand All @@ -41,6 +42,7 @@ use syntax::attr;
use syntax::attr::{AttrMetaMethods};
use syntax::codemap;
use syntax::diagnostic;
use syntax::ext::base::CrateLoader;
use syntax::parse;
use syntax::parse::token;
use syntax::print::{pp, pprust};
Expand Down Expand Up @@ -163,6 +165,7 @@ pub fn phase_1_parse_input(sess: Session, cfg: ast::CrateConfig, input: &input)
/// standard library and prelude.
pub fn phase_2_configure_and_expand(sess: Session,
cfg: ast::CrateConfig,
loader: &mut CrateLoader,
mut crate: ast::Crate)
-> (ast::Crate, syntax::ast_map::Map) {
let time_passes = sess.time_passes();
Expand All @@ -188,9 +191,14 @@ pub fn phase_2_configure_and_expand(sess: Session,
crate = time(time_passes, "configuration 1", crate, |crate|
front::config::strip_unconfigured_items(crate));

crate = time(time_passes, "expansion", crate, |crate|
syntax::ext::expand::expand_crate(sess.parse_sess, cfg.clone(),
crate));
crate = time(time_passes, "expansion", crate, |crate| {
syntax::ext::expand::expand_crate(sess.parse_sess,
loader,
cfg.clone(),
crate)
});
// dump the syntax-time crates
sess.cstore.reset();

// strip again, in case expansion added anything with a #[cfg].
crate = time(time_passes, "configuration 2", crate, |crate|
Expand Down Expand Up @@ -248,6 +256,11 @@ pub fn phase_3_run_analysis_passes(sess: Session,
time(time_passes, "looking for entry point", (),
|_| middle::entry::find_entry_point(sess, crate, ast_map));

sess.macro_registrar_fn.with_mut(|r| *r =
time(time_passes, "looking for macro registrar", (), |_|
syntax::ext::registrar::find_macro_registrar(
sess.span_diagnostic, crate)));

let freevars = time(time_passes, "freevar finding", (), |_|
freevars::annotate_freevars(def_map, crate));

Expand Down Expand Up @@ -491,7 +504,8 @@ pub fn compile_input(sess: Session, cfg: ast::CrateConfig, input: &input,
let (expanded_crate, ast_map) = {
let crate = phase_1_parse_input(sess, cfg.clone(), input);
if stop_after_phase_1(sess) { return; }
phase_2_configure_and_expand(sess, cfg, crate)
let loader = &mut Loader::new(sess);
phase_2_configure_and_expand(sess, cfg, loader, crate)
};
let outputs = build_output_filenames(input, outdir, output,
expanded_crate.attrs, sess);
Expand Down Expand Up @@ -579,7 +593,8 @@ pub fn pretty_print_input(sess: Session,

let (crate, ast_map, is_expanded) = match ppm {
PpmExpanded | PpmExpandedIdentified | PpmTyped => {
let (crate, ast_map) = phase_2_configure_and_expand(sess, cfg, crate);
let loader = &mut Loader::new(sess);
let (crate, ast_map) = phase_2_configure_and_expand(sess, cfg, loader, crate);
(crate, Some(ast_map), true)
}
_ => (crate, None, false)
Expand Down Expand Up @@ -912,6 +927,7 @@ pub fn build_session_(sopts: @session::options,
// For a library crate, this is always none
entry_fn: RefCell::new(None),
entry_type: Cell::new(None),
macro_registrar_fn: RefCell::new(None),
span_diagnostic: span_diagnostic_handler,
filesearch: filesearch,
building_library: Cell::new(false),
Expand Down
1 change: 1 addition & 0 deletions src/librustc/driver/session.rs
Original file line number Diff line number Diff line change
Expand Up @@ -210,6 +210,7 @@ pub struct Session_ {
entry_fn: RefCell<Option<(NodeId, codemap::Span)>>,
entry_type: Cell<Option<EntryFnType>>,
span_diagnostic: @diagnostic::SpanHandler,
macro_registrar_fn: RefCell<Option<ast::DefId>>,
filesearch: @filesearch::FileSearch,
building_library: Cell<bool>,
working_dir: Path,
Expand Down
20 changes: 19 additions & 1 deletion src/librustc/front/feature_gate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,8 @@ static KNOWN_FEATURES: &'static [(&'static str, Status)] = &[
("non_ascii_idents", Active),
("thread_local", Active),
("link_args", Active),
("phase", Active),
("macro_registrar", Active),

// These are used to test this portion of the compiler, they don't actually
// mean anything
Expand Down Expand Up @@ -114,7 +116,15 @@ impl Visitor<()> for Context {
}
}
}
_ => {}
ast::ViewItemExternMod(..) => {
for attr in i.attrs.iter() {
if "phase" == attr.name() {
self.gate_feature("phase", attr.span,
"compile time crate loading is \
experimental and possibly buggy");
}
}
}
}
visit::walk_view_item(self, i, ())
}
Expand Down Expand Up @@ -151,6 +161,14 @@ impl Visitor<()> for Context {
}
}

ast::ItemFn(..) => {
if attr::contains_name(i.attrs, "macro_registrar") {
self.gate_feature("macro_registrar", i.span,
"cross-crate macro exports are \
experimental and possibly buggy");
}
}

_ => {}
}

Expand Down
14 changes: 8 additions & 6 deletions src/librustc/front/test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
use driver::session;
use front::config;
use front::std_inject::with_version;
use metadata::creader::Loader;

use std::cell::RefCell;
use std::vec;
Expand All @@ -38,10 +39,10 @@ struct Test {
should_fail: bool
}

struct TestCtxt {
struct TestCtxt<'a> {
sess: session::Session,
path: RefCell<~[ast::Ident]>,
ext_cx: ExtCtxt,
ext_cx: ExtCtxt<'a>,
testfns: RefCell<~[Test]>,
is_extra: bool,
config: ast::CrateConfig,
Expand All @@ -63,11 +64,11 @@ pub fn modify_for_testing(sess: session::Session,
}
}

struct TestHarnessGenerator {
cx: TestCtxt,
struct TestHarnessGenerator<'a> {
cx: TestCtxt<'a>,
}

impl fold::Folder for TestHarnessGenerator {
impl<'a> fold::Folder for TestHarnessGenerator<'a> {
fn fold_crate(&mut self, c: ast::Crate) -> ast::Crate {
let folded = fold::noop_fold_crate(c, self);

Expand Down Expand Up @@ -155,9 +156,10 @@ impl fold::Folder for TestHarnessGenerator {

fn generate_test_harness(sess: session::Session, crate: ast::Crate)
-> ast::Crate {
let loader = &mut Loader::new(sess);
let mut cx: TestCtxt = TestCtxt {
sess: sess,
ext_cx: ExtCtxt::new(sess.parse_sess, sess.opts.cfg.clone()),
ext_cx: ExtCtxt::new(sess.parse_sess, sess.opts.cfg.clone(), loader),
path: RefCell::new(~[]),
testfns: RefCell::new(~[]),
is_extra: is_extra(&crate),
Expand Down
4 changes: 4 additions & 0 deletions src/librustc/metadata/common.rs
Original file line number Diff line number Diff line change
Expand Up @@ -204,6 +204,10 @@ pub static tag_native_libraries_lib: uint = 0x104;
pub static tag_native_libraries_name: uint = 0x105;
pub static tag_native_libraries_kind: uint = 0x106;

pub static tag_macro_registrar_fn: uint = 0x110;
pub static tag_exported_macros: uint = 0x111;
pub static tag_macro_def: uint = 0x112;

#[deriving(Clone)]
pub struct LinkMeta {
crateid: CrateId,
Expand Down
135 changes: 105 additions & 30 deletions src/librustc/metadata/creader.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,13 @@

//! Validates all used crates and extern libraries and loads their metadata
use driver::{driver, session};
use driver::session::Session;
use metadata::csearch;
use metadata::cstore;
use metadata::decoder;
use metadata::loader;
use metadata::loader::Os;

use std::cell::RefCell;
use std::hashmap::HashMap;
Expand All @@ -23,6 +26,7 @@ use syntax::attr;
use syntax::attr::AttrMetaMethods;
use syntax::codemap::{Span, DUMMY_SP};
use syntax::diagnostic::SpanHandler;
use syntax::ext::base::{CrateLoader, MacroCrate};
use syntax::parse::token;
use syntax::parse::token::IdentInterner;
use syntax::crateid::CrateId;
Expand Down Expand Up @@ -131,37 +135,65 @@ fn visit_crate(e: &Env, c: &ast::Crate) {
}

fn visit_view_item(e: &mut Env, i: &ast::ViewItem) {
let should_load = i.attrs.iter().all(|attr| {
"phase" != attr.name() ||
attr.meta_item_list().map_or(false, |phases| {
attr::contains_name(phases, "link")
})
});

if !should_load {
return;
}

match extract_crate_info(i) {
Some(info) => {
let cnum = resolve_crate(e, info.ident, info.name, info.version,
@"", i.span);
e.sess.cstore.add_extern_mod_stmt_cnum(info.id, cnum);
}
None => ()
}
}

struct CrateInfo {
ident: @str,
name: @str,
version: @str,
id: ast::NodeId,
}

fn extract_crate_info(i: &ast::ViewItem) -> Option<CrateInfo> {
match i.node {
ast::ViewItemExternMod(ident, path_opt, id) => {
let ident = token::ident_to_str(&ident);
debug!("resolving extern mod stmt. ident: {:?} path_opt: {:?}",
ident, path_opt);
let (name, version) = match path_opt {
Some((path_str, _)) => {
let crateid: Option<CrateId> = from_str(path_str);
match crateid {
None => (@"", @""),
Some(crateid) => {
let version = match crateid.version {
None => @"",
Some(ref ver) => ver.to_managed(),
};
(crateid.name.to_managed(), version)
}
}
}
None => (ident, @""),
};
let cnum = resolve_crate(e,
ident,
name,
version,
@"",
i.span);
e.sess.cstore.add_extern_mod_stmt_cnum(id, cnum);
}
_ => ()
}
ast::ViewItemExternMod(ident, path_opt, id) => {
let ident = token::ident_to_str(&ident);
debug!("resolving extern mod stmt. ident: {:?} path_opt: {:?}",
ident, path_opt);
let (name, version) = match path_opt {
Some((path_str, _)) => {
let crateid: Option<CrateId> = from_str(path_str);
match crateid {
None => (@"", @""),
Some(crateid) => {
let version = match crateid.version {
None => @"",
Some(ref ver) => ver.to_managed(),
};
(crateid.name.to_managed(), version)
}
}
}
None => (ident, @""),
};
Some(CrateInfo {
ident: ident,
name: name,
version: version,
id: id,
})
}
_ => None
}
}

fn visit_item(e: &Env, i: &ast::Item) {
Expand Down Expand Up @@ -355,3 +387,46 @@ fn resolve_crate_deps(e: &mut Env, cdata: &[u8]) -> cstore::cnum_map {
}
return @RefCell::new(cnum_map);
}

pub struct Loader {
priv env: Env,
}

impl Loader {
pub fn new(sess: Session) -> Loader {
let os = driver::get_os(driver::host_triple()).unwrap();
let os = session::sess_os_to_meta_os(os);
Loader {
env: Env {
sess: sess,
os: os,
crate_cache: @RefCell::new(~[]),
next_crate_num: 1,
intr: token::get_ident_interner(),
}
}
}
}

impl CrateLoader for Loader {
fn load_crate(&mut self, crate: &ast::ViewItem) -> MacroCrate {
let info = extract_crate_info(crate).unwrap();
let cnum = resolve_crate(&mut self.env, info.ident, info.name,
info.version, @"", crate.span);
let library = self.env.sess.cstore.get_used_crate_source(cnum).unwrap();
MacroCrate {
lib: library.dylib,
cnum: cnum
}
}

fn get_exported_macros(&mut self, cnum: ast::CrateNum) -> ~[@ast::Item] {
csearch::get_exported_macros(self.env.sess.cstore, cnum)
}

fn get_registrar_symbol(&mut self, cnum: ast::CrateNum) -> Option<~str> {
let cstore = self.env.sess.cstore;
csearch::get_macro_registrar_fn(cstore, cnum)
.map(|did| csearch::get_symbol(cstore, did))
}
}
13 changes: 13 additions & 0 deletions src/librustc/metadata/csearch.rs
Original file line number Diff line number Diff line change
Expand Up @@ -301,3 +301,16 @@ pub fn get_trait_of_method(cstore: @cstore::CStore,
decoder::get_trait_of_method(cdata, def_id.node, tcx)
}

pub fn get_macro_registrar_fn(cstore: @cstore::CStore,
crate_num: ast::CrateNum)
-> Option<ast::DefId> {
let cdata = cstore.get_crate_data(crate_num);
decoder::get_macro_registrar_fn(cdata)
}

pub fn get_exported_macros(cstore: @cstore::CStore,
crate_num: ast::CrateNum)
-> ~[@ast::Item] {
let cdata = cstore.get_crate_data(crate_num);
decoder::get_exported_macros(cdata)
}
Loading

9 comments on commit 328b47d

@bors
Copy link
Contributor

@bors bors commented on 328b47d Jan 16, 2014

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

saw approval from alexcrichton
at sfackler@328b47d

@bors
Copy link
Contributor

@bors bors commented on 328b47d Jan 16, 2014

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

merging sfackler/rust/ext-crate = 328b47d into auto

@bors
Copy link
Contributor

@bors bors commented on 328b47d Jan 16, 2014

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sfackler/rust/ext-crate = 328b47d merged ok, testing candidate = c08aa418

@bors
Copy link
Contributor

@bors bors commented on 328b47d Jan 17, 2014

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

saw approval from alexcrichton
at sfackler@328b47d

@bors
Copy link
Contributor

@bors bors commented on 328b47d Jan 17, 2014

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

merging sfackler/rust/ext-crate = 328b47d into auto

@bors
Copy link
Contributor

@bors bors commented on 328b47d Jan 17, 2014

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sfackler/rust/ext-crate = 328b47d merged ok, testing candidate = 80a3f45

@bors
Copy link
Contributor

@bors bors commented on 328b47d Jan 17, 2014

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@bors
Copy link
Contributor

@bors bors commented on 328b47d Jan 17, 2014

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fast-forwarding master to auto = 80a3f45

Please sign in to comment.