diff options
| author | Patrick Walton <pcwalton@mimiga.net> | 2012-05-22 10:54:12 -0700 |
|---|---|---|
| committer | Patrick Walton <pcwalton@mimiga.net> | 2012-07-02 18:30:12 -0700 |
| commit | f093d374edb89aedc940468d3d789dd95cec6347 (patch) | |
| tree | 8d9197ba35866b536c4a5ed8178f69387e4a69af /src/rustc/metadata | |
| parent | 0b1edb7f0e25cae2a1f519af17bfc76682af0e14 (diff) | |
| download | rust-f093d374edb89aedc940468d3d789dd95cec6347.tar.gz rust-f093d374edb89aedc940468d3d789dd95cec6347.zip | |
rustc: Implement a new resolve pass behind a compile flag
Diffstat (limited to 'src/rustc/metadata')
| -rw-r--r-- | src/rustc/metadata/csearch.rs | 8 | ||||
| -rw-r--r-- | src/rustc/metadata/cstore.rs | 2 | ||||
| -rw-r--r-- | src/rustc/metadata/decoder.rs | 155 | ||||
| -rw-r--r-- | src/rustc/metadata/encoder.rs | 4 |
4 files changed, 148 insertions, 21 deletions
diff --git a/src/rustc/metadata/csearch.rs b/src/rustc/metadata/csearch.rs index 700913498e9..4943e3e3e6e 100644 --- a/src/rustc/metadata/csearch.rs +++ b/src/rustc/metadata/csearch.rs @@ -22,6 +22,7 @@ export lookup_method_purity; export get_enum_variants; export get_impls_for_mod; export get_iface_methods; +export each_path; export get_type; export get_impl_iface; export get_impl_method; @@ -81,6 +82,13 @@ fn resolve_path(cstore: cstore::cstore, cnum: ast::crate_num, ret result; } +#[doc="Iterates over all the paths in the given crate."] +fn each_path(cstore: cstore::cstore, cnum: ast::crate_num, + f: fn(decoder::path_entry) -> bool) { + let crate_data = cstore::get_crate_data(cstore, cnum); + decoder::each_path(crate_data, f); +} + fn get_item_path(tcx: ty::ctxt, def: ast::def_id) -> ast_map::path { let cstore = tcx.cstore; let cdata = cstore::get_crate_data(cstore, def.crate); diff --git a/src/rustc/metadata/cstore.rs b/src/rustc/metadata/cstore.rs index f912dd92a4a..21506a59f56 100644 --- a/src/rustc/metadata/cstore.rs +++ b/src/rustc/metadata/cstore.rs @@ -6,7 +6,7 @@ import std::map::hashmap; import syntax::{ast, attr}; import syntax::ast_util::new_def_hash; -export cstore::{}; +export cstore; export cnum_map; export crate_metadata; export mk_cstore; diff --git a/src/rustc/metadata/decoder.rs b/src/rustc/metadata/decoder.rs index ccb3472325b..1f8aae87b7c 100644 --- a/src/rustc/metadata/decoder.rs +++ b/src/rustc/metadata/decoder.rs @@ -1,7 +1,7 @@ // Decoding metadata from a single crate's metadata import std::{ebml, map}; -import std::map::hashmap; +import std::map::{hashmap, str_hash}; import io::writer_util; import syntax::{ast, ast_util}; import syntax::attr; @@ -37,6 +37,12 @@ export get_crate_vers; export get_impls_for_mod; export get_iface_methods; export get_crate_module_paths; +export def_like; +export dl_def; +export dl_impl; +export dl_field; +export path_entry; +export each_path; export get_item_path; export maybe_find_item; // sketchy export item_type; // sketchy @@ -116,6 +122,7 @@ fn item_parent_item(d: ebml::doc) -> option<ast::def_id> { found } +// XXX: This has nothing to do with classes. fn class_member_id(d: ebml::doc, cdata: cmd) -> ast::def_id { let tagdoc = ebml::get_doc(d, tag_def_id); ret translate_def_id(cdata, parse_def_id(ebml::doc_data(tagdoc))); @@ -257,31 +264,39 @@ fn lookup_item_name(data: @~[u8], id: ast::node_id) -> ast::ident { item_name(lookup_item(id, data)) } -fn lookup_def(cnum: ast::crate_num, data: @~[u8], did_: ast::def_id) -> - ast::def { - let item = lookup_item(did_.node, data); +fn item_to_def_like(item: ebml::doc, did: ast::def_id, cnum: ast::crate_num) + -> def_like { let fam_ch = item_family(item); - let did = {crate: cnum, node: did_.node}; - // We treat references to enums as references to types. - alt check fam_ch { - 'c' { ast::def_const(did) } - 'C' { ast::def_class(did) } - 'u' { ast::def_fn(did, ast::unsafe_fn) } - 'f' { ast::def_fn(did, ast::impure_fn) } - 'p' { ast::def_fn(did, ast::pure_fn) } - 'y' { ast::def_ty(did) } - 't' { ast::def_ty(did) } - 'm' { ast::def_mod(did) } - 'n' { ast::def_foreign_mod(did) } + alt fam_ch { + 'c' { dl_def(ast::def_const(did)) } + 'C' { dl_def(ast::def_class(did)) } + 'u' { dl_def(ast::def_fn(did, ast::unsafe_fn)) } + 'f' { dl_def(ast::def_fn(did, ast::impure_fn)) } + 'p' { dl_def(ast::def_fn(did, ast::pure_fn)) } + 'y' { dl_def(ast::def_ty(did)) } + 't' { dl_def(ast::def_ty(did)) } + 'm' { dl_def(ast::def_mod(did)) } + 'n' { dl_def(ast::def_foreign_mod(did)) } 'v' { let mut tid = option::get(item_parent_item(item)); tid = {crate: cnum, node: tid.node}; - ast::def_variant(tid, did) + dl_def(ast::def_variant(tid, did)) } - 'I' { ast::def_ty(did) } + 'I' { dl_def(ast::def_ty(did)) } + 'i' { dl_impl(did) } + 'g' | 'j' { dl_field } + ch { fail #fmt("unexpected family code: '%c'", ch) } } } +fn lookup_def(cnum: ast::crate_num, data: @~[u8], did_: ast::def_id) -> + ast::def { + let item = lookup_item(did_.node, data); + let did = {crate: cnum, node: did_.node}; + // We treat references to enums as references to types. + ret def_like_to_def(item_to_def_like(item, did, cnum)); +} + fn get_type(cdata: cmd, id: ast::node_id, tcx: ty::ctxt) -> ty::ty_param_bounds_and_ty { @@ -356,6 +371,104 @@ fn get_symbol(data: @~[u8], id: ast::node_id) -> str { ret item_symbol(lookup_item(id, data)); } +// Something that a name can resolve to. +enum def_like { + dl_def(ast::def), + dl_impl(ast::def_id), + dl_field +} + +fn def_like_to_def(def_like: def_like) -> ast::def { + alt def_like { + dl_def(def) { ret def; } + dl_impl(*) { fail "found impl in def_like_to_def"; } + dl_field { fail "found field in def_like_to_def"; } + } +} + +// A path. +class path_entry { + // The full path, separated by '::'. + let path_string: str; + // The definition, implementation, or field that this path corresponds to. + let def_like: def_like; + + new(path_string: str, def_like: def_like) { + self.path_string = path_string; + self.def_like = def_like; + } +} + +#[doc="Iterates over all the paths in the given crate."] +fn each_path(cdata: cmd, f: fn(path_entry) -> bool) { + let root = ebml::doc(cdata.data); + let items = ebml::get_doc(root, tag_items); + let items_data = ebml::get_doc(items, tag_items_data); + + let mut broken = false; + + // First, go through all the explicit items. + do ebml::tagged_docs(items_data, tag_items_data_item) |item_doc| { + if !broken { + let name = ast_map::path_to_str_with_sep(item_path(item_doc), + "::"); + if name != "" { + // Extract the def ID. + let def_id = class_member_id(item_doc, cdata); + + // Construct the def for this item. + #debug("(each_path) yielding explicit item: %s", name); + let def_like = item_to_def_like(item_doc, def_id, cdata.cnum); + + // Hand the information off to the iteratee. + let this_path_entry = path_entry(name, def_like); + if !f(this_path_entry) { + broken = true; // XXX: This is awful. + } + } + } + } + + // If broken, stop here. + if broken { + ret; + } + + // Next, go through all the paths. We will find items that we didn't know + // about before (reexports in particular). + let outer_paths = ebml::get_doc(root, tag_paths); + let inner_paths = ebml::get_doc(outer_paths, tag_paths); + do ebml::tagged_docs(inner_paths, tag_paths_data_item) |path_doc| { + if !broken { + let path = item_name(path_doc); + + // Extract the def ID. + let def_id = class_member_id(path_doc, cdata); + + // Get the item. + alt maybe_find_item(def_id.node, items) { + none { + #debug("(each_path) ignoring implicit item: %s", + *path); + } + some(item_doc) { + // Construct the def for this item. + let def_like = item_to_def_like(item_doc, def_id, + cdata.cnum); + + // Hand the information off to the iteratee. + #debug("(each_path) yielding implicit item: %s", + *path); + let this_path_entry = path_entry(*path, def_like); + if (!f(this_path_entry)) { + broken = true; // XXX: This is awful. + } + } + } + } + } +} + fn get_item_path(cdata: cmd, id: ast::node_id) -> ast_map::path { item_path(lookup_item(id, cdata.data)) } @@ -441,10 +554,12 @@ fn item_impl_methods(cdata: cmd, item: ebml::doc, base_tps: uint) rslt } -fn get_impls_for_mod(cdata: cmd, m_id: ast::node_id, +fn get_impls_for_mod(cdata: cmd, + m_id: ast::node_id, name: option<ast::ident>, get_cdata: fn(ast::crate_num) -> cmd) - -> @~[@_impl] { + -> @~[@_impl] { + let data = cdata.data; let mod_item = lookup_item(m_id, data); let mut result = ~[]; diff --git a/src/rustc/metadata/encoder.rs b/src/rustc/metadata/encoder.rs index 0c01414847d..13ce52daae6 100644 --- a/src/rustc/metadata/encoder.rs +++ b/src/rustc/metadata/encoder.rs @@ -385,9 +385,13 @@ fn encode_info_for_mod(ecx: @encode_ctxt, ebml_w: ebml::writer, md: _mod, encode_def_id(ebml_w, local_def(id)); encode_family(ebml_w, 'm'); encode_name(ebml_w, name); + #debug("(encoding info for module) encoding info for module ID %d", id); let impls = ecx.impl_map(id); for impls.each |i| { let (ident, did) = i; + #debug("(encoding info for module) ... encoding impl %s (%?), \ + exported? %?", + *ident, did, ast_util::is_exported(ident, md)); if ast_util::is_exported(ident, md) { ebml_w.start_tag(tag_mod_impl); alt ecx.tcx.items.find(did.node) { |
