about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorPatrick Walton <pcwalton@mimiga.net>2011-04-01 13:02:44 -0700
committerPatrick Walton <pcwalton@mimiga.net>2011-04-01 13:02:44 -0700
commit6dc452335a410e139220c4ecadbbda9dd15fe8e2 (patch)
tree96d3fe1107c175f3792eb960cf3d9b9cc87731b7 /src
parentec9d7abf8ce7f8c62894b772928303e5ee71970f (diff)
downloadrust-6dc452335a410e139220c4ecadbbda9dd15fe8e2.tar.gz
rust-6dc452335a410e139220c4ecadbbda9dd15fe8e2.zip
rustc: Get tag variants from the crate metadata
Diffstat (limited to 'src')
-rw-r--r--src/comp/front/creader.rs55
-rw-r--r--src/comp/middle/metadata.rs33
-rw-r--r--src/comp/middle/trans.rs5
-rw-r--r--src/comp/rustc.rc1
4 files changed, 78 insertions, 16 deletions
diff --git a/src/comp/front/creader.rs b/src/comp/front/creader.rs
index 22c38c3172c..151411c6bca 100644
--- a/src/comp/front/creader.rs
+++ b/src/comp/front/creader.rs
@@ -8,6 +8,7 @@ import lib.llvm.mk_object_file;
 import lib.llvm.mk_section_iter;
 import middle.fold;
 import middle.metadata;
+import middle.trans;
 import middle.ty;
 import back.x86;
 import util.common;
@@ -324,7 +325,8 @@ impure fn move_to_item(&ebml.reader ebml_r, int item_id) {
     auto eqer = bind eq_item(_, item_id);
     auto hash = metadata.hash_def_num(item_id);
     ebml.move_to_sibling_with_id(ebml_r, metadata.tag_items);
-    lookup_hash_entry(ebml_r, eqer, hash);
+    auto found = lookup_hash_entry(ebml_r, eqer, hash);
+    check (found);
 }
 
 // Looks up an item in the given metadata and returns an EBML reader pointing
@@ -409,17 +411,17 @@ impure fn get_item_type(&ebml.reader ebml_r, int this_cnum) -> @ty.t {
     ret get_item_generic[@ty.t](ebml_r, metadata.tag_items_data_item_type, f);
 }
 
