]> git.lizzy.rs Git - rust.git/blob - src/librustc/middle/lang_items.rs
2de12b9eb9746ec7e9c0213cf12f54d304fb34dd
[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. "const", "copy", "owned".
17 //
18 // * Traits that represent operators; e.g. "add", "sub", "index".
19 //
20 // * Functions called by the compiler itself.
21
22 use driver::session::Session;
23 use metadata::csearch::each_lang_item;
24 use metadata::cstore::iter_crate_data;
25 use syntax::ast::{crate, def_id, lit_str, meta_item};
26 use syntax::ast::{meta_list, meta_name_value, meta_word};
27 use syntax::ast_util::local_def;
28 use syntax::visit::{default_simple_visitor, mk_simple_visitor, SimpleVisitor};
29 use syntax::visit::visit_crate;
30
31 use core::cast::transmute;
32 use core::hashmap::HashMap;
33
34 pub enum LangItem {
35     ConstTraitLangItem,         // 0
36     CopyTraitLangItem,          // 1
37     OwnedTraitLangItem,         // 2
38     DurableTraitLangItem,       // 3
39
40     DropTraitLangItem,          // 4
41
42     AddTraitLangItem,           // 5
43     SubTraitLangItem,           // 6
44     MulTraitLangItem,           // 7
45     QuotTraitLangItem,          // 8
46     RemTraitLangItem,           // 9
47     NegTraitLangItem,           // 10
48     NotTraitLangItem,           // 11
49     BitXorTraitLangItem,        // 12
50     BitAndTraitLangItem,        // 13
51     BitOrTraitLangItem,         // 14
52     ShlTraitLangItem,           // 15
53     ShrTraitLangItem,           // 16
54     IndexTraitLangItem,         // 17
55
56     EqTraitLangItem,            // 18
57     OrdTraitLangItem,           // 19
58
59     StrEqFnLangItem,            // 20
60     UniqStrEqFnLangItem,        // 21
61     AnnihilateFnLangItem,       // 22
62     LogTypeFnLangItem,          // 23
63     FailFnLangItem,             // 24
64     FailBoundsCheckFnLangItem,  // 25
65     ExchangeMallocFnLangItem,   // 26
66     ExchangeFreeFnLangItem,     // 27
67     MallocFnLangItem,           // 28
68     FreeFnLangItem,             // 29
69     BorrowAsImmFnLangItem,      // 30
70     ReturnToMutFnLangItem,      // 31
71     CheckNotBorrowedFnLangItem, // 32
72     StrDupUniqFnLangItem,       // 33
73
74     StartFnLangItem,            // 34
75 }
76
77 pub struct LanguageItems {
78     items: [Option<def_id>, ..35]
79 }
80
81 pub impl LanguageItems {
82     pub fn new() -> LanguageItems {
83         LanguageItems {
84             items: [ None, ..35 ]
85         }
86     }
87
88     fn each_item(&self, f: &fn(def_id: def_id, i: uint) -> bool) {
89         for self.items.eachi |i, &item| {
90             if !f(item.get(), i) {
91                 break;
92             }
93         }
94     }
95
96     pub fn item_name(index: uint) -> &'static str {
97         match index {
98             0  => "const",
99             1  => "copy",
100             2  => "owned",
101             3  => "durable",
102
103             4  => "drop",
104
105             5  => "add",
106             6  => "sub",
107             7  => "mul",
108             8  => "quot",
109             9  => "rem",
110             10 => "neg",
111             11 => "not",
112             12 => "bitxor",
113             13 => "bitand",
114             14 => "bitor",
115             15 => "shl",
116             16 => "shr",
117             17 => "index",
118             18 => "eq",
119             19 => "ord",
120
121             20 => "str_eq",
122             21 => "uniq_str_eq",
123             22 => "annihilate",
124             23 => "log_type",
125             24 => "fail_",
126             25 => "fail_bounds_check",
127             26 => "exchange_malloc",
128             27 => "exchange_free",
129             28 => "malloc",
130             29 => "free",
131             30 => "borrow_as_imm",
132             31 => "return_to_mut",
133             32 => "check_not_borrowed",
134             33 => "strdup_uniq",
135
136             34 => "start",
137
138             _ => "???"
139         }
140     }
141
142     // FIXME #4621: Method macros sure would be nice here.
143
144     pub fn const_trait(&const self) -> def_id {
145         self.items[ConstTraitLangItem as uint].get()
146     }
147     pub fn copy_trait(&const self) -> def_id {
148         self.items[CopyTraitLangItem as uint].get()
149     }
150     pub fn owned_trait(&const self) -> def_id {
151         self.items[OwnedTraitLangItem as uint].get()
152     }
153     pub fn durable_trait(&const self) -> def_id {
154         self.items[DurableTraitLangItem as uint].get()
155     }
156
157     pub fn drop_trait(&const self) -> def_id {
158         self.items[DropTraitLangItem as uint].get()
159     }
160
161     pub fn add_trait(&const self) -> def_id {
162         self.items[AddTraitLangItem as uint].get()
163     }
164     pub fn sub_trait(&const self) -> def_id {
165         self.items[SubTraitLangItem as uint].get()
166     }
167     pub fn mul_trait(&const self) -> def_id {
168         self.items[MulTraitLangItem as uint].get()
169     }
170     pub fn quot_trait(&const self) -> def_id {
171         self.items[QuotTraitLangItem as uint].get()
172     }
173     pub fn rem_trait(&const self) -> def_id {
174         self.items[RemTraitLangItem as uint].get()
175     }
176     pub fn neg_trait(&const self) -> def_id {
177         self.items[NegTraitLangItem as uint].get()
178     }
179     pub fn not_trait(&const self) -> def_id {
180         self.items[NotTraitLangItem as uint].get()
181     }
182     pub fn bitxor_trait(&const self) -> def_id {
183         self.items[BitXorTraitLangItem as uint].get()
184     }
185     pub fn bitand_trait(&const self) -> def_id {
186         self.items[BitAndTraitLangItem as uint].get()
187     }
188     pub fn bitor_trait(&const self) -> def_id {
189         self.items[BitOrTraitLangItem as uint].get()
190     }
191     pub fn shl_trait(&const self) -> def_id {
192         self.items[ShlTraitLangItem as uint].get()
193     }
194     pub fn shr_trait(&const self) -> def_id {
195         self.items[ShrTraitLangItem as uint].get()
196     }
197     pub fn index_trait(&const self) -> def_id {
198         self.items[IndexTraitLangItem as uint].get()
199     }
200
201     pub fn eq_trait(&const self) -> def_id {
202         self.items[EqTraitLangItem as uint].get()
203     }
204     pub fn ord_trait(&const self) -> def_id {
205         self.items[OrdTraitLangItem as uint].get()
206     }
207
208     pub fn str_eq_fn(&const self) -> def_id {
209         self.items[StrEqFnLangItem as uint].get()
210     }
211     pub fn uniq_str_eq_fn(&const self) -> def_id {
212         self.items[UniqStrEqFnLangItem as uint].get()
213     }
214     pub fn annihilate_fn(&const self) -> def_id {
215         self.items[AnnihilateFnLangItem as uint].get()
216     }
217     pub fn log_type_fn(&const self) -> def_id {
218         self.items[LogTypeFnLangItem as uint].get()
219     }
220     pub fn fail_fn(&const self) -> def_id {
221         self.items[FailFnLangItem as uint].get()
222     }
223     pub fn fail_bounds_check_fn(&const self) -> def_id {
224         self.items[FailBoundsCheckFnLangItem as uint].get()
225     }
226     pub fn exchange_malloc_fn(&const self) -> def_id {
227         self.items[ExchangeMallocFnLangItem as uint].get()
228     }
229     pub fn exchange_free_fn(&const self) -> def_id {
230         self.items[ExchangeFreeFnLangItem as uint].get()
231     }
232     pub fn malloc_fn(&const self) -> def_id {
233         self.items[MallocFnLangItem as uint].get()
234     }
235     pub fn free_fn(&const self) -> def_id {
236         self.items[FreeFnLangItem as uint].get()
237     }
238     pub fn borrow_as_imm_fn(&const self) -> def_id {
239         self.items[BorrowAsImmFnLangItem as uint].get()
240     }
241     pub fn return_to_mut_fn(&const self) -> def_id {
242         self.items[ReturnToMutFnLangItem as uint].get()
243     }
244     pub fn check_not_borrowed_fn(&const self) -> def_id {
245         self.items[CheckNotBorrowedFnLangItem as uint].get()
246     }
247     pub fn strdup_uniq_fn(&const self) -> def_id {
248         self.items[StrDupUniqFnLangItem as uint].get()
249     }
250     pub fn start_fn(&const self) -> def_id {
251         self.items[StartFnLangItem as uint].get()
252     }
253 }
254
255 fn LanguageItemCollector<'r>(crate: @crate,
256                              session: Session,
257                              items: &'r mut LanguageItems)
258                           -> LanguageItemCollector<'r> {
259     let mut item_refs = HashMap::new();
260
261     item_refs.insert(@~"const", ConstTraitLangItem as uint);
262     item_refs.insert(@~"copy", CopyTraitLangItem as uint);
263     item_refs.insert(@~"owned", OwnedTraitLangItem as uint);
264     item_refs.insert(@~"durable", DurableTraitLangItem as uint);
265
266     item_refs.insert(@~"drop", DropTraitLangItem as uint);
267
268     item_refs.insert(@~"add", AddTraitLangItem as uint);
269     item_refs.insert(@~"sub", SubTraitLangItem as uint);
270     item_refs.insert(@~"mul", MulTraitLangItem as uint);
271     item_refs.insert(@~"quot", QuotTraitLangItem as uint);
272     item_refs.insert(@~"rem", RemTraitLangItem as uint);
273     item_refs.insert(@~"neg", NegTraitLangItem as uint);
274     item_refs.insert(@~"not", NotTraitLangItem as uint);
275     item_refs.insert(@~"bitxor", BitXorTraitLangItem as uint);
276     item_refs.insert(@~"bitand", BitAndTraitLangItem as uint);
277     item_refs.insert(@~"bitor", BitOrTraitLangItem as uint);
278     item_refs.insert(@~"shl", ShlTraitLangItem as uint);
279     item_refs.insert(@~"shr", ShrTraitLangItem as uint);
280     item_refs.insert(@~"index", IndexTraitLangItem as uint);
281
282     item_refs.insert(@~"eq", EqTraitLangItem as uint);
283     item_refs.insert(@~"ord", OrdTraitLangItem as uint);
284
285     item_refs.insert(@~"str_eq", StrEqFnLangItem as uint);
286     item_refs.insert(@~"uniq_str_eq", UniqStrEqFnLangItem as uint);
287     item_refs.insert(@~"annihilate", AnnihilateFnLangItem as uint);
288     item_refs.insert(@~"log_type", LogTypeFnLangItem as uint);
289     item_refs.insert(@~"fail_", FailFnLangItem as uint);
290     item_refs.insert(@~"fail_bounds_check",
291                      FailBoundsCheckFnLangItem as uint);
292     item_refs.insert(@~"exchange_malloc", ExchangeMallocFnLangItem as uint);
293     item_refs.insert(@~"exchange_free", ExchangeFreeFnLangItem as uint);
294     item_refs.insert(@~"malloc", MallocFnLangItem as uint);
295     item_refs.insert(@~"free", FreeFnLangItem as uint);
296     item_refs.insert(@~"borrow_as_imm", BorrowAsImmFnLangItem as uint);
297     item_refs.insert(@~"return_to_mut", ReturnToMutFnLangItem as uint);
298     item_refs.insert(@~"check_not_borrowed",
299                      CheckNotBorrowedFnLangItem as uint);
300     item_refs.insert(@~"strdup_uniq", StrDupUniqFnLangItem as uint);
301     item_refs.insert(@~"start", StartFnLangItem as uint);
302
303     LanguageItemCollector {
304         crate: crate,
305         session: session,
306         items: items,
307         item_refs: item_refs
308     }
309 }
310
311 struct LanguageItemCollector<'self> {
312     items: &'self mut LanguageItems,
313
314     crate: @crate,
315     session: Session,
316
317     item_refs: HashMap<@~str, uint>,
318 }
319
320 pub impl<'self> LanguageItemCollector<'self> {
321     fn match_and_collect_meta_item(&self, item_def_id: def_id,
322                                    meta_item: @meta_item) {
323         match meta_item.node {
324             meta_name_value(key, literal) => {
325                 match literal.node {
326                     lit_str(value) => {
327                         self.match_and_collect_item(item_def_id, key, value);
328                     }
329                     _ => {} // Skip.
330                 }
331             }
332             meta_word(*) | meta_list(*) => {} // Skip.
333         }
334     }
335
336     fn collect_item(&self, item_index: uint, item_def_id: def_id) {
337         // Check for duplicates.
338         match self.items.items[item_index] {
339             Some(original_def_id) if original_def_id != item_def_id => {
340                 self.session.err(fmt!("duplicate entry for `%s`",
341                                       LanguageItems::item_name(item_index)));
342             }
343             Some(_) | None => {
344                 // OK.
345             }
346         }
347
348         // Matched.
349         self.items.items[item_index] = Some(item_def_id);
350     }
351
352     fn match_and_collect_item(&self,
353                               item_def_id: def_id, key: @~str, value: @~str) {
354         if *key != ~"lang" {
355             return;    // Didn't match.
356         }
357
358         match self.item_refs.find(&value) {
359             None => {
360                 // Didn't match.
361             }
362             Some(&item_index) => {
363                 self.collect_item(item_index, item_def_id)
364             }
365         }
366     }
367
368     fn collect_local_language_items(&self) {
369         unsafe {
370             let this: *LanguageItemCollector<'self> = transmute(self);
371             visit_crate(self.crate, (), mk_simple_visitor(@SimpleVisitor {
372                 visit_item: |item| {
373                     for item.attrs.each |attribute| {
374                         unsafe {
375                             (*this).match_and_collect_meta_item(
376                                 local_def(item.id),
377                                 attribute.node.value
378                             );
379                         }
380                     }
381                 },
382                 .. *default_simple_visitor()
383             }));
384         }
385     }
386
387     fn collect_external_language_items(&self) {
388         let crate_store = self.session.cstore;
389         do iter_crate_data(crate_store) |crate_number, _crate_metadata| {
390             for each_lang_item(crate_store, crate_number)
391                     |node_id, item_index| {
392                 let def_id = def_id { crate: crate_number, node: node_id };
393                 self.collect_item(item_index, def_id);
394             }
395         }
396     }
397
398     fn check_completeness(&self) {
399         for self.item_refs.each |&key, &item_ref| {
400             match self.items.items[item_ref] {
401                 None => {
402                     self.session.err(fmt!("no item found for `%s`", *key));
403                 }
404                 Some(_) => {
405                     // OK.
406                 }
407             }
408         }
409     }
410
411     fn collect(&self) {
412         self.collect_local_language_items();
413         self.collect_external_language_items();
414         self.check_completeness();
415     }
416 }
417
418 pub fn collect_language_items(crate: @crate,
419                               session: Session)
420                            -> LanguageItems {
421     let mut items = LanguageItems::new();
422     let collector = LanguageItemCollector(crate, session, &mut items);
423     collector.collect();
424     copy items
425 }
426