about summary refs log tree commit diff
path: root/src/rustc/metadata
diff options
context:
space:
mode:
authorPatrick Walton <pcwalton@mimiga.net>2012-05-22 10:54:12 -0700
committerPatrick Walton <pcwalton@mimiga.net>2012-07-02 18:30:12 -0700
commitf093d374edb89aedc940468d3d789dd95cec6347 (patch)
tree8d9197ba35866b536c4a5ed8178f69387e4a69af /src/rustc/metadata
parent0b1edb7f0e25cae2a1f519af17bfc76682af0e14 (diff)
downloadrust-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.rs8
-rw-r--r--src/rustc/metadata/cstore.rs2
-rw-r--r--src/rustc/metadata/decoder.rs155
-rw-r--r--src/rustc/metadata/encoder.rs4
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) {