about summary refs log tree commit diff
path: root/src/rustc/metadata
diff options
context:
space:
mode:
authorTim Chevalier <chevalier@alum.wellesley.edu>2012-03-06 08:02:13 -0800
committerTim Chevalier <chevalier@alum.wellesley.edu>2012-03-16 15:28:05 -0700
commit1680ccce1ed1b89bc746c6c764173e8f0b233ca6 (patch)
tree48f5f3d13bd0d893df92266b6f13c7ecbf1a1f71 /src/rustc/metadata
parent47d468f08c770485baa61e3a353e83b85ba5037f (diff)
downloadrust-1680ccce1ed1b89bc746c6c764173e8f0b233ca6.tar.gz
rust-1680ccce1ed1b89bc746c6c764173e8f0b233ca6.zip
Classes WIP
Cross-crate metadata for classes works well enough that programs with
classes in other crates compile successfully, but output wrong results.
Checking in work so far to avoid merge hassles. (Tests are xfailed.)
Diffstat (limited to 'src/rustc/metadata')
-rw-r--r--src/rustc/metadata/common.rs1
-rw-r--r--src/rustc/metadata/csearch.rs8
-rw-r--r--src/rustc/metadata/cstore.rs7
-rw-r--r--src/rustc/metadata/decoder.rs59
-rw-r--r--src/rustc/metadata/encoder.rs128
-rw-r--r--src/rustc/metadata/tydecode.rs27
-rw-r--r--src/rustc/metadata/tyencode.rs11
7 files changed, 221 insertions, 20 deletions
diff --git a/src/rustc/metadata/common.rs b/src/rustc/metadata/common.rs
index 88800e17aff..493166144f5 100644
--- a/src/rustc/metadata/common.rs
+++ b/src/rustc/metadata/common.rs
@@ -78,6 +78,7 @@ const tag_path: uint = 0x40u;
 const tag_path_len: uint = 0x41u;
 const tag_path_elt_mod: uint = 0x42u;
 const tag_path_elt_name: uint = 0x43u;
