rustc: Introduce a lang_items pass, part of coherence and operator overloading.
This will also help us remove kinds.
This commit is contained in:
parent
e1d4bd463c
commit
da80bd17c3
8 changed files with 242 additions and 0 deletions
209
src/rustc/middle/lang_items.rs
Normal file
209
src/rustc/middle/lang_items.rs
Normal file
|
|
@ -0,0 +1,209 @@
|
|||
// Detecting language items.
|
||||
//
|
||||
// Language items are items that represent concepts intrinsic to the language
|
||||
// itself. Examples are:
|
||||
//
|
||||
// * Traits that specify "kinds"; e.g. "const", "copy", "send".
|
||||
//
|
||||
// * Traits that represent operators; e.g. "add", "sub", "index".
|
||||
//
|
||||
// * Functions called by the compiler itself.
|
||||
|
||||
import driver::session::session;
|
||||
import metadata::csearch::{each_path, get_item_attrs};
|
||||
import metadata::cstore::{iter_crate_data};
|
||||
import metadata::decoder::{dl_def, dl_field, dl_impl};
|
||||
import syntax::ast::{crate, def_id, def_ty, lit_str, meta_item, meta_list};
|
||||
import syntax::ast::{meta_name_value, meta_word};
|
||||
import syntax::ast_util::{local_def};
|
||||
import syntax::visit::{default_simple_visitor, mk_simple_visitor};
|
||||
import syntax::visit::{visit_crate, visit_item};
|
||||
|
||||
import std::map::{hashmap, str_hash};
|
||||
import str_eq = str::eq;
|
||||
|
||||
class LanguageItems {
|
||||
let mut const_trait: option<def_id>;
|
||||
let mut copy_trait: option<def_id>;
|
||||
let mut send_trait: option<def_id>;
|
||||
let mut owned_trait: option<def_id>;
|
||||
|
||||
let mut add_trait: option<def_id>;
|
||||
let mut sub_trait: option<def_id>;
|
||||
let mut mul_trait: option<def_id>;
|
||||
let mut div_trait: option<def_id>;
|
||||
let mut modulo_trait: option<def_id>;
|
||||
let mut neg_trait: option<def_id>;
|
||||
let mut bitops_trait: option<def_id>;
|
||||
let mut index_trait: option<def_id>;
|
||||
|
||||
new() {
|
||||
self.const_trait = none;
|
||||
self.copy_trait = none;
|
||||
self.send_trait = none;
|
||||
self.owned_trait = none;
|
||||
|
||||
self.add_trait = none;
|
||||
self.sub_trait = none;
|
||||
self.mul_trait = none;
|
||||
self.div_trait = none;
|
||||
self.modulo_trait = none;
|
||||
self.neg_trait = none;
|
||||
self.bitops_trait = none;
|
||||
self.index_trait = none;
|
||||
}
|
||||
}
|
||||
|
||||
class LanguageItemCollector {
|
||||
let items: LanguageItems;
|
||||
|
||||
let crate: @crate;
|
||||
let session: session;
|
||||
|
||||
let item_refs: hashmap<~str,&mut option<def_id>>;
|
||||
|
||||
new(crate: @crate, session: session) {
|
||||
self.crate = crate;
|
||||
self.session = session;
|
||||
|
||||
self.items = LanguageItems();
|
||||
|
||||
self.item_refs = str_hash();
|
||||
}
|
||||
|
||||
// XXX: Needed to work around an issue with constructors.
|
||||
fn init() {
|
||||
self.item_refs.insert(~"const", &mut self.items.const_trait);
|
||||
self.item_refs.insert(~"copy", &mut self.items.copy_trait);
|
||||
self.item_refs.insert(~"send", &mut self.items.send_trait);
|
||||
self.item_refs.insert(~"owned", &mut self.items.owned_trait);
|
||||
|
||||
self.item_refs.insert(~"add", &mut self.items.add_trait);
|
||||
self.item_refs.insert(~"sub", &mut self.items.sub_trait);
|
||||
self.item_refs.insert(~"mul", &mut self.items.mul_trait);
|
||||
self.item_refs.insert(~"div", &mut self.items.div_trait);
|
||||
self.item_refs.insert(~"modulo", &mut self.items.modulo_trait);
|
||||
self.item_refs.insert(~"neg", &mut self.items.neg_trait);
|
||||
self.item_refs.insert(~"bitops", &mut self.items.bitops_trait);
|
||||
self.item_refs.insert(~"index", &mut self.items.index_trait);
|
||||
}
|
||||
|
||||
fn match_and_collect_meta_item(item_def_id: def_id,
|
||||
meta_item: meta_item) {
|
||||
|
||||
alt meta_item.node {
|
||||
meta_name_value(key, literal) => {
|
||||
alt literal.node {
|
||||
lit_str(value) => {
|
||||
self.match_and_collect_item(item_def_id,
|
||||
*key,
|
||||
*value);
|
||||
}
|
||||
_ => {
|
||||
// Skip.
|
||||
}
|
||||
}
|
||||
}
|
||||
meta_word(*) | meta_list(*) {
|
||||
// Skip.
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn match_and_collect_item(item_def_id: def_id, key: ~str, value: ~str) {
|
||||
if !str_eq(key, ~"lang") {
|
||||
ret; // Didn't match.
|
||||
}
|
||||
|
||||
alt self.item_refs.find(value) {
|
||||
none => {
|
||||
// Didn't match.
|
||||
}
|
||||
some(item_ref) => {
|
||||
// Check for duplicates.
|
||||
alt copy *item_ref {
|
||||
some(original_def_id)
|
||||
if original_def_id != item_def_id => {
|
||||
|
||||
self.session.warn(#fmt("duplicate entry for `%s`",
|
||||
value));
|
||||
}
|
||||
some(_) | none => {
|
||||
// OK.
|
||||
}
|
||||
}
|
||||
|
||||
// Matched.
|
||||
*item_ref = some(item_def_id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn collect_local_language_items() {
|
||||
let this = unsafe { ptr::addr_of(self) };
|
||||
visit_crate(*self.crate, (), mk_simple_visitor(@{
|
||||
visit_item: |item| {
|
||||
for item.attrs.each |attribute| {
|
||||
unsafe {
|
||||
(*this).match_and_collect_meta_item(local_def(item
|
||||
.id),
|
||||
attribute.node
|
||||
.value);
|
||||
}
|
||||
}
|
||||
}
|
||||
with *default_simple_visitor()
|
||||
}));
|
||||
}
|
||||
|
||||
fn collect_external_language_items() {
|
||||
let crate_store = self.session.cstore;
|
||||
do iter_crate_data(crate_store) |crate_number, _crate_metadata| {
|
||||
for each_path(crate_store, crate_number) |path_entry| {
|
||||
let def_id;
|
||||
alt path_entry.def_like {
|
||||
dl_def(def_ty(did)) => {
|
||||
def_id = did;
|
||||
}
|
||||
dl_def(_) | dl_impl(_) | dl_field {
|
||||
// Skip this.
|
||||
again;
|
||||
}
|
||||
}
|
||||
|
||||
do get_item_attrs(crate_store, def_id) |meta_items| {
|
||||
for meta_items.each |meta_item| {
|
||||
self.match_and_collect_meta_item(def_id, *meta_item);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn check_completeness() {
|
||||
for self.item_refs.each |key, item_ref| {
|
||||
alt copy *item_ref {
|
||||
none => {
|
||||
self.session.warn(#fmt("no item found for `%s`", key));
|
||||
}
|
||||
some(did) => {
|
||||
// OK.
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn collect() {
|
||||
self.init();
|
||||
self.collect_local_language_items();
|
||||
self.collect_external_language_items();
|
||||
self.check_completeness();
|
||||
}
|
||||
}
|
||||
|
||||
fn collect_language_items(crate: @crate, session: session) -> LanguageItems {
|
||||
let collector = LanguageItemCollector(crate, session);
|
||||
collector.collect();
|
||||
copy collector.items
|
||||
}
|
||||
|
||||
Loading…
Add table
Add a link
Reference in a new issue