]> git.lizzy.rs Git - rust.git/blob - src/librustc/middle/lang_items.rs
auto merge of #8623 : pnkfelix/rust/fsk-visitor-vpar-defaults-step4, r=nmatsakis
[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 metadata::cstore::iter_crate_data;
26 use syntax::ast::{Crate, def_id, MetaItem};
27 use syntax::ast_util::local_def;
28 use syntax::attr::AttrMetaMethods;
29 use syntax::ast::{item};
30 use syntax::visit;
31 use syntax::visit::Visitor;
32
33 use std::hashmap::HashMap;
34
35 pub enum LangItem {
36     FreezeTraitLangItem,               // 0
37     SendTraitLangItem,                 // 1
38     SizedTraitLangItem,                // 2
39
40     DropTraitLangItem,                 // 3
41
42     AddTraitLangItem,                  // 4
43     SubTraitLangItem,                  // 5
44     MulTraitLangItem,                  // 6
45     DivTraitLangItem,                  // 7
46     RemTraitLangItem,                  // 8
47     NegTraitLangItem,                  // 9
48     NotTraitLangItem,                  // 10
49     BitXorTraitLangItem,               // 11
50     BitAndTraitLangItem,               // 12
51     BitOrTraitLangItem,                // 13
52     ShlTraitLangItem,                  // 14
53     ShrTraitLangItem,                  // 15
54     IndexTraitLangItem,                // 16
55
56     EqTraitLangItem,                   // 17
57     OrdTraitLangItem,                  // 18
58
59     StrEqFnLangItem,                   // 19
60     UniqStrEqFnLangItem,               // 20
61     LogTypeFnLangItem,                 // 21
62     FailFnLangItem,                    // 22
63     FailBoundsCheckFnLangItem,         // 23
64     ExchangeMallocFnLangItem,          // 24
65     ClosureExchangeMallocFnLangItem,   // 25
66     ExchangeFreeFnLangItem,            // 26
67     MallocFnLangItem,                  // 27
68     FreeFnLangItem,                    // 28
69     BorrowAsImmFnLangItem,             // 29
70     BorrowAsMutFnLangItem,             // 30
71     ReturnToMutFnLangItem,             // 31
72     CheckNotBorrowedFnLangItem,        // 32
73     StrDupUniqFnLangItem,              // 33
74     RecordBorrowFnLangItem,            // 34
75     UnrecordBorrowFnLangItem,          // 35
76
77     StartFnLangItem,                   // 36
78
79     TyDescStructLangItem,              // 37
80     TyVisitorTraitLangItem,            // 38
81     OpaqueStructLangItem,              // 39
82 }
83
84 pub struct LanguageItems {
85     items: [Option<def_id>, ..41]
86 }
87
88 impl LanguageItems {
89     pub fn new() -> LanguageItems {
90         LanguageItems {
91             items: [ None, ..41 ]
92         }
93     }
94
95     pub fn each_item(&self, f: &fn(Option<def_id>, uint) -> bool) -> bool {
96         self.items.iter().enumerate().advance(|(i, &item)| f(item, i))
97     }
98
99     pub fn item_name(index: uint) -> &'static str {
100         match index {
101             0  => "freeze",
102             1  => "send",
103             2  => "sized",
104
105             3  => "drop",
106
107             4  => "add",
108             5  => "sub",
109             6  => "mul",
110             7  => "div",
111             8  => "rem",
112             9  => "neg",
113             10 => "not",
114             11 => "bitxor",
115             12 => "bitand",
116             13 => "bitor",
117             14 => "shl",
118             15 => "shr",
119             16 => "index",
120             17 => "eq",
121             18 => "ord",
122
123             19 => "str_eq",
124             20 => "uniq_str_eq",
125             21 => "log_type",
126             22 => "fail_",
127             23 => "fail_bounds_check",
128             24 => "exchange_malloc",
129             25 => "closure_exchange_malloc",
130             26 => "exchange_free",
131             27 => "malloc",
132             28 => "free",
133             29 => "borrow_as_imm",
134             30 => "borrow_as_mut",
135             31 => "return_to_mut",
136             32 => "check_not_borrowed",
137             33 => "strdup_uniq",
138             34 => "record_borrow",
139             35 => "unrecord_borrow",
140
141             36 => "start",
142
143             37 => "ty_desc",
144             38 => "ty_visitor",
145             39 => "opaque",
146
147             _ => "???"
148         }
149     }
150
151     // FIXME #4621: Method macros sure would be nice here.
152
153     pub fn require(&self, it: LangItem) -> Result<def_id, ~str> {
154         match self.items[it as uint] {
155             Some(id) => Ok(id),
156             None => Err(fmt!("requires `%s` lang_item",
157                              LanguageItems::item_name(it as uint)))
158         }
159     }
160
161     pub fn freeze_trait(&self) -> Option<def_id> {
162         self.items[FreezeTraitLangItem as uint]
163     }
164     pub fn send_trait(&self) -> Option<def_id> {
165         self.items[SendTraitLangItem as uint]
166     }
167     pub fn sized_trait(&self) -> Option<def_id> {
168         self.items[SizedTraitLangItem as uint]
169     }
170
171     pub fn drop_trait(&self) -> Option<def_id> {
172         self.items[DropTraitLangItem as uint]
173     }
174
175     pub fn add_trait(&self) -> Option<def_id> {
176         self.items[AddTraitLangItem as uint]
177     }
178     pub fn sub_trait(&self) -> Option<def_id> {
179         self.items[SubTraitLangItem as uint]
180     }
181     pub fn mul_trait(&self) -> Option<def_id> {
182         self.items[MulTraitLangItem as uint]
183     }
184     pub fn div_trait(&self) -> Option<def_id> {
185         self.items[DivTraitLangItem as uint]
186     }
187     pub fn rem_trait(&self) -> Option<def_id> {
188         self.items[RemTraitLangItem as uint]
189     }
190     pub fn neg_trait(&self) -> Option<def_id> {
191         self.items[NegTraitLangItem as uint]
192     }
193     pub fn not_trait(&self) -> Option<def_id> {
194         self.items[NotTraitLangItem as uint]
195     }
196     pub fn bitxor_trait(&self) -> Option<def_id> {
197         self.items[BitXorTraitLangItem as uint]
198     }
199     pub fn bitand_trait(&self) -> Option<def_id> {
200         self.items[BitAndTraitLangItem as uint]
201     }
202     pub fn bitor_trait(&self) -> Option<def_id> {
203         self.items[BitOrTraitLangItem as uint]
204     }
205     pub fn shl_trait(&self) -> Option<def_id> {
206         self.items[ShlTraitLangItem as uint]
207     }
208     pub fn shr_trait(&self) -> Option<def_id> {
209         self.items[ShrTraitLangItem as uint]
210     }
211     pub fn index_trait(&self) -> Option<def_id> {
212         self.items[IndexTraitLangItem as uint]
213     }
214
215     pub fn eq_trait(&self) -> Option<def_id> {
216         self.items[EqTraitLangItem as uint]
217     }
218     pub fn ord_trait(&self) -> Option<def_id> {
219         self.items[OrdTraitLangItem as uint]
220     }
221
222     pub fn str_eq_fn(&self) -> Option<def_id> {
223         self.items[StrEqFnLangItem as uint]
224     }
225     pub fn uniq_str_eq_fn(&self) -> Option<def_id> {
226         self.items[UniqStrEqFnLangItem as uint]
227     }
228     pub fn log_type_fn(&self) -> Option<def_id> {
229         self.items[LogTypeFnLangItem as uint]
230     }
231     pub fn fail_fn(&self) -> Option<def_id> {
232         self.items[FailFnLangItem as uint]
233     }
234     pub fn fail_bounds_check_fn(&self) -> Option<def_id> {
235         self.items[FailBoundsCheckFnLangItem as uint]
236     }
237     pub fn exchange_malloc_fn(&self) -> Option<def_id> {
238         self.items[ExchangeMallocFnLangItem as uint]
239     }
240     pub fn closure_exchange_malloc_fn(&self) -> Option<def_id> {
241         self.items[ClosureExchangeMallocFnLangItem as uint]
242     }
243     pub fn exchange_free_fn(&self) -> Option<def_id> {
244         self.items[ExchangeFreeFnLangItem as uint]
245     }
246     pub fn malloc_fn(&self) -> Option<def_id> {
247         self.items[MallocFnLangItem as uint]
248     }
249     pub fn free_fn(&self) -> Option<def_id> {
250         self.items[FreeFnLangItem as uint]
251     }
252     pub fn borrow_as_imm_fn(&self) -> Option<def_id> {
253         self.items[BorrowAsImmFnLangItem as uint]
254     }
255     pub fn borrow_as_mut_fn(&self) -> Option<def_id> {
256         self.items[BorrowAsMutFnLangItem as uint]
257     }
258     pub fn return_to_mut_fn(&self) -> Option<def_id> {
259         self.items[ReturnToMutFnLangItem as uint]
260     }
261     pub fn check_not_borrowed_fn(&self) -> Option<def_id> {
262         self.items[CheckNotBorrowedFnLangItem as uint]
263     }
264     pub fn strdup_uniq_fn(&self) -> Option<def_id> {
265         self.items[StrDupUniqFnLangItem as uint]
266     }
267     pub fn record_borrow_fn(&self) -> Option<def_id> {
268         self.items[RecordBorrowFnLangItem as uint]
269     }
270     pub fn unrecord_borrow_fn(&self) -> Option<def_id> {
271         self.items[UnrecordBorrowFnLangItem as uint]
272     }
273     pub fn start_fn(&self) -> Option<def_id> {
274         self.items[StartFnLangItem as uint]
275     }
276     pub fn ty_desc(&self) -> Option<def_id> {
277         self.items[TyDescStructLangItem as uint]
278     }
279     pub fn ty_visitor(&self) -> Option<def_id> {
280         self.items[TyVisitorTraitLangItem as uint]
281     }
282     pub fn opaque(&self) -> Option<def_id> {
283         self.items[OpaqueStructLangItem as uint]
284     }
285 }
286
287 struct LanguageItemCollector<'self> {
288     items: LanguageItems,
289
290     crate: &'self Crate,
291     session: Session,
292
293     item_refs: HashMap<@str, uint>,
294 }
295
296 struct LanguageItemVisitor<'self> {
297     this: *mut LanguageItemCollector<'self>,
298 }
299
300 impl<'self> Visitor<()> for LanguageItemVisitor<'self> {
301
302     fn visit_item(&mut self, item:@item, _:()) {
303
304                 for attribute in item.attrs.iter() {
305                     unsafe {
306                         (*self.this).match_and_collect_meta_item(
307                             local_def(item.id),
308                             attribute.node.value
309                         );
310                     }
311                 }
312
313         visit::walk_item(self, item, ());
314     }
315 }
316
317 impl<'self> LanguageItemCollector<'self> {
318     pub fn new<'a>(crate: &'a Crate, session: Session)
319                    -> LanguageItemCollector<'a> {
320         let mut item_refs = HashMap::new();
321
322         item_refs.insert(@"freeze", FreezeTraitLangItem as uint);
323         item_refs.insert(@"send", SendTraitLangItem as uint);
324         item_refs.insert(@"sized", SizedTraitLangItem as uint);
325
326         item_refs.insert(@"drop", DropTraitLangItem as uint);
327
328         item_refs.insert(@"add", AddTraitLangItem as uint);
329         item_refs.insert(@"sub", SubTraitLangItem as uint);
330         item_refs.insert(@"mul", MulTraitLangItem as uint);
331         item_refs.insert(@"div", DivTraitLangItem as uint);
332         item_refs.insert(@"rem", RemTraitLangItem as uint);
333         item_refs.insert(@"neg", NegTraitLangItem as uint);
334         item_refs.insert(@"not", NotTraitLangItem as uint);
335         item_refs.insert(@"bitxor", BitXorTraitLangItem as uint);
336         item_refs.insert(@"bitand", BitAndTraitLangItem as uint);
337         item_refs.insert(@"bitor", BitOrTraitLangItem as uint);
338         item_refs.insert(@"shl", ShlTraitLangItem as uint);
339         item_refs.insert(@"shr", ShrTraitLangItem as uint);
340         item_refs.insert(@"index", IndexTraitLangItem as uint);
341
342         item_refs.insert(@"eq", EqTraitLangItem as uint);
343         item_refs.insert(@"ord", OrdTraitLangItem as uint);
344
345         item_refs.insert(@"str_eq", StrEqFnLangItem as uint);
346         item_refs.insert(@"uniq_str_eq", UniqStrEqFnLangItem as uint);
347         item_refs.insert(@"log_type", LogTypeFnLangItem as uint);
348         item_refs.insert(@"fail_", FailFnLangItem as uint);
349         item_refs.insert(@"fail_bounds_check",
350                          FailBoundsCheckFnLangItem as uint);
351         item_refs.insert(@"exchange_malloc", ExchangeMallocFnLangItem as uint);
352         item_refs.insert(@"closure_exchange_malloc", ClosureExchangeMallocFnLangItem as uint);
353         item_refs.insert(@"exchange_free", ExchangeFreeFnLangItem as uint);
354         item_refs.insert(@"malloc", MallocFnLangItem as uint);
355         item_refs.insert(@"free", FreeFnLangItem as uint);
356         item_refs.insert(@"borrow_as_imm", BorrowAsImmFnLangItem as uint);
357         item_refs.insert(@"borrow_as_mut", BorrowAsMutFnLangItem as uint);
358         item_refs.insert(@"return_to_mut", ReturnToMutFnLangItem as uint);
359         item_refs.insert(@"check_not_borrowed",
360                          CheckNotBorrowedFnLangItem as uint);
361         item_refs.insert(@"strdup_uniq", StrDupUniqFnLangItem as uint);
362         item_refs.insert(@"record_borrow", RecordBorrowFnLangItem as uint);
363         item_refs.insert(@"unrecord_borrow", UnrecordBorrowFnLangItem as uint);
364         item_refs.insert(@"start", StartFnLangItem as uint);
365         item_refs.insert(@"ty_desc", TyDescStructLangItem as uint);
366         item_refs.insert(@"ty_visitor", TyVisitorTraitLangItem as uint);
367         item_refs.insert(@"opaque", OpaqueStructLangItem as uint);
368
369         LanguageItemCollector {
370             crate: crate,
371             session: session,
372             items: LanguageItems::new(),
373             item_refs: item_refs
374         }
375     }
376
377     pub fn match_and_collect_meta_item(&mut self,
378                                        item_def_id: def_id,
379                                        meta_item: &MetaItem) {
380         match meta_item.name_str_pair() {
381             Some((key, value)) => {
382                 self.match_and_collect_item(item_def_id, key, value);
383             }
384             None => {} // skip
385         }
386     }
387
388     pub fn collect_item(&mut self, item_index: uint, item_def_id: def_id) {
389         // Check for duplicates.
390         match self.items.items[item_index] {
391             Some(original_def_id) if original_def_id != item_def_id => {
392                 self.session.err(fmt!("duplicate entry for `%s`",
393                                       LanguageItems::item_name(item_index)));
394             }
395             Some(_) | None => {
396                 // OK.
397             }
398         }
399
400         // Matched.
401         self.items.items[item_index] = Some(item_def_id);
402     }
403
404     pub fn match_and_collect_item(&mut self,
405                                   item_def_id: def_id,
406                                   key: &str,
407                                   value: @str) {
408         if "lang" != key {
409             return;    // Didn't match.
410         }
411
412         let item_index = self.item_refs.find(&value).map_move(|x| *x);
413         // prevent borrow checker from considering   ^~~~~~~~~~~
414         // self to be borrowed (annoying)
415
416         match item_index {
417             Some(item_index) => {
418                 self.collect_item(item_index, item_def_id);
419             }
420             None => {
421                 // Didn't match.
422                 return;
423             }
424         }
425     }
426
427     pub fn collect_local_language_items(&mut self) {
428         let this: *mut LanguageItemCollector = &mut *self;
429         let mut v = LanguageItemVisitor { this: this };
430         visit::walk_crate(&mut v, self.crate, ());
431     }
432
433     pub fn collect_external_language_items(&mut self) {
434         let crate_store = self.session.cstore;
435         do iter_crate_data(crate_store) |crate_number, _crate_metadata| {
436             do each_lang_item(crate_store, crate_number)
437                     |node_id, item_index| {
438                 let def_id = def_id { crate: crate_number, node: node_id };
439                 self.collect_item(item_index, def_id);
440                 true
441             };
442         }
443     }
444
445     pub fn collect(&mut self) {
446         self.collect_local_language_items();
447         self.collect_external_language_items();
448     }
449 }
450
451 pub fn collect_language_items(crate: &Crate,
452                               session: Session)
453                            -> LanguageItems {
454     let mut collector = LanguageItemCollector::new(crate, session);
455     collector.collect();
456     let LanguageItemCollector { items, _ } = collector;
457     session.abort_if_errors();
458     items
459 }