Extend crate format to allow multiple definitions for a single name

The type/value namespace distinction pretty much works now. Module
namespace is up next.
This commit is contained in:
Marijn Haverbeke 2011-05-13 15:17:24 +02:00
parent 1a12a7b04b
commit eb419fd8c7
4 changed files with 84 additions and 112 deletions

View file

@ -34,11 +34,6 @@ type env = @rec(
mutable int next_crate_num mutable int next_crate_num
); );
tag resolve_result {
rr_ok(ast::def_id);
rr_not_found(ast::ident);
}
// Type decoding // Type decoding
// Compact string representation for ty::t values. API ty_str & parse_from_str // Compact string representation for ty::t values. API ty_str & parse_from_str
@ -282,7 +277,7 @@ fn parse_def_id(vec[u8] buf) -> ast::def_id {
} }
fn lookup_hash(&ebml::doc d, fn(vec[u8]) -> bool eq_fn, uint hash) fn lookup_hash(&ebml::doc d, fn(vec[u8]) -> bool eq_fn, uint hash)
-> option::t[ebml::doc] { -> vec[ebml::doc] {
auto index = ebml::get_doc(d, metadata::tag_index); auto index = ebml::get_doc(d, metadata::tag_index);
auto table = ebml::get_doc(index, metadata::tag_index_table); auto table = ebml::get_doc(index, metadata::tag_index_table);
@ -290,18 +285,12 @@ fn lookup_hash(&ebml::doc d, fn(vec[u8]) -> bool eq_fn, uint hash)
auto pos = ebml::be_uint_from_bytes(d.data, hash_pos, 4u); auto pos = ebml::be_uint_from_bytes(d.data, hash_pos, 4u);
auto bucket = ebml::doc_at(d.data, pos); auto bucket = ebml::doc_at(d.data, pos);
// Awkward logic because we can't ret from foreach yet // Awkward logic because we can't ret from foreach yet
auto result = option::none[ebml::doc]; let vec[ebml::doc] result = vec();
auto belt = metadata::tag_index_buckets_bucket_elt; auto belt = metadata::tag_index_buckets_bucket_elt;
for each (ebml::doc elt in ebml::tagged_docs(bucket, belt)) { for each (ebml::doc elt in ebml::tagged_docs(bucket, belt)) {
alt (result) {
case (option::none[ebml::doc]) {
auto pos = ebml::be_uint_from_bytes(elt.data, elt.start, 4u); auto pos = ebml::be_uint_from_bytes(elt.data, elt.start, 4u);
if (eq_fn(_vec::slice[u8](elt.data, elt.start+4u, elt.end))) { if (eq_fn(_vec::slice[u8](elt.data, elt.start+4u, elt.end))) {
result = option::some[ebml::doc] _vec::push(result, ebml::doc_at(d.data, pos));
(ebml::doc_at(d.data, pos));
}
}
case (_) {}
} }
} }
ret result; ret result;
@ -309,7 +298,7 @@ fn lookup_hash(&ebml::doc d, fn(vec[u8]) -> bool eq_fn, uint hash)
// Given a path and serialized crate metadata, returns the ID of the // Given a path and serialized crate metadata, returns the ID of the
// definition the path refers to. // definition the path refers to.
fn resolve_path(vec[ast::ident] path, vec[u8] data) -> resolve_result { fn resolve_path(vec[ast::ident] path, vec[u8] data) -> vec[ast::def_id] {
fn eq_item(vec[u8] data, str s) -> bool { fn eq_item(vec[u8] data, str s) -> bool {
ret _str::eq(_str::unsafe_from_bytes(data), s); ret _str::eq(_str::unsafe_from_bytes(data), s);
} }
@ -317,15 +306,12 @@ fn resolve_path(vec[ast::ident] path, vec[u8] data) -> resolve_result {
auto md = ebml::new_doc(data); auto md = ebml::new_doc(data);
auto paths = ebml::get_doc(md, metadata::tag_paths); auto paths = ebml::get_doc(md, metadata::tag_paths);
auto eqer = bind eq_item(_, s); auto eqer = bind eq_item(_, s);
alt (lookup_hash(paths, eqer, metadata::hash_path(s))) { let vec[ast::def_id] result = vec();
case (option::some[ebml::doc](?d)) { for (ebml::doc doc in lookup_hash(paths, eqer, metadata::hash_path(s))) {
auto did_doc = ebml::get_doc(d, metadata::tag_def_id); auto did_doc = ebml::get_doc(doc, metadata::tag_def_id);
ret rr_ok(parse_def_id(ebml::doc_data(did_doc))); _vec::push(result, parse_def_id(ebml::doc_data(did_doc)));
}
case (option::none[ebml::doc]) {
ret rr_not_found(s);
}
} }
ret result;
} }
fn maybe_find_item(int item_id, &ebml::doc items) -> option::t[ebml::doc] { fn maybe_find_item(int item_id, &ebml::doc items) -> option::t[ebml::doc] {
@ -333,13 +319,16 @@ fn maybe_find_item(int item_id, &ebml::doc items) -> option::t[ebml::doc] {
ret ebml::be_uint_from_bytes(bytes, 0u, 4u) as int == item_id; ret ebml::be_uint_from_bytes(bytes, 0u, 4u) as int == item_id;
} }
auto eqer = bind eq_item(_, item_id); auto eqer = bind eq_item(_, item_id);
ret lookup_hash(items, eqer, metadata::hash_def_num(item_id)); auto found = lookup_hash(items, eqer, metadata::hash_def_num(item_id));
if (_vec::len(found) == 0u) {
ret option::none[ebml::doc];
} else {
ret option::some[ebml::doc](found.(0));
}
} }
fn find_item(int item_id, &ebml::doc items) -> ebml::doc { fn find_item(int item_id, &ebml::doc items) -> ebml::doc {
alt (maybe_find_item(item_id, items)) { ret option::get(maybe_find_item(item_id, items));
case (option::some[ebml::doc](?d)) {ret d;}
}
} }
// Looks up an item in the given metadata and returns an ebml doc pointing // Looks up an item in the given metadata and returns an ebml doc pointing
@ -478,67 +467,49 @@ fn read_crates(session::session sess,
fn kind_has_type_params(u8 kind_ch) -> bool { fn kind_has_type_params(u8 kind_ch) -> bool {
// FIXME: It'd be great if we had u8 char literals. ret alt (kind_ch as char) {
if (kind_ch == ('c' as u8)) { ret false; } case ('c') { false } case ('f') { true } case ('F') { true }
else if (kind_ch == ('f' as u8)) { ret true; } case ('y') { true } case ('o') { true } case ('t') { true }
else if (kind_ch == ('F' as u8)) { ret true; } case ('T') { false } case ('m') { false } case ('n') { false }
else if (kind_ch == ('y' as u8)) { ret true; } case ('v') { true }
else if (kind_ch == ('o' as u8)) { ret true; } };
else if (kind_ch == ('t' as u8)) { ret true; }
else if (kind_ch == ('T' as u8)) { ret false; }
else if (kind_ch == ('m' as u8)) { ret false; }
else if (kind_ch == ('n' as u8)) { ret false; }
else if (kind_ch == ('v' as u8)) { ret true; }
else {
log_err #fmt("kind_has_type_params(): unknown kind char: %d",
kind_ch as int);
fail;
}
} }
// Crate metadata queries // Crate metadata queries
fn lookup_def(session::session sess, int cnum, vec[ast::ident] path) fn lookup_defs(session::session sess, int cnum, vec[ast::ident] path)
-> option::t[ast::def] { -> vec[ast::def] {
auto data = sess.get_external_crate(cnum).data; auto data = sess.get_external_crate(cnum).data;
auto did; ret _vec::map(bind lookup_def(cnum, data, _),
alt (resolve_path(path, data)) { resolve_path(path, data));
case (rr_ok(?di)) { did = di; } }
case (rr_not_found(?name)) {
ret none[ast::def];
}
}
// FIXME doesn't yet handle re-exported externals
fn lookup_def(int cnum, vec[u8] data, &ast::def_id did) -> ast::def {
auto item = lookup_item(did._1, data); auto item = lookup_item(did._1, data);
auto kind_ch = item_kind(item); auto kind_ch = item_kind(item);
did = tup(cnum, did._1); did = tup(cnum, did._1);
// FIXME: It'd be great if we had u8 char literals. auto def = alt (kind_ch as char) {
auto def; case ('c') { ast::def_const(did) }
if (kind_ch == ('c' as u8)) { def = ast::def_const(did); } case ('f') { ast::def_fn(did) }
else if (kind_ch == ('f' as u8)) { def = ast::def_fn(did); } case ('F') { ast::def_native_fn(did) }
else if (kind_ch == ('F' as u8)) { def = ast::def_native_fn(did); } case ('y') { ast::def_ty(did) }
else if (kind_ch == ('y' as u8)) { def = ast::def_ty(did); } case ('o') { ast::def_obj(did) }
else if (kind_ch == ('o' as u8)) { def = ast::def_obj(did); } case ('T') { ast::def_native_ty(did) }
else if (kind_ch == ('T' as u8)) { def = ast::def_native_ty(did); }
else if (kind_ch == ('t' as u8)) {
// We treat references to tags as references to types. // We treat references to tags as references to types.
def = ast::def_ty(did); case ('t') { ast::def_ty(did) }
} else if (kind_ch == ('m' as u8)) { def = ast::def_mod(did); } case ('m') { ast::def_mod(did) }
else if (kind_ch == ('n' as u8)) { def = ast::def_native_mod(did); } case ('n') { ast::def_native_mod(did) }
else if (kind_ch == ('v' as u8)) { case ('v') {
auto tid = variant_tag_id(item); auto tid = variant_tag_id(item);
tid = tup(cnum, tid._1); tid = tup(cnum, tid._1);
def = ast::def_variant(tid, did); ast::def_variant(tid, did)
} else {
log_err #fmt("lookup_def(): unknown kind char: %d", kind_ch as int);
fail;
} }
};
ret some[ast::def](def); ret def;
} }
fn get_type(session::session sess, ty::ctxt tcx, ast::def_id def) fn get_type(session::session sess, ty::ctxt tcx, ast::def_id def)
@ -563,8 +534,7 @@ fn get_type(session::session sess, ty::ctxt tcx, ast::def_id def)
fn get_symbol(session::session sess, ast::def_id def) -> str { fn get_symbol(session::session sess, ast::def_id def) -> str {
auto external_crate_id = def._0; auto external_crate_id = def._0;
auto data = sess.get_external_crate(external_crate_id).data; auto data = sess.get_external_crate(external_crate_id).data;
auto item = lookup_item(def._1, data); ret item_symbol(lookup_item(def._1, data));
ret item_symbol(item);
} }
fn get_tag_variants(session::session sess, ty::ctxt tcx, ast::def_id def) fn get_tag_variants(session::session sess, ty::ctxt tcx, ast::def_id def)
@ -636,9 +606,8 @@ fn list_crate_metadata(vec[u8] bytes, io::writer out) {
} }
fn describe_def(&ebml::doc items, ast::def_id id) -> str { fn describe_def(&ebml::doc items, ast::def_id id) -> str {
if (id._0 != 0) {ret "external";} if (id._0 != 0) { ret "external"; }
auto item = find_item(id._1, items); ret item_kind_to_str(item_kind(find_item(id._1, items)));
ret item_kind_to_str(item_kind(item));
} }
fn item_kind_to_str(u8 kind) -> str { fn item_kind_to_str(u8 kind) -> str {

View file

@ -37,7 +37,6 @@ const uint tag_items_data_item_type = 0x0cu;
const uint tag_items_data_item_symbol = 0x0du; const uint tag_items_data_item_symbol = 0x0du;
const uint tag_items_data_item_variant = 0x0eu; const uint tag_items_data_item_variant = 0x0eu;
const uint tag_items_data_item_tag_id = 0x0fu; const uint tag_items_data_item_tag_id = 0x0fu;
const uint tag_items_data_item_obj_type_id = 0x10u;
const uint tag_index = 0x11u; const uint tag_index = 0x11u;
const uint tag_index_buckets = 0x12u; const uint tag_index_buckets = 0x12u;
@ -165,7 +164,7 @@ mod Encode {
} }
case (ty::ty_char) {w.write_char('c');} case (ty::ty_char) {w.write_char('c');}
case (ty::ty_str) {w.write_char('s');} case (ty::ty_str) {w.write_char('s');}
case (ty::ty_tag(?def,?tys)) { // TODO restore def_id case (ty::ty_tag(?def,?tys)) {
w.write_str("t["); w.write_str("t[");
w.write_str(cx.ds(def)); w.write_str(cx.ds(def));
w.write_char('|'); w.write_char('|');
@ -387,7 +386,12 @@ fn encode_module_item_paths(&ebml::writer ebml_w,
ebml::start_tag(ebml_w, tag_paths_data_item); ebml::start_tag(ebml_w, tag_paths_data_item);
encode_name(ebml_w, id); encode_name(ebml_w, id);
encode_def_id(ebml_w, odid.ctor); encode_def_id(ebml_w, odid.ctor);
encode_obj_type_id(ebml_w, odid.ty); ebml::end_tag(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_def_id(ebml_w, odid.ty);
ebml::end_tag(ebml_w); ebml::end_tag(ebml_w);
} }
} }
@ -459,11 +463,6 @@ fn encode_tag_id(&ebml::writer ebml_w, &ast::def_id id) {
ebml::end_tag(ebml_w); ebml::end_tag(ebml_w);
} }
fn encode_obj_type_id(&ebml::writer ebml_w, &ast::def_id id) {
ebml::start_tag(ebml_w, tag_items_data_item_obj_type_id);
ebml_w.writer.write(_str::bytes(def_to_str(id)));
ebml::end_tag(ebml_w);
}
fn encode_tag_variant_info(&@trans::crate_ctxt cx, &ebml::writer ebml_w, fn encode_tag_variant_info(&@trans::crate_ctxt cx, &ebml::writer ebml_w,
@ -550,6 +549,7 @@ fn encode_info_for_item(@trans::crate_ctxt cx, &ebml::writer ebml_w,
encode_symbol(cx, ebml_w, odid.ctor); encode_symbol(cx, ebml_w, odid.ctor);
ebml::end_tag(ebml_w); ebml::end_tag(ebml_w);
index += vec(tup(odid.ty._1, ebml_w.writer.tell()));
ebml::start_tag(ebml_w, tag_items_data_item); ebml::start_tag(ebml_w, tag_items_data_item);
encode_def_id(ebml_w, odid.ty); encode_def_id(ebml_w, odid.ty);
encode_kind(ebml_w, 'y' as u8); encode_kind(ebml_w, 'y' as u8);

View file

@ -47,16 +47,22 @@ tag import_state {
resolved(option::t[def] /* value */, option::t[def] /* type */); resolved(option::t[def] /* value */, option::t[def] /* type */);
} }
type ext_hash = hashmap[tup(def_id,str),def]; type ext_hash = hashmap[tup(def_id,str,namespace),def];
fn new_ext_hash() -> ext_hash { fn new_ext_hash() -> ext_hash {
fn hash(&tup(def_id,str) v) -> uint { fn hash(&tup(def_id,str,namespace) v) -> uint {
ret _str::hash(v._1) + util::common::hash_def(v._0); ret _str::hash(v._1) + util::common::hash_def(v._0) + (alt (v._2) {
case (ns_value) { 1u }
case (ns_type) { 2u }
case (ns_module) { 3u }
});
} }
fn eq(&tup(def_id,str) v1, &tup(def_id,str) v2) -> bool { fn eq(&tup(def_id,str,namespace) v1,
&tup(def_id,str,namespace) v2) -> bool {
ret util::common::def_eq(v1._0, v2._0) && ret util::common::def_eq(v1._0, v2._0) &&
_str::eq(v1._1, v2._1); _str::eq(v1._1, v2._1) &&
v1._2 == v2._2;
} }
ret std::map::mk_hashmap[tup(def_id,str),def](hash, eq); ret std::map::mk_hashmap[tup(def_id,str,namespace),def](hash, eq);
} }
tag mod_index_entry { tag mod_index_entry {
@ -509,7 +515,7 @@ fn lookup_in_scope(&env e, list[scope] sc, &span sp, &ident id, namespace ns)
} }
case (cons[scope](?hd, ?tl)) { case (cons[scope](?hd, ?tl)) {
auto fnd = in_scope(e, id, hd, ns); auto fnd = in_scope(e, id, hd, ns);
if (fnd != none[def]) { if (!option::is_none(fnd)) {
auto df = option::get(fnd); auto df = option::get(fnd);
if ((left_fn && def_is_local(df)) || if ((left_fn && def_is_local(df)) ||
(left_fn_level2 && def_is_obj_field(df))) { (left_fn_level2 && def_is_obj_field(df))) {
@ -550,7 +556,7 @@ fn lookup_in_pat(&ident id, &ast::pat pat) -> option::t[def] {
case (ast::pat_tag(_, ?pats, _)) { case (ast::pat_tag(_, ?pats, _)) {
for (@ast::pat p in pats) { for (@ast::pat p in pats) {
auto found = lookup_in_pat(id, *p); auto found = lookup_in_pat(id, *p);
if (found != none[def]) { ret found; } if (!option::is_none(found)) { ret found; }
} }
} }
} }
@ -617,7 +623,7 @@ fn lookup_in_block(&ident id, &ast::block_ b, namespace ns)
case (_) { case (_) {
if (_str::eq(ast::item_ident(it), id)) { if (_str::eq(ast::item_ident(it), id)) {
auto found = found_def_item(it, ns); auto found = found_def_item(it, ns);
if (found != none[def]) { ret found; } if (!option::is_none(found)) { ret found; }
} }
} }
} }
@ -676,17 +682,15 @@ fn lookup_in_mod(&env e, def m, &ident id, namespace ns, dir dr)
-> option::t[def] { -> option::t[def] {
auto defid = ast::def_id_of_def(m); auto defid = ast::def_id_of_def(m);
if (defid._0 != ast::local_crate) { // Not in this crate if (defid._0 != ast::local_crate) { // Not in this crate
auto cached = e.ext_cache.find(tup(defid,id)); auto cached = e.ext_cache.find(tup(defid,id,ns));
if (cached != none[def] && check_def_by_ns(option::get(cached), ns)) { if (!option::is_none(cached)) { ret cached; }
ret cached;
}
auto path = vec(id); auto path = vec(id);
if (defid._1 != -1) { if (defid._1 != -1) {
path = e.ext_map.get(defid) + path; path = e.ext_map.get(defid) + path;
} }
auto fnd = lookup_external(e, defid._0, path, ns); auto fnd = lookup_external(e, defid._0, path, ns);
if (fnd != none[def]) { if (!option::is_none(fnd)) {
e.ext_cache.insert(tup(defid,id), option::get(fnd)); e.ext_cache.insert(tup(defid,id,ns), option::get(fnd));
} }
ret fnd; ret fnd;
} }
@ -728,8 +732,8 @@ fn lookup_import(&env e, def_id defid, namespace ns) -> option::t[def] {
} }
} }
fn lookup_in_regular_mod(&env e, def_id defid, &ident id, namespace ns, dir dr) fn lookup_in_regular_mod(&env e, def_id defid, &ident id, namespace ns,
-> option::t[def] { dir dr) -> option::t[def] {
auto info = e.mod_map.get(defid._1); auto info = e.mod_map.get(defid._1);
auto found = info.index.find(id); auto found = info.index.find(id);
if (option::is_none(found) || if (option::is_none(found) ||
@ -935,13 +939,11 @@ fn check_def_by_ns(def d, namespace ns) -> bool {
fn lookup_external(&env e, int cnum, vec[ident] ids, namespace ns) fn lookup_external(&env e, int cnum, vec[ident] ids, namespace ns)
-> option::t[def] { -> option::t[def] {
auto found = creader::lookup_def(e.sess, cnum, ids); for (def d in creader::lookup_defs(e.sess, cnum, ids)) {
if (found != none[def]) {
auto d = option::get(found);
if (!check_def_by_ns(d, ns)) { ret none[def]; }
e.ext_map.insert(ast::def_id_of_def(d), ids); e.ext_map.insert(ast::def_id_of_def(d), ids);
if (check_def_by_ns(d, ns)) { ret some(d); }
} }
ret found; ret none[def];
} }
// Local Variables: // Local Variables:

View file

@ -1929,6 +1929,7 @@ mod Unify {
} else if (actual_input.mode == mo_either) { } else if (actual_input.mode == mo_either) {
result_mode = expected_input.mode; result_mode = expected_input.mode;
} else if (expected_input.mode != actual_input.mode) { } else if (expected_input.mode != actual_input.mode) {
// FIXME this is the wrong error
ret fn_common_res_err(ures_err(terr_arg_count, ret fn_common_res_err(ures_err(terr_arg_count,
expected, actual)); expected, actual));
} else { } else {