Skip to content

Commit 15e7a7d

Browse files
sfacklernathanielherman
authored andcommitted
Move macro_rules! macros to libstd
They all have to go into a single module at the moment unfortunately. Ideally, the logging macros would live in std::logging, condition! would live in std::condition, format! in std::fmt, etc. However, this introduces cyclic dependencies between those modules and the macros they use which the current expansion system can't deal with. We may be able to get around this by changing the expansion phase to a two-pass system but that's for a later PR. Closes rust-lang#2247 cc rust-lang#11763
1 parent dfee06e commit 15e7a7d

File tree

6 files changed

+247
-271
lines changed

6 files changed

+247
-271
lines changed

Diff for: src/librustc/driver/driver.rs

+5-6
Original file line numberDiff line numberDiff line change
@@ -176,17 +176,16 @@ pub fn phase_2_configure_and_expand(sess: Session,
176176
time(time_passes, "gated feature checking", (), |_|
177177
front::feature_gate::check_crate(sess, &crate));
178178

179+
crate = time(time_passes, "crate injection", crate, |crate|
180+
front::std_inject::maybe_inject_crates_ref(sess, crate));
181+
179182
// strip before expansion to allow macros to depend on
180183
// configuration variables e.g/ in
181184
//
182185
// #[macro_escape] #[cfg(foo)]
183186
// mod bar { macro_rules! baz!(() => {{}}) }
184187
//
185188
// baz! should not use this definition unless foo is enabled.
186-
crate = time(time_passes, "std macros injection", crate, |crate|
187-
syntax::ext::expand::inject_std_macros(sess.parse_sess,
188-
cfg.clone(),
189-
crate));
190189

191190
crate = time(time_passes, "configuration 1", crate, |crate|
192191
front::config::strip_unconfigured_items(crate));
@@ -207,8 +206,8 @@ pub fn phase_2_configure_and_expand(sess: Session,
207206
crate = time(time_passes, "maybe building test harness", crate, |crate|
208207
front::test::modify_for_testing(sess, crate));
209208

210-
crate = time(time_passes, "std injection", crate, |crate|
211-
front::std_inject::maybe_inject_libstd_ref(sess, crate));
209+
crate = time(time_passes, "prelude injection", crate, |crate|
210+
front::std_inject::maybe_inject_prelude(sess, crate));
212211

213212
time(time_passes, "assinging node ids and indexing ast", crate, |crate|
214213
front::assign_node_ids_and_map::assign_node_ids_and_map(sess, crate))

Diff for: src/librustc/front/std_inject.rs

+46-20
Original file line numberDiff line numberDiff line change
@@ -23,10 +23,18 @@ use syntax::util::small_vector::SmallVector;
2323

2424
pub static VERSION: &'static str = "0.10-pre";
2525

26-
pub fn maybe_inject_libstd_ref(sess: Session, crate: ast::Crate)
26+
pub fn maybe_inject_crates_ref(sess: Session, crate: ast::Crate)
2727
-> ast::Crate {
2828
if use_std(&crate) {
29-
inject_libstd_ref(sess, crate)
29+
inject_crates_ref(sess, crate)
30+
} else {
31+
crate
32+
}
33+
}
34+
35+
pub fn maybe_inject_prelude(sess: Session, crate: ast::Crate) -> ast::Crate {
36+
if use_std(&crate) {
37+
inject_prelude(sess, crate)
3038
} else {
3139
crate
3240
}
@@ -44,13 +52,6 @@ fn no_prelude(attrs: &[ast::Attribute]) -> bool {
4452
attr::contains_name(attrs, "no_implicit_prelude")
4553
}
4654

47-
fn spanned<T>(x: T) -> codemap::Spanned<T> {
48-
codemap::Spanned {
49-
node: x,
50-
span: DUMMY_SP,
51-
}
52-
}
53-
5455
struct StandardLibraryInjector {
5556
sess: Session,
5657
}
@@ -71,7 +72,11 @@ impl fold::Folder for StandardLibraryInjector {
7172
node: ast::ViewItemExternMod(self.sess.ident_of("std"),
7273
with_version("std"),
7374
ast::DUMMY_NODE_ID),
74-
attrs: ~[],
75+
attrs: ~[
76+
attr::mk_attr(attr::mk_list_item(@"phase",
77+
~[attr::mk_word_item(@"syntax"),
78+
attr::mk_word_item(@"link")]))
79+
],
7580
vis: ast::Inherited,
7681
span: DUMMY_SP
7782
}];
@@ -96,22 +101,43 @@ impl fold::Folder for StandardLibraryInjector {
96101
}
97102

98103
vis.push_all(crate.module.view_items);
99-
let mut new_module = ast::Mod {
104+
let new_module = ast::Mod {
100105
view_items: vis,
101106
..crate.module.clone()
102107
};
103108

104-
if !no_prelude(crate.attrs) {
105-
// only add `use std::prelude::*;` if there wasn't a
106-
// `#[no_implicit_prelude];` at the crate level.
107-
new_module = self.fold_mod(&new_module);
108-
}
109-
110109
ast::Crate {
111110
module: new_module,
112111
..crate
113112
}
114113
}
114+
}
115+
116+
fn inject_crates_ref(sess: Session, crate: ast::Crate) -> ast::Crate {
117+
let mut fold = StandardLibraryInjector {
118+
sess: sess,
119+
};
120+
fold.fold_crate(crate)
121+
}
122+
123+
struct PreludeInjector {
124+
sess: Session,
125+
}
126+
127+
128+
impl fold::Folder for PreludeInjector {
129+
fn fold_crate(&mut self, crate: ast::Crate) -> ast::Crate {
130+
if !no_prelude(crate.attrs) {
131+
// only add `use std::prelude::*;` if there wasn't a
132+
// `#[no_implicit_prelude];` at the crate level.
133+
ast::Crate {
134+
module: self.fold_mod(&crate.module),
135+
..crate
136+
}
137+
} else {
138+
crate
139+
}
140+
}
115141

116142
fn fold_item(&mut self, item: @ast::Item) -> SmallVector<@ast::Item> {
117143
if !no_prelude(item.attrs) {
@@ -142,7 +168,7 @@ impl fold::Folder for StandardLibraryInjector {
142168
],
143169
};
144170

145-
let vp = @spanned(ast::ViewPathGlob(prelude_path, ast::DUMMY_NODE_ID));
171+
let vp = @codemap::dummy_spanned(ast::ViewPathGlob(prelude_path, ast::DUMMY_NODE_ID));
146172
let vi2 = ast::ViewItem {
147173
node: ast::ViewItemUse(~[vp]),
148174
attrs: ~[],
@@ -161,8 +187,8 @@ impl fold::Folder for StandardLibraryInjector {
161187
}
162188
}
163189

164-
fn inject_libstd_ref(sess: Session, crate: ast::Crate) -> ast::Crate {
165-
let mut fold = StandardLibraryInjector {
190+
fn inject_prelude(sess: Session, crate: ast::Crate) -> ast::Crate {
191+
let mut fold = PreludeInjector {
166192
sess: sess,
167193
};
168194
fold.fold_crate(crate)

Diff for: src/libstd/lib.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT
1+
// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT
22
// file at the top-level directory of this distribution and at
33
// http://rust-lang.org/COPYRIGHT.
44
//
@@ -76,6 +76,8 @@
7676
#[cfg(test)] pub use ops = realstd::ops;
7777
#[cfg(test)] pub use cmp = realstd::cmp;
7878

79+
mod macros;
80+
7981
mod rtdeps;
8082

8183
/* The Prelude. */

Diff for: src/libstd/macros.rs

+192
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,192 @@
1+
// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
#[macro_escape];
11+
12+
#[macro_export]
13+
macro_rules! ignore (($($x:tt)*) => (()))
14+
15+
#[macro_export]
16+
macro_rules! log(
17+
($lvl:expr, $($arg:tt)+) => ({
18+
let lvl = $lvl;
19+
if lvl <= __log_level() {
20+
format_args!(|args| {
21+
::std::logging::log(lvl, args)
22+
}, $($arg)+)
23+
}
24+
})
25+
)
26+
#[macro_export]
27+
macro_rules! error( ($($arg:tt)*) => (log!(1u32, $($arg)*)) )
28+
#[macro_export]
29+
macro_rules! warn ( ($($arg:tt)*) => (log!(2u32, $($arg)*)) )
30+
#[macro_export]
31+
macro_rules! info ( ($($arg:tt)*) => (log!(3u32, $($arg)*)) )
32+
#[macro_export]
33+
macro_rules! debug( ($($arg:tt)*) => (
34+
if cfg!(not(ndebug)) { log!(4u32, $($arg)*) }
35+
))
36+
37+
#[macro_export]
38+
macro_rules! log_enabled(
39+
($lvl:expr) => ( {
40+
let lvl = $lvl;
41+
lvl <= __log_level() && (lvl != 4 || cfg!(not(ndebug)))
42+
} )
43+
)
44+
45+
#[macro_export]
46+
macro_rules! fail(
47+
() => (
48+
fail!("explicit failure")
49+
);
50+
($msg:expr) => (
51+
::std::rt::begin_unwind($msg, file!(), line!())
52+
);
53+
($fmt:expr, $($arg:tt)*) => (
54+
::std::rt::begin_unwind(format!($fmt, $($arg)*), file!(), line!())
55+
)
56+
)
57+
58+
#[macro_export]
59+
macro_rules! assert(
60+
($cond:expr) => {
61+
if !$cond {
62+
fail!("assertion failed: {:s}", stringify!($cond))
63+
}
64+
};
65+
($cond:expr, $msg:expr) => {
66+
if !$cond {
67+
fail!($msg)
68+
}
69+
};
70+
($cond:expr, $( $arg:expr ),+) => {
71+
if !$cond {
72+
fail!( $($arg),+ )
73+
}
74+
}
75+
)
76+
77+
#[macro_export]
78+
macro_rules! assert_eq (
79+
($given:expr , $expected:expr) => (
80+
{
81+
let given_val = &($given);
82+
let expected_val = &($expected);
83+
// check both directions of equality....
84+
if !((*given_val == *expected_val) &&
85+
(*expected_val == *given_val)) {
86+
fail!("assertion failed: `(left == right) && (right == left)` \
87+
(left: `{:?}`, right: `{:?}`)", *given_val, *expected_val)
88+
}
89+
}
90+
)
91+
)
92+
93+
/// A utility macro for indicating unreachable code. It will fail if
94+
/// executed. This is occasionally useful to put after loops that never
95+
/// terminate normally, but instead directly return from a function.
96+
///
97+
/// # Example
98+
///
99+
/// ```rust
100+
/// fn choose_weighted_item(v: &[Item]) -> Item {
101+
/// assert!(!v.is_empty());
102+
/// let mut so_far = 0u;
103+
/// for item in v.iter() {
104+
/// so_far += item.weight;
105+
/// if so_far > 100 {
106+
/// return item;
107+
/// }
108+
/// }
109+
/// // The above loop always returns, so we must hint to the
110+
/// // type checker that it isn't possible to get down here
111+
/// unreachable!();
112+
/// }
113+
/// ```
114+
#[macro_export]
115+
macro_rules! unreachable (() => (
116+
fail!("internal error: entered unreachable code");
117+
))
118+
119+
#[macro_export]
120+
macro_rules! condition (
121+
122+
{ pub $c:ident: $input:ty -> $out:ty; } => {
123+
124+
pub mod $c {
125+
#[allow(unused_imports)];
126+
#[allow(non_uppercase_statics)];
127+
#[allow(missing_doc)];
128+
129+
use super::*;
130+
131+
local_data_key!(key: @::std::condition::Handler<$input, $out>)
132+
133+
pub static cond :
134+
::std::condition::Condition<$input,$out> =
135+
::std::condition::Condition {
136+
name: stringify!($c),
137+
key: key
138+
};
139+
}
140+
};
141+
142+
{ $c:ident: $input:ty -> $out:ty; } => {
143+
144+
mod $c {
145+
#[allow(unused_imports)];
146+
#[allow(non_uppercase_statics)];
147+
#[allow(dead_code)];
148+
149+
use super::*;
150+
151+
local_data_key!(key: @::std::condition::Handler<$input, $out>)
152+
153+
pub static cond :
154+
::std::condition::Condition<$input,$out> =
155+
::std::condition::Condition {
156+
name: stringify!($c),
157+
key: key
158+
};
159+
}
160+
}
161+
)
162+
163+
#[macro_export]
164+
macro_rules! format(($($arg:tt)*) => (
165+
format_args!(::std::fmt::format, $($arg)*)
166+
))
167+
#[macro_export]
168+
macro_rules! write(($dst:expr, $($arg:tt)*) => (
169+
format_args!(|args| { ::std::fmt::write($dst, args) }, $($arg)*)
170+
))
171+
#[macro_export]
172+
macro_rules! writeln(($dst:expr, $($arg:tt)*) => (
173+
format_args!(|args| { ::std::fmt::writeln($dst, args) }, $($arg)*)
174+
))
175+
#[macro_export]
176+
macro_rules! print (
177+
($($arg:tt)*) => (format_args!(::std::io::stdio::print_args, $($arg)*))
178+
)
179+
#[macro_export]
180+
macro_rules! println (
181+
($($arg:tt)*) => (format_args!(::std::io::stdio::println_args, $($arg)*))
182+
)
183+
184+
#[macro_export]
185+
macro_rules! local_data_key (
186+
($name:ident: $ty:ty) => (
187+
static $name: ::std::local_data::Key<$ty> = &::std::local_data::Key;
188+
);
189+
(pub $name:ident: $ty:ty) => (
190+
pub static $name: ::std::local_data::Key<$ty> = &::std::local_data::Key;
191+
)
192+
)

0 commit comments

Comments
 (0)