diff --git a/src/comp/front/creader.rs b/src/comp/front/creader.rs index 22c38c3172c76ada5f21433b2e928b41ff89ffb0..151411c6bcac67053a6ae7f6fa8b7822b35723d1 100644 --- a/src/comp/front/creader.rs +++ b/src/comp/front/creader.rs @@ -8,6 +8,7 @@ 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 @@ fn parse_def_id(vec[u8] buf) -> ast.def_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 @@ fn parse_external_def_id(int this_cnum, str s) -> ast.def_id { 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 @@ fn parse_external_def_id(int this_cnum, str s) -> ast.def_id { 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 c42ed6dbade8b21664e147426393a918b1ffcf92..587db223af8b4581cd3fd9dd3b21b3d98c28d512 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 263ac94010494b94f7d15551c4f05019407b3654..7859393e56d303daa21a74eeeb5000df72393f25 100644 --- a/src/comp/middle/trans.rs +++ b/src/comp/middle/trans.rs @@ -1911,7 +1911,10 @@ fn tag_ty_params(@crate_ctxt cx, ast.def_id id) -> vec[ast.def_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 afa8471170759e8722d3adbfef58a897c394397b..98fae38b232a9895c6447b509a4377020c731481 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;