rustc: Get tag variants from the crate metadata

This commit is contained in:
Patrick Walton 2011-04-01 13:02:44 -07:00
parent ec9d7abf8c
commit 6dc452335a
4 changed files with 78 additions and 16 deletions

View File

@ -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;

View File

@ -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()) {

View File

@ -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, _, _, _)) {

View File

@ -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;