+const tag_items_class_member: uint = 0x44u;
 
 // used to encode crate_ctxt side tables
 enum astencode_tag { // Reserves 0x50 -- 0x6f
diff --git a/src/rustc/metadata/csearch.rs b/src/rustc/metadata/csearch.rs
index 08836703836..2451f9f37c7 100644
--- a/src/rustc/metadata/csearch.rs
+++ b/src/rustc/metadata/csearch.rs
@@ -9,6 +9,7 @@ import middle::trans::common::maps;
 import std::map::hashmap;
 
 export get_symbol;
+export get_class_items;
 export get_type_param_count;
 export lookup_defs;
 export lookup_method_purity;
@@ -35,6 +36,7 @@ fn get_type_param_count(cstore: cstore::cstore, def: ast::def_id) -> uint {
 fn lookup_defs(cstore: cstore::cstore, cnum: ast::crate_num,
                path: [ast::ident]) -> [ast::def] {
     let result = [];
+    #debug("lookup_defs: path = %? cnum = %?", path, cnum);
     for (c, data, def) in resolve_path(cstore, cnum, path) {
         result += [decoder::lookup_def(c, data, def)];
     }
@@ -116,6 +118,12 @@ fn get_iface_methods(tcx: ty::ctxt, def: ast::def_id) -> @[ty::method] {
     decoder::get_iface_methods(cdata, def.node, tcx)
 }
 
+fn get_class_items(tcx: ty::ctxt, def: ast::def_id) -> [@ty::class_item_ty] {
+    let cstore = tcx.sess.cstore;
+    let cdata = cstore::get_crate_data(cstore, def.crate);
+    decoder::get_class_items(cdata, def.node, tcx)
+}
+
 fn get_type(tcx: ty::ctxt, def: ast::def_id) -> ty::ty_param_bounds_and_ty {
     let cstore = tcx.sess.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 f8071538df4..1dc779232c9 100644
--- a/src/rustc/metadata/cstore.rs
+++ b/src/rustc/metadata/cstore.rs
@@ -162,10 +162,9 @@ fn get_dep_hashes(cstore: cstore) -> [str] {
 }
 
 fn get_path(cstore: cstore, d: ast::def_id) -> [str] {
-    alt p(cstore).mod_path_map.find(d) {
-      option::some(ds) { str::split_str(ds, "::") }
-      option::none { [] }
-    }
+    // let f = bind str::split_str(_, "::");
+    option::maybe([], p(cstore).mod_path_map.find(d),
+                  {|ds| str::split_str(ds, "::")})
 }
 // Local Variables:
 // mode: rust
diff --git a/src/rustc/metadata/decoder.rs b/src/rustc/metadata/decoder.rs
index 70c771b85c1..6effd8e2516 100644
--- a/src/rustc/metadata/decoder.rs
+++ b/src/rustc/metadata/decoder.rs
@@ -9,11 +9,13 @@ import front::attr;
 import middle::ty;
 import middle::ast_map;
 import common::*;
-import tydecode::{parse_ty_data, parse_def_id, parse_bounds_data};
+import tydecode::{parse_ty_data, parse_def_id, parse_bounds_data,
+        parse_ident};
 import syntax::print::pprust;
 import cmd=cstore::crate_metadata;
 import middle::trans::common::maps;
 
+export get_class_items;
 export get_symbol;
 export get_enum_variants;
 export get_type;
@@ -84,7 +86,10 @@ fn find_item(item_id: int, items: ebml::doc) -> ebml::doc {
 // to the item data.
 fn lookup_item(item_id: int, data: @[u8]) -> ebml::doc {
     let items = ebml::get_doc(ebml::doc(data), tag_items);
-    ret find_item(item_id, items);
+    alt maybe_find_item(item_id, items) {
+       none { fail(#fmt("lookup_item: id not found: %d", item_id)); }
+       some(d) { d }
+    }
 }
 
 fn item_family(item: ebml::doc) -> char {
@@ -105,6 +110,11 @@ fn item_parent_item(d: ebml::doc) -> option<ast::def_id> {
     found
 }
 
+fn class_field_id(d: ebml::doc) -> ast::def_id {
+    let tagdoc = ebml::get_doc(d, tag_def_id);
+    ret parse_def_id(ebml::doc_data(tagdoc));
+}
+
 fn variant_disr_val(d: ebml::doc) -> option<int> {
     option::chain(ebml::maybe_get_doc(d, tag_disr_val)) {|val_doc|
         int::parse_buf(ebml::doc_data(val_doc), 10u)
@@ -178,6 +188,7 @@ fn resolve_path(path: [ast::ident], data: @[u8]) -> [ast::def_id] {
     let paths = ebml::get_doc(md, tag_paths);
     let eqer = bind eq_item(_, s);
     let result: [ast::def_id] = [];
+    #debug("resolve_path: looking up %s", s);
     for doc: ebml::doc in lookup_hash(paths, eqer, hash_path(s)) {
         let did_doc = ebml::get_doc(doc, tag_def_id);
         result += [parse_def_id(ebml::doc_data(did_doc))];
@@ -226,6 +237,7 @@ fn lookup_def(cnum: ast::crate_num, data: @[u8], did_: ast::def_id) ->
     // 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) }
@@ -393,10 +405,48 @@ fn get_iface_methods(cdata: cmd, id: ast::node_id, tcx: ty::ctxt)
     @result
 }
 
+/*
+  FIXME
+  This is not working. metadata is broken -- fields get encoded correctly,
+  but not decoded. look at this code, see what it's actually writing out
+  also see what "data" is
+ */
+fn get_class_items(cdata: cmd, id: ast::node_id, tcx: ty::ctxt)
+    -> [@ty::class_item_ty] {
+    let data = cdata.data;
+    let item = lookup_item(id, data), result = [];
+    #debug("get_class_items: %s", item_name(item));
+    #debug("item: %?", item);
+    // right tag?
+    ebml::tagged_docs(item, tag_items_class_member) {|an_item|
+        let fam = item_family(an_item);
+        let decl = alt check fam {
+                'g' {
+                    let name = item_name(an_item);
+                    #debug("why hello there! %s", name);
+                    let ty = doc_type(an_item, tcx, cdata);
+                    let did = class_field_id(an_item);
+                    {ident: name,
+                     id: did.node,
+                     contents: ty::var_ty(ty)}
+                }
+                _ {
+                    fail; // FIXME
+                }
+        };
+        result += [@decl];
+    }
+    result
+}
+
+
+
 fn family_has_type_params(fam_ch: char) -> bool {
     alt check fam_ch {
-      'c' | 'T' | 'm' | 'n' { false }
-      'f' | 'u' | 'p' | 'F' | 'U' | 'P' | 'y' | 't' | 'v' | 'i' | 'I' { true }
+      'c' | 'T' | 'm' | 'n' | 'g' | 'h' { false }
+      'f' | 'u' | 'p' | 'F' | 'U' | 'P' | 'y' | 't' | 'v' | 'i' | 'I' | 'C'
+          | 'a'
+          { true }
     }
 }
 
@@ -434,6 +484,7 @@ fn item_family_to_str(fam: char) -> str {
       'v' { ret "enum"; }
       'i' { ret "impl"; }
       'I' { ret "iface"; }
+      'C' { ret "class"; }
     }
 }
 
diff --git a/src/rustc/metadata/encoder.rs b/src/rustc/metadata/encoder.rs
index fee50a927e6..fe2f01624ca 100644
--- a/src/rustc/metadata/encoder.rs
+++ b/src/rustc/metadata/encoder.rs
@@ -76,6 +76,23 @@ fn encode_native_module_item_paths(ebml_w: ebml::writer, nmod: native_mod,
     }
 }
 
+fn encode_class_item_paths(ebml_w: ebml::writer,
+     items: [@class_item], path: [str], &index: [entry<str>]) {
+    for it in items {
+       alt it.node.privacy {
+          priv { cont; }
+          pub {
+              let (id, ident) = alt it.node.decl {
+                      instance_var(v, _, _, vid) { (vid, v) }
+                      class_method(it) { (it.id, it.ident) }
+              };
+              add_to_index(ebml_w, path, index, ident);
+              encode_named_def_id(ebml_w, ident, local_def(id));
+          }
+       }
+    }
+}
+
 fn encode_module_item_paths(ebml_w: ebml::writer, ecx: @encode_ctxt,
                             module: _mod, path: [str], &index: [entry<str>]) {
     // FIXME factor out add_to_index/start/encode_name/encode_def_id/end ops
@@ -128,8 +145,20 @@ fn encode_module_item_paths(ebml_w: ebml::writer, ecx: @encode_ctxt,
             encode_def_id(ebml_w, local_def(it.id));
             ebml_w.end_tag();
           }
-          item_class(_,_,_) {
-              fail "encode: implement item_class";
+          item_class(tps,items,ctor) {
+              add_to_index(ebml_w, path, index, it.ident);
+              ebml_w.start_tag(tag_paths_data_item);
+              encode_name(ebml_w, it.ident);
+              encode_def_id(ebml_w, local_def(it.id));
+              ebml_w.end_tag();
+              ebml_w.start_tag(tag_paths);
+              /* a bit confused -- adding the same ident twice
+               (once for class, once for ctor) */
+              add_to_index(ebml_w, path, index, it.ident);
+              encode_named_def_id(ebml_w, it.ident, local_def(ctor.node.id));
+              encode_class_item_paths(ebml_w, items, path + [it.ident],
+                                      index);
+              ebml_w.end_tag();
           }
           item_enum(variants, tps) {
             add_to_index(ebml_w, path, index, it.ident);
@@ -312,13 +341,80 @@ fn encode_info_for_mod(ecx: @encode_ctxt, ebml_w: ebml::writer, md: _mod,
             }
         }
       }
-      _ { ecx.ccx.tcx.sess.bug("encode_info_for_mod: \
-             undocumented invariant"); }
+      _ { ecx.ccx.tcx.sess.bug(#fmt("encode_info_for_mod: empty impl_map \
+            entry for %?", path)); }
     }
     encode_path(ebml_w, path, ast_map::path_mod(name));
     ebml_w.end_tag();
 }
 
+fn encode_info_for_class(ecx: @encode_ctxt, ebml_w: ebml::writer,
+                         id: node_id, path: ast_map::path, name: ident,
+                         tps: [ty_param], items: [@class_item]) {
+    let tcx = ecx.ccx.tcx;
+    encode_def_id(ebml_w, local_def(id));
+    encode_family(ebml_w, 'C');
+    encode_type_param_bounds(ebml_w, ecx, tps);
+    encode_type(ecx, ebml_w, node_id_to_type(tcx, id));
+    encode_name(ebml_w, name);
+
+    for ci in items {
+      alt ci.node.privacy {
+        pub {
+            ebml_w.start_tag(tag_items_class_member); // ???
+            alt ci.node.decl {
+               instance_var(nm, _, _, id) {
+                   #debug("encode_info_for_class: doing %s", nm);
+                   encode_family(ebml_w, 'g');
+                   encode_name(ebml_w, nm);
+                   encode_type(ecx, ebml_w, node_id_to_type(tcx, id));
+                   /* TODO: mutability */
+                   encode_def_id(ebml_w, local_def(id));
+               }
+               class_method(it) {
+                   encode_family(ebml_w, 'h');
+                   encode_name(ebml_w, it.ident);
+                   alt it.node {
+                      item_fn(fdecl, tps, _) {
+                          encode_info_for_fn(ecx, ebml_w, it.id, it.ident,
+                                             path, none, tps, fdecl);
+                      }
+                      _ { fail; /* TODO */ }
+                   }
+               }
+            }
+            ebml_w.end_tag();
+        }
+        priv {
+            /* don't export it, then! */
+        }
+      }
+    }
+}
+
+fn encode_info_for_fn(ecx: @encode_ctxt, ebml_w: ebml::writer,
+                      id: node_id, ident: ident, path: ast_map::path,
+                      item: option<@item>, tps: [ty_param], decl: fn_decl) {
+        ebml_w.start_tag(tag_items_data_item);
+        encode_def_id(ebml_w, local_def(id));
+        encode_family(ebml_w, purity_fn_family(decl.purity));
+        encode_type_param_bounds(ebml_w, ecx, tps);
+        let its_ty = node_id_to_type(ecx.ccx.tcx, id);
+        #debug("fn name = %s ty = %s", ident,
+               util::ppaux::ty_to_str(ecx.ccx.tcx, its_ty));
+        encode_type(ecx, ebml_w, its_ty);
+        encode_path(ebml_w, path, ast_map::path_name(ident));
+        alt item {
+           some(it) {
+             astencode::encode_inlined_item(ecx, ebml_w, path, ii_item(it));
+           }
+           none {
+             encode_symbol(ecx, ebml_w, id);
+           }
+        }
+        ebml_w.end_tag();
+}
+
 fn purity_fn_family(p: purity) -> char {
     alt p {
       unsafe_fn { 'u' }
@@ -404,8 +500,13 @@ fn encode_info_for_item(ecx: @encode_ctxt, ebml_w: ebml::writer, item: @item,
         encode_enum_variant_info(ecx, ebml_w, item.id, variants,
                                  path, index, tps);
       }
-      item_class(_,_,_) {
-          fail "encode: implement item_class";
+      item_class(tps,items,_) {
+          /* We're not forgetting about the ctor here! It gets
+           encoded elsewhere */
+          ebml_w.start_tag(tag_items_data_item);
+         encode_info_for_class(ecx, ebml_w, item.id, path, item.ident,
+                               tps, items);
+         ebml_w.end_tag();
       }
       item_res(_, tps, _, _, ctor_id) {
         let fn_ty = node_id_to_type(tcx, ctor_id);
@@ -539,6 +640,21 @@ fn encode_info_for_items(ecx: @encode_ctxt, ebml_w: ebml::writer,
               ast_map::node_item(_, pt) {
                 encode_info_for_item(ecx, ebml_w, i, index, *pt);
               }
+          /* TODO: encode info for class items! */
+          /* encode ctor, then encode items */
+          ast_map::node_ctor(i, path) {
+            alt i.node {
+               item_class(tps, _, ctor) {
+                   #debug("class, encoding a fn: %d", ctor.node.id);
+                   /* this is assuming that ctors aren't inlined...
+                      probably shouldn't assume that */
+                   encode_info_for_fn(ecx, ebml_w, ctor.node.id, i.ident,
+                                      *path, none, tps, ctor.node.dec)
+               }
+               _ { /* TODO: should handle item_res, probably */ }
+            }
+          }
+
             }
         },
         visit_native_item: {|ni, cx, v|
diff --git a/src/rustc/metadata/tydecode.rs b/src/rustc/metadata/tydecode.rs
index eebbe51c665..9b2a87d9e18 100644
--- a/src/rustc/metadata/tydecode.rs
+++ b/src/rustc/metadata/tydecode.rs
@@ -7,7 +7,7 @@ import syntax::ast_util::respan;
 import middle::ty;
 import std::map::hashmap;
 
-export parse_ty_data, parse_def_id;
+export parse_ty_data, parse_def_id, parse_ident;
 export parse_bounds_data;
 
 // Compact string representation for ty::t values. API ty_str &
@@ -303,6 +303,17 @@ fn parse_ty(st: @pstate, conv: conv_did) -> ty::t {
         ty::mk_with_id(st.tcx, inner, def)
       }
       'B' { ty::mk_opaque_box(st.tcx) }
+      'a' {
+          #debug("saw a class");
+          assert (next(st) == '[');
+          #debug("saw a [");
+          let did = parse_def(st, conv);
+          #debug("parsed a def_id %?", did);
+          let params: [ty::t] = [];
+          while peek(st) != ']' { params += [parse_ty(st, conv)]; }
+          assert (next(st) == ']');
+          ret ty::mk_class(st.tcx, did, params);
+      }
       c { #error("unexpected char in type string: %c", c); fail;}
     }
 }
@@ -387,8 +398,18 @@ fn parse_def_id(buf: [u8]) -> ast::def_id {
     for b: u8 in crate_part { crate_part_vec += [b]; }
     for b: u8 in def_part { def_part_vec += [b]; }
 
-    let crate_num = option::get(uint::parse_buf(crate_part_vec, 10u)) as int;
-    let def_num = option::get(uint::parse_buf(def_part_vec, 10u)) as int;
+    let crate_num = alt uint::parse_buf(crate_part_vec, 10u) {
+       some(cn) { cn as int }
+       none { fail (#fmt("internal error: parse_def_id: error parsing %? \
+                         as crate",
+                         crate_part_vec)); }
+    };
+    let def_num = alt uint::parse_buf(def_part_vec, 10u) {
+       some(dn) { dn as int }
+       none { fail (#fmt("internal error: parse_def_id: error parsing %? \
+                         as id",
+                         def_part_vec)); }
+    };
     ret {crate: crate_num, node: def_num};
 }
 
diff --git a/src/rustc/metadata/tyencode.rs b/src/rustc/metadata/tyencode.rs
index ebe9342f87a..7e16129846c 100644
--- a/src/rustc/metadata/tyencode.rs
+++ b/src/rustc/metadata/tyencode.rs
@@ -214,10 +214,15 @@ fn enc_sty(w: io::writer, cx: @ctxt, st: ty::sty) {
       }
       ty::ty_opaque_box { w.write_char('B'); }
       ty::ty_class(def, tys) {
-          w.write_str("c[");
-          w.write_str(cx.ds(def));
-          w.write_char('|');
+          #debug("~~~~ %s", "a[");
+          w.write_str("a[");
+          let s = cx.ds(def);
+          #debug("~~~~ %s", s);
+          w.write_str(s);
+          #debug("~~~~ %s", "|");
+          w.write_str("|");
           for t: ty::t in tys { enc_ty(w, cx, t); }
+          #debug("~~~~ %s", "]");
           w.write_char(']');
       }
     }