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.
DEPS_sync := std alloc
DEPS_getopts := std
DEPS_collections := core alloc
-DEPS_fourcc := syntax std
-DEPS_hexfloat := syntax std
+DEPS_fourcc := rustc syntax std
+DEPS_hexfloat := rustc syntax std
DEPS_num := std
DEPS_test := std getopts serialize term time regex native:rust_test_helpers
DEPS_time := std serialize sync
DEPS_url := std
DEPS_log := std sync
DEPS_regex := std
-DEPS_regex_macros = syntax std regex
+DEPS_regex_macros = rustc syntax std regex
DEPS_fmt_macros = std
TOOL_DEPS_compiletest := test green rustuv getopts
extern crate test;
extern crate getopts;
-#[phase(link, syntax)]
-extern crate log;
extern crate green;
extern crate rustuv;
+#[cfg(stage0)]
+#[phase(syntax, link)]
+extern crate log;
+
+#[cfg(not(stage0))]
+#[phase(plugin, link)]
+extern crate log;
+
extern crate regex;
use std::os;
### Function-only attributes
-- `macro_registrar` - when using loadable syntax extensions, mark this
- function as the registration point for the current crate's syntax
- extensions.
+- `plugin_registrar` - mark this function as the registration point for
+ compiler plugins, such as loadable syntax extensions.
- `main` - indicates that this function should be passed to the entry point,
rather than the function in the crate root named `main`.
- `start` - indicates that this function should be used as the entry point,
~~~~
#![feature(phase)]
-#[phase(syntax, link)] extern crate log;
+#[phase(plugin, link)] extern crate log;
fn main() {
error!("This is an error log")
#![no_std]
#![feature(phase)]
+#[cfg(stage0)]
#[phase(syntax, link)]
extern crate core;
+
+#[cfg(not(stage0))]
+#[phase(plugin, link)]
+extern crate core;
+
extern crate libc;
#[cfg(test)] extern crate debug;
#[cfg(test)] extern crate sync;
#[cfg(test)] extern crate native;
-#[cfg(test)] #[phase(syntax, link)] extern crate std;
-#[cfg(test)] #[phase(syntax, link)] extern crate log;
+#[cfg(test, stage0)] #[phase(syntax, link)] extern crate std;
+#[cfg(test, stage0)] #[phase(syntax, link)] extern crate log;
+#[cfg(test, not(stage0))] #[phase(plugin, link)] extern crate std;
+#[cfg(test, not(stage0))] #[phase(plugin, link)] extern crate log;
// Heaps provided for low-level allocation strategies
#![feature(macro_rules, managed_boxes, default_type_params, phase, globs)]
#![no_std]
-#[phase(syntax, link)] extern crate core;
extern crate alloc;
+#[cfg(stage0)]
+#[phase(syntax, link)]
+extern crate core;
+
+#[cfg(not(stage0))]
+#[phase(plugin, link)]
+extern crate core;
+
#[cfg(test)] extern crate native;
#[cfg(test)] extern crate test;
#[cfg(test)] extern crate debug;
-#[cfg(test)] #[phase(syntax, link)] extern crate std;
-#[cfg(test)] #[phase(syntax, link)] extern crate log;
+
+#[cfg(test, stage0)] #[phase(syntax, link)] extern crate std;
+#[cfg(test, stage0)] #[phase(syntax, link)] extern crate log;
+#[cfg(test, not(stage0))] #[phase(plugin, link)] extern crate std;
+#[cfg(test, not(stage0))] #[phase(plugin, link)] extern crate log;
use core::prelude::*;
#![feature(phase)]
#![deny(deprecated_owned_vector)]
-#[cfg(test)] #[phase(syntax, link)] extern crate log;
+#[cfg(test, stage0)] #[phase(syntax, link)] extern crate log;
+#[cfg(test, not(stage0))] #[phase(plugin, link)] extern crate log;
extern crate libc;
To load the extension and use it:
```rust,ignore
-#[phase(syntax)]
+#[phase(plugin)]
extern crate fourcc;
fn main() {
html_root_url = "http://doc.rust-lang.org/")]
#![deny(deprecated_owned_vector)]
-#![feature(macro_registrar, managed_boxes)]
+#![feature(plugin_registrar, managed_boxes)]
extern crate syntax;
+extern crate rustc;
use syntax::ast;
-use syntax::ast::Name;
use syntax::attr::contains;
use syntax::codemap::{Span, mk_sp};
use syntax::ext::base;
-use syntax::ext::base::{SyntaxExtension, BasicMacroExpander, NormalTT, ExtCtxt, MacExpr};
+use syntax::ext::base::{ExtCtxt, MacExpr};
use syntax::ext::build::AstBuilder;
use syntax::parse;
use syntax::parse::token;
use syntax::parse::token::InternedString;
+use rustc::plugin::Registry;
-#[macro_registrar]
-pub fn macro_registrar(register: |Name, SyntaxExtension|) {
- register(token::intern("fourcc"),
- NormalTT(box BasicMacroExpander {
- expander: expand_syntax_ext,
- span: None,
- },
- None));
+#[plugin_registrar]
+pub fn plugin_registrar(reg: &mut Registry) {
+ reg.register_macro("fourcc", expand_syntax_ext);
}
pub fn expand_syntax_ext(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree])
#![deny(deprecated_owned_vector)]
#[cfg(test)] extern crate debug;
-#[cfg(test)] #[phase(syntax, link)] extern crate log;
+#[cfg(test, stage0)] #[phase(syntax, link)] extern crate log;
+#[cfg(test, not(stage0))] #[phase(plugin, link)] extern crate log;
use std::cmp::PartialEq;
use std::result::{Err, Ok};
//!
//! ```
//! #![feature(phase)]
-//! #[phase(syntax)] extern crate green;
+//! #[phase(plugin)] extern crate green;
//!
//! green_start!(main)
//!
#![allow(visible_private_types)]
#![deny(deprecated_owned_vector)]
-#[cfg(test)] #[phase(syntax, link)] extern crate log;
+#[cfg(test)] #[phase(plugin, link)] extern crate log;
#[cfg(test)] extern crate rustuv;
extern crate libc;
extern crate alloc;
///
/// ```
/// #![feature(phase)]
-/// #[phase(syntax)] extern crate green;
+/// #[phase(plugin)] extern crate green;
///
/// green_start!(main)
///
To load the extension and use it:
```rust,ignore
-#[phase(syntax)]
+#[phase(plugin)]
extern crate hexfloat;
fn main() {
html_root_url = "http://doc.rust-lang.org/")]
#![deny(deprecated_owned_vector)]
-#![feature(macro_registrar, managed_boxes)]
+#![feature(plugin_registrar, managed_boxes)]
extern crate syntax;
+extern crate rustc;
use syntax::ast;
-use syntax::ast::Name;
use syntax::codemap::{Span, mk_sp};
use syntax::ext::base;
-use syntax::ext::base::{SyntaxExtension, BasicMacroExpander, NormalTT, ExtCtxt, MacExpr};
+use syntax::ext::base::{ExtCtxt, MacExpr};
use syntax::ext::build::AstBuilder;
use syntax::parse;
use syntax::parse::token;
+use rustc::plugin::Registry;
-#[macro_registrar]
-pub fn macro_registrar(register: |Name, SyntaxExtension|) {
- register(token::intern("hexfloat"),
- NormalTT(box BasicMacroExpander {
- expander: expand_syntax_ext,
- span: None,
- },
- None));
+#[plugin_registrar]
+pub fn plugin_registrar(reg: &mut Registry) {
+ reg.register_macro("hexfloat", expand_syntax_ext);
}
//Check if the literal is valid (as LLVM expects),
```
#![feature(phase)]
-#[phase(syntax, link)] extern crate log;
+#[phase(plugin, link)] extern crate log;
fn main() {
debug!("this is a debug {}", "message");
///
/// ```
/// #![feature(phase)]
-/// #[phase(syntax, link)] extern crate log;
+/// #[phase(plugin, link)] extern crate log;
///
/// # fn main() {
/// log!(log::DEBUG, "this is a debug message");
///
/// ```
/// #![feature(phase)]
-/// #[phase(syntax, link)] extern crate log;
+/// #[phase(plugin, link)] extern crate log;
///
/// # fn main() {
/// # let error = 3;
///
/// ```
/// #![feature(phase)]
-/// #[phase(syntax, link)] extern crate log;
+/// #[phase(plugin, link)] extern crate log;
///
/// # fn main() {
/// # let code = 3;
///
/// ```
/// #![feature(phase)]
-/// #[phase(syntax, link)] extern crate log;
+/// #[phase(plugin, link)] extern crate log;
///
/// # fn main() {
/// # let ret = 3;
///
/// ```
/// #![feature(phase)]
-/// #[phase(syntax, link)] extern crate log;
+/// #[phase(plugin, link)] extern crate log;
///
/// # fn main() {
/// debug!("x = {x}, y = {y}", x=10, y=20);
///
/// ```
/// #![feature(phase)]
-/// #[phase(syntax, link)] extern crate log;
+/// #[phase(plugin, link)] extern crate log;
///
/// # fn main() {
/// # struct Point { x: int, y: int }
#![no_std]
#![experimental]
+#[cfg(stage0)]
#[phase(syntax, link)]
extern crate core;
+#[cfg(not(stage0))]
+#[phase(plugin, link)]
+extern crate core;
+
+#[cfg(test, stage0)]
+#[phase(syntax, link)] extern crate std;
+
+#[cfg(test, stage0)]
+#[phase(syntax, link)] extern crate log;
+
+#[cfg(test, not(stage0))]
+#[phase(plugin, link)] extern crate std;
+
+#[cfg(test, not(stage0))]
+#[phase(plugin, link)] extern crate log;
+
#[cfg(test)] extern crate native;
#[cfg(test)] extern crate debug;
-#[cfg(test)] #[phase(syntax, link)] extern crate std;
-#[cfg(test)] #[phase(syntax, link)] extern crate log;
use core::prelude::*;
//!
//! ```rust
//! #![feature(phase)]
-//! #[phase(syntax)]
+//! #[phase(plugin)]
//! extern crate regex_macros;
//! extern crate regex;
//!
//!
//! ```rust
//! # #![feature(phase)]
-//! # extern crate regex; #[phase(syntax)] extern crate regex_macros;
+//! # extern crate regex; #[phase(plugin)] extern crate regex_macros;
//! # fn main() {
//! let re = regex!(r"(\d{4})-(\d{2})-(\d{2})");
//! let text = "2012-03-14, 2013-01-01 and 2014-07-05";
//!
//! ```rust
//! # #![feature(phase)]
-//! # extern crate regex; #[phase(syntax)] extern crate regex_macros;
+//! # extern crate regex; #[phase(plugin)] extern crate regex_macros;
//! # fn main() {
//! let re = regex!(r"(?P<y>\d{4})-(?P<m>\d{2})-(?P<d>\d{2})");
//! let before = "2012-03-14, 2013-01-01 and 2014-07-05";
//!
//! ```rust
//! # #![feature(phase)]
-//! # extern crate regex; #[phase(syntax)] extern crate regex_macros;
+//! # extern crate regex; #[phase(plugin)] extern crate regex_macros;
//! # fn main() {
//! let re = regex!(r"(?i)Δ+");
//! assert_eq!(re.find("ΔδΔ"), Some((0, 6)));
//!
//! ```rust
//! # #![feature(phase)]
-//! # extern crate regex; #[phase(syntax)] extern crate regex_macros;
+//! # extern crate regex; #[phase(plugin)] extern crate regex_macros;
//! # fn main() {
//! let re = regex!(r"[\pN\p{Greek}\p{Cherokee}]+");
//! assert_eq!(re.find("abcΔᎠβⅠᏴγδⅡxyz"), Some((3, 23)));
//!
//! ```rust
//! # #![feature(phase)]
-//! # extern crate regex; #[phase(syntax)] extern crate regex_macros;
+//! # extern crate regex; #[phase(plugin)] extern crate regex_macros;
//! # fn main() {
//! let re = regex!(r"(?i)a+(?-i)b+");
//! let cap = re.captures("AaAaAbbBBBb").unwrap();
/// ```rust
/// #![feature(phase)]
/// extern crate regex;
-/// #[phase(syntax)] extern crate regex_macros;
+/// #[phase(plugin)] extern crate regex_macros;
///
/// fn main() {
/// let re = regex!(r"\d+");
///
/// ```rust
/// # #![feature(phase)]
- /// # extern crate regex; #[phase(syntax)] extern crate regex_macros;
+ /// # extern crate regex; #[phase(plugin)] extern crate regex_macros;
/// # fn main() {
/// let text = "I categorically deny having triskaidekaphobia.";
/// let matched = regex!(r"\b\w{13}\b").is_match(text);
///
/// ```rust
/// # #![feature(phase)]
- /// # extern crate regex; #[phase(syntax)] extern crate regex_macros;
+ /// # extern crate regex; #[phase(plugin)] extern crate regex_macros;
/// # fn main() {
/// let text = "I categorically deny having triskaidekaphobia.";
/// let pos = regex!(r"\b\w{13}\b").find(text);
///
/// ```rust
/// # #![feature(phase)]
- /// # extern crate regex; #[phase(syntax)] extern crate regex_macros;
+ /// # extern crate regex; #[phase(plugin)] extern crate regex_macros;
/// # fn main() {
/// let text = "Retroactively relinquishing remunerations is reprehensible.";
/// for pos in regex!(r"\b\w{13}\b").find_iter(text) {
///
/// ```rust
/// # #![feature(phase)]
- /// # extern crate regex; #[phase(syntax)] extern crate regex_macros;
+ /// # extern crate regex; #[phase(plugin)] extern crate regex_macros;
/// # fn main() {
/// let re = regex!(r"'([^']+)'\s+\((\d{4})\)");
/// let text = "Not my favorite movie: 'Citizen Kane' (1941).";
///
/// ```rust
/// # #![feature(phase)]
- /// # extern crate regex; #[phase(syntax)] extern crate regex_macros;
+ /// # extern crate regex; #[phase(plugin)] extern crate regex_macros;
/// # fn main() {
/// let re = regex!(r"'(?P<title>[^']+)'\s+\((?P<year>\d{4})\)");
/// let text = "Not my favorite movie: 'Citizen Kane' (1941).";
///
/// ```rust
/// # #![feature(phase)]
- /// # extern crate regex; #[phase(syntax)] extern crate regex_macros;
+ /// # extern crate regex; #[phase(plugin)] extern crate regex_macros;
/// # fn main() {
/// let re = regex!(r"'(?P<title>[^']+)'\s+\((?P<year>\d{4})\)");
/// let text = "'Citizen Kane' (1941), 'The Wizard of Oz' (1939), 'M' (1931).";
///
/// ```rust
/// # #![feature(phase)]
- /// # extern crate regex; #[phase(syntax)] extern crate regex_macros;
+ /// # extern crate regex; #[phase(plugin)] extern crate regex_macros;
/// # fn main() {
/// let re = regex!(r"[ \t]+");
/// let fields: Vec<&str> = re.split("a b \t c\td e").collect();
///
/// ```rust
/// # #![feature(phase)]
- /// # extern crate regex; #[phase(syntax)] extern crate regex_macros;
+ /// # extern crate regex; #[phase(plugin)] extern crate regex_macros;
/// # fn main() {
/// let re = regex!(r"\W+");
/// let fields: Vec<&str> = re.splitn("Hey! How are you?", 3).collect();
///
/// ```rust
/// # #![feature(phase)]
- /// # extern crate regex; #[phase(syntax)] extern crate regex_macros;
+ /// # extern crate regex; #[phase(plugin)] extern crate regex_macros;
/// # fn main() {
/// let re = regex!("[^01]+");
/// assert_eq!(re.replace("1078910", "").as_slice(), "1010");
///
/// ```rust
/// # #![feature(phase)]
- /// # extern crate regex; #[phase(syntax)] extern crate regex_macros;
+ /// # extern crate regex; #[phase(plugin)] extern crate regex_macros;
/// # use regex::Captures; fn main() {
/// let re = regex!(r"([^,\s]+),\s+(\S+)");
/// let result = re.replace("Springsteen, Bruce", |caps: &Captures| {
///
/// ```rust
/// # #![feature(phase)]
- /// # extern crate regex; #[phase(syntax)] extern crate regex_macros;
+ /// # extern crate regex; #[phase(plugin)] extern crate regex_macros;
/// # fn main() {
/// let re = regex!(r"(?P<last>[^,\s]+),\s+(?P<first>\S+)");
/// let result = re.replace("Springsteen, Bruce", "$first $last");
///
/// ```rust
/// # #![feature(phase)]
- /// # extern crate regex; #[phase(syntax)] extern crate regex_macros;
+ /// # extern crate regex; #[phase(plugin)] extern crate regex_macros;
/// # fn main() {
/// use regex::NoExpand;
///
// except according to those terms.
#[cfg(not(stage1))]
-#[phase(syntax)]
+#[phase(plugin)]
extern crate regex_macros;
#[cfg(not(stage1))]
html_favicon_url = "http://www.rust-lang.org/favicon.ico",
html_root_url = "http://doc.rust-lang.org/")]
-#![feature(macro_registrar, managed_boxes, quote)]
+#![feature(plugin_registrar, managed_boxes, quote)]
extern crate regex;
extern crate syntax;
+extern crate rustc;
use std::rc::Rc;
use syntax::ast;
use syntax::codemap;
use syntax::ext::build::AstBuilder;
-use syntax::ext::base::{
- SyntaxExtension, ExtCtxt, MacResult, MacExpr, DummyResult,
- NormalTT, BasicMacroExpander,
-};
+use syntax::ext::base::{ExtCtxt, MacResult, MacExpr, DummyResult};
use syntax::parse;
use syntax::parse::token;
use syntax::print::pprust;
+use rustc::plugin::Registry;
+
use regex::Regex;
use regex::native::{
OneChar, CharClass, Any, Save, Jump, Split,
};
/// For the `regex!` syntax extension. Do not use.
-#[macro_registrar]
+#[plugin_registrar]
#[doc(hidden)]
-pub fn macro_registrar(register: |ast::Name, SyntaxExtension|) {
- let expander = box BasicMacroExpander { expander: native, span: None };
- register(token::intern("regex"), NormalTT(expander, None))
+pub fn plugin_registrar(reg: &mut Registry) {
+ reg.register_macro("regex", native);
}
/// Generates specialized code for the Pike VM for a particular regular
use lib::llvm::{ContextRef, ModuleRef};
use metadata::common::LinkMeta;
use metadata::creader;
-use metadata::creader::Loader;
use middle::cfg;
use middle::cfg::graphviz::LabelledCFG;
use middle::{trans, freevars, kind, ty, typeck, lint, reachable};
use middle::dependency_format;
use middle;
+use plugin::load::Plugins;
+use plugin::registry::Registry;
+use plugin;
use util::common::time;
use util::ppaux;
use util::nodemap::{NodeSet};
use syntax::attr;
use syntax::attr::{AttrMetaMethods};
use syntax::crateid::CrateId;
-use syntax::ext::base::CrateLoader;
use syntax::parse;
use syntax::parse::token;
use syntax::print::{pp, pprust};
output,
krate.attrs.as_slice(),
&sess);
- let loader = &mut Loader::new(&sess);
let id = link::find_crate_id(krate.attrs.as_slice(),
outputs.out_filestem.as_slice());
let (expanded_crate, ast_map) =
- phase_2_configure_and_expand(&sess, loader, krate, &id);
+ phase_2_configure_and_expand(&sess, krate, &id);
(outputs, expanded_crate, ast_map)
};
write_out_deps(&sess, input, &outputs, &expanded_crate);
/// harness if one is to be provided and injection of a dependency on the
/// standard library and prelude.
pub fn phase_2_configure_and_expand(sess: &Session,
- loader: &mut CrateLoader,
mut krate: ast::Crate,
crate_id: &CrateId)
-> (ast::Crate, syntax::ast_map::Map) {
krate = time(time_passes, "configuration 1", krate, |krate|
front::config::strip_unconfigured_items(krate));
- krate = time(time_passes, "expansion", krate, |krate| {
- // Windows dlls do not have rpaths, so they don't know how to find their
- // dependencies. It's up to us to tell the system where to find all the
- // dependent dlls. Note that this uses cfg!(windows) as opposed to
- // targ_cfg because syntax extensions are always loaded for the host
- // compiler, not for the target.
- if cfg!(windows) {
- sess.host_filesearch().add_dylib_search_paths();
+ let Plugins { macros, registrars }
+ = time(time_passes, "plugin loading", (), |_|
+ plugin::load::load_plugins(sess, &krate));
+
+ let mut registry = Registry::new(&krate);
+
+ time(time_passes, "plugin registration", (), |_| {
+ for ®istrar in registrars.iter() {
+ registrar(&mut registry);
}
- let cfg = syntax::ext::expand::ExpansionConfig {
- loader: loader,
- deriving_hash_type_parameter: sess.features.default_type_params.get(),
- crate_id: crate_id.clone(),
- };
- syntax::ext::expand::expand_crate(&sess.parse_sess,
- cfg,
- krate)
});
+ let Registry { syntax_exts, .. } = registry;
+
+ krate = time(time_passes, "expansion", (krate, macros, syntax_exts),
+ |(krate, macros, syntax_exts)| {
+ // Windows dlls do not have rpaths, so they don't know how to find their
+ // dependencies. It's up to us to tell the system where to find all the
+ // dependent dlls. Note that this uses cfg!(windows) as opposed to
+ // targ_cfg because syntax extensions are always loaded for the host
+ // compiler, not for the target.
+ if cfg!(windows) {
+ sess.host_filesearch().add_dylib_search_paths();
+ }
+ let cfg = syntax::ext::expand::ExpansionConfig {
+ deriving_hash_type_parameter: sess.features.default_type_params.get(),
+ crate_id: crate_id.clone(),
+ };
+ syntax::ext::expand::expand_crate(&sess.parse_sess,
+ cfg,
+ macros,
+ syntax_exts,
+ krate)
+ }
+ );
+
// strip again, in case expansion added anything with a #[cfg].
krate = time(time_passes, "configuration 2", krate, |krate|
front::config::strip_unconfigured_items(krate));
time(time_passes, "looking for entry point", (),
|_| middle::entry::find_entry_point(&sess, krate, &ast_map));
- sess.macro_registrar_fn.set(
- time(time_passes, "looking for macro registrar", (), |_|
- syntax::ext::registrar::find_macro_registrar(
+ sess.plugin_registrar_fn.set(
+ time(time_passes, "looking for plugin registrar", (), |_|
+ plugin::build::find_plugin_registrar(
sess.diagnostic(), krate)));
let freevars = time(time_passes, "freevar finding", (), |_|
let (krate, ast_map, is_expanded) = match ppm {
PpmExpanded | PpmExpandedIdentified | PpmTyped | PpmFlowGraph(_) => {
- let loader = &mut Loader::new(&sess);
let (krate, ast_map) = phase_2_configure_and_expand(&sess,
- loader,
krate,
&id);
(krate, Some(ast_map), true)
// For a library crate, this is always none
pub entry_fn: RefCell<Option<(NodeId, codemap::Span)>>,
pub entry_type: Cell<Option<config::EntryFnType>>,
- pub macro_registrar_fn: Cell<Option<ast::NodeId>>,
+ pub plugin_registrar_fn: Cell<Option<ast::NodeId>>,
pub default_sysroot: Option<Path>,
// The name of the root source file of the crate, in the local file system. The path is always
// expected to be absolute. `None` means that there is no source file.
// For a library crate, this is always none
entry_fn: RefCell::new(None),
entry_type: Cell::new(None),
- macro_registrar_fn: Cell::new(None),
+ plugin_registrar_fn: Cell::new(None),
default_sysroot: default_sysroot,
local_crate_source_file: local_crate_source_file,
working_dir: os::getcwd(),
("thread_local", Active),
("link_args", Active),
("phase", Active),
- ("macro_registrar", Active),
+ ("plugin_registrar", Active),
("log_syntax", Active),
("trace_macros", Active),
("concat_idents", Active),
}
ast::ItemFn(..) => {
- if attr::contains_name(i.attrs.as_slice(), "macro_registrar") {
- self.gate_feature("macro_registrar", i.span,
- "cross-crate macro exports are \
- experimental and possibly buggy");
+ if attr::contains_name(i.attrs.as_slice(), "plugin_registrar") {
+ self.gate_feature("plugin_registrar", i.span,
+ "compiler plugins are experimental and possibly buggy");
}
}
attr::mk_attr_outer(attr::mk_attr_id(), attr::mk_list_item(
InternedString::new("phase"),
vec!(
- attr::mk_word_item(InternedString::new("syntax")),
+ attr::mk_word_item(InternedString::new("plugin")),
attr::mk_word_item(InternedString::new("link")
))))),
vis: ast::Inherited,
use driver::session::Session;
use front::config;
use front::std_inject::with_version;
-use metadata::creader::Loader;
use std::cell::RefCell;
use std::slice;
fn generate_test_harness(sess: &Session, krate: 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(),
ExpansionConfig {
- loader: loader,
deriving_hash_type_parameter: false,
crate_id: from_str("test").unwrap(),
}),
extern crate syntax;
extern crate time;
+#[cfg(stage0)]
#[phase(syntax, link)]
extern crate log;
+#[cfg(not(stage0))]
+#[phase(plugin, link)]
+extern crate log;
+
pub mod middle {
pub mod def;
pub mod trans;
pub mod driver;
+pub mod plugin;
+
pub mod util {
pub mod common;
pub mod ppaux;
pub static tag_native_libraries_name: uint = 0x89;
pub static tag_native_libraries_kind: uint = 0x8a;
-pub static tag_macro_registrar_fn: uint = 0x8b;
+pub static tag_plugin_registrar_fn: uint = 0x8b;
pub static tag_exported_macros: uint = 0x8c;
pub static tag_macro_def: uint = 0x8d;
use metadata::decoder;
use metadata::loader;
use metadata::loader::CratePaths;
+use plugin::load::PluginMetadata;
use std::rc::Rc;
use std::collections::HashMap;
use syntax::attr::AttrMetaMethods;
use syntax::codemap::{Span};
use syntax::diagnostic::SpanHandler;
-use syntax::ext::base::{CrateLoader, MacroCrate};
use syntax::parse::token::InternedString;
use syntax::parse::token;
use syntax::crateid::CrateId;
}).collect()
}
-pub struct Loader<'a> {
+pub struct PluginMetadataReader<'a> {
env: Env<'a>,
}
-impl<'a> Loader<'a> {
- pub fn new(sess: &'a Session) -> Loader<'a> {
- Loader {
+impl<'a> PluginMetadataReader<'a> {
+ pub fn new(sess: &'a Session) -> PluginMetadataReader<'a> {
+ PluginMetadataReader {
env: Env {
sess: sess,
next_crate_num: sess.cstore.next_crate_num(),
}
}
}
-}
-impl<'a> CrateLoader for Loader<'a> {
- fn load_crate(&mut self, krate: &ast::ViewItem) -> MacroCrate {
+ pub fn read_plugin_metadata(&mut self, krate: &ast::ViewItem) -> PluginMetadata {
let info = extract_crate_info(&self.env, krate).unwrap();
let target_triple = self.env.sess.targ_cfg.target_strs.target_triple.as_slice();
let is_cross = target_triple != driver::host_triple();
load_ctxt.os = config::cfg_os_to_meta_os(self.env.sess.targ_cfg.os);
load_ctxt.filesearch = self.env.sess.target_filesearch();
let lib = load_ctxt.load_library_crate();
- if decoder::get_macro_registrar_fn(lib.metadata.as_slice()).is_some() {
- let message = format!("crate `{}` contains a macro_registrar fn but \
+ if decoder::get_plugin_registrar_fn(lib.metadata.as_slice()).is_some() {
+ let message = format!("crate `{}` contains a plugin_registrar fn but \
only a version for triple `{}` could be found (need {})",
info.ident, target_triple, driver::host_triple());
self.env.sess.span_err(krate.span, message.as_slice());
None => { load_ctxt.report_load_errs(); unreachable!() },
};
let macros = decoder::get_exported_macros(library.metadata.as_slice());
- let registrar = decoder::get_macro_registrar_fn(library.metadata.as_slice()).map(|id| {
+ let registrar = decoder::get_plugin_registrar_fn(library.metadata.as_slice()).map(|id| {
decoder::get_symbol(library.metadata.as_slice(), id).to_string()
});
- let mc = MacroCrate {
+ let pc = PluginMetadata {
lib: library.dylib.clone(),
macros: macros.move_iter().map(|x| x.to_string()).collect(),
registrar_symbol: registrar,
register_crate(&mut self.env, &None, info.ident.as_slice(),
&info.crate_id, krate.span, library);
}
- mc
+ pc
}
}
.map(|source| source.clone())
}
- pub fn dump_phase_syntax_crates(&self) {
- }
-
pub fn reset(&self) {
self.metas.borrow_mut().clear();
self.extern_mod_crate_map.borrow_mut().clear();
return result;
}
-pub fn get_macro_registrar_fn(data: &[u8]) -> Option<ast::NodeId> {
- reader::maybe_get_doc(ebml::Doc::new(data), tag_macro_registrar_fn)
+pub fn get_plugin_registrar_fn(data: &[u8]) -> Option<ast::NodeId> {
+ reader::maybe_get_doc(ebml::Doc::new(data), tag_plugin_registrar_fn)
.map(|doc| FromPrimitive::from_u32(reader::doc_as_u32(doc)).unwrap())
}
ebml_w.end_tag();
}
-fn encode_macro_registrar_fn(ecx: &EncodeContext, ebml_w: &mut Encoder) {
- match ecx.tcx.sess.macro_registrar_fn.get() {
- Some(id) => { ebml_w.wr_tagged_u32(tag_macro_registrar_fn, id); }
+fn encode_plugin_registrar_fn(ecx: &EncodeContext, ebml_w: &mut Encoder) {
+ match ecx.tcx.sess.plugin_registrar_fn.get() {
+ Some(id) => { ebml_w.wr_tagged_u32(tag_plugin_registrar_fn, id); }
None => {}
}
}
dep_bytes: u64,
lang_item_bytes: u64,
native_lib_bytes: u64,
- macro_registrar_fn_bytes: u64,
+ plugin_registrar_fn_bytes: u64,
macro_defs_bytes: u64,
impl_bytes: u64,
misc_bytes: u64,
dep_bytes: 0,
lang_item_bytes: 0,
native_lib_bytes: 0,
- macro_registrar_fn_bytes: 0,
+ plugin_registrar_fn_bytes: 0,
macro_defs_bytes: 0,
impl_bytes: 0,
misc_bytes: 0,
encode_native_libraries(&ecx, &mut ebml_w);
stats.native_lib_bytes = ebml_w.writer.tell().unwrap() - i;
- // Encode the macro registrar function
+ // Encode the plugin registrar function
i = ebml_w.writer.tell().unwrap();
- encode_macro_registrar_fn(&ecx, &mut ebml_w);
- stats.macro_registrar_fn_bytes = ebml_w.writer.tell().unwrap() - i;
+ encode_plugin_registrar_fn(&ecx, &mut ebml_w);
+ stats.plugin_registrar_fn_bytes = ebml_w.writer.tell().unwrap() - i;
// Encode macro definitions
i = ebml_w.writer.tell().unwrap();
}
println!("metadata stats:");
- println!(" attribute bytes: {}", stats.attr_bytes);
- println!(" dep bytes: {}", stats.dep_bytes);
- println!(" lang item bytes: {}", stats.lang_item_bytes);
- println!(" native bytes: {}", stats.native_lib_bytes);
- println!("macro registrar bytes: {}", stats.macro_registrar_fn_bytes);
- println!(" macro def bytes: {}", stats.macro_defs_bytes);
- println!(" impl bytes: {}", stats.impl_bytes);
- println!(" misc bytes: {}", stats.misc_bytes);
- println!(" item bytes: {}", stats.item_bytes);
- println!(" index bytes: {}", stats.index_bytes);
- println!(" zero bytes: {}", stats.zero_bytes);
- println!(" total bytes: {}", stats.total_bytes);
+ println!(" attribute bytes: {}", stats.attr_bytes);
+ println!(" dep bytes: {}", stats.dep_bytes);
+ println!(" lang item bytes: {}", stats.lang_item_bytes);
+ println!(" native bytes: {}", stats.native_lib_bytes);
+ println!("plugin registrar bytes: {}", stats.plugin_registrar_fn_bytes);
+ println!(" macro def bytes: {}", stats.macro_defs_bytes);
+ println!(" impl bytes: {}", stats.impl_bytes);
+ println!(" misc bytes: {}", stats.misc_bytes);
+ println!(" item bytes: {}", stats.item_bytes);
+ println!(" index bytes: {}", stats.index_bytes);
+ println!(" zero bytes: {}", stats.zero_bytes);
+ println!(" total bytes: {}", stats.total_bytes);
}
}
--- /dev/null
+// 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.
+
+//! Used by `rustc` when compiling a plugin crate.
+
+use syntax::ast;
+use syntax::attr;
+use syntax::codemap::Span;
+use syntax::diagnostic;
+use syntax::visit;
+use syntax::visit::Visitor;
+
+struct RegistrarFinder {
+ registrars: Vec<(ast::NodeId, Span)> ,
+}
+
+impl Visitor<()> for RegistrarFinder {
+ fn visit_item(&mut self, item: &ast::Item, _: ()) {
+ match item.node {
+ ast::ItemFn(..) => {
+ if attr::contains_name(item.attrs.as_slice(),
+ "plugin_registrar") {
+ self.registrars.push((item.id, item.span));
+ }
+ }
+ _ => {}
+ }
+
+ visit::walk_item(self, item, ());
+ }
+}
+
+/// Find the function marked with `#[plugin_registrar]`, if any.
+pub fn find_plugin_registrar(diagnostic: &diagnostic::SpanHandler,
+ krate: &ast::Crate) -> Option<ast::NodeId> {
+ let mut finder = RegistrarFinder { registrars: Vec::new() };
+ visit::walk_crate(&mut finder, krate, ());
+
+ match finder.registrars.len() {
+ 0 => None,
+ 1 => {
+ let (node_id, _) = finder.registrars.pop().unwrap();
+ Some(node_id)
+ },
+ _ => {
+ diagnostic.handler().err("multiple plugin registration functions found");
+ for &(_, span) in finder.registrars.iter() {
+ diagnostic.span_note(span, "one is here");
+ }
+ diagnostic.handler().abort_if_errors();
+ unreachable!();
+ }
+ }
+}
--- /dev/null
+// 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.
+
+//! 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;
+use std::unstable::dynamic_lib::DynamicLibrary;
+use syntax::ast;
+use syntax::attr;
+use syntax::visit;
+use syntax::visit::Visitor;
+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<String>,
+ /// Path to the shared library file.
+ pub lib: Option<Path>,
+ /// Symbol name of the plugin registrar function.
+ pub registrar_symbol: Option<String>,
+}
+
+/// 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<ExportedMacros>,
+ /// Registrars, as function pointers.
+ pub registrars: Vec<PluginRegistrarFun>,
+}
+
+struct PluginLoader<'a> {
+ sess: &'a Session,
+ reader: PluginMetadataReader<'a>,
+ plugins: Plugins,
+}
+
+impl<'a> PluginLoader<'a> {
+ fn new(sess: &'a Session) -> PluginLoader<'a> {
+ PluginLoader {
+ sess: sess,
+ reader: PluginMetadataReader::new(sess),
+ plugins: Plugins {
+ macros: vec!(),
+ registrars: vec!(),
+ },
+ }
+ }
+}
+
+/// 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, ());
+ loader.plugins
+}
+
+impl<'a> Visitor<()> for PluginLoader<'a> {
+ fn visit_view_item(&mut self, vi: &ast::ViewItem, _: ()) {
+ match vi.node {
+ ast::ViewItemExternCrate(name, _, _) => {
+ let mut plugin_phase = false;
+
+ for attr in vi.attrs.iter().filter(|a| a.check_name("phase")) {
+ let phases = attr.meta_item_list().unwrap_or(&[]);
+ if attr::contains_name(phases, "plugin") {
+ plugin_phase = true;
+ }
+ if attr::contains_name(phases, "syntax") {
+ plugin_phase = true;
+ self.sess.span_warn(attr.span,
+ "phase(syntax) is a deprecated synonym for phase(plugin)");
+ }
+ }
+
+ if !plugin_phase { return; }
+
+ let PluginMetadata { macros, lib, registrar_symbol } =
+ self.reader.read_plugin_metadata(vi);
+
+ self.plugins.macros.push(ExportedMacros {
+ crate_name: name,
+ macros: macros,
+ });
+
+ match (lib, registrar_symbol) {
+ (Some(lib), Some(symbol))
+ => self.dylink_registrar(vi, lib, symbol),
+ _ => (),
+ }
+ }
+ _ => (),
+ }
+ }
+}
+
+impl<'a> PluginLoader<'a> {
+ // Dynamically link a registrar function into the compiler process.
+ fn dylink_registrar(&mut self, vi: &ast::ViewItem, path: Path, symbol: String) {
+ // Make sure the path contains a / or the linker will search for it.
+ let path = os::make_absolute(&path);
+
+ 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) => self.sess.span_fatal(vi.span, err.as_slice())
+ };
+
+ unsafe {
+ let registrar: PluginRegistrarFun =
+ match lib.symbol(symbol.as_slice()) {
+ Ok(registrar) => registrar,
+ // again fatal if we can't register macros
+ Err(err) => self.sess.span_fatal(vi.span, err.as_slice())
+ };
+
+ self.plugins.registrars.push(registrar);
+
+ // Intentionally leak the dynamic library. We can't ever unload it
+ // since the library can make things that will live arbitrarily long
+ // (e.g. an @-box cycle or a task).
+ mem::forget(lib);
+
+ }
+ }
+}
--- /dev/null
+// 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.
+
+/*!
+ * 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;
--- /dev/null
+// 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.
+
+//! 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};
+use syntax::codemap::Span;
+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,
+
+ #[doc(hidden)]
+ pub syntax_exts: Vec<NamedSyntaxExtension>,
+}
+
+impl Registry {
+ #[doc(hidden)]
+ pub fn new(krate: &ast::Crate) -> Registry {
+ Registry {
+ krate_span: krate.span,
+ syntax_exts: vec!(),
+ }
+ }
+
+ /// 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)),
+ IdentTT(ext, _) => IdentTT(ext, Some(self.krate_span)),
+ ItemDecorator(ext) => ItemDecorator(ext),
+ ItemModifier(ext) => ItemModifier(ext),
+ }));
+ }
+
+ /// 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),
+ NormalTT(box BasicMacroExpander {
+ expander: expander,
+ span: None,
+ }, None));
+ }
+}
use rustc;
use rustc::{driver, middle};
-use rustc::metadata::creader::Loader;
use rustc::middle::privacy;
use rustc::middle::lint;
}
let krate = phase_1_parse_input(&sess, cfg, &input);
- let (krate, ast_map) = phase_2_configure_and_expand(&sess, &mut Loader::new(&sess),
- krate, &from_str("rustdoc").unwrap());
+ let (krate, ast_map) = phase_2_configure_and_expand(&sess, krate,
+ &from_str("rustdoc").unwrap());
let driver::driver::CrateAnalysis {
exported_items, public_items, ty_cx, ..
} = phase_3_run_analysis_passes(sess, &krate, ast_map);
extern crate debug;
extern crate getopts;
extern crate libc;
-#[phase(syntax, link)]
-extern crate log;
extern crate rustc;
extern crate serialize;
extern crate sync;
extern crate testing = "test";
extern crate time;
+#[cfg(stage0)]
+#[phase(syntax, link)]
+extern crate log;
+
+#[cfg(not(stage0))]
+#[phase(plugin, link)]
+extern crate log;
+
use std::io;
use std::io::{File, MemWriter};
use std::str;
use rustc::driver::config;
use rustc::driver::driver;
use rustc::driver::session;
-use rustc::metadata::creader::Loader;
use syntax::ast;
use syntax::codemap::{CodeMap, dummy_spanned};
use syntax::diagnostic;
@dummy_spanned(ast::MetaWord(cfg_))
}));
let krate = driver::phase_1_parse_input(&sess, cfg, &input);
- let (krate, _) = driver::phase_2_configure_and_expand(&sess, &mut Loader::new(&sess), krate,
+ let (krate, _) = driver::phase_2_configure_and_expand(&sess, krate,
&from_str("rustdoc-test").unwrap());
let ctx = @core::DocContext {
#![no_std]
#![experimental]
+#[cfg(stage0)]
#[phase(syntax, link)]
extern crate core;
+
+#[cfg(not(stage0))]
+#[phase(plugin, link)]
+extern crate core;
+
extern crate alloc;
extern crate libc;
extern crate collections;
#[cfg(test)] extern crate realrustrt = "rustrt";
#[cfg(test)] extern crate test;
#[cfg(test)] extern crate native;
-#[cfg(test)] #[phase(syntax, link)] extern crate std;
+
+#[cfg(test, stage0)] #[phase(syntax, link)] extern crate std;
+#[cfg(test, not(stage0))] #[phase(plugin, link)] extern crate std;
pub use self::util::{Stdio, Stdout, Stderr};
pub use self::unwind::{begin_unwind, begin_unwind_fmt};
// test harness access
#[cfg(test)]
extern crate test;
+
+#[cfg(stage0)]
#[phase(syntax, link)]
extern crate log;
+#[cfg(not(stage0))]
+#[phase(plugin, link)]
+extern crate log;
+
pub use self::serialize::{Decoder, Encoder, Decodable, Encodable,
DecoderHelpers, EncoderHelpers};
#[cfg(test)] extern crate native;
#[cfg(test)] extern crate green;
#[cfg(test)] extern crate debug;
-#[cfg(test)] #[phase(syntax, link)] extern crate log;
+#[cfg(test, stage0)] #[phase(syntax, link)] extern crate log;
+#[cfg(test, not(stage0))] #[phase(plugin, link)] extern crate log;
extern crate alloc;
extern crate core;
#![deny(missing_doc)]
-#[cfg(test)]
+#[cfg(test, stage0)]
#[phase(syntax, link)] extern crate log;
+#[cfg(test, not(stage0))]
+#[phase(plugin, link)] extern crate log;
+
extern crate alloc;
pub use comm::{DuplexStream, duplex};
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`).
IdentTT(Box<IdentMacroExpander:'static>, Option<Span>),
}
+pub type NamedSyntaxExtension = (Name, SyntaxExtension);
+
pub struct BlockInfo {
// should macros escape from this scope?
pub macros_escape: bool,
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.
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,
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,
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
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?
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)
}
}
}
-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 {
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;
use attr;
use codemap;
use codemap::Spanned;
- use ext::base::{CrateLoader, MacroCrate};
use ext::mtwt;
use parse;
use parse::token;
}
}
- 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.
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
"<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
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 (){
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 {
+++ /dev/null
-// 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!();
- }
- }
-}
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;
pub mod asm;
pub mod base;
pub mod expand;
- pub mod registrar;
pub mod quote;
#![deny(missing_doc)]
-#[phase(syntax, link)] extern crate log;
+#[cfg(stage0)] #[phase(syntax, link)] extern crate log;
+#[cfg(not(stage0))] #[phase(plugin, link)] extern crate log;
pub use terminfo::TerminfoTerminal;
#[cfg(windows)]
#![deny(deprecated_owned_vector)]
#[cfg(test)] extern crate debug;
-#[cfg(test)] #[phase(syntax, link)] extern crate log;
+
+#[cfg(test, stage0)] #[phase(syntax, link)] extern crate log;
+#[cfg(test, not(stage0))] #[phase(plugin, link)] extern crate log;
extern crate serialize;
extern crate libc;
#![crate_type = "rlib"]
#![feature(phase)]
-#[phase(syntax)] extern crate t1 = "issue-13560-1";
-#[phase(syntax, link)] extern crate t2 = "issue-13560-2";
+#[phase(plugin)] extern crate t1 = "issue-13560-1";
+#[phase(plugin, link)] extern crate t2 = "issue-13560-2";
// except according to those terms.
#![feature(phase)]
-#[phase(syntax, link)] extern crate log;
+#[phase(plugin, link)] extern crate log;
extern crate debug;
pub fn foo<T>() {
+++ /dev/null
-// Copyright 2014 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.
-
-// force-host
-
-#![feature(macro_registrar)]
-
-extern crate syntax;
-
-use std::any::Any;
-use syntax::ast::Name;
-use syntax::ext::base::SyntaxExtension;
-
-struct Foo {
- foo: int
-}
-
-impl Drop for Foo {
- fn drop(&mut self) {}
-}
-
-#[macro_registrar]
-pub fn registrar(_: |Name, SyntaxExtension|) {
- local_data_key!(foo: Box<Any:Send>);
- foo.replace(Some(box Foo { foo: 10 } as Box<Any:Send>));
-}
-
// force-host
-#![feature(globs, macro_registrar, macro_rules, quote, managed_boxes)]
+#![feature(globs, plugin_registrar, macro_rules, quote, managed_boxes)]
extern crate syntax;
+extern crate rustc;
-use syntax::ast::{Name, TokenTree, Item, MetaItem};
+use syntax::ast::{TokenTree, Item, MetaItem};
use syntax::codemap::Span;
use syntax::ext::base::*;
use syntax::parse::token;
+use rustc::plugin::Registry;
#[macro_export]
macro_rules! exported_macro (() => (2))
macro_rules! unexported_macro (() => (3))
-#[macro_registrar]
-pub fn macro_registrar(register: |Name, SyntaxExtension|) {
- register(token::intern("make_a_1"),
- NormalTT(box BasicMacroExpander {
- expander: expand_make_a_1,
- span: None,
- },
- None));
- register(token::intern("into_foo"), ItemModifier(expand_into_foo));
+#[plugin_registrar]
+pub fn plugin_registrar(reg: &mut Registry) {
+ reg.register_macro("make_a_1", expand_make_a_1);
+ reg.register_syntax_extension(
+ token::intern("into_foo"),
+ ItemModifier(expand_into_foo));
}
fn expand_make_a_1(cx: &mut ExtCtxt, sp: Span, tts: &[TokenTree])
--- /dev/null
+// Copyright 2014 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.
+
+// force-host
+
+#![feature(plugin_registrar)]
+
+extern crate rustc;
+
+use std::any::Any;
+use rustc::plugin::Registry;
+
+struct Foo {
+ foo: int
+}
+
+impl Drop for Foo {
+ fn drop(&mut self) {}
+}
+
+#[plugin_registrar]
+pub fn registrar(_: &mut Registry) {
+ local_data_key!(foo: Box<Any:Send>);
+ foo.replace(Some(box Foo { foo: 10 } as Box<Any:Send>));
+}
+
// no-prefer-dynamic
#![crate_type = "dylib"]
-#![feature(macro_registrar, quote, globs)]
+#![feature(plugin_registrar, quote, globs)]
extern crate other = "syntax-extension-with-dll-deps-1";
extern crate syntax;
+extern crate rustc;
-use syntax::ast::{Name, TokenTree, Item, MetaItem};
+use syntax::ast::{TokenTree, Item, MetaItem};
use syntax::codemap::Span;
use syntax::ext::base::*;
-use syntax::parse::token;
+use rustc::plugin::Registry;
-#[macro_registrar]
-pub fn macro_registrar(register: |Name, SyntaxExtension|) {
- register(token::intern("foo"),
- NormalTT(box BasicMacroExpander {
- expander: expand_foo,
- span: None,
- },
- None));
+#[plugin_registrar]
+pub fn plugin_registrar(reg: &mut Registry) {
+ reg.register_macro("foo", expand_foo);
}
fn expand_foo(cx: &mut ExtCtxt, sp: Span, tts: &[TokenTree])
#![feature(phase)]
#![crate_type = "rlib"]
-#[phase(syntax, link)]
+#[phase(plugin, link)]
extern crate core;
struct A;
// no-pretty-expanded
#![feature(phase)]
-#[phase(syntax)] extern crate green;
+#[phase(plugin)] extern crate green;
use std::string::String;
use std::fmt;
// OF THE POSSIBILITY OF SUCH DAMAGE.
#![feature(phase)]
-#[phase(syntax)] extern crate green;
+#[phase(plugin)] extern crate green;
extern crate sync;
use sync::Arc;
#![feature(macro_rules, phase)]
extern crate regex;
-#[phase(syntax)]extern crate regex_macros;
+#[phase(plugin)]extern crate regex_macros;
extern crate sync;
use std::io;
#![feature(phase)]
#![allow(non_snake_case_functions)]
-#[phase(syntax)] extern crate green;
+#[phase(plugin)] extern crate green;
extern crate sync;
use std::from_str::FromStr;
// except according to those terms.
#![feature(phase)]
-#[phase(syntax)] extern crate green;
+#[phase(plugin)] extern crate green;
green_start!(main)
fn start(n_tasks: int, token: int) {
// aux-build:macro_crate_test.rs
// ignore-stage1
-#[phase(syntax)]
+#[phase(plugin)]
//~^ ERROR compile time crate loading is experimental and possibly buggy
extern crate macro_crate_test;
#![feature(phase)]
-#[phase(syntax)]
+#[phase(plugin)]
extern crate macro_crate_test;
fn main() {
#![feature(phase)]
-#[phase(syntax)]
+#[phase(plugin)]
extern crate doesnt_exist; //~ ERROR can't find crate
fn main() {}
#![feature(phase)]
-#[phase(syntax)]
+#[phase(plugin)]
extern crate macro_crate_test;
fn main() {
#![feature(phase)]
-#[phase(syntax)]
+#[phase(plugin)]
extern crate fourcc;
fn main() {
#![feature(phase)]
-#[phase(syntax)]
+#[phase(plugin)]
extern crate fourcc;
fn main() {
#![feature(phase)]
-#[phase(syntax)]
+#[phase(plugin)]
extern crate fourcc;
fn main() {
#![feature(phase)]
-#[phase(syntax)]
+#[phase(plugin)]
extern crate fourcc;
fn main() {
#![feature(phase)]
-#[phase(syntax)]
+#[phase(plugin)]
extern crate fourcc;
fn main() {
#![feature(phase)]
-#[phase(syntax)]
+#[phase(plugin)]
extern crate hexfloat;
fn main() {
#![feature(phase)]
-#[phase(syntax)]
+#[phase(plugin)]
extern crate hexfloat;
fn main() {
#![feature(phase)]
extern crate regex;
-#[phase(syntax)] extern crate regex_macros;
+#[phase(plugin)] extern crate regex_macros;
// Tests to make sure that `regex!` will produce a compile error when given
// an invalid regular expression.
#![feature(phase)]
extern crate regex;
-#[phase(syntax)] extern crate regex_macros;
+#[phase(plugin)] extern crate regex_macros;
#[deny(unused_variable)]
#[deny(dead_code)]
#![feature(phase)]
extern crate regex;
-#[phase(syntax)] extern crate regex_macros;
+#[phase(plugin)] extern crate regex_macros;
#[deny(unused_variable)]
#[deny(dead_code)]
+++ /dev/null
-// Copyright 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.
-
-// the registration function isn't typechecked yet
-#[macro_registrar]
-pub fn registrar() {} //~ ERROR cross-crate macro exports are experimental
-
-fn main() {}
--- /dev/null
+// Copyright 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.
+
+// the registration function isn't typechecked yet
+#[plugin_registrar]
+pub fn registrar() {} //~ ERROR compiler plugins are experimental
+
+fn main() {}
+++ /dev/null
-// Copyright 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.
-
-// error-pattern: multiple macro registration functions found
-
-#![feature(macro_registrar)]
-
-// the registration function isn't typechecked yet
-#[macro_registrar]
-pub fn one() {}
-
-#[macro_registrar]
-pub fn two() {}
-
-fn main() {}
--- /dev/null
+// Copyright 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.
+
+// error-pattern: multiple plugin registration functions found
+
+#![feature(plugin_registrar)]
+
+// the registration function isn't typechecked yet
+#[plugin_registrar]
+pub fn one() {}
+
+#[plugin_registrar]
+pub fn two() {}
+
+fn main() {}
// error-pattern:whatever
#![feature(phase)]
-#[phase(syntax, link)] extern crate log;
+#[phase(plugin, link)] extern crate log;
use std::os;
fn main() {
// error-pattern:whatever
#![feature(phase)]
-#[phase(syntax, link)] extern crate log;
+#[phase(plugin, link)] extern crate log;
use std::os;
use std::task;
// error-pattern:whatever
#![feature(phase)]
-#[phase(syntax, link)] extern crate log;
+#[phase(plugin, link)] extern crate log;
use std::os;
fn main() {
#![feature(phase)]
extern crate lib;
-#[phase(syntax)] extern crate fourcc;
+#[phase(plugin)] extern crate fourcc;
fn main() {
fourcc!("1234");
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-// aux-build:macro_crate_outlive_expansion_phase.rs
+// aux-build:plugin_crate_outlive_expansion_phase.rs
// ignore-stage1
#![feature(phase)]
-#[phase(syntax)]
-extern crate macro_crate_outlive_expansion_phase;
+#[phase(plugin)]
+extern crate plugin_crate_outlive_expansion_phase;
pub fn main() {}
#![feature(phase)]
-#[phase(syntax)]
+#[phase(plugin)]
extern crate macro_crate_test;
#[into_foo]
#![feature(phase)]
-#[phase(syntax, link)]
+#[phase(plugin, link)]
extern crate macro_crate_test;
fn main() {
#![feature(phase)]
-#[phase(syntax)]
+#[phase(plugin)]
extern crate fourcc;
static static_val: u32 = fourcc!("foo ");
// ignore-pretty
#![feature(phase)]
-#[phase(syntax)]
+#[phase(plugin)]
extern crate hexfloat;
pub fn main() {
#![feature(phase)]
-#[phase(syntax)]
+#[phase(plugin)]
extern crate extension = "syntax-extension-with-dll-deps-2";
fn main() {
#![feature(phase)]
-#[phase(syntax, link)]
+#[phase(plugin, link)]
extern crate log;
extern crate native;
// exec-env:RUST_LOG=conditional-debug-macro-off=4
#![feature(phase)]
-#[phase(syntax, link)]
+#[phase(plugin, link)]
extern crate log;
extern crate debug;
--- /dev/null
+// Copyright 2013-2014 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.
+
+#![feature(phase)]
+
+//~ WARNING phase(syntax) is a deprecated synonym for phase(plugin)
+#[phase(syntax, link)]
+extern crate log;
+
+fn main() {
+ debug!("foo");
+}
#![feature(phase)]
-#[phase(syntax, link)]
+#[phase(plugin, link)]
extern crate green;
extern crate native;
// exec-env:RUST_LOG=logging-enabled-debug=debug
#![feature(phase)]
-#[phase(syntax, link)]
+#[phase(plugin, link)]
extern crate log;
pub fn main() {
// exec-env:RUST_LOG=logging-enabled=info
#![feature(phase)]
-#[phase(syntax, link)]
+#[phase(plugin, link)]
extern crate log;
pub fn main() {
#![feature(phase)]
-#[phase(syntax, link)]
+#[phase(plugin, link)]
extern crate log;
use std::io::Command;
#![feature(phase)]
-#[phase(syntax)]
+#[phase(plugin)]
extern crate macro_crate_def_only;
pub fn main() {
#![feature(phase)]
-#[phase(syntax)]
+#[phase(plugin)]
extern crate macro_export_inner_module;
pub fn main() {
#![feature(phase)]
-#[phase(syntax)]
+#[phase(plugin)]
use std::mem;
fn main() {}
// exec-env:RUST_LOG=debug
#![feature(phase)]
-#[phase(syntax, link)]
+#[phase(plugin, link)]
extern crate log;
extern crate libc;
extern crate green;