-impure fn get_item_ty_params(&ebml.reader ebml_r, int this_cnum)
+impure fn collect_def_ids(&ebml.reader ebml_r, int this_cnum, uint tag_id)
         -> vec[ast.def_id] {
-    let vec[ast.def_id] tps = vec();
+    let vec[ast.def_id] def_ids = vec();
     while (ebml.bytes_left(ebml_r) > 0u) {
         auto ebml_tag = ebml.peek(ebml_r);
-        if (ebml_tag.id == metadata.tag_items_data_item_ty_param) {
+        if (ebml_tag.id == tag_id) {
             ebml.move_to_first_child(ebml_r);
 
             auto data = ebml.read_data(ebml_r);
             auto external_def_id = parse_def_id(data);
-            tps += vec(tup(this_cnum, external_def_id._1));
+            def_ids += vec(tup(this_cnum, external_def_id._1));
 
             ebml.move_to_parent(ebml_r);
         }
@@ -430,7 +432,19 @@ impure fn get_item_ty_params(&ebml.reader ebml_r, int this_cnum)
     ebml.move_to_parent(ebml_r);
     ebml.move_to_first_child(ebml_r);
 
-    ret tps;
+    ret def_ids;
+}
+
+impure fn get_item_ty_params(&ebml.reader ebml_r, int this_cnum)
+        -> vec[ast.def_id] {
+    ret collect_def_ids(ebml_r, this_cnum,
+                        metadata.tag_items_data_item_ty_param);
+}
+
+impure fn collect_tag_variant_ids(&ebml.reader ebml_r, int this_cnum)
+        -> vec[ast.def_id] {
+    ret collect_def_ids(ebml_r, this_cnum,
+                        metadata.tag_items_data_item_variant);
 }
 
 
@@ -590,6 +604,35 @@ fn get_symbol(session.session sess, ast.def_id def) -> str {
     ret get_item_symbol(ebml_r);
 }
 
+fn get_tag_variants(session.session sess, ast.def_id def)
+        -> vec[trans.variant_info] {
+    auto external_crate_id = def._0;
+    auto data = sess.get_external_crate(external_crate_id);
+    auto ebml_r = lookup_item(def._1, data);
+
+    let vec[trans.variant_info] infos = vec();
+    auto variant_ids = collect_tag_variant_ids(ebml_r, external_crate_id);
+    for (ast.def_id did in variant_ids) {
+        ebml.reset_reader(ebml_r, 0u);
+        move_to_item(ebml_r, did._1);
+        auto ctor_ty = get_item_type(ebml_r, external_crate_id);
+        let vec[@ty.t] arg_tys = vec();
+        alt (ctor_ty.struct) {
+            case (ty.ty_fn(_, ?args, _)) {
+                for (ty.arg a in args) {
+                    arg_tys += vec(a.ty);
+                }
+            }
+            case (_) {
+                // Nullary tag variant.
+            }
+        }
+        infos += vec(rec(args=arg_tys, ctor_ty=ctor_ty, id=did));
+    }
+
+    ret infos;
+}
+
 // Local Variables:
 // mode: rust
 // fill-column: 78;
diff --git a/src/comp/middle/metadata.rs b/src/comp/middle/metadata.rs
index c42ed6dbade..587db223af8 100644
--- a/src/comp/middle/metadata.rs
+++ b/src/comp/middle/metadata.rs
@@ -176,8 +176,12 @@ fn encode_def_id(&ebml.writer ebml_w, &ast.def_id id) {
     ebml.end_tag(ebml_w);
 }
 
-fn encode_tag_variant_paths(&ebml.writer ebml_w, vec[ast.variant] variants) {
+fn encode_tag_variant_paths(&ebml.writer ebml_w,
+                            vec[ast.variant] variants,
+                            vec[str] path,
+                            &mutable vec[tup(str, uint)] index) {
     for (ast.variant variant in variants) {
+        add_to_index(ebml_w, path, index, variant.node.name);
         ebml.start_tag(ebml_w, tag_paths_data_item);
         encode_name(ebml_w, variant.node.name);
         encode_def_id(ebml_w, variant.node.id);
@@ -266,9 +270,10 @@ fn encode_module_item_paths(&ebml.writer ebml_w,
                 add_to_index(ebml_w, path, index, id);
                 ebml.start_tag(ebml_w, tag_paths_data_item);
                 encode_name(ebml_w, id);
-                encode_tag_variant_paths(ebml_w, variants);
                 encode_def_id(ebml_w, did);
                 ebml.end_tag(ebml_w);
+
+                encode_tag_variant_paths(ebml_w, variants, path, index);
             }
             case (ast.item_obj(?id, _, ?tps, ?odid, ?ann)) {
                 add_to_index(ebml_w, path, index, id);
@@ -314,6 +319,12 @@ fn encode_type_params(&ebml.writer ebml_w, vec[ast.ty_param] tps) {
     }
 }
 
+fn encode_variant_id(&ebml.writer ebml_w, ast.def_id vid) {
+    ebml.start_tag(ebml_w, tag_items_data_item_variant);
+    ebml_w.writer.write(_str.bytes(def_to_str(vid)));
+    ebml.end_tag(ebml_w);
+}
+
 fn encode_type(&ebml.writer ebml_w, @ty.t typ) {
     ebml.start_tag(ebml_w, tag_items_data_item_type);
     auto f = def_to_str;
@@ -348,23 +359,24 @@ fn encode_obj_type_id(&ebml.writer ebml_w, &ast.def_id id) {
 
 
 fn encode_tag_variant_info(@trans.crate_ctxt cx, &ebml.writer ebml_w,
-                           ast.def_id did, vec[ast.variant] variants) {
+                           ast.def_id did, vec[ast.variant] variants,
+                           &mutable vec[tup(int, uint)] index) {
     for (ast.variant variant in variants) {
+        index += vec(tup(variant.node.id._1, ebml_w.writer.tell()));
+
         ebml.start_tag(ebml_w, tag_items_data_item);
         encode_def_id(ebml_w, variant.node.id);
         encode_kind(ebml_w, 'v' as u8);
         encode_tag_id(ebml_w, did);
         encode_type(ebml_w, trans.node_ann_type(cx, variant.node.ann));
-        if (_vec.len[ast.variant_arg](variant.node.args) > 0u) {
-            encode_symbol(cx, ebml_w, variant.node.id);
-        }
+        encode_symbol(cx, ebml_w, variant.node.id);
         encode_discriminant(cx, ebml_w, variant.node.id);
         ebml.end_tag(ebml_w);
     }
 }
 
 fn encode_info_for_item(@trans.crate_ctxt cx, &ebml.writer ebml_w,
-                        @ast.item item) {
+                        @ast.item item, &mutable vec[tup(int, uint)] index) {
     alt (item.node) {
         case (ast.item_const(_, _, _, ?did, ?ann)) {
             ebml.start_tag(ebml_w, tag_items_data_item);
@@ -409,9 +421,12 @@ fn encode_info_for_item(@trans.crate_ctxt cx, &ebml.writer ebml_w,
             encode_kind(ebml_w, 't' as u8);
             encode_type_params(ebml_w, tps);
             encode_type(ebml_w, trans.node_ann_type(cx, ann));
+            for (ast.variant v in variants) {
+                encode_variant_id(ebml_w, v.node.id);
+            }
             ebml.end_tag(ebml_w);
 
-            encode_tag_variant_info(cx, ebml_w, did, variants);
+            encode_tag_variant_info(cx, ebml_w, did, variants, index);
         }
         case (ast.item_obj(?id, _, ?tps, ?odid, ?ann)) {
             ebml.start_tag(ebml_w, tag_items_data_item);
@@ -458,7 +473,7 @@ fn encode_info_for_items(@trans.crate_ctxt cx, &ebml.writer ebml_w)
     ebml.start_tag(ebml_w, tag_items_data);
     for each (@tup(ast.def_id, @ast.item) kvp in cx.items.items()) {
         index += vec(tup(kvp._0._1, ebml_w.writer.tell()));
-        encode_info_for_item(cx, ebml_w, kvp._1);
+        encode_info_for_item(cx, ebml_w, kvp._1, index);
     }
     for each (@tup(ast.def_id, @ast.native_item) kvp in
             cx.native_items.items()) {
diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs
index 263ac940104..7859393e56d 100644
--- a/src/comp/middle/trans.rs
+++ b/src/comp/middle/trans.rs
@@ -1911,7 +1911,10 @@ type variant_info = rec(vec[@ty.t] args, @ty.t ctor_ty, ast.def_id id);
 
 // Returns information about the variants in a tag.
 fn tag_variants(@crate_ctxt cx, ast.def_id id) -> vec[variant_info] {
-    // FIXME: This doesn't work for external variants.
+    if (cx.sess.get_targ_crate_num() != id._0) {
+        ret creader.get_tag_variants(cx.sess, id);
+    }
+
     check (cx.items.contains_key(id));
     alt (cx.items.get(id).node) {
         case (ast.item_tag(_, ?variants, _, _, _)) {
diff --git a/src/comp/rustc.rc b/src/comp/rustc.rc
index afa84711707..98fae38b232 100644
--- a/src/comp/rustc.rc
+++ b/src/comp/rustc.rc
@@ -47,6 +47,7 @@ auth front.creader.load_crate = unsafe;
 auth front.creader.lookup_def = impure;
 auth front.creader.get_type = impure;
 auth front.creader.get_symbol = impure;
+auth front.creader.get_tag_variants = impure;
 auth front.creader.impure_no_op = impure;
 auth middle.metadata = unsafe;
 auth middle.metadata.encode_index = impure;