about summary refs log tree commit diff
path: root/src/libsyntax
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2014-06-09 15:52:07 -0700
committerbors <bors@rust-lang.org>2014-06-09 15:52:07 -0700
commit0ea7aa30cc864d00fc30b9ba610f2daefab4e850 (patch)
tree2f3216efe5cc25851595c14d803dc69738030a72 /src/libsyntax
parentb6146e652ae7f6d373d55dd021dc50cb00e0caf8 (diff)
parentdeecda6a94b31489045d420f16840a72c44af7e1 (diff)
downloadrust-0ea7aa30cc864d00fc30b9ba610f2daefab4e850.tar.gz
rust-0ea7aa30cc864d00fc30b9ba610f2daefab4e850.zip
auto merge of #14554 : kmcallister/rust/plugin_registrar, r=cmr
This implements the design in rust-lang/rfcs#86.  It shouldn't be merged until that RFC is accepted, but it would be great if somebody has time to review the code before then.
Diffstat (limited to 'src/libsyntax')
-rw-r--r--src/libsyntax/ext/base.rs19
-rw-r--r--src/libsyntax/ext/expand.rs152
-rw-r--r--src/libsyntax/ext/registrar.rs58
-rw-r--r--src/libsyntax/lib.rs8
4 files changed, 41 insertions, 196 deletions
diff --git a/src/libsyntax/ext/base.rs b/src/libsyntax/ext/base.rs
index 521b7ee0063..e81421cff04 100644
--- a/src/libsyntax/ext/base.rs
+++ b/src/libsyntax/ext/base.rs
@@ -95,9 +95,6 @@ impl IdentMacroExpander for BasicIdentMacroExpander {
 pub type IdentMacroExpanderFn =
     fn(&mut ExtCtxt, Span, ast::Ident, Vec<ast::TokenTree>) -> Box<MacResult>;
 
-pub type MacroCrateRegistrationFun =
-    fn(|ast::Name, SyntaxExtension|);
-
 /// The result of a macro expansion. The return values of the various
 /// methods are spliced into the AST at the callsite of the macro (or
 /// just into the compiler's internal macro table, for `make_def`).
@@ -268,6 +265,8 @@ pub enum SyntaxExtension {
     IdentTT(Box<IdentMacroExpander:'static>, Option<Span>),
 }
 
+pub type NamedSyntaxExtension = (Name, SyntaxExtension);
+
 pub struct BlockInfo {
     // should macros escape from this scope?
     pub macros_escape: bool,
@@ -392,16 +391,6 @@ pub fn syntax_expander_table() -> SyntaxEnv {
     syntax_expanders
 }
 
-pub struct MacroCrate {
-    pub lib: Option<Path>,
-    pub macros: Vec<String>,
-    pub registrar_symbol: Option<String>,
-}
-
-pub trait CrateLoader {
-    fn load_crate(&mut self, krate: &ast::ViewItem) -> MacroCrate;
-}
-
 // One of these is made during expansion and incrementally updated as we go;
 // when a macro expansion occurs, the resulting nodes have the backtrace()
 // -> expn_info of their expansion context stored into their span.
@@ -409,7 +398,7 @@ pub struct ExtCtxt<'a> {
     pub parse_sess: &'a parse::ParseSess,
     pub cfg: ast::CrateConfig,
     pub backtrace: Option<@ExpnInfo>,
-    pub ecfg: expand::ExpansionConfig<'a>,
+    pub ecfg: expand::ExpansionConfig,
 
     pub mod_path: Vec<ast::Ident> ,
     pub trace_mac: bool,
@@ -417,7 +406,7 @@ pub struct ExtCtxt<'a> {
 
 impl<'a> ExtCtxt<'a> {
     pub fn new<'a>(parse_sess: &'a parse::ParseSess, cfg: ast::CrateConfig,
-                   ecfg: expand::ExpansionConfig<'a>) -> ExtCtxt<'a> {
+                   ecfg: expand::ExpansionConfig) -> ExtCtxt<'a> {
         ExtCtxt {
             parse_sess: parse_sess,
             cfg: cfg,
diff --git a/src/libsyntax/ext/expand.rs b/src/libsyntax/ext/expand.rs
index 03001acc5d0..bb335e7bed0 100644
--- a/src/libsyntax/ext/expand.rs
+++ b/src/libsyntax/ext/expand.rs
@@ -29,10 +29,6 @@ use visit;
 use visit::Visitor;
 use util::small_vector::SmallVector;
 
-use std::mem;
-use std::os;
-use std::unstable::dynamic_lib::DynamicLibrary;
-
 pub fn expand_expr(e: @ast::Expr, fld: &mut MacroExpander) -> @ast::Expr {
     match e.node {
         // expr_mac should really be expr_ext or something; it's the
@@ -497,96 +493,6 @@ pub fn expand_item_mac(it: @ast::Item, fld: &mut MacroExpander)
     return items;
 }
 
-// load macros from syntax-phase crates
-pub fn expand_view_item(vi: &ast::ViewItem,
-                        fld: &mut MacroExpander)
-                        -> ast::ViewItem {
-    match vi.node {
-        ast::ViewItemExternCrate(..) => {
-            let should_load = vi.attrs.iter().any(|attr| {
-                attr.check_name("phase") &&
-                    attr.meta_item_list().map_or(false, |phases| {
-                        attr::contains_name(phases, "syntax")
-                    })
-            });
-
-            if should_load {
-                load_extern_macros(vi, fld);
-            }
-        }
-        ast::ViewItemUse(_) => {}
-    }
-
-    noop_fold_view_item(vi, fld)
-}
-
-fn load_extern_macros(krate: &ast::ViewItem, fld: &mut MacroExpander) {
-    let MacroCrate { lib, macros, registrar_symbol } =
-        fld.cx.ecfg.loader.load_crate(krate);
-
-    let crate_name = match krate.node {
-        ast::ViewItemExternCrate(name, _, _) => name,
-        _ => unreachable!()
-    };
-    let name = format!("<{} macros>", token::get_ident(crate_name));
-    let name = name.to_string();
-
-    for source in macros.iter() {
-        let item = parse::parse_item_from_source_str(name.clone(),
-                                                     (*source).clone(),
-                                                     fld.cx.cfg(),
-                                                     fld.cx.parse_sess())
-                .expect("expected a serialized item");
-        expand_item_mac(item, fld);
-    }
-
-    let path = match lib {
-        Some(path) => path,
-        None => return
-    };
-    // Make sure the path contains a / or the linker will search for it.
-    let path = os::make_absolute(&path);
-
-    let registrar = match registrar_symbol {
-        Some(registrar) => registrar,
-        None => return
-    };
-
-    debug!("load_extern_macros: mapped crate {} to path {} and registrar {:s}",
-           crate_name, path.display(), registrar);
-
-    let lib = match DynamicLibrary::open(Some(&path)) {
-        Ok(lib) => lib,
-        // this is fatal: there are almost certainly macros we need
-        // inside this crate, so continue would spew "macro undefined"
-        // errors
-        Err(err) => fld.cx.span_fatal(krate.span, err.as_slice())
-    };
-
-    unsafe {
-        let registrar: MacroCrateRegistrationFun =
-            match lib.symbol(registrar.as_slice()) {
-                Ok(registrar) => registrar,
-                // again fatal if we can't register macros
-                Err(err) => fld.cx.span_fatal(krate.span, err.as_slice())
-            };
-        registrar(|name, extension| {
-            let extension = match extension {
-                NormalTT(ext, _) => NormalTT(ext, Some(krate.span)),
-                IdentTT(ext, _) => IdentTT(ext, Some(krate.span)),
-                ItemDecorator(ext) => ItemDecorator(ext),
-                ItemModifier(ext) => ItemModifier(ext),
-            };
-            fld.extsbox.insert(name, extension);
-        });
-
-        // Intentionally leak the dynamic library. We can't ever unload it
-        // since the library can do things that will outlive the expansion
-        // phase (e.g. make an @-box cycle or launch a task).
-        mem::forget(lib);
-    }
-}
-
 // expand a stmt
 pub fn expand_stmt(s: &Stmt, fld: &mut MacroExpander) -> SmallVector<@Stmt> {
     // why the copying here and not in expand_expr?
@@ -969,10 +875,6 @@ impl<'a, 'b> Folder for MacroExpander<'a, 'b> {
         expand_item(item, self)
     }
 
-    fn fold_view_item(&mut self, vi: &ast::ViewItem) -> ast::ViewItem {
-        expand_view_item(vi, self)
-    }
-
     fn fold_stmt(&mut self, stmt: &ast::Stmt) -> SmallVector<@ast::Stmt> {
         expand_stmt(stmt, self)
     }
@@ -986,14 +888,20 @@ impl<'a, 'b> Folder for MacroExpander<'a, 'b> {
     }
 }
 
-pub struct ExpansionConfig<'a> {
-    pub loader: &'a mut CrateLoader,
+pub struct ExpansionConfig {
     pub deriving_hash_type_parameter: bool,
     pub crate_id: CrateId,
 }
 
+pub struct ExportedMacros {
+    pub crate_name: Ident,
+    pub macros: Vec<String>,
+}
+
 pub fn expand_crate(parse_sess: &parse::ParseSess,
                     cfg: ExpansionConfig,
+                    macros: Vec<ExportedMacros>,
+                    user_exts: Vec<NamedSyntaxExtension>,
                     c: Crate) -> Crate {
     let mut cx = ExtCtxt::new(parse_sess, c.config.clone(), cfg);
     let mut expander = MacroExpander {
@@ -1001,6 +909,24 @@ pub fn expand_crate(parse_sess: &parse::ParseSess,
         cx: &mut cx,
     };
 
+    for ExportedMacros { crate_name, macros } in macros.move_iter() {
+        let name = format!("<{} macros>", token::get_ident(crate_name))
+            .into_string();
+
+        for source in macros.move_iter() {
+            let item = parse::parse_item_from_source_str(name.clone(),
+                                                         source,
+                                                         expander.cx.cfg(),
+                                                         expander.cx.parse_sess())
+                    .expect("expected a serialized item");
+            expand_item_mac(item, &mut expander);
+        }
+    }
+
+    for (name, extension) in user_exts.move_iter() {
+        expander.extsbox.insert(name, extension);
+    }
+
     let ret = expander.fold_crate(c);
     parse_sess.span_diagnostic.handler().abort_if_errors();
     return ret;
@@ -1093,7 +1019,6 @@ mod test {
     use attr;
     use codemap;
     use codemap::Spanned;
-    use ext::base::{CrateLoader, MacroCrate};
     use ext::mtwt;
     use parse;
     use parse::token;
@@ -1137,14 +1062,6 @@ mod test {
         }
     }
 
-    struct ErrLoader;
-
-    impl CrateLoader for ErrLoader {
-        fn load_crate(&mut self, _: &ast::ViewItem) -> MacroCrate {
-            fail!("lolwut")
-        }
-    }
-
     // these following tests are quite fragile, in that they don't test what
     // *kind* of failure occurs.
 
@@ -1159,13 +1076,11 @@ mod test {
             src,
             Vec::new(), &sess);
         // should fail:
-        let mut loader = ErrLoader;
         let cfg = ::syntax::ext::expand::ExpansionConfig {
-            loader: &mut loader,
             deriving_hash_type_parameter: false,
             crate_id: from_str("test").unwrap(),
         };
-        expand_crate(&sess,cfg,crate_ast);
+        expand_crate(&sess,cfg,vec!(),vec!(),crate_ast);
     }
 
     // make sure that macros can leave scope for modules
@@ -1178,14 +1093,11 @@ mod test {
             "<test>".to_string(),
             src,
             Vec::new(), &sess);
-        // should fail:
-        let mut loader = ErrLoader;
         let cfg = ::syntax::ext::expand::ExpansionConfig {
-            loader: &mut loader,
             deriving_hash_type_parameter: false,
             crate_id: from_str("test").unwrap(),
         };
-        expand_crate(&sess,cfg,crate_ast);
+        expand_crate(&sess,cfg,vec!(),vec!(),crate_ast);
     }
 
     // macro_escape modules shouldn't cause macros to leave scope
@@ -1198,13 +1110,11 @@ mod test {
             src,
             Vec::new(), &sess);
         // should fail:
-        let mut loader = ErrLoader;
         let cfg = ::syntax::ext::expand::ExpansionConfig {
-            loader: &mut loader,
             deriving_hash_type_parameter: false,
             crate_id: from_str("test").unwrap(),
         };
-        expand_crate(&sess, cfg, crate_ast);
+        expand_crate(&sess, cfg, vec!(), vec!(), crate_ast);
     }
 
     #[test] fn test_contains_flatten (){
@@ -1237,13 +1147,11 @@ mod test {
         let ps = parse::new_parse_sess();
         let crate_ast = string_to_parser(&ps, crate_str).parse_crate_mod();
         // the cfg argument actually does matter, here...
-        let mut loader = ErrLoader;
         let cfg = ::syntax::ext::expand::ExpansionConfig {
-            loader: &mut loader,
             deriving_hash_type_parameter: false,
             crate_id: from_str("test").unwrap(),
         };
-        expand_crate(&ps,cfg,crate_ast)
+        expand_crate(&ps,cfg,vec!(),vec!(),crate_ast)
     }
 
     //fn expand_and_resolve(crate_str: @str) -> ast::crate {
diff --git a/src/libsyntax/ext/registrar.rs b/src/libsyntax/ext/registrar.rs
deleted file mode 100644
index b76708147e1..00000000000
--- a/src/libsyntax/ext/registrar.rs
+++ /dev/null
@@ -1,58 +0,0 @@
-// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-use ast;
-use attr;
-use codemap::Span;
-use diagnostic;
-use visit;
-use visit::Visitor;
-
-struct MacroRegistrarContext {
-    registrars: Vec<(ast::NodeId, Span)> ,
-}
-
-impl Visitor<()> for MacroRegistrarContext {
-    fn visit_item(&mut self, item: &ast::Item, _: ()) {
-        match item.node {
-            ast::ItemFn(..) => {
-                if attr::contains_name(item.attrs.as_slice(),
-                                       "macro_registrar") {
-                    self.registrars.push((item.id, item.span));
-                }
-            }
-            _ => {}
-        }
-
-        visit::walk_item(self, item, ());
-    }
-}
-
-pub fn find_macro_registrar(diagnostic: &diagnostic::SpanHandler,
-                            krate: &ast::Crate) -> Option<ast::NodeId> {
-    let mut ctx = MacroRegistrarContext { registrars: Vec::new() };
-    visit::walk_crate(&mut ctx, krate, ());
-
-    match ctx.registrars.len() {
-        0 => None,
-        1 => {
-            let (node_id, _) = ctx.registrars.pop().unwrap();
-            Some(node_id)
-        },
-        _ => {
-            diagnostic.handler().err("multiple macro registration functions found");
-            for &(_, span) in ctx.registrars.iter() {
-                diagnostic.span_note(span, "one is here");
-            }
-            diagnostic.handler().abort_if_errors();
-            unreachable!();
-        }
-    }
-}
diff --git a/src/libsyntax/lib.rs b/src/libsyntax/lib.rs
index 1ab420eb69b..754518f5fea 100644
--- a/src/libsyntax/lib.rs
+++ b/src/libsyntax/lib.rs
@@ -32,8 +32,15 @@ This API is completely unstable and subject to change.
 
 extern crate serialize;
 extern crate term;
+
+#[cfg(stage0)]
 #[phase(syntax, link)]
 extern crate log;
+
+#[cfg(not(stage0))]
+#[phase(plugin, link)]
+extern crate log;
+
 extern crate fmt_macros;
 extern crate debug;
 
@@ -74,7 +81,6 @@ pub mod ext {
     pub mod asm;
     pub mod base;
     pub mod expand;
-    pub mod registrar;
 
     pub mod quote;