]> git.lizzy.rs Git - rust.git/blob - src/librustc/middle/lang_items.rs
0194d4a2510487622323d6d159e7f77da3d568c1
[rust.git] / src / librustc / middle / lang_items.rs
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 // Detecting language items.
12 //
13 // Language items are items that represent concepts intrinsic to the language
14 // itself. Examples are:
15 //
16 // * Traits that specify "kinds"; e.g. "Freeze", "Send".
17 //
18 // * Traits that represent operators; e.g. "Add", "Sub", "Index".
19 //
20 // * Functions called by the compiler itself.
21
22
23 use driver::session::Session;
24 use metadata::csearch::each_lang_item;
25 use middle::ty::{BuiltinBound, BoundFreeze, BoundPod, BoundSend, BoundSized};
26 use syntax::ast;
27 use syntax::ast_util::local_def;
28 use syntax::attr::AttrMetaMethods;
29 use syntax::parse::token::InternedString;
30 use syntax::visit::Visitor;
31 use syntax::visit;
32
33 use collections::HashMap;
34 use std::iter::Enumerate;
35 use std::vec;
36
37 // The actual lang items defined come at the end of this file in one handy table.
38 // So you probably just want to nip down to the end.
39 macro_rules! lets_do_this {
40     (
41         $( $variant:ident, $name:expr, $method:ident; )*
42     ) => {
43
44 #[deriving(FromPrimitive)]
45 pub enum LangItem {
46     $($variant),*
47 }
48
49 pub struct LanguageItems {
50     items: ~[Option<ast::DefId>],
51 }
52
53 impl LanguageItems {
54     pub fn new() -> LanguageItems {
55         fn foo(_: LangItem) -> Option<ast::DefId> { None }
56
57         LanguageItems {
58             items: ~[$(foo($variant)),*]
59         }
60     }
61
62     pub fn items<'a>(&'a self) -> Enumerate<vec::Items<'a, Option<ast::DefId>>> {
63         self.items.iter().enumerate()
64     }
65
66     pub fn item_name(index: uint) -> &'static str {
67         let item: Option<LangItem> = FromPrimitive::from_uint(index);
68         match item {
69             $( Some($variant) => $name, )*
70             None => "???"
71         }
72     }
73
74     pub fn require(&self, it: LangItem) -> Result<ast::DefId, ~str> {
75         match self.items[it as uint] {
76             Some(id) => Ok(id),
77             None => Err(format!("requires `{}` lang_item",
78                              LanguageItems::item_name(it as uint)))
79         }
80     }
81
82     pub fn to_builtin_kind(&self, id: ast::DefId) -> Option<BuiltinBound> {
83         if Some(id) == self.freeze_trait() {
84             Some(BoundFreeze)
85         } else if Some(id) == self.send_trait() {
86             Some(BoundSend)
87         } else if Some(id) == self.sized_trait() {
88             Some(BoundSized)
89         } else if Some(id) == self.pod_trait() {
90             Some(BoundPod)
91         } else {
92             None
93         }
94     }
95
96     $(
97         pub fn $method(&self) -> Option<ast::DefId> {
98             self.items[$variant as uint]
99         }
100     )*
101 }
102
103 struct LanguageItemCollector {
104     items: LanguageItems,
105
106     session: Session,
107
108     item_refs: HashMap<&'static str, uint>,
109 }
110
111 struct LanguageItemVisitor<'a> {
112     this: &'a mut LanguageItemCollector,
113 }
114
115 impl<'a> Visitor<()> for LanguageItemVisitor<'a> {
116     fn visit_item(&mut self, item: &ast::Item, _: ()) {
117         match extract(item.attrs) {
118             Some(value) => {
119                 let item_index = self.this.item_refs.find_equiv(&value).map(|x| *x);
120
121                 match item_index {
122                     Some(item_index) => {
123                         self.this.collect_item(item_index, local_def(item.id))
124                     }
125                     None => {}
126                 }
127             }
128             None => {}
129         }
130
131         visit::walk_item(self, item, ());
132     }
133 }
134
135 impl LanguageItemCollector {
136     pub fn new(session: Session) -> LanguageItemCollector {
137         let mut item_refs = HashMap::new();
138
139         $( item_refs.insert($name, $variant as uint); )*
140
141         LanguageItemCollector {
142             session: session,
143             items: LanguageItems::new(),
144             item_refs: item_refs
145         }
146     }
147
148     pub fn collect_item(&mut self, item_index: uint, item_def_id: ast::DefId) {
149         // Check for duplicates.
150         match self.items.items[item_index] {
151             Some(original_def_id) if original_def_id != item_def_id => {
152                 self.session.err(format!("duplicate entry for `{}`",
153                                       LanguageItems::item_name(item_index)));
154             }
155             Some(_) | None => {
156                 // OK.
157             }
158         }
159
160         // Matched.
161         self.items.items[item_index] = Some(item_def_id);
162     }
163
164     pub fn collect_local_language_items(&mut self, krate: &ast::Crate) {
165         let mut v = LanguageItemVisitor { this: self };
166         visit::walk_crate(&mut v, krate, ());
167     }
168
169     pub fn collect_external_language_items(&mut self) {
170         let crate_store = self.session.cstore;
171         crate_store.iter_crate_data(|crate_number, _crate_metadata| {
172             each_lang_item(crate_store, crate_number, |node_id, item_index| {
173                 let def_id = ast::DefId { krate: crate_number, node: node_id };
174                 self.collect_item(item_index, def_id);
175                 true
176             });
177         })
178     }
179
180     pub fn collect(&mut self, krate: &ast::Crate) {
181         self.collect_local_language_items(krate);
182         self.collect_external_language_items();
183     }
184 }
185
186 pub fn extract(attrs: &[ast::Attribute]) -> Option<InternedString> {
187     for attribute in attrs.iter() {
188         match attribute.name_str_pair() {
189             Some((ref key, ref value)) if key.equiv(&("lang")) => {
190                 return Some((*value).clone());
191             }
192             Some(..) | None => {}
193         }
194     }
195
196     return None;
197 }
198
199 pub fn collect_language_items(krate: &ast::Crate,
200                               session: Session) -> @LanguageItems {
201     let mut collector = LanguageItemCollector::new(session);
202     collector.collect(krate);
203     let LanguageItemCollector { items, .. } = collector;
204     session.abort_if_errors();
205     @items
206 }
207
208 // End of the macro
209     }
210 }
211
212 lets_do_this! {
213 //  Variant name,                    Name,                      Method name;
214     FreezeTraitLangItem,             "freeze",                  freeze_trait;
215     SendTraitLangItem,               "send",                    send_trait;
216     SizedTraitLangItem,              "sized",                   sized_trait;
217     PodTraitLangItem,                "pod",                     pod_trait;
218
219     DropTraitLangItem,               "drop",                    drop_trait;
220
221     AddTraitLangItem,                "add",                     add_trait;
222     SubTraitLangItem,                "sub",                     sub_trait;
223     MulTraitLangItem,                "mul",                     mul_trait;
224     DivTraitLangItem,                "div",                     div_trait;
225     RemTraitLangItem,                "rem",                     rem_trait;
226     NegTraitLangItem,                "neg",                     neg_trait;
227     NotTraitLangItem,                "not",                     not_trait;
228     BitXorTraitLangItem,             "bitxor",                  bitxor_trait;
229     BitAndTraitLangItem,             "bitand",                  bitand_trait;
230     BitOrTraitLangItem,              "bitor",                   bitor_trait;
231     ShlTraitLangItem,                "shl",                     shl_trait;
232     ShrTraitLangItem,                "shr",                     shr_trait;
233     IndexTraitLangItem,              "index",                   index_trait;
234
235     EqTraitLangItem,                 "eq",                      eq_trait;
236     OrdTraitLangItem,                "ord",                     ord_trait;
237
238     StrEqFnLangItem,                 "str_eq",                  str_eq_fn;
239     UniqStrEqFnLangItem,             "uniq_str_eq",             uniq_str_eq_fn;
240     FailFnLangItem,                  "fail_",                   fail_fn;
241     FailBoundsCheckFnLangItem,       "fail_bounds_check",       fail_bounds_check_fn;
242     ExchangeMallocFnLangItem,        "exchange_malloc",         exchange_malloc_fn;
243     ClosureExchangeMallocFnLangItem, "closure_exchange_malloc", closure_exchange_malloc_fn;
244     ExchangeFreeFnLangItem,          "exchange_free",           exchange_free_fn;
245     MallocFnLangItem,                "malloc",                  malloc_fn;
246     FreeFnLangItem,                  "free",                    free_fn;
247     StrDupUniqFnLangItem,            "strdup_uniq",             strdup_uniq_fn;
248
249     StartFnLangItem,                 "start",                   start_fn;
250
251     TyDescStructLangItem,            "ty_desc",                 ty_desc;
252     TyVisitorTraitLangItem,          "ty_visitor",              ty_visitor;
253     OpaqueStructLangItem,            "opaque",                  opaque;
254
255     EventLoopFactoryLangItem,        "event_loop_factory",      event_loop_factory;
256
257     TypeIdLangItem,                  "type_id",                 type_id;
258
259     EhPersonalityLangItem,           "eh_personality",          eh_personality_fn;
260
261     ManagedHeapLangItem,             "managed_heap",            managed_heap;
262     ExchangeHeapLangItem,            "exchange_heap",           exchange_heap;
263     GcLangItem,                      "gc",                      gc;
264
265     CovariantTypeItem,               "covariant_type",          covariant_type;
266     ContravariantTypeItem,           "contravariant_type",      contravariant_type;
267     InvariantTypeItem,               "invariant_type",          invariant_type;
268
269     CovariantLifetimeItem,           "covariant_lifetime",      covariant_lifetime;
270     ContravariantLifetimeItem,       "contravariant_lifetime",  contravariant_lifetime;
271     InvariantLifetimeItem,           "invariant_lifetime",      invariant_lifetime;
272
273     NoFreezeItem,                    "no_freeze_bound",         no_freeze_bound;
274     NoSendItem,                      "no_send_bound",           no_send_bound;
275     NoPodItem,                       "no_pod_bound",            no_pod_bound;
276     ManagedItem,                     "managed_bound",           managed_bound;
277 }