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.
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.
11 // Detecting language items.
13 // Language items are items that represent concepts intrinsic to the language
14 // itself. Examples are:
16 // * Traits that specify "kinds"; e.g. "const", "copy", "owned".
18 // * Traits that represent operators; e.g. "add", "sub", "index".
20 // * Functions called by the compiler itself.
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;
31 use core::cast::transmute;
32 use core::hashmap::HashMap;
35 ConstTraitLangItem, // 0
36 CopyTraitLangItem, // 1
37 OwnedTraitLangItem, // 2
38 DurableTraitLangItem, // 3
40 DropTraitLangItem, // 4
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
56 EqTraitLangItem, // 18
57 OrdTraitLangItem, // 19
59 StrEqFnLangItem, // 20
60 UniqStrEqFnLangItem, // 21
61 AnnihilateFnLangItem, // 22
62 LogTypeFnLangItem, // 23
64 FailBoundsCheckFnLangItem, // 25
65 ExchangeMallocFnLangItem, // 26
66 ExchangeFreeFnLangItem, // 27
67 MallocFnLangItem, // 28
69 BorrowAsImmFnLangItem, // 30
70 ReturnToMutFnLangItem, // 31
71 CheckNotBorrowedFnLangItem, // 32
72 StrDupUniqFnLangItem, // 33
74 StartFnLangItem, // 34
77 pub struct LanguageItems {
78 items: [Option<def_id>, ..35]
81 pub impl LanguageItems {
82 pub fn new() -> LanguageItems {
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) {
96 pub fn item_name(index: uint) -> &'static str {
126 25 => "fail_bounds_check",
127 26 => "exchange_malloc",
128 27 => "exchange_free",
131 30 => "borrow_as_imm",
132 31 => "return_to_mut",
133 32 => "check_not_borrowed",
142 // FIXME #4621: Method macros sure would be nice here.
144 pub fn const_trait(&const self) -> def_id {
145 self.items[ConstTraitLangItem as uint].get()
147 pub fn copy_trait(&const self) -> def_id {
148 self.items[CopyTraitLangItem as uint].get()
150 pub fn owned_trait(&const self) -> def_id {
151 self.items[OwnedTraitLangItem as uint].get()
153 pub fn durable_trait(&const self) -> def_id {
154 self.items[DurableTraitLangItem as uint].get()
157 pub fn drop_trait(&const self) -> def_id {
158 self.items[DropTraitLangItem as uint].get()
161 pub fn add_trait(&const self) -> def_id {
162 self.items[AddTraitLangItem as uint].get()
164 pub fn sub_trait(&const self) -> def_id {
165 self.items[SubTraitLangItem as uint].get()
167 pub fn mul_trait(&const self) -> def_id {
168 self.items[MulTraitLangItem as uint].get()
170 pub fn quot_trait(&const self) -> def_id {
171 self.items[QuotTraitLangItem as uint].get()
173 pub fn rem_trait(&const self) -> def_id {
174 self.items[RemTraitLangItem as uint].get()
176 pub fn neg_trait(&const self) -> def_id {
177 self.items[NegTraitLangItem as uint].get()
179 pub fn not_trait(&const self) -> def_id {
180 self.items[NotTraitLangItem as uint].get()
182 pub fn bitxor_trait(&const self) -> def_id {
183 self.items[BitXorTraitLangItem as uint].get()
185 pub fn bitand_trait(&const self) -> def_id {
186 self.items[BitAndTraitLangItem as uint].get()
188 pub fn bitor_trait(&const self) -> def_id {
189 self.items[BitOrTraitLangItem as uint].get()
191 pub fn shl_trait(&const self) -> def_id {
192 self.items[ShlTraitLangItem as uint].get()
194 pub fn shr_trait(&const self) -> def_id {
195 self.items[ShrTraitLangItem as uint].get()
197 pub fn index_trait(&const self) -> def_id {
198 self.items[IndexTraitLangItem as uint].get()
201 pub fn eq_trait(&const self) -> def_id {
202 self.items[EqTraitLangItem as uint].get()
204 pub fn ord_trait(&const self) -> def_id {
205 self.items[OrdTraitLangItem as uint].get()
208 pub fn str_eq_fn(&const self) -> def_id {
209 self.items[StrEqFnLangItem as uint].get()
211 pub fn uniq_str_eq_fn(&const self) -> def_id {
212 self.items[UniqStrEqFnLangItem as uint].get()
214 pub fn annihilate_fn(&const self) -> def_id {
215 self.items[AnnihilateFnLangItem as uint].get()
217 pub fn log_type_fn(&const self) -> def_id {
218 self.items[LogTypeFnLangItem as uint].get()
220 pub fn fail_fn(&const self) -> def_id {
221 self.items[FailFnLangItem as uint].get()
223 pub fn fail_bounds_check_fn(&const self) -> def_id {
224 self.items[FailBoundsCheckFnLangItem as uint].get()
226 pub fn exchange_malloc_fn(&const self) -> def_id {
227 self.items[ExchangeMallocFnLangItem as uint].get()
229 pub fn exchange_free_fn(&const self) -> def_id {
230 self.items[ExchangeFreeFnLangItem as uint].get()
232 pub fn malloc_fn(&const self) -> def_id {
233 self.items[MallocFnLangItem as uint].get()
235 pub fn free_fn(&const self) -> def_id {
236 self.items[FreeFnLangItem as uint].get()
238 pub fn borrow_as_imm_fn(&const self) -> def_id {
239 self.items[BorrowAsImmFnLangItem as uint].get()
241 pub fn return_to_mut_fn(&const self) -> def_id {
242 self.items[ReturnToMutFnLangItem as uint].get()
244 pub fn check_not_borrowed_fn(&const self) -> def_id {
245 self.items[CheckNotBorrowedFnLangItem as uint].get()
247 pub fn strdup_uniq_fn(&const self) -> def_id {
248 self.items[StrDupUniqFnLangItem as uint].get()
250 pub fn start_fn(&const self) -> def_id {
251 self.items[StartFnLangItem as uint].get()
255 fn LanguageItemCollector<'r>(crate: @crate,
257 items: &'r mut LanguageItems)
258 -> LanguageItemCollector<'r> {
259 let mut item_refs = HashMap::new();
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);
266 item_refs.insert(@~"drop", DropTraitLangItem as uint);
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);
282 item_refs.insert(@~"eq", EqTraitLangItem as uint);
283 item_refs.insert(@~"ord", OrdTraitLangItem as uint);
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);
303 LanguageItemCollector {
311 struct LanguageItemCollector<'self> {
312 items: &'self mut LanguageItems,
317 item_refs: HashMap<@~str, uint>,
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) => {
327 self.match_and_collect_item(item_def_id, key, value);
332 meta_word(*) | meta_list(*) => {} // Skip.
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)));
349 self.items.items[item_index] = Some(item_def_id);
352 fn match_and_collect_item(&self,
353 item_def_id: def_id, key: @~str, value: @~str) {
355 return; // Didn't match.
358 match self.item_refs.find(&value) {
362 Some(&item_index) => {
363 self.collect_item(item_index, item_def_id)
368 fn collect_local_language_items(&self) {
370 let this: *LanguageItemCollector<'self> = transmute(self);
371 visit_crate(self.crate, (), mk_simple_visitor(@SimpleVisitor {
373 for item.attrs.each |attribute| {
375 (*this).match_and_collect_meta_item(
382 .. *default_simple_visitor()
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);
398 fn check_completeness(&self) {
399 for self.item_refs.each |&key, &item_ref| {
400 match self.items.items[item_ref] {
402 self.session.err(fmt!("no item found for `%s`", *key));
412 self.collect_local_language_items();
413 self.collect_external_language_items();
414 self.check_completeness();
418 pub fn collect_language_items(crate: @crate,
421 let mut items = LanguageItems::new();
422 let collector = LanguageItemCollector(crate, session, &mut items);