diff --git a/src/librustc/lib.rs b/src/librustc/lib.rs index bdbb1a98ac5..4ac4e3a5a9f 100644 --- a/src/librustc/lib.rs +++ b/src/librustc/lib.rs @@ -114,13 +114,7 @@ pub mod back { pub mod driver; -pub mod plugin { - pub use self::registry::Registry; - - pub mod registry; - pub mod load; - pub mod build; -} +pub mod plugin; pub mod util { pub mod common; diff --git a/src/librustc/plugin/build.rs b/src/librustc/plugin/build.rs index a27632882fc..ad35c4efe11 100644 --- a/src/librustc/plugin/build.rs +++ b/src/librustc/plugin/build.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +//! Used by `rustc` when compiling a plugin crate. + use syntax::ast; use syntax::attr; use syntax::codemap::Span; @@ -36,7 +38,6 @@ fn visit_item(&mut self, item: &ast::Item, _: ()) { } /// Find the function marked with `#[plugin_registrar]`, if any. -/// Used while compiling a crate which defines a registrar. pub fn find_plugin_registrar(diagnostic: &diagnostic::SpanHandler, krate: &ast::Crate) -> Option { let mut finder = RegistrarFinder { registrars: Vec::new() }; diff --git a/src/librustc/plugin/load.rs b/src/librustc/plugin/load.rs index c80f8f96c4b..ba50a15a82b 100644 --- a/src/librustc/plugin/load.rs +++ b/src/librustc/plugin/load.rs @@ -8,9 +8,11 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use plugin::registry::PluginRegistrarFun; +//! Used by `rustc` when loading a plugin. + use driver::session::Session; use metadata::creader::PluginMetadataReader; +use plugin::registry::Registry; use std::mem; use std::os; @@ -22,14 +24,25 @@ use syntax::ext::expand::ExportedMacros; use syntax::attr::AttrMetaMethods; +/// Plugin-related crate metadata. pub struct PluginMetadata { + /// Source code of macros exported by the crate. pub macros: Vec, + /// Path to the shared library file. pub lib: Option, + /// Symbol name of the plugin registrar function. pub registrar_symbol: Option, } +/// Pointer to a registrar function. +pub type PluginRegistrarFun = + fn(&mut Registry); + +/// Information about loaded plugins. pub struct Plugins { + /// Source code of exported macros. pub macros: Vec, + /// Registrars, as function pointers. pub registrars: Vec, } @@ -52,6 +65,7 @@ fn new(sess: &'a Session) -> PluginLoader<'a> { } } +/// Read plugin metadata and dynamically load registrar functions. pub fn load_plugins(sess: &Session, krate: &ast::Crate) -> Plugins { let mut loader = PluginLoader::new(sess); visit::walk_crate(&mut loader, krate, ()); diff --git a/src/librustc/plugin/mod.rs b/src/librustc/plugin/mod.rs new file mode 100644 index 00000000000..fa70ffc7392 --- /dev/null +++ b/src/librustc/plugin/mod.rs @@ -0,0 +1,64 @@ +// 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +/*! + * Infrastructure for compiler plugins. + * + * Plugins are Rust libraries which extend the behavior of `rustc` + * in various ways. + * + * Plugin authors will use the `Registry` type re-exported by + * this module, along with its methods. The rest of the module + * is for use by `rustc` itself. + * + * To define a plugin, build a dylib crate with a + * `#[plugin_registrar]` function: + * + * ```rust,ignore + * #![crate_id = "myplugin"] + * #![crate_type = "dylib"] + * #![feature(plugin_registrar)] + * + * extern crate rustc; + * + * use rustc::plugin::Registry; + * + * #[plugin_registrar] + * pub fn plugin_registrar(reg: &mut Registry) { + * reg.register_macro("mymacro", expand_mymacro); + * } + * + * fn expand_mymacro(...) { // details elided + * ``` + * + * WARNING: We currently don't check that the registrar function + * has the appropriate type! + * + * To use a plugin while compiling another crate: + * + * ```rust + * #![feature(phase)] + * + * #[phase(plugin)] + * extern crate myplugin; + * ``` + * + * If you also need the plugin crate available at runtime, use + * `phase(plugin, link)`. + * + * See `src/test/auxiliary/macro_crate_test.rs` and `src/libfourcc` + * for examples of syntax extension plugins. + */ + +pub use self::registry::Registry; + +pub mod registry; +pub mod load; +pub mod build; diff --git a/src/librustc/plugin/registry.rs b/src/librustc/plugin/registry.rs index 6402b116536..f6e37822325 100644 --- a/src/librustc/plugin/registry.rs +++ b/src/librustc/plugin/registry.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +//! Used by plugin crates to tell `rustc` about the plugins they provide. + use syntax::ext::base::{SyntaxExtension, NamedSyntaxExtension, NormalTT}; use syntax::ext::base::{IdentTT, ItemDecorator, ItemModifier, BasicMacroExpander}; use syntax::ext::base::{MacroExpanderFn}; @@ -15,6 +17,14 @@ use syntax::parse::token; use syntax::ast; +/// Structure used to register plugins. +/// +/// A plugin registrar function takes an `&mut Registry` and should call +/// methods to register its plugins. +/// +/// This struct has public fields and other methods for use by `rustc` +/// itself. They are not documented here, and plugin authors should +/// not use them. pub struct Registry { #[doc(hidden)] pub krate_span: Span, @@ -23,9 +33,6 @@ pub struct Registry { pub syntax_exts: Vec, } -pub type PluginRegistrarFun = - fn(&mut Registry); - impl Registry { #[doc(hidden)] pub fn new(krate: &ast::Crate) -> Registry { @@ -35,6 +42,9 @@ pub fn new(krate: &ast::Crate) -> Registry { } } + /// Register a syntax extension of any kind. + /// + /// This is the most general hook into `libsyntax`'s expansion behavior. pub fn register_syntax_extension(&mut self, name: ast::Name, extension: SyntaxExtension) { self.syntax_exts.push((name, match extension { NormalTT(ext, _) => NormalTT(ext, Some(self.krate_span)), @@ -44,6 +54,11 @@ pub fn register_syntax_extension(&mut self, name: ast::Name, extension: SyntaxEx })); } + /// Register a macro of the usual kind. + /// + /// This is a convenience wrapper for `register_syntax_extension`. + /// It builds for you a `NormalTT` with a `BasicMacroExpander`, + /// and also takes care of interning the macro's name. pub fn register_macro(&mut self, name: &str, expander: MacroExpanderFn) { self.register_syntax_extension( token::intern(name),