1 // Copyright 2012 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
11 use driver::session;
12 use driver::session::Session;
13
14 use syntax::ast;
15 use syntax::attr;
16 use syntax::codemap::DUMMY_SP;
17 use syntax::codemap;
18 use syntax::fold::Folder;
19 use syntax::fold;
20 use syntax::owned_slice::OwnedSlice;
21 use syntax::parse::token::InternedString;
22 use syntax::parse::token;
23 use syntax::util::small_vector::SmallVector;
24
25 pub static VERSION: &'static str = "0.11-pre";
26
27 pub fn maybe_inject_crates_ref(sess: &Session, krate: ast::Crate)
28 -> ast::Crate {
29 if use_std(&krate) {
30 inject_crates_ref(sess, krate)
31 } else {
32 krate
33 }
34 }
35
36 pub fn maybe_inject_prelude(sess: &Session, krate: ast::Crate) -> ast::Crate {
37 if use_std(&krate) {
38 inject_prelude(sess, krate)
39 } else {
40 krate
41 }
42 }
43
44 fn use_std(krate: &ast::Crate) -> bool {
45 !attr::contains_name(krate.attrs.as_slice(), "no_std")
46 }
47
48 fn use_start(krate: &ast::Crate) -> bool {
49 !attr::contains_name(krate.attrs.as_slice(), "no_start")
50 }
51
52 fn no_prelude(attrs: &[ast::Attribute]) -> bool {
53 attr::contains_name(attrs, "no_implicit_prelude")
54 }
55
56 struct StandardLibraryInjector<'a> {
57 sess: &'a Session,
58 }
59
60 pub fn with_version(krate: &str) -> Option<(InternedString, ast::StrStyle)> {
61 match option_env!("CFG_DISABLE_INJECT_STD_VERSION") {
62 Some("1") => None,
63 _ => {
64 Some((token::intern_and_get_ident(format!("{}\\#{}",
65 krate,
66 VERSION)),
67 ast::CookedStr))
68 }
69 }
70 }
71
72 impl<'a> fold::Folder for StandardLibraryInjector<'a> {
73 fn fold_crate(&mut self, krate: ast::Crate) -> ast::Crate {
74 let mut vis = vec!(ast::ViewItem {
75 node: ast::ViewItemExternCrate(token::str_to_ident("std"),
76 with_version("std"),
77 ast::DUMMY_NODE_ID),
78 attrs: vec!(
79 attr::mk_attr(attr::mk_list_item(
80 InternedString::new("phase"),
81 vec!(
82 attr::mk_word_item(InternedString::new("syntax")),
83 attr::mk_word_item(InternedString::new("link")
84 ))))),
85 vis: ast::Inherited,
86 span: DUMMY_SP
87 });
88
89 let any_exe = self.sess.crate_types.borrow().iter().any(|ty| {
90 *ty == session::CrateTypeExecutable
91 });
92 if use_start(&krate) && any_exe {
93 vis.push(ast::ViewItem {
94 node: ast::ViewItemExternCrate(token::str_to_ident("native"),
95 with_version("native"),
96 ast::DUMMY_NODE_ID),
97 attrs: Vec::new(),
98 vis: ast::Inherited,
99 span: DUMMY_SP
100 });
101 }
102
103 vis.push_all_move(krate.module.view_items.clone());
104 let new_module = ast::Mod {
105 view_items: vis,
106 ..krate.module.clone()
107 };
108
109 ast::Crate {
110 module: new_module,
111 ..krate
112 }
113 }
114 }
115
116 fn inject_crates_ref(sess: &Session, krate: ast::Crate) -> ast::Crate {
117 let mut fold = StandardLibraryInjector {
118 sess: sess,
119 };
120 fold.fold_crate(krate)
121 }
122
123 struct PreludeInjector<'a> {
124 sess: &'a Session,
125 }
126
127
128 impl<'a> fold::Folder for PreludeInjector<'a> {
129 fn fold_crate(&mut self, krate: ast::Crate) -> ast::Crate {
130 if !no_prelude(krate.attrs.as_slice()) {
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(&krate.module),
135 ..krate
136 }
137 } else {
138 krate
139 }
140 }
141
142 fn fold_item(&mut self, item: @ast::Item) -> SmallVector<@ast::Item> {
143 if !no_prelude(item.attrs.as_slice()) {
144 // only recur if there wasn't `#![no_implicit_prelude]`
145 // on this item, i.e. this means that the prelude is not
146 // implicitly imported though the whole subtree
147 fold::noop_fold_item(item, self)
148 } else {
149 SmallVector::one(item)
150 }
151 }
152
153 fn fold_mod(&mut self, module: &ast::Mod) -> ast::Mod {
154 let prelude_path = ast::Path {
155 span: DUMMY_SP,
156 global: false,
157 segments: vec!(
158 ast::PathSegment {
159 identifier: token::str_to_ident("std"),
160 lifetimes: Vec::new(),
161 types: OwnedSlice::empty(),
162 },
163 ast::PathSegment {
164 identifier: token::str_to_ident("prelude"),
165 lifetimes: Vec::new(),
166 types: OwnedSlice::empty(),
167 }),
168 };
169
170 let vp = @codemap::dummy_spanned(ast::ViewPathGlob(prelude_path, ast::DUMMY_NODE_ID));
171 let vi2 = ast::ViewItem {
172 node: ast::ViewItemUse(vp),
173 attrs: Vec::new(),
174 vis: ast::Inherited,
175 span: DUMMY_SP,
176 };
177
178 let vis = (vec!(vi2)).append(module.view_items.as_slice());
179
180 // FIXME #2543: Bad copy.
181 let new_module = ast::Mod {
182 view_items: vis,
183 ..(*module).clone()
184 };
185 fold::noop_fold_mod(&new_module, self)
186 }
187 }
188
189 fn inject_prelude(sess: &Session, krate: ast::Crate) -> ast::Crate {
190 let mut fold = PreludeInjector {
191 sess: sess,
192 };
193 fold.fold_crate(krate)
194 }
librustc/front/std_inject.rs:55:1-55:1 -struct- definition:
struct StandardLibraryInjector<'a> {
sess: &'a Session,
}
references:- 2116: fn inject_crates_ref(sess: &Session, krate: ast::Crate) -> ast::Crate {
117: let mut fold = StandardLibraryInjector {
118: sess: sess,
librustc/front/std_inject.rs:122:1-122:1 -struct- definition:
struct PreludeInjector<'a> {
sess: &'a Session,
}
references:- 2189: fn inject_prelude(sess: &Session, krate: ast::Crate) -> ast::Crate {
190: let mut fold = PreludeInjector {
191: sess: sess,
librustc/front/std_inject.rs:51:1-51:1 -fn- definition:
fn no_prelude(attrs: &[ast::Attribute]) -> bool {
attr::contains_name(attrs, "no_implicit_prelude")
}
references:- 2142: fn fold_item(&mut self, item: @ast::Item) -> SmallVector<@ast::Item> {
143: if !no_prelude(item.attrs.as_slice()) {
144: // only recur if there wasn't `#![no_implicit_prelude]`
librustc/front/std_inject.rs:59:1-59:1 -fn- definition:
pub fn with_version(krate: &str) -> Option<(InternedString, ast::StrStyle)> {
match option_env!("CFG_DISABLE_INJECT_STD_VERSION") {
Some("1") => None,
references:- 375: node: ast::ViewItemExternCrate(token::str_to_ident("std"),
76: with_version("std"),
77: ast::DUMMY_NODE_ID),
librustc/front/test.rs:
304: (ast::ViewItemExternCrate(id_test,
305: with_version("test"),
306: ast::DUMMY_NODE_ID),
librustc/front/std_inject.rs:
94: node: ast::ViewItemExternCrate(token::str_to_ident("native"),
95: with_version("native"),
96: ast::DUMMY_NODE_ID),
librustc/front/std_inject.rs:43:1-43:1 -fn- definition:
fn use_std(krate: &ast::Crate) -> bool {
!attr::contains_name(krate.attrs.as_slice(), "no_std")
}
references:- 236: pub fn maybe_inject_prelude(sess: &Session, krate: ast::Crate) -> ast::Crate {
37: if use_std(&krate) {
38: inject_prelude(sess, krate)