rustc: Introduce a lang_items pass, part of coherence and operator overloading.

This will also help us remove kinds.
This commit is contained in:
Patrick Walton 2012-07-25 18:36:18 -07:00
parent e1d4bd463c
commit da80bd17c3
8 changed files with 242 additions and 0 deletions

View File

@ -161,6 +161,7 @@ mod tuple;
// Ubiquitous-utility-type modules
mod ops;
mod cmp;
mod num;
mod hash;

View File

@ -30,6 +30,8 @@ import float::num;
import f32::num;
import f64::num;
import num::num;
import ops::{const, copy, send, owned};
import ops::{add, sub, mul, div, modulo, neg, bitops, index};
export path, option, some, none, unreachable;
export extensions;
@ -42,6 +44,9 @@ export immutable_copyable_vector, iter_trait_extensions, vec_concat;
export base_iter, copyable_iter, extended_iter;
export tuple_ops, extended_tuple_ops;
export ptr;
// The following exports are the core operators and kinds
export const, copy, send, owned;
export add, sub, mul, div, modulo, neg, bitops, index;
// Export the log levels as global constants. Higher levels mean
// more-verbosity. Error is the bottom level, default logging level is

View File

@ -170,6 +170,9 @@ fn compile_upto(sess: session, cfg: ast::crate_cfg,
session::sess_os_to_meta_os(sess.targ_cfg.os),
sess.opts.static));
time(time_passes, ~"language item collection", ||
middle::lang_items::collect_language_items(crate, sess));
let { def_map: def_map,
exp_map: exp_map,
impl_map: impl_map,

View File

@ -25,6 +25,7 @@ export get_enum_variants;
export get_impls_for_mod;
export get_trait_methods;
export get_method_names_if_trait;
export get_item_attrs;
export each_path;
export get_type;
export get_impl_traits;
@ -149,6 +150,14 @@ fn get_method_names_if_trait(cstore: cstore::cstore, def: ast::def_id)
ret decoder::get_method_names_if_trait(cdata, def.node);
}
fn get_item_attrs(cstore: cstore::cstore,
def_id: ast::def_id,
f: fn(~[@ast::meta_item])) {
let cdata = cstore::get_crate_data(cstore, def_id.crate);
decoder::get_item_attrs(cdata, def_id.node, f)
}
fn get_class_fields(tcx: ty::ctxt, def: ast::def_id) -> ~[ty::field_ty] {
let cstore = tcx.cstore;
let cdata = cstore::get_crate_data(cstore, def.crate);

View File

@ -39,6 +39,7 @@ export get_crate_vers;
export get_impls_for_mod;
export get_trait_methods;
export get_method_names_if_trait;
export get_item_attrs;
export get_crate_module_paths;
export def_like;
export dl_def;
@ -659,6 +660,18 @@ fn get_method_names_if_trait(cdata: cmd, node_id: ast::node_id)
ret some(resulting_method_names);
}
fn get_item_attrs(cdata: cmd,
node_id: ast::node_id,
f: fn(~[@ast::meta_item])) {
let item = lookup_item(node_id, cdata.data);
do ebml::tagged_docs(item, tag_attributes) |attributes| {
do ebml::tagged_docs(attributes, tag_attribute) |attribute| {
f(get_meta_items(attribute));
}
}
}
// Helper function that gets either fields or methods
fn get_class_members(cdata: cmd, id: ast::node_id,
p: fn(char) -> bool) -> ~[ty::field_ty] {

View File

@ -759,6 +759,7 @@ fn encode_info_for_item(ecx: @encode_ctxt, ebml_w: ebml::writer, item: @item,
encode_type_param_bounds(ebml_w, ecx, tps);
encode_type(ecx, ebml_w, node_id_to_type(tcx, item.id));
encode_name(ebml_w, item.ident);
encode_attributes(ebml_w, item.attrs);
let mut i = 0u;
for vec::each(*ty::trait_methods(tcx, local_def(item.id))) |mty| {
alt ms[i] {

View 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
}

View File

@ -88,6 +88,7 @@ mod middle {
mod region;
mod const_eval;
mod astencode;
mod lang_items;
}
mod front {